Pull fixes to radwho & radzap (including docs) from the CVS head
authoraland <aland>
Mon, 11 Apr 2005 23:29:48 +0000 (23:29 +0000)
committeraland <aland>
Mon, 11 Apr 2005 23:29:48 +0000 (23:29 +0000)
man/man1/radwho.1
man/man1/radzap.1
src/main/Makefile.in
src/main/radwho.c
src/main/radzap [new file with mode: 0755]
src/main/radzap.c [deleted file]

index bbb7db5..ed75468 100644 (file)
@@ -1,63 +1,98 @@
-.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.
index 3403cb0..0f69513 100644 (file)
@@ -1,47 +1,62 @@
-.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>
index 5f0b463..a226944 100644 (file)
@@ -137,14 +137,8 @@ radrelay.o: radrelay.c $(INCLUDES)
 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
@@ -152,7 +146,7 @@ clean:
 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)
index 40b0aef..b5cf36e 100644 (file)
@@ -55,15 +55,11 @@ static const char rcsid[] =
  */
 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";
 
@@ -74,7 +70,6 @@ static int showcid = 0;
 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;
@@ -83,11 +78,18 @@ const char *radlib_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 }
 };
@@ -234,71 +236,6 @@ static char *dotime(time_t t)
        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.
@@ -314,21 +251,29 @@ static const char *hostname(char *buf, size_t buflen, uint32_t ipaddr)
 /*
  *     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);
 }
 
 
@@ -340,42 +285,51 @@ int main(int argc, char **argv)
        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;
@@ -385,6 +339,9 @@ int main(int argc, char **argv)
                case 'p':
                        showptype = 1;
                        break;
+               case 'P':
+                       nas_port = atoi(optarg);
+                       break;
                case 'c':
                        showcid = 1;
                        showname = 1;
@@ -392,30 +349,68 @@ int main(int argc, char **argv)
                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 */
@@ -451,108 +446,161 @@ int main(int argc, char **argv)
                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;
diff --git a/src/main/radzap b/src/main/radzap
new file mode 100755 (executable)
index 0000000..2cc7fd1
Binary files /dev/null and b/src/main/radzap differ
diff --git a/src/main/radzap.c b/src/main/radzap.c
deleted file mode 100644 (file)
index 74860fb..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * 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);
-}