2 * radzap.c Zap a user from the radutmp and radwtmp file.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000 The FreeRADIUS server project
21 * Copyright 2000 Alan DeKok <aland@ox.org>
25 #include "libradius.h"
35 #include <sys/types.h>
36 #include <sys/socket.h>
39 # include <netinet/in.h>
49 /* FIXME: Some of the following are unused and just there to make the linker
50 * happy. Also all of log.o is linked in mainly to make the linker happy. */
53 const char *radlog_dir = NULL;
54 const char *radius_dir = NULL;
56 int auth_port; /* Not really used */
60 #define LOCK_LEN sizeof(struct radutmp)
63 * Internal wrapper for locking, to minimize the number of ifdef's
64 * in the source. Copied from rlm_radutmp.c (was src/main/radutmp.c),
65 * perhaps these wrappers should be #defined in radutmp.h
67 * Lock the utmp file, prefer lockf() over flock()
69 static void radutmp_lock(int fd)
71 #if defined(F_LOCK) && !defined(BSD)
72 (void)lockf(fd, F_LOCK, LOCK_LEN);
74 (void)flock(fd, LOCK_EX);
79 * Internal wrapper for unlocking, to minimize the number of ifdef's
82 * Unlock the utmp file, prefer lockf() over flock()
84 static void radutmp_unlock(int fd)
86 #if defined(F_LOCK) && !defined(BSD)
87 (void)lockf(fd, F_ULOCK, LOCK_LEN);
89 (void)flock(fd, LOCK_UN);
93 static int radutmp_lookup(struct radutmp *u, uint32_t nasaddr, int port,
98 if ((fd = open(RADUTMP, O_RDONLY|O_CREAT, 0644)) >= 0) {
100 * Lock the utmp file, prefer lockf() over flock().
105 * Find the entry for this NAS / portno combination.
107 while (read(fd, u, sizeof(*u)) == sizeof(*u)) {
108 if ((nasaddr != 0 && nasaddr != u->nas_address) ||
109 (port >= 0 && port != u->nas_port) ||
111 strncmp(u->login, user, sizeof u->login) != 0) ||
124 static int do_accton_packet(uint32_t nasaddr);
125 static int do_stop_packet(const struct radutmp *u);
128 * Zap a user from the radutmp and radwtmp file.
130 int main(int argc, char **argv)
142 if (argc > 1 && !strcmp(argv[0], "-p")) {
143 acct_port = atoi(argv[1]);
146 if (argc < 1 || argc > 3 || argv[1][0] == '-') {
147 fprintf(stderr, "Usage: radzap termserver [port] [user]\n");
148 fprintf(stderr, " radzap is only an admin tool to clean the radutmp file!\n");
153 if (*s == 's' || *s == 'S') s++;
156 if (argc > 2) user = argv[2];
158 radius_dir = strdup(RADIUS_DIR);
161 * Read the "naslist" file.
163 sprintf(buf, "%s/%s", RADIUS_DIR, RADIUS_NASLIST);
164 if (read_naslist_file(buf) < 0)
168 * Find the IP address of the terminal server.
170 if ((nas = nas_findbyname(argv[0])) == NULL && argv[0][0] != 0) {
171 if ((ip = ip_getaddr(argv[0])) == INADDR_NONE) {
172 fprintf(stderr, "%s: host not found.\n", argv[0]);
176 if (nas) ip = nas->ipaddr;
178 printf("radzap: zapping termserver %s, port %d",
179 ip_hostname(buf, sizeof(buf), ip), nas_port);
180 if (user) printf(", user %s", user);
184 return do_accton_packet(ip);
187 if(!radutmp_lookup(&u, ip, nas_port, user)) {
188 fprintf(stderr, "Entry not found\n");
192 return do_stop_packet(&u);
195 static int getport(const char *name)
199 svp = getservbyname (name, "udp");
204 return ntohs(svp->s_port);
207 static const char *getlocalhostsecret(void)
211 snprintf(fn, sizeof fn, "%s/%s", radius_dir, RADIUS_CLIENTS);
212 if(read_clients_file(fn)<0) {
213 radlog(L_ERR|L_CONS, "Errors reading clients");
216 cl=client_find(htonl(INADDR_LOOPBACK));
218 radlog(L_ERR|L_CONS, "No clients entry for localhost");
221 return (const char *)cl->secret;
224 /* Packet-fabrication macros. Don't stare directly at them without protective
226 #define PAIR(n,v,t,e) do { \
227 if(!(vp=paircreate(n, t))) { \
228 radlog(L_ERR|L_CONS, "no memory"); \
229 pairfree(&req->vps); \
233 pairadd(&req->vps, vp); \
235 #define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,lvalue)
236 #define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,lvalue)
237 #define STRINGPAIR(n,v) do { \
238 if(!(vp=paircreate(n, PW_TYPE_STRING))) { \
239 radlog(L_ERR|L_CONS, "no memory"); \
240 pairfree(&req->vps); \
243 strNcpy((char *)vp->strvalue, v, sizeof vp->strvalue); \
244 vp->length=strlen(v); \
245 pairadd(&req->vps, vp); \
248 static int do_packet(int allports, uint32_t nasaddr, const struct radutmp *u)
250 int i, retries=5, timeout=3;
252 RADIUS_PACKET *req, *rep;
254 const char *secret=getlocalhostsecret();
256 if ((req = rad_alloc(1)) == NULL) {
257 librad_perror("radzap");
260 req->id = getpid() & 0xFF;
261 req->code = PW_ACCOUNTING_REQUEST;
262 req->dst_port = acct_port;
263 if(req->dst_port == 0) req->dst_port = getport("radacct");
264 if(req->dst_port == 0) req->dst_port = PW_ACCT_UDP_PORT;
265 req->dst_ipaddr = ip_getaddr("localhost");
266 if(!req->dst_ipaddr) req->dst_ipaddr = 0x7f000001;
270 INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_ACCOUNTING_OFF);
271 IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
272 INTPAIR(PW_ACCT_DELAY_TIME, 0);
274 char login[sizeof u->login+1];
275 char session_id[sizeof u->session_id+1];
276 strNcpy(login, u->login, sizeof login);
277 strNcpy(session_id, u->session_id, sizeof session_id);
278 INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
279 IPPAIR(PW_NAS_IP_ADDRESS, u->nas_address);
280 INTPAIR(PW_ACCT_DELAY_TIME, 0);
281 STRINGPAIR(PW_USER_NAME, login);
282 INTPAIR(PW_NAS_PORT_ID, u->nas_port);
283 STRINGPAIR(PW_ACCT_SESSION_ID, session_id);
285 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
286 INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
287 } else if(u->proto=='S') {
288 INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
289 INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
291 INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
293 IPPAIR(PW_FRAMED_IP_ADDRESS, u->framed_address);
294 INTPAIR(PW_ACCT_SESSION_TIME, 0);
295 INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
296 INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
297 INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
298 INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
300 if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
301 perror("radzap: socket: ");
305 for (i = 0; i < retries; i++) {
308 rad_send(req, secret);
310 /* And wait for reply, timing out as necessary */
312 FD_SET(req->sockfd, &rdfdesc);
314 tv.tv_sec = (int)timeout;
315 tv.tv_usec = 1000000 * (timeout - (int)timeout);
317 /* Something's wrong if we don't get exactly one fd. */
318 if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) {
322 rep = rad_recv(req->sockfd);
325 } else { /* NULL: couldn't receive the packet */
326 librad_perror("radzap:");
331 /* No response or no data read (?) */
333 fprintf(stderr, "radzap: no response from server\n");
337 if (rad_decode(rep, req, secret) != 0) {
338 librad_perror("rad_decode");
342 vp_printlist(stdout, rep->vps);
346 static int do_accton_packet(uint32_t nasaddr)
348 return do_packet(1, nasaddr, 0);
351 static int do_stop_packet(const struct radutmp *u)
353 return do_packet(0, 0, u);
357 /* FIXME: Not called. Needed for files.o to link. Ick */
358 int setup_modules(void); /* -Wmissing-prototypes */
359 int setup_modules(void)
364 /* FIXME: Not called. Needed for files.o to link. Ick */
365 int read_radius_conf_file(void); /* -Wmissing-prototypes */
366 int read_radius_conf_file(void)