25 RCSID(
"$Id: 895807dce431321b4b5d8d6828c91beec72d051c $")
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/sysutmp.h>
29 #include <freeradius-devel/radutmp.h>
39 "Login Name What TTY When From Location";
42 "Login Port What When From Location";
44 static char const *
eol =
"\n";
73 return waitpid(pid, status, 0);
95 if ((pwd = getpwnam(username)) != NULL) {
96 if ((s = strchr(pwd->pw_gecos,
',')) != NULL) *s = 0;
107 static char const *
proto(
int id,
int porttype)
112 if (!strchr(
"ASITX", porttype))
115 snprintf(buf,
sizeof(buf),
"SLP %c", porttype);
117 snprintf(buf,
sizeof(buf),
"PPP %c", porttype);
119 snprintf(buf,
sizeof(buf),
"shl %c", porttype);
122 if (
id ==
'S')
return "SLIP";
123 if (
id ==
'P')
return "PPP";
149 static char const *
hostname(
char *buf,
size_t buflen, uint32_t ipaddr)
154 if (ipaddr == 0 || ipaddr == (uint32_t)-1 || ipaddr == (uint32_t)-2)
157 return inet_ntop(AF_INET, &ipaddr, buf, buflen);
167 FILE *output = status?stderr:stdout;
169 fprintf(output,
"Usage: radwho [-d raddb] [-cfihnprRsSZ] [-N nas] [-P nas_port] [-u user] [-U user]\n");
170 fprintf(output,
" -c Show caller ID, if available.\n");
171 fprintf(output,
" -d Set the raddb directory (default is %s).\n",
RADIUS_DIR);
172 fprintf(output,
" -F <file> Use radutmp <file>.\n");
173 fprintf(output,
" -i Show session ID.\n");
174 fprintf(output,
" -n No full name.\n");
175 fprintf(output,
" -N <nas-ip-address> Show entries matching the given NAS IP address.\n");
176 fprintf(output,
" -p Show port type.\n");
177 fprintf(output,
" -P <port> Show entries matching the given nas port.\n");
178 fprintf(output,
" -r Print output as raw comma-delimited data.\n");
179 fprintf(output,
" -R Print output as RADIUS attributes and values.\n");
180 fprintf(output,
" includes ALL information from the radutmp record.\n");
181 fprintf(output,
" -s Show full name.\n");
182 fprintf(output,
" -S Hide shell users from radius.\n");
183 fprintf(output,
" -u <user> Show entries matching the given user.\n");
184 fprintf(output,
" -U <user> Like -u, but case-sensitive.\n");
185 fprintf(output,
" -Z Include accounting stop information in radius output. Requires -R.\n");
193 int main(
int argc,
char **argv)
204 int radiusoutput = 0;
209 char const *user = NULL;
213 uint32_t nas_ip_address = INADDR_NONE;
226 talloc_set_log_stderr();
228 while((c = getopt(argc, argv,
"d:D:fF:nN:sSipP:crRu:U:Z")) != EOF)
switch (c) {
236 radutmp_file = optarg;
248 if (
inet_pton(AF_INET, optarg, &nas_ip_address) < 0) {
262 nas_port = atoi(optarg);
313 if (zap && !radiusoutput) zap = 0;
318 if (zap && !user && (~nas_port == 0)) {
322 if (nas_ip_address == INADDR_NONE)
usage(1);
324 printf(
"Acct-Status-Type = Accounting-Off\n");
325 printf(
"NAS-IP-Address = %s\n",
326 hostname(buffer,
sizeof(buffer), nas_ip_address));
327 printf(
"Acct-Delay-Time = 0\n");
331 if (radutmp_file)
goto have_radutmp;
336 memset(&main_config, 0,
sizeof(main_config));
340 if (!maincs) exit(1);
342 snprintf(buffer,
sizeof(buffer),
"%.200s/radiusd.conf", raddb_dir);
344 fprintf(stderr,
"%s: Error reading or parsing radiusd.conf\n", argv[0]);
351 fprintf(stderr,
"%s: No modules section found in radiusd.conf\n", argv[0]);
357 fprintf(stderr,
"%s: No configuration information in radutmp section of radiusd.conf\n", argv[0]);
367 if (showname < 0) showname = 1;
372 if ((fp = fopen(radutmp_file,
"r")) == NULL) {
373 fprintf(stderr,
"%s: Error reading %s: %s\n",
381 if (!rawoutput && !radiusoutput) {
382 fputs(showname ? hdr1 : hdr2, stdout);
389 while (fread(&rt,
sizeof(rt), 1, fp) == 1) {
398 if (hideshell && !strchr(
"PCS", rt.
proto))
405 if (((user_cmp == 0) &&
408 (strncmp(rt.
login, user, strlen(user)) != 0))) {
416 if (~nas_port != 0) {
417 if (rt.
nas_port != nas_port)
continue;
423 if (nas_ip_address != INADDR_NONE) {
430 if (!rawoutput && rt.
nas_port > (showname ? 999 : 99999)) {
432 portno = (showname ? 999 : 99999);
443 nasname[
sizeof(rt.
login)] =
'\0';
445 fr_snprint(buffer,
sizeof(buffer), nasname, -1,
'"');
446 printf(
"User-Name = \"%s\"\n", buffer);
449 printf(
"Acct-Session-Id = \"%s\"\n", buffer);
451 if (zap) printf(
"Acct-Status-Type = Stop\n");
453 printf(
"NAS-IP-Address = %s\n",
456 printf(
"NAS-Port = %u\n", rt.
nas_port);
460 printf(
"Service-Type = Framed-User\n");
461 printf(
"Framed-Protocol = SLIP\n");
465 printf(
"Service-Type = Framed-User\n");
466 printf(
"Framed-Protocol = PPP\n");
470 printf(
"Service-type = Login-User\n");
474 printf(
"Framed-IP-Address = %s\n",
482 if ((rt.
time <= now) &&
483 (now - rt.
time) <= (86400 * 365)) {
484 printf(
"Acct-Session-Time = %" PRId64
"\n", (int64_t) (now - rt.
time));
492 fr_snprint(buffer,
sizeof(buffer), nasname, -1,
'"');
493 printf(
"Calling-Station-Id = \"%s\"\n", buffer);
507 if (rawoutput == 0) {
508 printf(
"%-10.10s %-17.17s %-5.5s %s%-3u %-9.9s %-15.15s %-.19s%s",
518 printf(
"%s,%s,%s,%s%u,%s,%s,%s%s",
529 if (rawoutput == 0) {
530 printf(
"%-10.10s %s%-5u %-6.6s %-13.13s %-15.15s %-.28s%s",
539 printf(
"%s,%s%u,%s,%s,%s,%s%s",
#define PW_TYPE_FILE_INPUT
File matching value must exist, and must be readable.
static char const * dict_dir
static char const * proto(int id, int porttype)
Main server configuration.
int fr_dict_read(fr_dict_t *dict, char const *dir, char const *filename)
#define CONF_PARSER_TERMINATOR
int cf_file_read(CONF_SECTION *cs, char const *file)
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
static char const * raddb_dir
static char const * hostname(char *buf, size_t buflen, uint32_t ipaddr)
#define rad_waitpid(a, b)
Defines a CONF_PAIR to C data type mapping.
size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
Escape any non printable or non-UTF8 characters in the input string.
int fr_fault_setup(char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
static char * dotime(time_t t)
Vendors and attribute names.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
unsigned int framed_address
static void NEVER_RETURNS usage(int status)
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
static const CONF_PARSER module_config[]
int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables)
Parse a configuration section into user-supplied variables.
void void fr_perror(char const *,...) CC_HINT(format(printf
#define RADIUS_DICTIONARY
main_config_t main_config
Main server configuration.
static char const * radutmp_file
int inet_pton(int af, char const *src, void *dst)
char const * fr_strerror(void)
Get the last library error.
CONF_SECTION * cf_section_sub_find(CONF_SECTION const *, char const *name)
Find a sub-section in a section.
int strncasecmp(char *s1, char *s2, int n)
CONF_SECTION * cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2)
Allocate a CONF_SECTION.
static struct radutmp_config_t radutmpconfig
static char * fullname(char *username)
size_t strlcpy(char *dst, char const *src, size_t siz)
int main(int argc, char **argv)
#define FR_CONF_POINTER(_n, _t, _p)
CONF_SECTION * cf_section_sub_find_name2(CONF_SECTION const *, char const *name1, char const *name2)
Find a CONF_SECTION with both names.
int fr_dict_init(TALLOC_CTX *ctx, fr_dict_t **out, char const *dir, char const *fn, char const *name)
(re)initialize a protocol dictionary
#define RADIUSD_MAGIC_NUMBER
static char const * progname