-.TH RADWHO 1 "23 February 2001" "" "FreeRADIUS Daemon"
+.TH RADWHO 1 "7 April 2005" "" "FreeRADIUS Daemon"
.SH NAME
radwho - show online users
.SH SYNOPSIS
.B radwho
+.RB [ \-c ]
.RB [ \-d
.IR raddb_directory ]
-.RB [ \-l ]
-.RB [ \-h ]
.RB [ \-f ]
-.RB [ \-n ]
-.RB [ \-s ]
.RB [ \-i ]
+.RB [ \-n ]
+.RB [ \-N
+.IR nas_ip_address ]
.RB [ \-p ]
-.RB [ \-c ]
+.RB [ \-P
+.IR nas_port ]
.RB [ \-r ]
+.RB [ \-R ]
+.RB [ \-s ]
+.RB [ \-S ]
+.RB [ \-u
+.IR user ]
+.RB [ \-U
+.IR user ]
+.RB [ \-Z ]
.SH DESCRIPTION
The FreeRADIUS server can be configured to maintain an active session
database in a file called \fIradutmp\fP. This utility shows the
content of that session database.
.SH OPTIONS
+.IP \-c
+Shows caller ID (if available) instead of the full name.
.IP \-d\ \fIraddb_directory\fP
The directory that contains the RADIUS configuration files. Defaults to
\fI/etc/raddb\fP.
-.IP \-l
-Show local shell users too. In this case, \fBradwho\fP reads the
-local "session database" aka the systems \fIutmp\fP file as well
-and shows the contents of that file before the contents of the
-radius "session database" aka the \fIradutmp\fP file, in the
-same format.
-.IP \-h
-Hide shell users. Doesn't show the entries for users that do not
-have a SLIP or PPP session.
.IP \-f
Behave as the 'fingerd' daemon - waits for one line of input, then
prints the output with lines \\r\\n terminated.
+.IP \-i
+Shows the session ID instead of the full name.
.IP \-n
Normally radwho looks up the username in the systems password file,
and shows the full username as well. The \fB-n\fP flags prevents this.
-.IP \-s
-Show full name.
-.IP \-i
-Shows the session ID instead of the full name.
+.IP \-N\ \fInas_ip_address\fP
+Show only those entries which match the given NAS IP address.
.IP \-p
Adds an extra column for the port type - I for ISDN, A for Analog.
-.IP \-c
-Shows caller ID (if available) instead of the full name.
+.IP \-P\ \fInas_port\fP
+Show only those entries which match the given NAS port.
.IP \-r
Outputs all data in \fIraw\fP format - no headers, no formatting,
-fields are comma-seperated.
+fields are comma-separated.
+.IP \-R
+Output all data in RADIUS attribute format. All fields are printed.
+.IP \-s
+Show full name.
+.IP \-S
+Hide shell users. Doesn't show the entries for users that do not
+have a SLIP or PPP session.
+.IP \-u\ \fIuser\fP
+Show only those entries which match the given username (case insensitive).
+.IP \-U\ \fIuser\fP
+Show only those entries which match the given username (case sensitive).
+.IP \-Z
+When combined with \fI-R\fP, prints out the contents of an
+Accounting-Request packet which can be passed to \fIradclient\fP, in
+order to "zap" that users session from \fIradutmp\fP.
+.PP
+For example,
+.RS
+.sp
+.nf
+.ne 3
+$ radwho -ZRN 10.0.0.1 | radclient -f - radius.example.net acct testing123
+.fi
+.sp
+.RE
+will result in all an Accounting-Request packet being sent to the
+RADIUS server, which tells the server that the NAS rebooted. i.e. It
+"zaps" all of the users on that NAS.
-.SH SEE ALSO
-radiusd(8).
-.SH AUTHOR
-Miquel van Smoorenburg, miquels@cistron.nl.
+To "zap" one user, specifiy NAS, username, and NAS port:
+.RS
+.sp
+.nf
+.ne 3
+$ radwho -ZRN 10.0.0.1 -u user -P 10 | radclient -f - radius.example.net acct testing123
+.fi
+.sp
+.RE
+Other combinations are also possible.
.SH SEE ALSO
radiusd(8),
-radiusd.conf(5),
-wtmp(5),
-last(1).
+radclient(1),
+radiusd.conf(5).
.SH AUTHOR
Miquel van Smoorenburg, miquels@cistron.nl.
-.TH RADZAP 1 "16 May 2002" "" "FreeRadius Daemon"
+.TH RADZAP 1 "8 April 2005" "" "FreeRadius Daemon"
.SH NAME
radzap - remove rogue entries from the active sessions database
.SH SYNOPSIS
.B radzap
.RB [ \-d
.IR raddb_directory ]
-.RB [ \-r
-.IR radius_server ]
-.RB [ \-p
-.IR accounting_port ]
-.RB [ \-v ]
-.I nas
-.RB [ port ]
-.RB [ username ]
+.RB [ \-N
+.IR nas_ip_address ]
+.RB [ \-P
+.IR nas_port ]
+.RB [ \-u
+.IR user ]
+.RB [ \-U
+.IR user ]
+\fIserver[:port] secret\fP
.SH DESCRIPTION
The FreeRadius server can be configured to maintain an active session
database in a file called \fIradutmp\fP. Commands like \fBradwho\fP(1)
use this database. Sometimes that database can get out of sync, and
then it might contain rogue entries. \fBradzap\fP can clean up this
database.
+
+As of FreeRADIUS 1.0.3, \fBradzap\fP is a simple shell-script wrapper
+around \fBradwho\fP(1) and \fBradclient\fP(1).
+
+The sessions are "zapped" by sending an Accounting-Request packet
+which contains the information necessary for the server to delete the
+session record. \fBradzap\fP sends a packet to the server, rather
+than writing to \fIradutmp\fP directly, because session records may
+also be maintained in SQL.
.SH OPTIONS
.IP \-d\ \fIraddb_directory\fP
The directory that contains the RADIUS configuration files.
-.IP \-r\ \fIradius_server\fP
-Host name or IP address of the RADIUS server.
-.IP \-p\ \fIaccounting_port\fP
-The port to which accounting packets are sent. See "/etc/services",
-port "radacct" for the default on your system (usually 1646 or 1813).
-.IP \-v
-Verbose. Shows you what it is doing.
-.IP nas
-Hostname or IP address of the NAS (Network Access Server, sometimes
-called "terminal server") of the session you want to remove.
-.IP port
-Port of the session you want to remove. This is the NAS-Port
-radius attribute, it doesn't have anything to do with UDP port
-numbers. Must be an integer. \fB-1\fP means "any", and is the
-default if this option is not specified.
-.IP username
-Optional: the username of the session you want to remove.
+\fBradzap\fP reads \fIradiusd.conf\fP to determine the location of the
+\fIradutmp\fP file.
+.IP \-N\ \fInas_ip_address\fP
+Zap the entries which match the given NAS IP address.
+.IP \-P\ \fInas_port\fP
+Zap the entries which match the given NAS port.
+.IP \-u\ \fIuser\fP
+Zap the entries which match the given username (case insensitive).
+.IP \-U\ \fIuser\fP
+Zap the entries which match the given username (case sensitive).
+.IP server[:port]
+The hostname or IP address of the remote server. Optionally a UDP port
+can be specified. If no UDP port is specified, it is looked up in
+\fI/etc/services\fP. The service name looked for is \fBradacct\fP for
+accounting packets, and \fBradius\fP for all other requests. If a
+service is not found in \fI/etc/services\fP, 1813 and 1812 are used
+respectively.
+.IP secret
+The shared secret for this client. It needs to be defined on the
+radius server side too, for the IP address you are sending the radius
+packets from.
.SH SEE ALSO
radwho(1),
+radclient(1),
radiusd(8),
radiusd.conf(5).
.SH AUTHOR
-Miquel van Smoorenburg, miquels@cistron.nl., and others.
+Alan DeKok <aland@ox.org>
radwho.o: radwho.c $(INCLUDES)
$(CC) $(CFLAGS) -c radwho.c
-radwho: radwho.o mainconfig.o util.o nas.o client.o log.o conffile.o files.o xlat.o
- $(CC) $(LDFLAGS) -o radwho radwho.o mainconfig.o util.o nas.o client.o log.o conffile.o files.o xlat.o $(LIBS)
-
-radzap.o: radzap.c $(INCLUDES)
- $(CC) $(CFLAGS) -c radzap.c
-
-radzap: radzap.o mainconfig.o util.o nas.o log.o client.o conffile.o files.o xlat.o
- $(CC) $(CFLAGS) $(LDFLAGS) -o radzap radzap.o mainconfig.o util.o nas.o log.o client.o conffile.o files.o xlat.o $(LIBS)
+radwho: radwho.o util.o log.o conffile.o ../lib/libradius.la
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o radwho radwho.o util.o log.o conffile.o ../lib/libradius.la $(LIBS) $(LCRYPT)
clean:
rm -rf *.o *.so *~ $(BINARIES) .libs
install:
$(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) radiusd$(EXEEXT) $(R)$(sbindir)
$(INSTALL) -m 755 $(INSTALLSTRIP) radwho$(EXEEXT) $(R)$(bindir)
- $(INSTALL) -m 755 $(INSTALLSTRIP) radzap$(EXEEXT) $(R)$(bindir)
+ $(INSTALL) -m 755 $(INSTALLSTRIP) radzap $(R)$(bindir)
$(INSTALL) -m 755 radlast $(R)$(bindir)
$(INSTALL) -m 755 radclient$(EXEEXT) $(R)$(bindir)
$(INSTALL) -m 755 radrelay$(EXEEXT) $(R)$(bindir)
*/
static const char *hdr1 =
"Login Name What TTY When From Location";
-static const char *ufmt1 = "%-10.10s %-17.17s %-5.5s %-4.4s %-9.9s %-9.9s %-.16s%s";
-static const char *ufmt1r = "%s,%s,%s,%s,%s,%s,%s%s";
static const char *rfmt1 = "%-10.10s %-17.17s %-5.5s %s%-3d %-9.9s %-9.9s %-.19s%s";
static const char *rfmt1r = "%s,%s,%s,%s%d,%s,%s,%s%s";
static const char *hdr2 =
"Login Port What When From Location";
-static const char *ufmt2 = "%-10.10s %-6.6d %-7.7s %-13.13s %-10.10s %-.16s%s";
-static const char *ufmt2r = "%s,%d,%s,%s,%s,%s%s";
static const char *rfmt2 = "%-10.10s %s%-5d %-6.6s %-13.13s %-10.10s %-.28s%s";
static const char *rfmt2r = "%s,%s%d,%s,%s,%s,%s%s";
int debug_flag = 0;
const char *progname = "radwho";
const char *radlog_dir = NULL;
-radlog_dest_t radlog_dest = RADLOG_FILES;
const char *radutmp_file = NULL;
const char *radius_dir = NULL;
uint32_t myip = INADDR_ANY;
int log_stripped_names;
+radlog_dest_t radlog_dest = RADLOG_STDOUT;
+
+/*
+ * Global, for log.c to use.
+ */
+struct main_config_t mainconfig;
+
struct radutmp_config_t {
char *radutmp_fn;
} radutmpconfig;
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
{ "filename", PW_TYPE_STRING_PTR, 0, &radutmpconfig.radutmp_fn, RADUTMP },
{ NULL, -1, 0, NULL, NULL }
};
return s;
}
-#if 0 /*UNUSED*/
-/*
- * See how long a tty has been idle.
- */
-char *idletime(char *line)
-{
- char tty[16];
- static char tmp[8];
- time_t t;
- struct stat st;
- int hr, min, days;
-
- if (line[0] == '/')
- strcpy(tty, "/dev/");
- else
- tty[0] = 0;
- strncat(tty, line, 10);
- tty[15] = 0;
-
- tmp[0] = 0;
- if (stat(tty, &st) == 0) {
- time(&t);
- t -= st.st_mtime;
- if (t >= 60) {
- min = (t / 60);
- hr = min / 24;
- days = hr / 24;
- min %= 60;
- hr %= 24;
- if (days > 0)
- snprintf(tmp, sizeof(tmp), "%dd", days);
- else
- snprintf(tmp, sizeof(tmp), "%2d:%02d", hr, min);
- }
- }
- return tmp;
-}
-#endif
-
-/*
- * Shorten tty name.
- */
-static const char *ttyshort(char *tty)
-{
- static char tmp[16];
-
- if (tty[0] == '/') tty += 5;
-
- if (strncmp(tty, "tty", 3) == 0) {
- if (tty[3] >= '0' && tty[3] <= '9')
- snprintf(tmp, sizeof(tmp), "v%.14s", tty + 3);
- else
- snprintf(tmp, sizeof(tmp), "%.15s", tty + 3);
- return tmp;
- }
- if (strncmp(tty, "vc", 2) == 0) {
- snprintf(tmp, sizeof(tmp), "v.14%s", tty + 2);
- return tmp;
- }
- if (strncmp(tty, "cu", 2) == 0) {
- return tmp + 2;
- }
- return "??";
-}
-
/*
* Print address of NAS.
/*
* Print usage message and exit.
*/
-static void usage(void)
+static void usage(int status)
{
- fprintf(stderr, "Usage: radwho [-d raddb] [-lhfnsipcr]\n");
- fprintf(stderr, " -d: set the raddb directory (default is %s)\n",
+ FILE *output = status?stderr:stdout;
+
+ fprintf(output, "Usage: radwho [-d raddb] [-cfihnprRsSZ] [-N nas] [-P nas_port] [-u user] [-U user]\n");
+ fprintf(output, " -c: show caller ID, if available\n");
+ fprintf(output, " -d: set the raddb directory (default is %s)\n",
RADIUS_DIR);
- fprintf(stderr, " -l: show local (shell) users too\n");
- fprintf(stderr, " -h: hide shell users from radius\n");
- fprintf(stderr, " -f: give fingerd output\n");
- fprintf(stderr, " -n: no full name\n");
- fprintf(stderr, " -s: show full name\n");
- fprintf(stderr, " -i: show session ID\n");
- fprintf(stderr, " -p: show port type\n");
- fprintf(stderr, " -c: show caller ID, if available\n");
- fprintf(stderr, " -r: output as raw data\n");
- exit(1);
+ fprintf(output, " -f: give fingerd output\n");
+ fprintf(output, " -i: show session ID\n");
+ fprintf(output, " -n: no full name\n");
+ fprintf(output, " -N <nas-ip-address>: Show entries matching the given NAS IP address\n");
+ fprintf(output, " -p: show port type\n");
+ fprintf(output, " -P <port>: Show entries matching the given nas port\n");
+ fprintf(output, " -r: Print output as raw comma-delimited data\n");
+ fprintf(output, " -R: Print output as RADIUS attributes and values\n");
+ fprintf(output, " Includes ALL information from the radutmp record.\n");
+ fprintf(output, " -s: show full name\n");
+ fprintf(output, " -S: hide shell users from radius\n");
+ fprintf(output, " -u <user>: Show entries matching the given user\n");
+ fprintf(output, " -U <user>: like -u, but case-sensitive\n");
+ fprintf(output, " -Z: Include accounting stop information in radius output. Requires -R.\n");
+ exit(status);
}
CONF_SECTION *maincs, *cs;
FILE *fp;
struct radutmp rt;
- struct utmp ut;
- int hdrdone = 0;
char inbuf[128];
- char myname[128];
char othername[256];
char nasname[1024];
char session_id[sizeof(rt.session_id)+1];
int fingerd = 0;
- int showlocal = 0;
int hideshell = 0;
int showsid = 0;
int rawoutput = 0;
+ int radiusoutput = 0; /* Radius attributes */
char *p, *q;
const char *portind;
int c, portno;
+ char buffer[2048];
+ const char *user = NULL;
+ int user_cmp = 0;
+ time_t now = 0;
+ uint32_t nas_port = ~0;
+ uint32_t nas_ip_address = INADDR_NONE;
+ int zap = 0;
- radius_dir = strdup(RADIUS_DIR);
+ radius_dir = RADIUS_DIR;
- while((c = getopt(argc, argv, "d:flhnsipcr")) != EOF) switch(c) {
+ while((c = getopt(argc, argv, "d:flnN:sSipP:crRu:U:Z")) != EOF) switch(c) {
case 'd':
- if (radius_dir) free(radius_dir);
- radius_dir = strdup(optarg);
+ radius_dir = optarg;
break;
case 'f':
fingerd++;
showname = 0;
break;
- case 'l':
- showlocal = 1;
- break;
case 'h':
+ usage(0);
+ break;
+ case 'S':
hideshell = 1;
break;
case 'n':
showname = 0;
break;
+ case 'N':
+ nas_ip_address = ip_addr(optarg);
+ if (nas_ip_address == INADDR_NONE) {
+ usage(1);
+ }
+ break;
case 's':
showname = 1;
break;
case 'p':
showptype = 1;
break;
+ case 'P':
+ nas_port = atoi(optarg);
+ break;
case 'c':
showcid = 1;
showname = 1;
case 'r':
rawoutput = 1;
break;
+ case 'R':
+ radiusoutput = 1;
+ now = time(NULL);
+ break;
+ case 'u':
+ user = optarg;
+ user_cmp = 0;
+ break;
+ case 'U':
+ user = optarg;
+ user_cmp = 1;
+ break;
+ case 'Z':
+ zap = 1;
+ break;
default:
- usage();
+ usage(1);
break;
}
/*
- * Ensure that the configuration is initialized.
+ * Be safe.
*/
- memset(&mainconfig, 0, sizeof(mainconfig));
+ if (zap && !radiusoutput) zap = 0;
- /* Read radiusd.conf */
- if ((maincs = read_radius_conf_file()) == NULL) {
- fprintf(stderr, "%s: Errors reading radiusd.conf\n", argv[0]);
- exit(1);
+ /*
+ * zap EVERYONE, but only on this nas
+ */
+ if (zap && !user && (~nas_port == 0)) {
+ /*
+ * We need to know which NAS to zap users in.
+ */
+ if (nas_ip_address == INADDR_NONE) usage(1);
+
+ printf("Acct-Status-Type = Accounting-Off\n");
+ printf("NAS-IP-Address = %s\n",
+ ip_hostname(buffer, sizeof(buffer), nas_ip_address));
+ printf("Acct-Delay-Time = 0\n");
+ exit(0); /* don't bother printing anything else */
}
+
+ /*
+ * Initialize mainconfig
+ */
+ memset(&mainconfig, 0, sizeof(mainconfig));
- /* Read the radutmp section of radiusd.conf */
- cs = cf_section_sub_find(cf_section_sub_find(maincs, "modules"), "radutmp");
- if(!cs) {
- fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
- argv[0]);
+ /* Read radiusd.conf */
+ snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
+ maincs = conf_read(NULL, 0, buffer, NULL);
+ if (!maincs) {
+ fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]);
exit(1);
}
+ /* Read the radutmp section of radiusd.conf */
+ cs = cf_section_sub_find(cf_section_sub_find(maincs, "modules"), "radutmp");
+ if(!cs) {
+ fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
+ argv[0]);
+ exit(1);
+ }
+
cf_section_parse(cs, NULL, module_config);
/* Assign the correct path for the radutmp file */
if (*p) sys_finger(p);
}
- if (showlocal && (fp = fopen(radutmp_file, "r"))) {
- if (rawoutput == 0)
- {
- fputs(showname ? hdr1 : hdr2, stdout);
- fputs(eol, stdout);
- }
- hdrdone = 1;
-
- /*
- * Show the logged in UNIX users.
- */
- gethostname(myname, 128);
- while(fread(&ut, sizeof(ut), 1, fp) == 1) {
-#ifdef USER_PROCESS
- if (ut.ut_user[0] && ut.ut_line[0] &&
- ut.ut_type == USER_PROCESS) {
-#else
- if (ut.ut_user[0] && ut.ut_line[0]) {
-#endif
-#ifdef UT_HOSTSIZE
-
-#ifdef HAVE_UTMPX_H
-# define UT_TIME ut_xtime
-#else
-# define UT_TIME ut_time
-#endif
- if (showname)
- printf((rawoutput == 0? ufmt1: ufmt1r),
- ut.ut_name,
- fullname(ut.ut_name),
- "shell",
- ttyshort(ut.ut_line),
- dotime(ut.UT_TIME),
- ut.ut_host,
- myname, eol);
- else
- printf((rawoutput==0? ufmt2:ufmt2r),
- ut.ut_name,
- ttyshort(ut.ut_line),
- "shell",
- dotime(ut.UT_TIME),
- ut.ut_host,
- myname, eol);
-#endif
- }
- }
- fclose(fp);
- }
-
/*
* Show the users logged in on the terminal server(s).
*/
- if ((fp = fopen(radutmp_file, "r")) == NULL)
+ if ((fp = fopen(radutmp_file, "r")) == NULL) {
+ fprintf(stderr, "%s: Error reading %s: %s\n",
+ progname, radutmp_file, strerror(errno));
return 0;
+ }
- if (!hdrdone) {
+ /*
+ * Don't print the headers if raw or RADIUS
+ */
+ if (!rawoutput && !radiusoutput) {
fputs(showname ? hdr1 : hdr2, stdout);
fputs(eol, stdout);
}
- while(fread(&rt, sizeof(rt), 1, fp) == 1) {
- if (rt.type == P_LOGIN) {
- /*
- * We don't show shell users if we are
- * fingerd, as we have done that above.
- */
- if (hideshell && !strchr("PCS", rt.proto))
+ /*
+ * Read the file, printing out active entries.
+ */
+ while (fread(&rt, sizeof(rt), 1, fp) == 1) {
+ if (rt.type != P_LOGIN) continue; /* hide logout sessions */
+
+ /*
+ * We don't show shell users if we are
+ * fingerd, as we have done that above.
+ */
+ if (hideshell && !strchr("PCS", rt.proto))
+ continue;
+
+ /*
+ * Print out sessions only for the given user.
+ */
+ if (user) { /* only for a particular user */
+ if (((user_cmp == 0) &&
+ (strncasecmp(rt.login, user, strlen(user)) != 0)) ||
+ ((user_cmp == 1) &&
+ (strncmp(rt.login, user, strlen(user)) != 0))) {
continue;
+ }
+ }
+
+ /*
+ * Print out only for the given NAS port.
+ */
+ if (~nas_port != 0) {
+ if (rt.nas_port != nas_port) continue;
+ }
+
+ /*
+ * Print out only for the given NAS IP address
+ */
+ if (nas_ip_address != INADDR_NONE) {
+ if (rt.nas_address != nas_ip_address) continue;
+ }
+
+ memcpy(session_id, rt.session_id, sizeof(rt.session_id));
+ session_id[sizeof(rt.session_id)] = 0;
+
+ if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) {
+ portind = ">";
+ portno = (showname ? 999 : 99999);
+ } else {
+ portind = "S";
+ portno = rt.nas_port;
+ }
- memcpy(session_id, rt.session_id, sizeof(rt.session_id));
- session_id[sizeof(rt.session_id)] = 0;
+ /*
+ * Print output as RADIUS attributes
+ */
+ if (radiusoutput) {
+ memcpy(nasname, rt.login, sizeof(rt.login));
+ nasname[sizeof(rt.login)] = '\0';
+
+ librad_safeprint(nasname, -1, buffer,
+ sizeof(buffer));
+ printf("User-Name = \"%s\"\n", buffer);
+
+ librad_safeprint(session_id, -1, buffer,
+ sizeof(buffer));
+ printf("Acct-Session-Id = \"%s\"\n", buffer);
+
+ if (zap) printf("Acct-Status-Type = Stop\n");
+
+ printf("NAS-IP-Address = %s\n",
+ ip_hostname(buffer, sizeof(buffer),
+ rt.nas_address));
+ printf("NAS-Port = %d\n", rt.nas_port);
+
+ switch (rt.proto) {
+ case 'S':
+ printf("Service-Type = Framed-User\n");
+ printf("Framed-Protocol = SLIP\n");
+ break;
+ case 'P':
+ printf("Service-Type = Framed-User\n");
+ printf("Framed-Protocol = PPP\n");
+ break;
+ default:
+ printf("Service-type = Login-User\n");
+ break;
+ }
+ if (rt.framed_address != INADDR_NONE) {
+ printf("Framed-IP-Address = %s\n",
+ ip_hostname(buffer, sizeof(buffer),
+ rt.framed_address));
+ }
+
+ /*
+ * Some sanity checks on the time
+ */
+ if ((rt.time <= now) &&
+ (now - rt.time) <= (86400 * 365)) {
+ printf("Acct-Session-Time = %ld\n",
+ now - rt.time);
+ }
- if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) {
- portind = ">";
- portno = (showname ? 999 : 99999);
- } else {
- portind = "S";
- portno = rt.nas_port;
+ if (rt.caller_id[0] != '\0') {
+ memcpy(nasname, rt.caller_id,
+ sizeof(rt.caller_id));
+ nasname[sizeof(rt.caller_id)] = '\0';
+
+ librad_safeprint(nasname, -1, buffer,
+ sizeof(buffer));
+ printf("Calling-Station-Id = \"%s\"\n", buffer);
}
- if (showname)
- printf((rawoutput == 0? rfmt1: rfmt1r),
- rt.login,
- showcid ? rt.caller_id :
- (showsid? session_id : fullname(rt.login)),
- proto(rt.proto, rt.porttype),
- portind, portno,
- dotime(rt.time),
- nas_name3(nasname, sizeof(nasname), rt.nas_address),
- hostname(othername, sizeof(othername), rt.framed_address), eol);
- else
- printf((rawoutput == 0? rfmt2: rfmt2r),
- rt.login,
- portind, portno,
- proto(rt.proto, rt.porttype),
- dotime(rt.time),
- nas_name3(nasname, sizeof(nasname), rt.nas_address),
- hostname(othername, sizeof(othername), rt.framed_address),
- eol);
+
+ printf("\n"); /* separate entries with a blank line */
+ continue;
+ }
+
+ /*
+ * Show the fill name, or not.
+ */
+ if (showname) {
+ printf((rawoutput == 0? rfmt1: rfmt1r),
+ rt.login,
+ showcid ? rt.caller_id :
+ (showsid? session_id : fullname(rt.login)),
+ proto(rt.proto, rt.porttype),
+ portind, portno,
+ dotime(rt.time),
+ ip_hostname(nasname, sizeof(nasname), rt.nas_address),
+ hostname(othername, sizeof(othername), rt.framed_address), eol);
+ } else {
+ printf((rawoutput == 0? rfmt2: rfmt2r),
+ rt.login,
+ portind, portno,
+ proto(rt.proto, rt.porttype),
+ dotime(rt.time),
+ ip_hostname(nasname, sizeof(nasname), rt.nas_address),
+ hostname(othername, sizeof(othername), rt.framed_address),
+ eol);
}
}
- fflush(stdout);
- fflush(stderr);
fclose(fp);
return 0;
+++ /dev/null
-/*
- * radzap.c Zap a user from the radutmp and radwtmp file.
- *
- * Version: $Id$
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Copyright 2000 The FreeRADIUS server project
- * Copyright 2000 Alan DeKok <aland@ox.org>
- */
-
-#include "autoconf.h"
-#include "libradius.h"
-
-#include <sys/file.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netdb.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#include "radiusd.h"
-#include "radutmp.h"
-#include "conffile.h"
-
-const char *progname;
-const char *radlog_dir = NULL;
-const char *radius_dir = NULL;
-const char *radacct_dir = NULL;
-const char *radlib_dir = NULL;
-radlog_dest_t radlog_dest = RADLOG_FILES;
-int debug_flag = 0;
-int acct_port;
-int log_stripped_names;
-struct main_config_t mainconfig;
-uint32_t radiusip = INADDR_NONE;
-static void usage(void);
-
-struct radutmp_config_t {
- char *radutmp_fn;
-} radutmpconfig;
-
-static CONF_PARSER module_config[] = {
- { "filename", PW_TYPE_STRING_PTR, 0, &radutmpconfig.radutmp_fn, RADUTMP },
- { NULL, -1, 0, NULL, NULL }
-};
-
-#define LOCK_LEN sizeof(struct radutmp)
-
-static int radutmp_lookup(struct radutmp *u, uint32_t nasaddr,
- uint32_t port, const char *user)
-{
- int fd;
-
- if ((fd = open(radutmpconfig.radutmp_fn, O_RDONLY|O_CREAT, 0644)) >= 0) {
- /*
- * Lock the utmp file.
- */
- rad_lockfd(fd, LOCK_LEN);
-
- /*
- * Find the entry for this NAS / portno combination.
- */
- while (read(fd, u, sizeof(*u)) == sizeof(*u)) {
- if ((nasaddr != 0 && nasaddr != u->nas_address) ||
- (port != u->nas_port) ||
- (user != NULL &&
- strncmp(u->login, user, sizeof u->login) != 0) ||
- u->type != P_LOGIN)
- continue;
- /*
- * Match. Zap it.
- */
- close(fd);
- return 1;
- }
- close(fd);
- }
- return 0;
-}
-static int do_accton_packet(uint32_t nasaddr);
-static int do_stop_packet(const struct radutmp *u);
-
-/*
- * Display the syntax for starting this program.
- */
-static void usage(void)
-{
- fprintf(stderr,
- "Usage: %s [-d raddb] [-p acct_port] [-r servername|serverip] termserver [port] [user]\n", progname);
- fprintf(stderr, "Options:\n\n");
- fprintf(stderr, " -d raddb Set the raddb directory (default is %s)\n", RADIUS_DIR);
- fprintf(stderr, " -p acct_port Accounting port on radius server\n");
- fprintf(stderr, " -r radserver Radius server name or IP address\n");
- fprintf(stderr, " termserver Terminal Server (NAS) name or IP address to match, can be '' for any\n");
- fprintf(stderr, " [port] Terminal Server port to match\n");
- fprintf(stderr, " [user] Login account to match\n");
- exit(1);
-}
-
-
-/*
- * Zap a user from the radutmp and radwtmp file.
- */
-int main(int argc, char **argv)
-{
- CONF_SECTION *cs;
- NAS *nas;
- uint32_t ip = 0;
- uint32_t nas_port = ~0;
- char *user = NULL;
- char *s;
- char buf[256];
- struct radutmp u;
- int argval;
-
- progname = argv[0];
-
- radius_dir = strdup(RADIUS_DIR);
-
- /* Process the options. */
- while ((argval = getopt(argc, argv, "d:p:r:")) != EOF) {
-
- switch(argval) {
-
- case 'd':
- if (radius_dir) free(radius_dir);
- radius_dir = strdup(optarg);
- break;
- case 'p':
- acct_port = atoi(optarg);
- break;
-
- case 'r':
- if ((radiusip = ip_getaddr(optarg)) == INADDR_NONE) {
- fprintf(stderr, "%s: %s: radius server unknown\n",
- progname, optarg);
- exit(1);
- }
- break;
-
- default:
- usage();
- exit(1);
- }
- }
-
-
- if (argc == optind) { /* no terminal server specified */
- usage();
- exit(1);
- }
-
- if (argc > optind + 1) { /* NAS port given */
- s = argv[optind+1];
- if (*s == 's' || *s == 'S') s++;
- nas_port = strtoul(s, NULL, 10);
- }
-
- if (argc > optind + 2) { /* username (login) given */
- user = argv[optind+2];
- }
-
- /*
- * Find the IP address of the terminal server.
- */
- if ((nas = nas_findbyname(argv[optind])) == NULL && argv[optind][0] != 0) {
- if ((ip = ip_getaddr(argv[optind])) == INADDR_NONE) {
- fprintf(stderr, "%s: host not found.\n", argv[optind]);
- exit(1);
- }
- }
- if (nas != NULL)
- ip = nas->ipaddr;
-
- /*
- * Ensure that the configuration is initialized.
- */
- memset(&mainconfig, 0, sizeof(mainconfig));
-
- /* Read radiusd.conf */
- if (read_mainconfig(0) < 0) {
- fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]);
- exit(1);
- }
-
- /* Read the radutmp section of radiusd.conf */
- cs = cf_section_sub_find(cf_section_find("modules"), "radutmp");
- if(!cs) {
- fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
- argv[0]);
- exit(1);
- }
-
- cf_section_parse(cs, NULL, module_config);
-
- printf("%s: zapping termserver %s, port %u",
- progname, ip_hostname(buf, sizeof(buf), ip), nas_port);
- if (user != NULL)
- printf(", user %s", user);
- printf("\n");
-
- if (nas_port == ~0) {
- return do_accton_packet(ip);
- }
-
- if (!radutmp_lookup(&u, ip, nas_port, user)) {
- fprintf(stderr, "Entry not found\n");
- return 1;
- }
-
- return do_stop_packet(&u);
-}
-
-static int getport(const char *name)
-{
- struct servent *svp;
-
- svp = getservbyname(name, "udp");
- if (svp == NULL) {
- return 0;
- }
-
- return ntohs(svp->s_port);
-}
-
-static const char *getsecret(uint32_t server)
-{
- RADCLIENT *cl;
-
- cl = client_find(server);
- if (cl == NULL) {
- char buf[32];
- radlog(L_ERR|L_CONS, "No clients entry for %s",
- ip_ntoa(buf,server));
- exit(1);
- }
- return (const char *)cl->secret;
-}
-
-/* Packet-fabrication macros. Don't stare directly at them without protective
- * eye gear */
-#define PAIR(n,v,t,e) do { \
- if(!(vp=paircreate(n, t))) { \
- radlog(L_ERR|L_CONS, "no memory"); \
- pairfree(&req->vps); \
- return 1; \
- } \
- vp->e=v; \
- pairadd(&req->vps, vp); \
-} while(0)
-#define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,lvalue)
-#define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,lvalue)
-#define STRINGPAIR(n,v) do { \
- if(!(vp=paircreate(n, PW_TYPE_STRING))) { \
- radlog(L_ERR|L_CONS, "no memory"); \
- pairfree(&req->vps); \
- return 1; \
- } \
- strNcpy((char *)vp->strvalue, v, sizeof vp->strvalue); \
- vp->length=strlen(v); \
- pairadd(&req->vps, vp); \
-} while(0)
-
-static int do_packet(int allports, uint32_t nasaddr, const struct radutmp *u)
-{
- int i, retries=5, timeout=3;
- struct timeval tv;
- RADIUS_PACKET *req, *rep = NULL;
- VALUE_PAIR *vp;
- const char *secret;
-
- if ((req = rad_alloc(1)) == NULL) {
- librad_perror("radzap");
- exit(1);
- }
- req->id = getpid() & 0xFF;
- req->code = PW_ACCOUNTING_REQUEST;
- req->dst_port = acct_port;
- if(req->dst_port == 0)
- req->dst_port = getport("radacct");
- if(req->dst_port == 0)
- req->dst_port = PW_ACCT_UDP_PORT;
- if (radiusip == INADDR_NONE) {
- req->dst_ipaddr = ip_getaddr("localhost");
- }
- else {
- req->dst_ipaddr = radiusip;
- }
- if(!req->dst_ipaddr)
- req->dst_ipaddr = 0x7f000001;
- req->vps = NULL;
- secret = getsecret(req->dst_ipaddr);
-
- if(allports != 0) {
- INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_ACCOUNTING_OFF);
- IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
- INTPAIR(PW_ACCT_DELAY_TIME, 0);
- } else {
- char login[sizeof u->login+1];
- char session_id[sizeof u->session_id+1];
- strNcpy(login, u->login, sizeof login);
- strNcpy(session_id, u->session_id, sizeof session_id);
- INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
- IPPAIR(PW_NAS_IP_ADDRESS, u->nas_address);
- INTPAIR(PW_ACCT_DELAY_TIME, 0);
- STRINGPAIR(PW_USER_NAME, login);
- INTPAIR(PW_NAS_PORT, u->nas_port);
- STRINGPAIR(PW_ACCT_SESSION_ID, session_id);
- if(u->proto=='P') {
- INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
- INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
- } else if(u->proto=='S') {
- INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
- INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
- } else {
- INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
- }
- IPPAIR(PW_FRAMED_IP_ADDRESS, u->framed_address);
- INTPAIR(PW_ACCT_SESSION_TIME, 0);
- INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
- INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
- INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
- INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
- }
- if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- perror("radzap: socket: ");
- exit(1);
- }
-
- for (i = 0; i < retries; i++) {
- fd_set rdfdesc;
-
- rad_send(req, NULL, secret);
-
- /* And wait for reply, timing out as necessary */
- FD_ZERO(&rdfdesc);
- FD_SET(req->sockfd, &rdfdesc);
-
- tv.tv_sec = (int)timeout;
- tv.tv_usec = 1000000 * (timeout - (int)timeout);
-
- /* Something's wrong if we don't get exactly one fd. */
- if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) {
- continue;
- }
-
- rep = rad_recv(req->sockfd);
- if (rep != NULL) {
- break;
- } else { /* NULL: couldn't receive the packet */
- librad_perror("radzap:");
- exit(1);
- }
- }
-
- /* No response or no data read (?) */
- if (i == retries) {
- fprintf(stderr, "%s: no response from server\n", progname);
- exit(1);
- }
-
- if (rad_decode(rep, req, secret) != 0) {
- librad_perror("rad_decode");
- exit(1);
- }
-
- vp_printlist(stdout, rep->vps);
- return 0;
-}
-
-static int do_accton_packet(uint32_t nasaddr)
-{
- return do_packet(1, nasaddr, 0);
-}
-
-static int do_stop_packet(const struct radutmp *u)
-{
- return do_packet(0, 0, u);
-}