All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
command.c
Go to the documentation of this file.
1 /*
2  * command.c Command socket processing.
3  *
4  * Version: $Id: 82f4396662136effcb47d8dd35d93ac53f183927 $
5  *
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.
10  *
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.
15  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2008 The FreeRADIUS server project
21  * Copyright 2008 Alan DeKok <aland@deployingradius.com>
22  */
23 
24 #ifdef WITH_COMMAND_SOCKET
25 
26 #include <freeradius-devel/parser.h>
27 #include <freeradius-devel/md5.h>
28 #include <freeradius-devel/channel.h>
29 #include <freeradius-devel/state.h>
30 
31 #include <libgen.h>
32 #ifdef HAVE_INTTYPES_H
33 #include <inttypes.h>
34 #endif
35 
36 #ifdef HAVE_SYS_UN_H
37 #include <sys/un.h>
38 #ifndef SUN_LEN
39 #define SUN_LEN(su) (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
40 #endif
41 #endif
42 
43 #ifdef HAVE_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif
46 
47 #include <pwd.h>
48 #include <grp.h>
49 
50 #ifdef HAVE_GPERFTOOLS_PROFILER_H
51 # include <gperftools/profiler.h>
52 #endif
53 
55 
56 typedef int (*fr_command_func_t)(rad_listen_t *, int, char *argv[]);
57 
58 #define FR_READ (1)
59 #define FR_WRITE (2)
60 
61 #define CMD_FAIL FR_CHANNEL_FAIL
62 #define CMD_OK FR_CHANNEL_SUCCESS
63 
65  char const *command;
66  int mode; /* read/write */
67  char const *help;
70 };
71 
72 #define COMMAND_BUFFER_SIZE (1024)
73 
74 typedef struct fr_cs_buffer_t {
75  int auth;
76  int mode;
77  ssize_t offset;
78  ssize_t next;
81 
82 #define COMMAND_SOCKET_MAGIC (0xffdeadee)
83 typedef struct fr_command_socket_t {
84  uint32_t magic;
85  char const *path;
86  char *copy; /* <sigh> */
87  uid_t uid;
88  gid_t gid;
89  char const *uid_name;
90  char const *gid_name;
91  char const *mode_name;
92  bool peercred;
93  char user[256];
94 
95  /*
96  * The next few entries handle fake packets injected by
97  * the control socket.
98  */
99  fr_ipaddr_t src_ipaddr; /* src_port is always 0 */
101  uint16_t dst_port;
104 
107 
108 static const CONF_PARSER command_config[] = {
109  { FR_CONF_OFFSET("socket", PW_TYPE_STRING, fr_command_socket_t, path), .dflt = "${run_dir}/radiusd.sock" },
110  { FR_CONF_OFFSET("uid", PW_TYPE_STRING, fr_command_socket_t, uid_name) },
111  { FR_CONF_OFFSET("gid", PW_TYPE_STRING, fr_command_socket_t, gid_name) },
112  { FR_CONF_OFFSET("mode", PW_TYPE_STRING, fr_command_socket_t, mode_name) },
113  { FR_CONF_OFFSET("peercred", PW_TYPE_BOOLEAN, fr_command_socket_t, peercred), .dflt = "yes" },
115 };
116 
118  { "ro", FR_READ },
119  { "read-only", FR_READ },
120  { "read-write", FR_READ | FR_WRITE },
121  { "rw", FR_READ | FR_WRITE },
122  { NULL, 0 }
123 };
124 
125 static char debug_log_file_buffer[1024];
126 extern fr_cond_t *debug_condition;
127 extern fr_log_t debug_log;
128 
129 #if !defined(HAVE_GETPEEREID) && defined(SO_PEERCRED)
130 static int getpeereid(int s, uid_t *euid, gid_t *egid)
131 {
132  struct ucred cr;
133  socklen_t cl = sizeof(cr);
134 
135  if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cl) < 0) {
136  return -1;
137  }
138 
139  *euid = cr.uid;
140  *egid = cr.gid;
141  return 0;
142 }
143 
144 /* we now have getpeereid() in this file */
145 #define HAVE_GETPEEREID (1)
146 
147 #endif /* HAVE_GETPEEREID */
148 
149 /** Initialise a socket for use with peercred authentication
150  *
151  * This function initialises a socket and path in a way suitable for use with
152  * peercred.
153  *
154  * @param path to socket.
155  * @param uid that should own the socket (linux only).
156  * @param gid that should own the socket (linux only).
157  * @return
158  * - 0 on success.
159  * - -1 on failure.
160  */
161 #ifdef __linux__
162 static int fr_server_domain_socket_peercred(char const *path, uid_t uid, gid_t gid)
163 #else
164 static int fr_server_domain_socket_peercred(char const *path, uid_t UNUSED uid, UNUSED gid_t gid)
165 #endif
166 {
167  int sockfd;
168  size_t len;
169  socklen_t socklen;
170  struct sockaddr_un salocal;
171  struct stat buf;
172 
173  if (!path) {
174  fr_strerror_printf("No path provided, was NULL");
175  return -1;
176  }
177 
178  len = strlen(path);
179  if (len >= sizeof(salocal.sun_path)) {
180  fr_strerror_printf("Path too long in socket filename");
181  return -1;
182  }
183 
184  if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
185  fr_strerror_printf("Failed creating socket: %s", fr_syserror(errno));
186  return -1;
187  }
188 
189  memset(&salocal, 0, sizeof(salocal));
190  salocal.sun_family = AF_UNIX;
191  memcpy(salocal.sun_path, path, len + 1); /* SUN_LEN does strlen */
192 
193  socklen = SUN_LEN(&salocal);
194 
195  /*
196  * Check the path.
197  */
198  if (stat(path, &buf) < 0) {
199  if (errno != ENOENT) {
200  fr_strerror_printf("Failed to stat %s: %s", path, fr_syserror(errno));
201  close(sockfd);
202  return -1;
203  }
204 
205  /*
206  * FIXME: Check the enclosing directory?
207  */
208  } else { /* it exists */
209  int client_fd;
210 
211  if (!S_ISREG(buf.st_mode)
212 #ifdef S_ISSOCK
213  && !S_ISSOCK(buf.st_mode)
214 #endif
215  ) {
216  fr_strerror_printf("Cannot turn %s into socket", path);
217  close(sockfd);
218  return -1;
219  }
220 
221  /*
222  * Refuse to open sockets not owned by us.
223  */
224  if (buf.st_uid != geteuid()) {
225  fr_strerror_printf("We do not own %s", path);
226  close(sockfd);
227  return -1;
228  }
229 
230  /*
231  * Check if a server is already listening on the
232  * socket?
233  */
234  client_fd = fr_socket_client_unix(path, false);
235  if (client_fd >= 0) {
236  fr_strerror_printf("Control socket '%s' is already in use", path);
237  close(client_fd);
238  close(sockfd);
239  return -1;
240  }
241 
242  if (unlink(path) < 0) {
243  fr_strerror_printf("Failed to delete %s: %s", path, fr_syserror(errno));
244  close(sockfd);
245  return -1;
246  }
247  }
248 
249  if (bind(sockfd, (struct sockaddr *)&salocal, socklen) < 0) {
250  fr_strerror_printf("Failed binding to %s: %s", path, fr_syserror(errno));
251  close(sockfd);
252  return -1;
253  }
254 
255  /*
256  * FIXME: There's a race condition here. But Linux
257  * doesn't seem to permit fchmod on domain sockets.
258  */
259  if (chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) {
260  fr_strerror_printf("Failed setting permissions on %s: %s", path, fr_syserror(errno));
261  close(sockfd);
262  return -1;
263  }
264 
265  if (listen(sockfd, 8) < 0) {
266  fr_strerror_printf("Failed listening to %s: %s", path, fr_syserror(errno));
267  close(sockfd);
268  return -1;
269  }
270 
271 #ifdef O_NONBLOCK
272  {
273  int flags;
274 
275  if ((flags = fcntl(sockfd, F_GETFL, NULL)) < 0) {
276  fr_strerror_printf("Failure getting socket flags: %s", fr_syserror(errno));
277  close(sockfd);
278  return -1;
279  }
280 
281  flags |= O_NONBLOCK;
282  if( fcntl(sockfd, F_SETFL, flags) < 0) {
283  fr_strerror_printf("Failure setting socket flags: %s", fr_syserror(errno));
284  close(sockfd);
285  return -1;
286  }
287  }
288 #endif
289 
290  /*
291  * Changing socket permissions only works on linux.
292  * BSDs ignore socket permissions.
293  */
294 #ifdef __linux__
295  /*
296  * Don't chown it from (possibly) non-root to root.
297  * Do chown it from (possibly) root to non-root.
298  */
299  if ((uid != (uid_t) -1) || (gid != (gid_t) -1)) {
300  /*
301  * Don't do chown if it's already owned by us.
302  */
303  if (fstat(sockfd, &buf) < 0) {
304  fr_strerror_printf("Failed reading %s: %s", path, fr_syserror(errno));
305  close(sockfd);
306  return -1;
307  }
308 
309  if ((buf.st_uid != uid) || (buf.st_gid != gid)) {
310  rad_suid_up();
311  if (fchown(sockfd, uid, gid) < 0) {
312  fr_strerror_printf("Failed setting ownership of %s to (%d, %d): %s",
313  path, uid, gid, fr_syserror(errno));
314  rad_suid_down();
315  close(sockfd);
316  return -1;
317  }
318  rad_suid_down();
319  }
320  }
321 #endif
322 
323  return sockfd;
324 }
325 
326 #if !defined(HAVE_OPENAT) || !defined(HAVE_MKDIRAT) || !defined(HAVE_UNLINKAT)
327 static int fr_server_domain_socket_perm(UNUSED char const *path, UNUSED uid_t uid, UNUSED gid_t gid)
328 {
329  fr_strerror_printf("Unable to initialise control socket. Set peercred = yes or update to "
330  "POSIX-2008 compliant libc");
331  return -1;
332 }
333 #else
334 /** Alternative function for creating Unix domain sockets and enforcing permissions
335  *
336  * Unlike fr_server_unix_socket which is intended to be used with peercred auth
337  * this function relies on the file system to enforce access.
338  *
339  * The way it does this depends on the operating system. On Linux systems permissions
340  * can be set on the socket directly and the system will enforce them.
341  *
342  * On most other systems fchown and fchmod fail when called with socket descriptors,
343  * and although permissions can be changed in other ways, they're not enforced.
344  *
345  * For these systems we use the permissions on the parent directory to enforce
346  * permissions on the socket. It's not safe to modify these permissions ourselves
347  * due to TOCTOU attacks, so if they don't match what we require, we error out and
348  * get the user to change them (which arguably isn't any safer, but releases us of
349  * the responsibility).
350  *
351  * @note must be called without effective root permissions (#fr_suid_down).
352  *
353  * @param path where domain socket should be created.
354  * @return
355  * - A file descriptor for the bound socket on success.
356  * - -1 on failure.
357  */
358 static int fr_server_domain_socket_perm(char const *path, uid_t uid, gid_t gid)
359 {
360  int dir_fd = -1, path_fd = -1, sock_fd = -1, parent_fd = -1;
361  char const *name;
362  char *buff = NULL, *dir = NULL, *p;
363 
364  uid_t euid;
365  gid_t egid;
366 
367  mode_t perm = 0;
368  struct stat st;
369 
370  size_t len;
371 
372  socklen_t socklen;
373  struct sockaddr_un salocal;
374 
375  rad_assert(path);
376 
377  euid = geteuid();
378  egid = getegid();
379 
380  /*
381  * Determine the correct permissions for the socket, or its
382  * containing directory.
383  */
384  perm |= S_IREAD | S_IWRITE | S_IEXEC;
385  if (gid != (gid_t) -1) perm |= S_IRGRP | S_IWGRP | S_IXGRP;
386 
387  buff = talloc_strdup(NULL, path);
388  if (!buff) return -1;
389 
390  /*
391  * Some implementations modify it in place others use internal
392  * storage *sigh*. dirname also formats the path else we wouldn't
393  * be using it.
394  */
395  dir = dirname(buff);
396  if (dir != buff) {
397  dir = talloc_strdup(NULL, dir);
398  if (!dir) return -1;
399  talloc_free(buff);
400  }
401 
402  p = strrchr(dir, FR_DIR_SEP);
403  if (!p) {
404  fr_strerror_printf("Failed determining parent directory");
405  error:
406  talloc_free(dir);
407  close(dir_fd);
408  close(path_fd);
409  if (sock_fd >= 0) close(sock_fd);
410  if (parent_fd >= 0) close(parent_fd);
411  return -1;
412  }
413 
414  *p = '\0';
415 
416  /*
417  * Ensure the parent of the control socket directory exists,
418  * and the euid we're running under has access to it.
419  */
420  parent_fd = open(dir, O_DIRECTORY);
421  if (parent_fd < 0) {
422  struct passwd *user;
423  struct group *group;
424 
425  if (rad_getpwuid(NULL, &user, euid) < 0) goto error;
426  if (rad_getgrgid(NULL, &group, egid) < 0) {
427  talloc_free(user);
428  goto error;
429  }
430  fr_strerror_printf("Can't open directory \"%s\": %s. Must be created manually, or modified, "
431  "with permissions that allow writing by user %s or group %s", dir,
432  user->pw_name, group->gr_name, fr_syserror(errno));
433  talloc_free(user);
434  talloc_free(group);
435  goto error;
436  }
437 
438  *p = FR_DIR_SEP;
439 
440  dir_fd = openat(parent_fd, p + 1, O_NOFOLLOW | O_DIRECTORY);
441  if (dir_fd < 0) {
442  int ret = 0;
443 
444  if (errno != ENOENT) {
445  fr_strerror_printf("Failed opening control socket directory: %s", fr_syserror(errno));
446  goto error;
447  }
448 
449  /*
450  * This fails if the radius user can't write
451  * to the parent directory.
452  */
453  if (mkdirat(parent_fd, p + 1, 0700) < 0) {
454  fr_strerror_printf("Failed creating control socket directory: %s", fr_syserror(errno));
455  goto error;
456  }
457 
458  dir_fd = openat(parent_fd, p + 1, O_NOFOLLOW | O_DIRECTORY);
459  if (dir_fd < 0) {
460  fr_strerror_printf("Failed opening the control socket directory we created: %s",
461  fr_syserror(errno));
462  goto error;
463  }
464  if (fchmod(dir_fd, perm) < 0) {
465  fr_strerror_printf("Failed setting permissions on control socket directory: %s",
466  fr_syserror(errno));
467  goto error;
468  }
469 
470  rad_suid_up();
471  if ((uid != (uid_t)-1) || (gid != (gid_t)-1)) ret = fchown(dir_fd, uid, gid);
472  rad_suid_down();
473  if (ret < 0) {
474  fr_strerror_printf("Failed changing ownership of control socket directory: %s",
475  fr_syserror(errno));
476  return -1;
477  }
478  /*
479  * Control socket dir already exists, but we still need to
480  * check the permissions are what we expect.
481  */
482  } else {
483  int ret;
484  int client_fd;
485 
486  ret = fstat(dir_fd, &st);
487  if (ret < 0) {
488  fr_strerror_printf("Failed checking permissions of control socket directory: %s",
489  fr_syserror(errno));
490  goto error;
491  }
492 
493  if ((uid != (uid_t)-1) && (st.st_uid != uid)) {
494  struct passwd *need_user, *have_user;
495 
496  if (rad_getpwuid(NULL, &need_user, uid) < 0) goto error;
497  if (rad_getpwuid(NULL, &have_user, st.st_uid) < 0) {
498  talloc_free(need_user);
499  goto error;
500  }
501  fr_strerror_printf("Control socket directory must be owned by user %s, "
502  "currently owned by %s", need_user->pw_name, have_user->pw_name);
503  talloc_free(need_user);
504  talloc_free(have_user);
505  goto error;
506  }
507 
508  if ((gid != (gid_t)-1) && (st.st_gid != gid)) {
509  struct group *need_group, *have_group;
510 
511  if (rad_getgrgid(NULL, &need_group, gid) < 0) goto error;
512  if (rad_getgrgid(NULL, &have_group, st.st_gid) < 0) {
513  talloc_free(need_group);
514  goto error;
515  }
516  fr_strerror_printf("Control socket directory \"%s\" must be owned by group %s, "
517  "currently owned by %s", dir, need_group->gr_name, have_group->gr_name);
518  talloc_free(need_group);
519  talloc_free(have_group);
520  goto error;
521  }
522 
523  if ((perm & 0x0c) != (st.st_mode & 0x0c)) {
524  char str_need[10], oct_need[5];
525  char str_have[10], oct_have[5];
526 
527  rad_mode_to_str(str_need, perm);
528  rad_mode_to_oct(oct_need, perm);
529  rad_mode_to_str(str_have, st.st_mode);
530  rad_mode_to_oct(oct_have, st.st_mode);
531  fr_strerror_printf("Control socket directory must have permissions %s (%s), current "
532  "permissions are %s (%s)", str_need, oct_need, str_have, oct_have);
533  goto error;
534  }
535 
536  /*
537  * Check if a server is already listening on the
538  * socket?
539  */
540  client_fd = fr_socket_client_unix(path, false);
541  if (client_fd >= 0) {
542  fr_strerror_printf("Control socket '%s' is already in use", path);
543  close(client_fd);
544  return -1;
545  }
546  }
547 
548  name = strrchr(path, FR_DIR_SEP);
549  if (!name) {
550  fr_strerror_printf("Can't determine socket name");
551  goto error;
552  }
553  name++;
554 
555  /*
556  * We've checked the containing directory has the permissions
557  * we expect, and as we have the FD, and aren't following
558  * symlinks no one can trick us into changing or creating a
559  * file elsewhere.
560  *
561  * It's possible an attacker may still be able to create hard
562  * links, for the socket file. But they would need write
563  * access to the directory we just created or verified, so
564  * this attack vector is unlikely.
565  */
566  if ((uid != (uid_t)-1) && (rad_seuid(uid) < 0)) goto error;
567  if ((gid != (gid_t)-1) && (rad_segid(gid) < 0)) {
568  rad_seuid(euid);
569  goto error;
570  }
571 
572  /*
573  * The original code, did openat, used fstat to figure out
574  * what type the file was and then used unlinkat to unlink
575  * it. Except on OSX (at least) openat refuses to open
576  * socket files. So we now rely on the fact that unlinkat
577  * has sane and consistent behaviour, and will not unlink
578  * directories. unlinkat should also fail if the socket user
579  * hasn't got permission to modify the socket.
580  */
581  if ((unlinkat(dir_fd, name, 0) < 0) && (errno != ENOENT)) {
582  fr_strerror_printf("Failed removing stale socket: %s", fr_syserror(errno));
583  sock_error:
584  if (uid != (uid_t)-1) rad_seuid(euid);
585  if (gid != (gid_t)-1) rad_segid(egid);
586  goto error;
587  }
588 
589  /*
590  * At this point we should have established a secure directory
591  * to house our socket, and cleared out any stale sockets.
592  */
593  sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
594  if (sock_fd < 0) {
595  fr_strerror_printf("Failed creating socket: %s", fr_syserror(errno));
596  goto sock_error;
597  }
598 
599 #ifdef HAVE_BINDAT
600  len = strlen(name);
601 #else
602  len = strlen(path);
603 #endif
604  if (len >= sizeof(salocal.sun_path)) {
605  fr_strerror_printf("Path too long in socket filename");
606  goto error;
607  }
608 
609  memset(&salocal, 0, sizeof(salocal));
610  salocal.sun_family = AF_UNIX;
611 
612 #ifdef HAVE_BINDAT
613  memcpy(salocal.sun_path, name, len + 1); /* SUN_LEN does strlen */
614 #else
615  memcpy(salocal.sun_path, path, len + 1); /* SUN_LEN does strlen */
616 #endif
617  socklen = SUN_LEN(&salocal);
618 
619  /*
620  * Direct socket permissions are only useful on Linux which
621  * actually enforces them. BSDs don't. They also need to be
622  * set before binding the socket to a file.
623  */
624 #ifdef __linux__
625  if (fchmod(sock_fd, perm) < 0) {
626  char str_need[10], oct_need[5];
627 
628  rad_mode_to_str(str_need, perm);
629  rad_mode_to_oct(oct_need, perm);
630  fr_strerror_printf("Failed changing socket permissions to %s (%s)", str_need, oct_need);
631 
632  goto sock_error;
633  }
634 
635  if (fchown(sock_fd, uid, gid) < 0) {
636  struct passwd *user;
637  struct group *group;
638 
639  if (rad_getpwuid(NULL, &user, uid) < 0) goto sock_error;
640  if (rad_getgrgid(NULL, &group, gid) < 0) {
641  talloc_free(user);
642  goto sock_error;
643  }
644 
645  fr_strerror_printf("Failed changing ownership of socket to %s:%s", user->pw_name, group->gr_name);
646  talloc_free(user);
647  talloc_free(group);
648  goto sock_error;
649  }
650 #endif
651  /*
652  * The correct function to use here is bindat(), but only
653  * quite recent versions of FreeBSD actually have it, and
654  * it's definitely not POSIX.
655  */
656 #ifdef HAVE_BINDAT
657  if (bindat(dir_fd, sock_fd, (struct sockaddr *)&salocal, socklen) < 0) {
658 #else
659  if (bind(sock_fd, (struct sockaddr *)&salocal, socklen) < 0) {
660 #endif
661  fr_strerror_printf("Failed binding socket: %s", fr_syserror(errno));
662  goto sock_error;
663  }
664 
665  if (listen(sock_fd, 8) < 0) {
666  fr_strerror_printf("Failed listening on socket: %s", fr_syserror(errno));
667  goto sock_error;
668  }
669 
670 #ifdef O_NONBLOCK
671  {
672  int flags;
673 
674  flags = fcntl(sock_fd, F_GETFL, NULL);
675  if (flags < 0) {
676  fr_strerror_printf("Failed getting socket flags: %s", fr_syserror(errno));
677  goto sock_error;
678  }
679 
680  flags |= O_NONBLOCK;
681  if (fcntl(sock_fd, F_SETFL, flags) < 0) {
682  fr_strerror_printf("Failed setting nonblocking socket flag: %s", fr_syserror(errno));
683  goto sock_error;
684  }
685  }
686 #endif
687 
688  if (uid != (uid_t)-1) rad_seuid(euid);
689  if (gid != (gid_t)-1) rad_segid(egid);
690 
691  close(dir_fd);
692  close(path_fd);
693  close(parent_fd);
694 
695  return sock_fd;
696 }
697 #endif
698 
700 {
701  this->status = RAD_LISTEN_STATUS_EOL;
702 
703  /*
704  * This removes the socket from the event fd, so no one
705  * will be calling us any more.
706  */
708 }
709 
710 /*
711  * Turn off all debugging. But don't touch the debug condition.
712  */
713 static void command_debug_off(void)
714 {
715  debug_log.dst = L_DST_NULL;
716  debug_log.file = NULL;
717  debug_log.cookie = NULL;
718  debug_log.cookie_write = NULL;
719 }
720 
721 #if defined(HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
722 #ifdef HAVE_PTHREAD_H
723 static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
724 #endif
725 
726 
727 /*
728  * Callback from log.c, so that we can write debug output to the
729  * radmin socket.
730  *
731  * We only have one debug condition, so we only need one mutex.
732  */
733 #ifdef HAVE_FOPENCOOKIE
734 static ssize_t command_socket_write(void *cookie, char const *buffer, size_t len)
735 #else
736 static int command_socket_write(void *cookie, char const *buffer, int len)
737 #endif
738 {
739  ssize_t r;
740  rad_listen_t *listener = cookie;
741 
742  if (listener->status == RAD_LISTEN_STATUS_EOL) return 0;
743 
744 #ifdef HAVE_PTHREAD_H
745  pthread_mutex_lock(&debug_mutex);
746 #endif
747  r = fr_channel_write(listener->fd, FR_CHANNEL_STDOUT, buffer, len);
748 
749 #ifdef HAVE_PTHREAD_H
750  pthread_mutex_unlock(&debug_mutex);
751 #endif
752 
753  if (r <= 0) {
755  command_close_socket(listener);
756  }
757 
758  return r;
759 }
760 #endif
761 
762 static ssize_t CC_HINT(format (printf, 2, 3)) cprintf(rad_listen_t *listener, char const *fmt, ...)
763 {
764  ssize_t r, len;
765  va_list ap;
766  char buffer[256];
767 
768  va_start(ap, fmt);
769  len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
770  va_end(ap);
771 
772  if (listener->status == RAD_LISTEN_STATUS_EOL) return 0;
773 
774  r = fr_channel_write(listener->fd, FR_CHANNEL_STDOUT, buffer, len);
775  if (r <= 0) command_close_socket(listener);
776 
777  /*
778  * FIXME: Keep writing until done?
779  */
780  return r;
781 }
782 
783 static ssize_t CC_HINT(format (printf, 2, 3)) cprintf_error(rad_listen_t *listener, char const *fmt, ...)
784 {
785  ssize_t r, len;
786  va_list ap;
787  char buffer[256];
788 
789  va_start(ap, fmt);
790  len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
791  va_end(ap);
792 
793  if (listener->status == RAD_LISTEN_STATUS_EOL) return 0;
794 
795  r = fr_channel_write(listener->fd, FR_CHANNEL_STDERR, buffer, len);
796  if (r <= 0) command_close_socket(listener);
797 
798  /*
799  * FIXME: Keep writing until done?
800  */
801  return r;
802 }
803 
804 static int command_hup(rad_listen_t *listener, int argc, char *argv[])
805 {
806  CONF_SECTION *cs;
807  module_instance_t *mi;
808  char buffer[256];
809 
810  if (argc == 0) {
812  return CMD_OK;
813  }
814 
815  /*
816  * Hack a "main" HUP thingy
817  */
818  if (strcmp(argv[0], "main.log") == 0) {
819  hup_logfile();
820  return CMD_OK;
821  }
822 
823  cs = cf_section_sub_find(main_config.config, "modules");
824  if (!cs) return CMD_FAIL;
825 
826  mi = module_find(cs, argv[0]);
827  if (!mi) {
828  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
829  return CMD_FAIL;
830  }
831 
832  if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
833  cprintf_error(listener, "Module %s cannot be hup'd\n",
834  argv[0]);
835  return CMD_FAIL;
836  }
837 
838  if (!module_hup_module(mi->cs, mi, time(NULL))) {
839  cprintf_error(listener, "Failed to reload module\n");
840  return CMD_FAIL;
841  }
842 
843  snprintf(buffer, sizeof(buffer), "modules.%s.hup",
844  cf_section_name1(mi->cs));
845  exec_trigger(NULL, mi->cs, buffer, true);
846 
847  return CMD_OK;
848 }
849 
850 static int command_terminate(UNUSED rad_listen_t *listener,
851  UNUSED int argc, UNUSED char *argv[])
852 {
854 
855  return CMD_OK;
856 }
857 
858 static int command_uptime(rad_listen_t *listener,
859  UNUSED int argc, UNUSED char *argv[])
860 {
861  char buffer[128];
862 
863  CTIME_R(&fr_start_time, buffer, sizeof(buffer));
864  cprintf(listener, "Up since %s", buffer); /* no \r\n */
865 
866  return CMD_OK;
867 }
868 
869 static int command_show_config(rad_listen_t *listener, int argc, char *argv[])
870 {
871  CONF_ITEM *ci;
872  CONF_PAIR *cp;
873  char const *value;
874 
875  if (argc != 1) {
876  cprintf_error(listener, "No path was given\n");
877  return CMD_FAIL;
878  }
879 
881  if (!ci) return CMD_FAIL;
882 
883  if (!cf_item_is_pair(ci)) return CMD_FAIL;
884 
885  cp = cf_item_to_pair(ci);
886  value = cf_pair_value(cp);
887  if (!value) return CMD_FAIL;
888 
889  cprintf(listener, "%s\n", value);
890 
891  return CMD_OK;
892 }
893 
894 static char const tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
895 
896 /*
897  * FIXME: Recurse && indent?
898  */
899 static void cprint_conf_parser(rad_listen_t *listener, int indent, CONF_SECTION *cs,
900  void const *base)
901 
902 {
903  int i;
904  char const *name1 = cf_section_name1(cs);
905  char const *name2 = cf_section_name2(cs);
906  CONF_PARSER const *variables = cf_section_parse_table(cs);
907 
908  if (name2) {
909  cprintf(listener, "%.*s%s %s {\n", indent, tabs, name1, name2);
910  } else {
911  cprintf(listener, "%.*s%s {\n", indent, tabs, name1);
912  }
913 
914  indent++;
915 
916  /*
917  * Print
918  */
919  if (variables) for (i = 0; variables[i].name != NULL; i++) {
920  void const *data;
921  char buffer[INET6_ADDRSTRLEN];
922 
923  /*
924  * No base struct offset, data must be the pointer.
925  * If data doesn't exist, ignore the entry, there
926  * must be something wrong.
927  */
928  if (!base) {
929  if (!variables[i].data) {
930  continue;
931  }
932 
933  data = variables[i].data;
934 
935  } else if (variables[i].data) {
936  data = variables[i].data;
937 
938  } else {
939  data = (((char const *)base) + variables[i].offset);
940  }
941 
942  /*
943  * Ignore the various flags
944  */
945  switch (variables[i].type & 0xff) {
946  default:
947  cprintf(listener, "%.*s%s = ?\n", indent, tabs,
948  variables[i].name);
949  break;
950 
951  case PW_TYPE_INTEGER:
952  cprintf(listener, "%.*s%s = %u\n", indent, tabs,
953  variables[i].name, *(int const *) data);
954  break;
955 
956  case PW_TYPE_IPV4_ADDR:
957  inet_ntop(AF_INET, data, buffer, sizeof(buffer));
958  break;
959 
960  case PW_TYPE_IPV6_ADDR:
961  inet_ntop(AF_INET6, data, buffer, sizeof(buffer));
962  break;
963 
964  case PW_TYPE_BOOLEAN:
965  cprintf(listener, "%.*s%s = %s\n", indent, tabs,
966  variables[i].name,
967  ((*(bool const *) data) == false) ? "no" : "yes");
968  break;
969 
970  case PW_TYPE_STRING:
971  case PW_TYPE_FILE_INPUT:
972  case PW_TYPE_FILE_OUTPUT:
973  /*
974  * FIXME: Escape things in the string!
975  */
976  if (*(char const * const *) data) {
977  cprintf(listener, "%.*s%s = \"%s\"\n", indent, tabs,
978  variables[i].name, *(char const * const *) data);
979  } else {
980  cprintf(listener, "%.*s%s = \n", indent, tabs,
981  variables[i].name);
982  }
983 
984  break;
985  }
986  }
987 
988  indent--;
989 
990  cprintf(listener, "%.*s}\n", indent, tabs);
991 }
992 
993 static int command_show_module_config(rad_listen_t *listener, int argc, char *argv[])
994 {
995  CONF_SECTION *cs;
996  module_instance_t *mi;
997 
998  if (argc != 1) {
999  cprintf_error(listener, "No module name was given\n");
1000  return CMD_FAIL;
1001  }
1002 
1003  cs = cf_section_sub_find(main_config.config, "modules");
1004  if (!cs) return CMD_FAIL;
1005 
1006  mi = module_find(cs, argv[0]);
1007  if (!mi) {
1008  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1009  return CMD_FAIL;
1010  }
1011 
1012  cprint_conf_parser(listener, 0, mi->cs, mi->insthandle);
1013 
1014  return CMD_OK;
1015 }
1016 
1017 static char const *method_names[MOD_COUNT] = {
1018  "authenticate",
1019  "authorize",
1020  "preacct",
1021  "accounting",
1022  "session",
1023  "pre-proxy",
1024  "post-proxy",
1025  "post-auth"
1026 };
1027 
1028 
1029 static int command_show_module_methods(rad_listen_t *listener, int argc, char *argv[])
1030 {
1031  int i;
1032  CONF_SECTION *cs;
1033  module_instance_t const *mi;
1034  module_t const *mod;
1035 
1036  if (argc != 1) {
1037  cprintf_error(listener, "No module name was given\n");
1038  return CMD_FAIL;
1039  }
1040 
1041  cs = cf_section_sub_find(main_config.config, "modules");
1042  if (!cs) return CMD_FAIL;
1043 
1044  mi = module_find(cs, argv[0]);
1045  if (!mi) {
1046  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1047  return CMD_FAIL;
1048  }
1049 
1050  mod = mi->entry->module;
1051 
1052  for (i = 0; i < MOD_COUNT; i++) {
1053  if (mod->methods[i]) cprintf(listener, "%s\n", method_names[i]);
1054  }
1055 
1056  return CMD_OK;
1057 }
1058 
1059 
1060 static int command_show_module_flags(rad_listen_t *listener, int argc, char *argv[])
1061 {
1062  CONF_SECTION *cs;
1063  module_instance_t const *mi;
1064  module_t const *mod;
1065 
1066  if (argc != 1) {
1067  cprintf_error(listener, "No module name was given\n");
1068  return CMD_FAIL;
1069  }
1070 
1071  cs = cf_section_sub_find(main_config.config, "modules");
1072  if (!cs) return CMD_FAIL;
1073 
1074  mi = module_find(cs, argv[0]);
1075  if (!mi) {
1076  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1077  return CMD_FAIL;
1078  }
1079 
1080  mod = mi->entry->module;
1081 
1082  if ((mod->type & RLM_TYPE_THREAD_UNSAFE) != 0)
1083  cprintf(listener, "thread-unsafe\n");
1084 
1085  if ((mod->type & RLM_TYPE_HUP_SAFE) != 0)
1086  cprintf(listener, "reload-on-hup\n");
1087 
1088  return CMD_OK;
1089 }
1090 
1091 static int command_show_module_status(rad_listen_t *listener, int argc, char *argv[])
1092 {
1093  CONF_SECTION *cs;
1094  const module_instance_t *mi;
1095 
1096  if (argc != 1) {
1097  cprintf_error(listener, "No module name was given\n");
1098  return CMD_FAIL;
1099  }
1100 
1101  cs = cf_section_sub_find(main_config.config, "modules");
1102  if (!cs) return CMD_FAIL;
1103 
1104  mi = module_find(cs, argv[0]);
1105  if (!mi) {
1106  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1107  return CMD_FAIL;
1108  }
1109 
1110  if (!mi->force) {
1111  cprintf(listener, "alive\n");
1112  } else {
1113  cprintf(listener, "%s\n", fr_int2str(mod_rcode_table, mi->code, "<invalid>"));
1114  }
1115 
1116 
1117  return CMD_OK;
1118 }
1119 
1120 
1121 /*
1122  * Show all loaded modules
1123  */
1124 static int command_show_modules(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1125 {
1126  CONF_SECTION *cs, *subcs;
1127 
1128  cs = cf_section_sub_find(main_config.config, "modules");
1129  if (!cs) return CMD_FAIL;
1130 
1131  subcs = NULL;
1132  while ((subcs = cf_subsection_find_next(cs, subcs, NULL)) != NULL) {
1133  char const *name1 = cf_section_name1(subcs);
1134  char const *name2 = cf_section_name2(subcs);
1135 
1136  module_instance_t *mi;
1137 
1138  if (name2) {
1139  mi = module_find(cs, name2);
1140  if (!mi) continue;
1141 
1142  cprintf(listener, "%s (%s)\n", name2, name1);
1143  } else {
1144  mi = module_find(cs, name1);
1145  if (!mi) continue;
1146 
1147  cprintf(listener, "%s\n", name1);
1148  }
1149  }
1150 
1151  return CMD_OK;
1152 }
1153 
1154 #ifdef WITH_PROXY
1155 static int command_show_home_servers(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1156 {
1157  int i;
1158  home_server_t *home;
1159  char const *type, *state, *proto;
1160 
1161  char buffer[INET6_ADDRSTRLEN];
1162 
1163  for (i = 0; i < 256; i++) {
1164  home = home_server_bynumber(i);
1165  if (!home) break;
1166 
1167  /*
1168  * Internal "virtual" home server.
1169  */
1170  if (home->ipaddr.af == AF_UNSPEC) continue;
1171 
1172  if (home->type == HOME_TYPE_AUTH) {
1173  type = "auth";
1174 
1175  } else if (home->type == HOME_TYPE_ACCT) {
1176  type = "acct";
1177 
1178  } else if (home->type == HOME_TYPE_AUTH_ACCT) {
1179  type = "auth+acct";
1180 
1181 #ifdef WITH_COA
1182  } else if (home->type == HOME_TYPE_COA) {
1183  type = "coa";
1184 #endif
1185 
1186  } else continue;
1187 
1188  if (home->proto == IPPROTO_UDP) {
1189  proto = "udp";
1190  }
1191 #ifdef WITH_TCP
1192  else if (home->proto == IPPROTO_TCP) {
1193  proto = "tcp";
1194  }
1195 #endif
1196  else proto = "??";
1197 
1198  if (home->state == HOME_STATE_ALIVE) {
1199  state = "alive";
1200 
1201  } else if (home->state == HOME_STATE_ZOMBIE) {
1202  state = "zombie";
1203 
1204  } else if (home->state == HOME_STATE_IS_DEAD) {
1205  state = "dead";
1206 
1207  } else if (home->state == HOME_STATE_UNKNOWN) {
1208  time_t now = time(NULL);
1209 
1210  /*
1211  * We've recently received a packet, so
1212  * the home server seems to be alive.
1213  *
1214  * The *reported* state changes because
1215  * the internal state machine NEEDS THE
1216  * RIGHT STATE. However, reporting that
1217  * to the admin will confuse them.
1218  * So... we lie. No, that dress doesn't
1219  * make you look fat...
1220  */
1221  if ((home->last_packet_recv + (int)home->ping_interval) >= now) {
1222  state = "alive";
1223  } else {
1224  state = "unknown";
1225  }
1226 
1227  } else continue;
1228 
1229  cprintf(listener, "%s\t%s\t%d\t%s\t%s\t%s\t%d\n",
1230  fr_inet_ntoh(&home->ipaddr, buffer, sizeof(buffer)),
1231  home->name, home->port, proto, type, state,
1232  home->currently_outstanding);
1233  }
1234 
1235  return CMD_OK;
1236 }
1237 #endif
1238 
1239 static int command_show_clients(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1240 {
1241  int i;
1242  RADCLIENT *client;
1243  char buffer[256];
1244  char ipaddr[256];
1245 
1246  for (i = 0; i < 256; i++) {
1247  client = client_findbynumber(NULL, i);
1248  if (!client) break;
1249 
1250  fr_inet_ntoh(&client->ipaddr, buffer, sizeof(buffer));
1251 
1252  if (((client->ipaddr.af == AF_INET) &&
1253  (client->ipaddr.prefix != 32)) ||
1254  ((client->ipaddr.af == AF_INET6) &&
1255  (client->ipaddr.prefix != 128))) {
1256  snprintf(ipaddr, sizeof(ipaddr), "%s/%d", buffer, client->ipaddr.prefix);
1257  } else {
1258  snprintf(ipaddr, sizeof(ipaddr), "%s", buffer);
1259  }
1260 
1261  cprintf(listener, "%s\t%s\t%s\t%s\n", ipaddr,
1262  client->shortname ? client->shortname : "\t",
1263  client->nas_type ? client->nas_type : "\t",
1264  client->server ? client->server : "\t");
1265  }
1266 
1267  return CMD_OK;
1268 }
1269 
1270 
1271 static int command_show_version(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1272 {
1273  cprintf(listener, "%s\n", radiusd_version);
1274  return CMD_OK;
1275 }
1276 
1277 static int command_debug_level(rad_listen_t *listener, int argc, char *argv[])
1278 {
1279  int number;
1280 
1281  if (argc == 0) {
1282  cprintf_error(listener, "Must specify <number>\n");
1283  return -1;
1284  }
1285 
1286  number = atoi(argv[0]);
1287  if ((number < 0) || (number > 4)) {
1288  cprintf_error(listener, "<number> must be between 0 and 4\n");
1289  return -1;
1290  }
1291 
1292  fr_debug_lvl = rad_debug_lvl = number;
1293 
1294  return CMD_OK;
1295 }
1296 
1297 #if defined(HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
1298 static int command_debug_socket(rad_listen_t *listener, int argc, char *argv[])
1299 {
1300  uint32_t notify;
1301 
1303  cprintf_error(listener, "Cannot redirect debug logs to a socket when already in debugging mode.\n");
1304  return -1;
1305  }
1306 
1307  if ((argc == 0) || (strcmp(argv[0], "off") == 0)) {
1308  notify = htonl(FR_NOTIFY_BUFFERED);
1309 
1310  /*
1311  * Tell radmin to go into buffered mode.
1312  */
1313  (void) fr_channel_write(listener->fd, FR_CHANNEL_NOTIFY, &notify, sizeof(notify));
1314 
1316  return CMD_OK;
1317  }
1318 
1319  if (strcmp(argv[0], "on") != 0) {
1320  cprintf_error(listener, "Syntax error: got '%s', expected [on|off]", argv[0]);
1321  return -1;
1322  }
1323 
1324  /*
1325  * Don't allow people to stomp on each other.
1326  */
1327  if ((debug_log.cookie != NULL) &&
1328  (debug_log.cookie != listener)) {
1329  cprintf_error(listener, "ERROR: Someone else is already using the debug socket");
1330  return -1;
1331  }
1332 
1333  /*
1334  * Disable logging while we're mucking with the buffer.
1335  */
1337 
1338  debug_log.cookie = listener;
1339  debug_log.cookie_write = command_socket_write;
1340  debug_log.dst = L_DST_EXTRA;
1341 
1342  notify = htonl(FR_NOTIFY_UNBUFFERED);
1343 
1344  /*
1345  * Tell radmin to go into unbuffered mode.
1346  */
1347  (void) fr_channel_write(listener->fd, FR_CHANNEL_NOTIFY, &notify, sizeof(notify));
1348 
1349  return CMD_OK;
1350 }
1351 #endif
1352 
1353 static int command_debug_file(rad_listen_t *listener, int argc, char *argv[])
1354 {
1356  cprintf_error(listener, "Cannot redirect debug logs to a file when already in debugging mode.\n");
1357  return -1;
1358  }
1359 
1360  if ((argc > 0) && (strchr(argv[0], FR_DIR_SEP) != NULL)) {
1361  cprintf_error(listener, "Cannot direct debug logs to absolute path.\n");
1362  return -1;
1363  }
1364 
1365  if (argc == 0) {
1367  return CMD_OK;
1368  }
1369 
1370  /*
1371  * Disable logging while we're mucking with the buffer.
1372  */
1374 
1375  /*
1376  * This looks weird, but it's here to avoid locking
1377  * a mutex for every log message.
1378  */
1379  memset(debug_log_file_buffer, 0, sizeof(debug_log_file_buffer));
1380 
1381  /*
1382  * Debug files always go to the logging directory.
1383  */
1385  "%s/%s", radlog_dir, argv[0]);
1386 
1387  debug_log.file = &debug_log_file_buffer[0];
1388  debug_log.dst = L_DST_FILES;
1389 
1390  return CMD_OK;
1391 }
1392 
1393 static int command_debug_condition(rad_listen_t *listener, int argc, char *argv[])
1394 {
1395  int i;
1396  char const *error;
1397  ssize_t slen = 0;
1398  fr_cond_t *new_condition = NULL;
1399  char *p, buffer[1024];
1400 
1401  /*
1402  * Disable it.
1403  */
1404  if (argc == 0) {
1405  TALLOC_FREE(debug_condition);
1406  debug_condition = NULL;
1407  return CMD_OK;
1408  }
1409 
1410  if (!((argc == 1) &&
1411  ((argv[0][0] == '"') || (argv[0][0] == '\'')))) {
1412  p = buffer;
1413  *p = '\0';
1414  for (i = 0; i < argc; i++) {
1415  size_t len;
1416 
1417  len = strlcpy(p, argv[i], buffer + sizeof(buffer) - p);
1418  p += len;
1419  *(p++) = ' ';
1420  *p = '\0';
1421  }
1422 
1423  } else {
1424  /*
1425  * Backwards compatibility. De-escape the string.
1426  */
1427  char quote;
1428  char *q;
1429 
1430  p = argv[0];
1431  q = buffer;
1432 
1433  quote = *(p++);
1434 
1435  while (true) {
1436  if (!*p) {
1437  error = "Unexpected end of string";
1438  slen = -strlen(argv[0]);
1439  p = argv[0];
1440 
1441  goto parse_error;
1442  }
1443 
1444  if (*p == quote) {
1445  if (p[1]) {
1446  error = "Unexpected text after end of string";
1447  slen = -(p - argv[0]);
1448  p = argv[0];
1449 
1450  goto parse_error;
1451  }
1452  *q = '\0';
1453  break;
1454  }
1455 
1456  if (*p == '\\') {
1457  *(q++) = p[1];
1458  p += 2;
1459  continue;
1460  }
1461 
1462  *(q++) = *(p++);
1463  }
1464  }
1465 
1466  p = buffer;
1467 
1468  slen = fr_condition_tokenize(NULL, NULL, p, &new_condition, &error, FR_COND_ONE_PASS);
1469  if (slen <= 0) {
1470  char *spaces, *text;
1471 
1472  parse_error:
1473  fr_canonicalize_error(NULL, &spaces, &text, slen, p);
1474 
1475  ERROR("Parse error in condition");
1476  ERROR("%s", p);
1477  ERROR("%s^ %s", spaces, error);
1478 
1479  cprintf_error(listener, "Parse error in condition \"%s\": %s\n", p, error);
1480 
1481  talloc_free(spaces);
1482  talloc_free(text);
1483  return CMD_FAIL;
1484  }
1485 
1486  /*
1487  * Delete old condition.
1488  *
1489  * This is thread-safe because the condition is evaluated
1490  * in the main server thread, along with this code.
1491  */
1492  TALLOC_FREE(debug_condition);
1493  debug_condition = new_condition;
1494 
1495  return CMD_OK;
1496 }
1497 
1498 #ifdef HAVE_GPERFTOOLS_PROFILER_H
1499 static char profiler_log_buffer[1024];
1500 /** Start the gperftools profiler
1501  *
1502  */
1503 static int command_profiler_cpu_start(rad_listen_t *listener, int argc, char *argv[])
1504 {
1505  struct ProfilerState state;
1506 
1507  ProfilerGetCurrentState(&state);
1508 
1509  if (argc == 0) {
1510  cprintf_error(listener, "Need filename for profiler to write to.\n");
1511  return -1;
1512  }
1513 
1514  if ((argc > 0) && (strchr(argv[0], FR_DIR_SEP) != NULL)) {
1515  cprintf_error(listener, "Profiler file must be a relative path.\n");
1516  return -1;
1517  }
1518 
1519  /*
1520  * We get an error if we don't stop the current
1521  * profiler first.
1522  */
1523  if (state.enabled) {
1524  ProfilerFlush();
1525  ProfilerStop();
1526  }
1527 
1528  /*
1529  * Profiler files always go to the logging directory.
1530  */
1531  snprintf(profiler_log_buffer, sizeof(profiler_log_buffer),
1532  "%s/%s", radlog_dir, argv[0]);
1533 
1534  errno = 0;
1535  if (ProfilerStart(profiler_log_buffer) == 0) {
1536  cprintf_error(listener, "Failed enabling profiler: %s\n",
1537  errno ? fr_syserror(errno) : "unknown error");
1538  return -1;
1539  }
1540 
1541  return CMD_OK;
1542 }
1543 
1544 /** Stop the gperftools cpu profiler
1545  *
1546  */
1547 static int command_profiler_cpu_stop(UNUSED rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1548 {
1549  ProfilerFlush();
1550  ProfilerStop();
1551 
1552  return CMD_OK;
1553 }
1554 
1555 /** Show gperftools cpu profiler output file
1556  *
1557  */
1558 static int command_profiler_cpu_show_file(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1559 {
1560  struct ProfilerState state;
1561 
1562  ProfilerGetCurrentState(&state);
1563 
1564  if (!state.enabled) {
1565  cprintf_error(listener, "Profiler not enabled.\n");
1566  return -1;
1567  }
1568 
1569  cprintf(listener, "%s\n", state.profile_name);
1570 
1571  return CMD_OK;
1572 }
1573 
1574 /** Show gperftools cpu profiler samples collected
1575  *
1576  */
1577 static int command_profiler_cpu_show_samples(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1578 {
1579  struct ProfilerState state;
1580 
1581  ProfilerGetCurrentState(&state);
1582 
1583  if (!state.enabled) {
1584  cprintf_error(listener, "Profiler not enabled.\n");
1585  return -1;
1586  }
1587 
1588  cprintf(listener, "%i\n", state.samples_gathered);
1589 
1590  return CMD_OK;
1591 }
1592 
1593 /** Show gperftools cpu profiler start_time
1594  *
1595  */
1596 static int command_profiler_cpu_show_start_time(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1597 {
1598  char buffer[128];
1599  struct ProfilerState state;
1600 
1601  ProfilerGetCurrentState(&state);
1602 
1603  if (!state.enabled) {
1604  cprintf_error(listener, "Profiler not enabled.\n");
1605  return -1;
1606  }
1607 
1608  CTIME_R(&state.start_time, buffer, sizeof(buffer));
1609  cprintf(listener, "%s", buffer);
1610 
1611  return CMD_OK;
1612 }
1613 
1614 /** Show gperftools cpu profiler status
1615  *
1616  */
1617 static int command_profiler_cpu_show_status(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1618 {
1619  struct ProfilerState state;
1620 
1621  ProfilerGetCurrentState(&state);
1622 
1623  if (state.enabled) {
1624  cprintf(listener, "running\n");
1625  } else {
1626  cprintf(listener, "stopped\n");
1627  }
1628 
1629  return CMD_OK;
1630 }
1631 #endif
1632 
1634  UNUSED int argc, UNUSED char *argv[])
1635 {
1636  char buffer[1024];
1637 
1638  if (!debug_condition) {
1639  cprintf(listener, "\n");
1640  return CMD_OK;
1641  }
1642 
1643  fr_cond_snprint(buffer, sizeof(buffer), debug_condition);
1644 
1645  cprintf(listener, "%s\n", buffer);
1646  return CMD_OK;
1647 }
1648 
1649 
1651  UNUSED int argc, UNUSED char *argv[])
1652 {
1653  if (!debug_log.file) return CMD_FAIL;
1654 
1655  cprintf(listener, "%s\n", debug_log.file);
1656  return CMD_OK;
1657 }
1658 
1659 
1661  UNUSED int argc, UNUSED char *argv[])
1662 {
1663  cprintf(listener, "%d\n", rad_debug_lvl);
1664  return CMD_OK;
1665 }
1666 
1667 
1668 
1669 static RADCLIENT *get_client(rad_listen_t *listener, int argc, char *argv[])
1670 {
1671  RADCLIENT *client;
1672  fr_ipaddr_t ipaddr;
1673  int myarg;
1674  int proto = IPPROTO_UDP;
1675  RADCLIENT_LIST *list = NULL;
1676 
1677  if (argc < 1) {
1678  cprintf_error(listener, "Must specify <ipaddr>\n");
1679  return NULL;
1680  }
1681 
1682  /*
1683  * First arg is IP address.
1684  */
1685  if (fr_inet_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1686  cprintf_error(listener, "Failed parsing IP address; %s\n",
1687  fr_strerror());
1688  return NULL;
1689  }
1690  myarg = 1;
1691 
1692  while (myarg < argc) {
1693  if (strcmp(argv[myarg], "udp") == 0) {
1694  proto = IPPROTO_UDP;
1695  myarg++;
1696  continue;
1697  }
1698 
1699 #ifdef WITH_TCP
1700  if (strcmp(argv[myarg], "tcp") == 0) {
1701  proto = IPPROTO_TCP;
1702  myarg++;
1703  continue;
1704  }
1705 #endif
1706 
1707  if (strcmp(argv[myarg], "listen") == 0) {
1708  uint16_t server_port;
1710 
1711  if ((argc - myarg) < 2) {
1712  cprintf_error(listener, "Must specify listen <ipaddr> <port>\n");
1713  return NULL;
1714  }
1715 
1716  if (fr_inet_hton(&server_ipaddr, ipaddr.af, argv[myarg + 1], false) < 0) {
1717  cprintf_error(listener, "Failed parsing IP address; %s\n",
1718  fr_strerror());
1719  return NULL;
1720  }
1721 
1722  server_port = atoi(argv[myarg + 2]);
1723 
1724  list = listener_find_client_list(&server_ipaddr, server_port, proto);
1725  if (!list) {
1726  cprintf_error(listener, "No such listener %s %s\n", argv[myarg + 1], argv[myarg + 2]);
1727  return NULL;
1728  }
1729  myarg += 3;
1730  continue;
1731  }
1732 
1733  cprintf_error(listener, "Unknown argument %s.\n", argv[myarg]);
1734  return NULL;
1735  }
1736 
1737  client = client_find(list, &ipaddr, proto);
1738  if (!client) {
1739  cprintf_error(listener, "No such client\n");
1740  return NULL;
1741  }
1742 
1743  return client;
1744 }
1745 
1746 #ifdef WITH_PROXY
1747 static home_server_t *get_home_server(rad_listen_t *listener, int argc,
1748  char *argv[], int *last)
1749 {
1750  int myarg;
1751  home_server_t *home;
1752  uint16_t port;
1753  int proto = IPPROTO_UDP;
1754  fr_ipaddr_t ipaddr;
1755 
1756  if (argc < 2) {
1757  cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp]\n");
1758  return NULL;
1759  }
1760 
1761  if (fr_inet_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1762  cprintf_error(listener, "Failed parsing IP address; %s\n",
1763  fr_strerror());
1764  return NULL;
1765  }
1766 
1767  port = atoi(argv[1]);
1768 
1769  myarg = 2;
1770 
1771  while (myarg < argc) {
1772  if (strcmp(argv[myarg], "udp") == 0) {
1773  proto = IPPROTO_UDP;
1774  myarg++;
1775  continue;
1776  }
1777 
1778 #ifdef WITH_TCP
1779  if (strcmp(argv[myarg], "tcp") == 0) {
1780  proto = IPPROTO_TCP;
1781  myarg++;
1782  continue;
1783  }
1784 #endif
1785 
1786  /*
1787  * Unknown argument. Leave it for the caller.
1788  */
1789  break;
1790  }
1791 
1792  home = home_server_find(&ipaddr, port, proto);
1793  if (!home) {
1794  cprintf_error(listener, "No such home server\n");
1795  return NULL;
1796  }
1797 
1798  if (last) *last = myarg;
1799 
1800  return home;
1801 }
1802 
1803 static int command_set_home_server_state(rad_listen_t *listener, int argc, char *argv[])
1804 {
1805  int last;
1806  home_server_t *home;
1807 
1808  if (argc < 3) {
1809  cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp] <state>\n");
1810  return CMD_FAIL;
1811  }
1812 
1813  home = get_home_server(listener, argc, argv, &last);
1814  if (!home) {
1815  return CMD_FAIL;
1816  }
1817 
1818  if (strcmp(argv[last], "alive") == 0) {
1819  revive_home_server(home, NULL);
1820 
1821  } else if (strcmp(argv[last], "dead") == 0) {
1822  struct timeval now;
1823 
1824  gettimeofday(&now, NULL); /* we do this WAY too ofetn */
1825  mark_home_server_dead(home, &now);
1826 
1827  } else {
1828  cprintf_error(listener, "Unknown state \"%s\"\n", argv[last]);
1829  return CMD_FAIL;
1830  }
1831 
1832  return CMD_OK;
1833 }
1834 
1835 static int command_show_home_server_state(rad_listen_t *listener, int argc, char *argv[])
1836 {
1837  home_server_t *home;
1838 
1839  home = get_home_server(listener, argc, argv, NULL);
1840  if (!home) return CMD_FAIL;
1841 
1842  switch (home->state) {
1843  case HOME_STATE_ALIVE:
1844  cprintf(listener, "alive\n");
1845  break;
1846 
1847  case HOME_STATE_IS_DEAD:
1848  cprintf(listener, "dead\n");
1849  break;
1850 
1851  case HOME_STATE_ZOMBIE:
1852  cprintf(listener, "zombie\n");
1853  break;
1854 
1855  case HOME_STATE_UNKNOWN:
1856  cprintf(listener, "unknown\n");
1857  break;
1858 
1859  default:
1860  cprintf(listener, "invalid\n");
1861  break;
1862  }
1863 
1864  return CMD_OK;
1865 }
1866 #endif
1867 
1868 /*
1869  * For encode/decode stuff
1870  */
1871 static int null_socket_dencode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
1872 {
1873  return 0;
1874 }
1875 
1876 static int null_socket_send(UNUSED rad_listen_t *listener, REQUEST *request)
1877 {
1878  vp_cursor_t cursor;
1879  char *output_file;
1880  FILE *fp;
1881 
1882  output_file = request_data_reference(request, (void *)null_socket_send, 0);
1883  if (!output_file) {
1884  ERROR("No output file for injected packet %d", request->number);
1885  return 0;
1886  }
1887 
1888  fp = fopen(output_file, "w");
1889  if (!fp) {
1890  ERROR("Failed to send injected file to %s: %s", output_file, fr_syserror(errno));
1891  return 0;
1892  }
1893 
1894  if (request->reply->code != 0) {
1895  char const *what = "reply";
1896  VALUE_PAIR *vp;
1897  char buffer[1024];
1898 
1899  if (request->reply->code < FR_MAX_PACKET_CODE) {
1900  what = fr_packet_codes[request->reply->code];
1901  }
1902 
1903  fprintf(fp, "%s\n", what);
1904 
1905  if (rad_debug_lvl) {
1906  RDEBUG("Injected %s packet to host %s port 0 code=%d, id=%d", what,
1907  inet_ntop(request->reply->src_ipaddr.af,
1908  &request->reply->src_ipaddr.ipaddr,
1909  buffer, sizeof(buffer)),
1910  request->reply->code, request->reply->id);
1911  }
1912 
1913  RINDENT();
1914  for (vp = fr_cursor_init(&cursor, &request->reply->vps);
1915  vp;
1916  vp = fr_cursor_next(&cursor)) {
1917  fr_pair_snprint(buffer, sizeof(buffer), vp);
1918  fprintf(fp, "%s\n", buffer);
1919  RDEBUG("%s", buffer);
1920  }
1921  REXDENT();
1922  }
1923  fclose(fp);
1924 
1925  return 0;
1926 }
1927 
1928 static rad_listen_t *get_socket(rad_listen_t *listener, int argc,
1929  char *argv[], int *last)
1930 {
1931  rad_listen_t *sock;
1932  uint16_t port;
1933  int proto = IPPROTO_UDP;
1934  fr_ipaddr_t ipaddr;
1935 
1936  if (argc < 2) {
1937  cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp]\n");
1938  return NULL;
1939  }
1940 
1941  if (fr_inet_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1942  cprintf_error(listener, "Failed parsing IP address; %s\n",
1943  fr_strerror());
1944  return NULL;
1945  }
1946 
1947  port = atoi(argv[1]);
1948 
1949  if (last) *last = 2;
1950  if (argc > 2) {
1951  if (strcmp(argv[2], "udp") == 0) {
1952  proto = IPPROTO_UDP;
1953  if (last) *last = 3;
1954  }
1955 #ifdef WITH_TCP
1956  if (strcmp(argv[2], "tcp") == 0) {
1957  proto = IPPROTO_TCP;
1958  if (last) *last = 3;
1959  }
1960 #endif
1961  }
1962 
1963  sock = listener_find_byipaddr(&ipaddr, port, proto);
1964  if (!sock) {
1965  cprintf_error(listener, "No such listen section\n");
1966  return NULL;
1967  }
1968 
1969  return sock;
1970 }
1971 
1972 
1973 static int command_inject_to(rad_listen_t *listener, int argc, char *argv[])
1974 {
1975  fr_command_socket_t *sock = listener->data;
1977  rad_listen_t *found;
1978 
1979  found = get_socket(listener, argc, argv, NULL);
1980  if (!found) {
1981  return 0;
1982  }
1983 
1984  data = found->data;
1985  sock->inject_listener = found;
1986  sock->dst_ipaddr = data->my_ipaddr;
1987  sock->dst_port = data->my_port;
1988 
1989  return CMD_OK;
1990 }
1991 
1992 static int command_inject_from(rad_listen_t *listener, int argc, char *argv[])
1993 {
1994  RADCLIENT *client;
1995  fr_command_socket_t *sock = listener->data;
1996 
1997  if (argc < 1) {
1998  cprintf_error(listener, "No <ipaddr> was given\n");
1999  return 0;
2000  }
2001 
2002  if (!sock->inject_listener) {
2003  cprintf_error(listener, "You must specify \"inject to\" before using \"inject from\"\n");
2004  return 0;
2005  }
2006 
2007  sock->src_ipaddr.af = AF_UNSPEC;
2008  if (fr_inet_hton(&sock->src_ipaddr, AF_UNSPEC, argv[0], false) < 0) {
2009  cprintf_error(listener, "Failed parsing IP address; %s\n",
2010  fr_strerror());
2011  return 0;
2012  }
2013 
2014  client = client_listener_find(sock->inject_listener, &sock->src_ipaddr,
2015  0);
2016  if (!client) {
2017  cprintf_error(listener, "No such client %s\n", argv[0]);
2018  return 0;
2019  }
2020  sock->inject_client = client;
2021 
2022  return CMD_OK;
2023 }
2024 
2025 static int command_inject_file(rad_listen_t *listener, int argc, char *argv[])
2026 {
2027  static int inject_id = 0;
2028  int ret;
2029  bool filedone;
2030  fr_command_socket_t *sock = listener->data;
2031  rad_listen_t *fake;
2032  RADIUS_PACKET *packet;
2033  vp_cursor_t cursor;
2034  VALUE_PAIR *vp;
2035  FILE *fp;
2036  RAD_REQUEST_FUNP fun = NULL;
2037  char buffer[2048];
2038 
2039  if (argc < 2) {
2040  cprintf_error(listener, "You must specify <input-file> <output-file>\n");
2041  return 0;
2042  }
2043 
2044  if (!sock->inject_listener) {
2045  cprintf_error(listener, "You must specify \"inject to\" before using \"inject file\"\n");
2046  return 0;
2047  }
2048 
2049  if (!sock->inject_client) {
2050  cprintf_error(listener, "You must specify \"inject from\" before using \"inject file\"\n");
2051  return 0;
2052  }
2053 
2054  /*
2055  * Output files always go to the logging directory.
2056  */
2057  snprintf(buffer, sizeof(buffer), "%s/%s", radlog_dir, argv[1]);
2058 
2059  fp = fopen(argv[0], "r");
2060  if (!fp ) {
2061  cprintf_error(listener, "Failed opening %s: %s\n",
2062  argv[0], fr_syserror(errno));
2063  return 0;
2064  }
2065 
2066  ret = fr_pair_list_afrom_file(NULL, &vp, fp, &filedone);
2067  fclose(fp);
2068  if (ret < 0) {
2069  cprintf_error(listener, "Failed reading attributes from %s: %s\n",
2070  argv[0], fr_strerror());
2071  return 0;
2072  }
2073 
2074  fake = talloc(NULL, rad_listen_t);
2075  memcpy(fake, sock->inject_listener, sizeof(*fake));
2076 
2077  /*
2078  * Re-write the IO for the listener.
2079  */
2080  fake->encode = null_socket_dencode;
2081  fake->decode = null_socket_dencode;
2082  fake->send = null_socket_send;
2083 
2084  packet = fr_radius_alloc(NULL, false);
2085  packet->src_ipaddr = sock->src_ipaddr;
2086  packet->src_port = 0;
2087 
2088  packet->dst_ipaddr = sock->dst_ipaddr;
2089  packet->dst_port = sock->dst_port;
2090  packet->vps = vp;
2091  packet->id = inject_id++;
2092 
2093  if (fake->type == RAD_LISTEN_AUTH) {
2094  packet->code = PW_CODE_ACCESS_REQUEST;
2095  fun = rad_authenticate;
2096 
2097  } else {
2098 #ifdef WITH_ACCOUNTING
2099  packet->code = PW_CODE_ACCOUNTING_REQUEST;
2100  fun = rad_accounting;
2101 #else
2102  cprintf_error(listener, "This server was built without accounting support.\n");
2103  fr_radius_free(&packet);
2104  free(fake);
2105  return 0;
2106 #endif
2107  }
2108 
2109  if (rad_debug_lvl) {
2110  DEBUG("Injecting %s packet from host %s port 0 code=%d, id=%d",
2111  fr_packet_codes[packet->code],
2112  inet_ntop(packet->src_ipaddr.af,
2113  &packet->src_ipaddr.ipaddr,
2114  buffer, sizeof(buffer)),
2115  packet->code, packet->id);
2116 
2117  for (vp = fr_cursor_init(&cursor, &packet->vps);
2118  vp;
2119  vp = fr_cursor_next(&cursor)) {
2120  fr_pair_snprint(buffer, sizeof(buffer), vp);
2121  DEBUG("\t%s", buffer);
2122  }
2123 
2124  WARN("INJECTION IS LEAKING MEMORY!");
2125  }
2126 
2127  if (!request_receive(NULL, fake, packet, sock->inject_client, fun)) {
2128  cprintf_error(listener, "Failed to inject request. See log file for details\n");
2129  fr_radius_free(&packet);
2130  free(fake);
2131  return 0;
2132  }
2133 
2134 #if 0
2135  /*
2136  * Remember what the output file is, and remember to
2137  * delete the fake listener when done.
2138  */
2139  request_data_add(request, null_socket_send, 0, talloc_typed_strdup(NULL, buffer), true, false, false);
2140  request_data_add(request, null_socket_send, 1, fake, true, false, false);
2141 
2142 #endif
2143 
2144  return CMD_OK;
2145 }
2146 
2147 
2149  { "to", FR_WRITE,
2150  "inject to <ipaddr> <port> - Inject packets to the destination IP and port.",
2151  command_inject_to, NULL },
2152 
2153  { "from", FR_WRITE,
2154  "inject from <ipaddr> - Inject packets as if they came from <ipaddr>",
2155  command_inject_from, NULL },
2156 
2157  { "file", FR_WRITE,
2158  "inject file <input-file> <output-file> - Inject packet from <input-file>, with results sent to <output-file>",
2159  command_inject_file, NULL },
2160 
2161  { NULL, 0, NULL, NULL, NULL }
2162 };
2163 
2165  { "condition", FR_WRITE,
2166  "debug condition [condition] - Enable debugging for requests matching [condition]",
2167  command_debug_condition, NULL },
2168 
2169  { "level", FR_WRITE,
2170  "debug level <number> - Set debug level to <number>. Higher is more debugging.",
2171  command_debug_level, NULL },
2172 
2173  { "file", FR_WRITE,
2174  "debug file [filename] - Send all debugging output to [filename]",
2175  command_debug_file, NULL },
2176 
2177 #if defined(HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
2178  { "socket", FR_WRITE,
2179  "debug socket [on|off] - Send all debugging output to radmin socket.",
2180  command_debug_socket, NULL },
2181 #endif
2182 
2183  { NULL, 0, NULL, NULL, NULL }
2184 };
2185 
2186 #ifdef HAVE_GPERFTOOLS_PROFILER_H
2187 /** Commands to control the gperftools profiler
2188  *
2189  */
2190 static fr_command_table_t command_table_profiler_cpu[] = {
2191  { "start", FR_WRITE,
2192  "profiler cpu start <filename> - Start gperftools cpu profiler, writing output to filename",
2193  command_profiler_cpu_start, NULL },
2194 
2195  { "stop", FR_WRITE,
2196  "profiler cpu stop - Stop gperftools cpu profiler, and flush results to disk",
2197  command_profiler_cpu_stop, NULL },
2198 
2199  { NULL, 0, NULL, NULL, NULL }
2200 };
2201 
2202 static fr_command_table_t command_table_profiler[] = {
2203  { "cpu", FR_WRITE,
2204  "profiler cpu <command> do sub-command of cpu profiler",
2205  NULL, command_table_profiler_cpu },
2206 
2207  { NULL, 0, NULL, NULL, NULL }
2208 };
2209 #endif
2210 
2212  { "condition", FR_READ,
2213  "show debug condition - Shows current debugging condition.",
2215 
2216  { "level", FR_READ,
2217  "show debug level - Shows current debugging level.",
2218  command_show_debug_level, NULL },
2219 
2220  { "file", FR_READ,
2221  "show debug file - Shows current debugging file.",
2222  command_show_debug_file, NULL },
2223 
2224  { NULL, 0, NULL, NULL, NULL }
2225 };
2226 
2228  { "config", FR_READ,
2229  "show module config <module> - show configuration for given module",
2231  { "flags", FR_READ,
2232  "show module flags <module> - show other module properties",
2233  command_show_module_flags, NULL },
2234  { "list", FR_READ,
2235  "show module list - shows list of loaded modules",
2236  command_show_modules, NULL },
2237  { "methods", FR_READ,
2238  "show module methods <module> - show sections where <module> may be used",
2240  { "status", FR_READ,
2241  "show module status <module> - show the module status",
2243 
2244  { NULL, 0, NULL, NULL, NULL }
2245 };
2246 
2248  { "list", FR_READ,
2249  "show client list - shows list of global clients",
2250  command_show_clients, NULL },
2251 
2252  { NULL, 0, NULL, NULL, NULL }
2253 };
2254 
2255 #ifdef WITH_PROXY
2257  { "list", FR_READ,
2258  "show home_server list - shows list of home servers",
2259  command_show_home_servers, NULL },
2260  { "state", FR_READ,
2261  "show home_server state <ipaddr> <port> [udp|tcp] - shows state of given home server",
2263 
2264  { NULL, 0, NULL, NULL, NULL }
2265 };
2266 #endif
2267 
2268 #ifdef HAVE_GPERFTOOLS_PROFILER_H
2269 static fr_command_table_t command_table_show_profiler_cpu[] = {
2270  { "file", FR_WRITE,
2271  "show profiler cpu file - show where profile data is being written",
2272  command_profiler_cpu_show_file, NULL },
2273 
2274  { "samples", FR_WRITE,
2275  "show profiler cpu samples - show how many profiler samples have been collected",
2276  command_profiler_cpu_show_samples, NULL },
2277 
2278  { "start_time", FR_WRITE,
2279  "show profiler cpu start_time - show when profiling last started",
2280  command_profiler_cpu_show_start_time, NULL },
2281 
2282  { "status", FR_WRITE,
2283  "show profiler cpu status - show the current profiler state (running or stopped)",
2284  command_profiler_cpu_show_status, NULL },
2285 
2286  { NULL, 0, NULL, NULL, NULL }
2287 };
2288 
2289 static fr_command_table_t command_table_show_profiler[] = {
2290  { "cpu", FR_WRITE,
2291  "show profiler cpu <command> do sub-command of cpu profiler",
2292  NULL, command_table_show_profiler_cpu },
2293 
2294  { NULL, 0, NULL, NULL, NULL }
2295 };
2296 #endif
2297 
2299  { "client", FR_READ,
2300  "show client <command> - do sub-command of client",
2301  NULL, command_table_show_client },
2302  { "config", FR_READ,
2303  "show config <path> - shows the value of configuration option <path>",
2304  command_show_config, NULL },
2305  { "debug", FR_READ,
2306  "show debug <command> - show debug properties",
2307  NULL, command_table_show_debug },
2308 #ifdef WITH_PROXY
2309  { "home_server", FR_READ,
2310  "show home_server <command> - do sub-command of home_server",
2311  NULL, command_table_show_home },
2312 #endif
2313  { "module", FR_READ,
2314  "show module <command> - do sub-command of module",
2315  NULL, command_table_show_module },
2316 
2317 #ifdef HAVE_GPERFTOOLS_PROFILER_H
2318  { "profiler", FR_READ,
2319  "show profiler <command> - do sub-command of profiler",
2320  NULL, command_table_show_profiler },
2321 #endif
2322 
2323  { "uptime", FR_READ,
2324  "show uptime - shows time at which server started",
2325  command_uptime, NULL },
2326  { "version", FR_READ,
2327  "show version - Prints version of the running server",
2328  command_show_version, NULL },
2329  { NULL, 0, NULL, NULL, NULL }
2330 };
2331 
2332 static int command_set_module_config(rad_listen_t *listener, int argc, char *argv[])
2333 {
2334  int i, rcode;
2335  CONF_PAIR *cp;
2336  CONF_SECTION *cs;
2337  module_instance_t *mi;
2338  CONF_PARSER const *variables;
2339  void *data;
2340 
2341  if (argc < 3) {
2342  cprintf_error(listener, "No module name or variable was given\n");
2343  return 0;
2344  }
2345 
2346  cs = cf_section_sub_find(main_config.config, "modules");
2347  if (!cs) return 0;
2348 
2349  mi = module_find(cs, argv[0]);
2350  if (!mi) {
2351  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
2352  return 0;
2353  }
2354 
2355  if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
2356  cprintf_error(listener, "Cannot change configuration of module as it is cannot be HUP'd.\n");
2357  return 0;
2358  }
2359 
2360  variables = cf_section_parse_table(mi->cs);
2361  if (!variables) {
2362  cprintf_error(listener, "Cannot find configuration for module\n");
2363  return 0;
2364  }
2365 
2366  rcode = -1;
2367  for (i = 0; variables[i].name != NULL; i++) {
2368  /*
2369  * FIXME: Recurse into sub-types somehow...
2370  */
2371  if (variables[i].type == PW_TYPE_SUBSECTION) continue;
2372 
2373  if (strcmp(variables[i].name, argv[1]) == 0) {
2374  rcode = i;
2375  break;
2376  }
2377  }
2378 
2379  if (rcode < 0) {
2380  cprintf_error(listener, "No such variable \"%s\"\n", argv[1]);
2381  return 0;
2382  }
2383 
2384  i = rcode; /* just to be safe */
2385 
2386  /*
2387  * It's not part of the dynamic configuration. The module
2388  * needs to re-parse && validate things.
2389  */
2390  if (variables[i].data) {
2391  cprintf_error(listener, "Variable cannot be dynamically updated\n");
2392  return 0;
2393  }
2394 
2395  data = ((char *) mi->insthandle) + variables[i].offset;
2396 
2397  cp = cf_pair_find(mi->cs, argv[1]);
2398  if (!cp) return 0;
2399 
2400  /*
2401  * Replace the OLD value in the configuration file with
2402  * the NEW value.
2403  *
2404  * FIXME: Parse argv[2] depending on it's data type!
2405  * If it's a string, look for leading single/double quotes,
2406  * end then call tokenize functions???
2407  */
2408  cf_pair_replace(mi->cs, cp, argv[2]);
2409 
2410  rcode = cf_pair_parse(mi->cs, argv[1], variables[i].type, data, argv[2], T_DOUBLE_QUOTED_STRING);
2411  if (rcode < 0) {
2412  cprintf_error(listener, "Failed to parse value\n");
2413  return 0;
2414  }
2415 
2416  return CMD_OK;
2417 }
2418 
2419 static int command_set_module_status(rad_listen_t *listener, int argc, char *argv[])
2420 {
2421  CONF_SECTION *cs;
2422  module_instance_t *mi;
2423 
2424  if (argc < 2) {
2425  cprintf_error(listener, "No module name or status was given\n");
2426  return 0;
2427  }
2428 
2429  cs = cf_section_sub_find(main_config.config, "modules");
2430  if (!cs) return 0;
2431 
2432  mi = module_find(cs, argv[0]);
2433  if (!mi) {
2434  cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
2435  return 0;
2436  }
2437 
2438 
2439  if (strcmp(argv[1], "alive") == 0) {
2440  mi->force = false;
2441 
2442  } else if (strcmp(argv[1], "dead") == 0) {
2443  mi->code = RLM_MODULE_FAIL;
2444  mi->force = true;
2445 
2446  } else {
2447  int rcode;
2448 
2449  rcode = fr_str2int(mod_rcode_table, argv[1], -1);
2450  if (rcode < 0) {
2451  cprintf_error(listener, "Unknown status \"%s\"\n", argv[1]);
2452  return 0;
2453  }
2454 
2455  mi->code = rcode;
2456  mi->force = true;
2457  }
2458 
2459  return CMD_OK;
2460 }
2461 
2462 #ifdef WITH_STATS
2463 static char const *elapsed_names[8] = {
2464  "1us", "10us", "100us", "1ms", "10ms", "100ms", "1s", "10s"
2465 };
2466 
2467 #undef PU
2468 #ifdef WITH_STATS_64BIT
2469 #ifdef PRIu64
2470 #define PU "%" PRIu64
2471 #else
2472 #define PU "%lu"
2473 #endif
2474 #else
2475 #ifdef PRIu32
2476 #define PU "%" PRIu32
2477 #else
2478 #define PU "%u"
2479 #endif
2480 #endif
2481 
2483  int auth, int server)
2484 {
2485  int i;
2486 
2487  cprintf(listener, "requests\t" PU "\n", stats->total_requests);
2488  cprintf(listener, "responses\t" PU "\n", stats->total_responses);
2489 
2490  if (auth) {
2491  cprintf(listener, "accepts\t\t" PU "\n",
2492  stats->total_access_accepts);
2493  cprintf(listener, "rejects\t\t" PU "\n",
2494  stats->total_access_rejects);
2495  cprintf(listener, "challenges\t" PU "\n",
2496  stats->total_access_challenges);
2497  }
2498 
2499  cprintf(listener, "dup\t\t" PU "\n", stats->total_dup_requests);
2500  cprintf(listener, "invalid\t\t" PU "\n", stats->total_invalid_requests);
2501  cprintf(listener, "malformed\t" PU "\n", stats->total_malformed_requests);
2502  cprintf(listener, "bad_authenticator\t" PU "\n", stats->total_bad_authenticators);
2503  cprintf(listener, "dropped\t\t" PU "\n", stats->total_packets_dropped);
2504  cprintf(listener, "unknown_types\t" PU "\n", stats->total_unknown_types);
2505 
2506  if (server) {
2507  cprintf(listener, "timeouts\t" PU "\n", stats->total_timeouts);
2508  }
2509 
2510  cprintf(listener, "last_packet\t%" PRId64 "\n", (int64_t) stats->last_packet);
2511  for (i = 0; i < 8; i++) {
2512  cprintf(listener, "elapsed.%s\t%u\n",
2513  elapsed_names[i], stats->elapsed[i]);
2514  }
2515 
2516  return CMD_OK;
2517 }
2518 
2519 static int command_stats_state(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
2520 {
2521  cprintf(listener, "states_created\t\t%" PRIu64 "\n", fr_state_entries_created(global_state));
2522  cprintf(listener, "states_timeout\t\t%" PRIu64 "\n", fr_state_entries_timeout(global_state));
2523  cprintf(listener, "states_tracked\t\t%" PRIu32 "\n", fr_state_entries_tracked(global_state));
2524 
2525  return CMD_OK;
2526 }
2527 
2528 #ifdef HAVE_PTHREAD_H
2529 static int command_stats_queue(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
2530 {
2531  int array[RAD_LISTEN_MAX], pps[2];
2532 
2533  thread_pool_queue_stats(array, pps);
2534 
2535  cprintf(listener, "queue_len_internal\t" PU "\n", array[0]);
2536  cprintf(listener, "queue_len_proxy\t\t" PU "\n", array[1]);
2537  cprintf(listener, "queue_len_auth\t\t" PU "\n", array[2]);
2538  cprintf(listener, "queue_len_acct\t\t" PU "\n", array[3]);
2539  cprintf(listener, "queue_len_detail\t" PU "\n", array[4]);
2540 
2541  cprintf(listener, "queue_pps_in\t\t" PU "\n", pps[0]);
2542  cprintf(listener, "queue_pps_out\t\t" PU "\n", pps[1]);
2543 
2544  return CMD_OK;
2545 }
2546 #endif
2547 
2548 #ifndef NDEBUG
2549 static int command_stats_memory(rad_listen_t *listener, int argc, char *argv[])
2550 {
2551 
2553  cprintf(listener, "No memory debugging was enabled.\n");
2554  return CMD_OK;
2555  }
2556 
2557  if (argc == 0) goto fail;
2558 
2559  if (strcmp(argv[0], "total") == 0) {
2560  cprintf(listener, "%zd\n", talloc_total_size(NULL));
2561  return CMD_OK;
2562  }
2563 
2564  if (strcmp(argv[0], "blocks") == 0) {
2565  cprintf(listener, "%zd\n", talloc_total_blocks(NULL));
2566  return CMD_OK;
2567  }
2568 
2569  if (strcmp(argv[0], "full") == 0) {
2570  cprintf(listener, "see stdout of the server for the full report.\n");
2571  fr_log_talloc_report(NULL);
2572  return CMD_OK;
2573  }
2574 
2575 fail:
2576  cprintf_error(listener, "Must use 'stats memory [blocks|full|total]'\n");
2577  return CMD_FAIL;
2578 }
2579 #endif
2580 
2581 #ifdef WITH_DETAIL
2583  { "unopened", STATE_UNOPENED },
2584  { "unlocked", STATE_UNLOCKED },
2585  { "header", STATE_HEADER },
2586  { "reading", STATE_READING },
2587  { "queued", STATE_QUEUED },
2588  { "running", STATE_RUNNING },
2589  { "no-reply", STATE_NO_REPLY },
2590  { "replied", STATE_REPLIED },
2591 
2592  { NULL, 0 }
2593 };
2594 
2595 static int command_stats_detail(rad_listen_t *listener, int argc, char *argv[])
2596 {
2597  rad_listen_t *this;
2598  listen_detail_t *data, *needle;
2599  struct stat buf;
2600 
2601  if (argc == 0) {
2602  cprintf_error(listener, "Must specify <filename>\n");
2603  return 0;
2604  }
2605 
2606  data = NULL;
2607  for (this = main_config.listen; this != NULL; this = this->next) {
2608  if (this->type != RAD_LISTEN_DETAIL) continue;
2609 
2610  needle = this->data;
2611  if (!strcmp(argv[0], needle->filename)) {
2612  data = needle;
2613  break;
2614  }
2615  }
2616 
2617  if (!data) {
2618  cprintf_error(listener, "No detail file listener\n");
2619  return 0;
2620  }
2621 
2622  cprintf(listener, "state\t%s\n",
2623  fr_int2str(state_names, data->state, "?"));
2624 
2625  if ((data->state == STATE_UNOPENED) ||
2626  (data->state == STATE_UNLOCKED)) {
2627  return CMD_OK;
2628  }
2629 
2630  /*
2631  * Race conditions: file might not exist.
2632  */
2633  if (stat(data->filename_work, &buf) < 0) {
2634  cprintf(listener, "packets\t0\n");
2635  cprintf(listener, "tries\t0\n");
2636  cprintf(listener, "offset\t0\n");
2637  cprintf(listener, "size\t0\n");
2638  return CMD_OK;
2639  }
2640 
2641  cprintf(listener, "packets\t%d\n", data->packets);
2642  cprintf(listener, "tries\t%d\n", data->tries);
2643  cprintf(listener, "offset\t%u\n", (unsigned int) data->offset);
2644  cprintf(listener, "size\t%u\n", (unsigned int) buf.st_size);
2645 
2646  return CMD_OK;
2647 }
2648 #endif
2649 
2650 #ifdef WITH_PROXY
2651 static int command_stats_home_server(rad_listen_t *listener, int argc, char *argv[])
2652 {
2653  home_server_t *home;
2654 
2655  if (argc == 0) {
2656  cprintf_error(listener, "Must specify [auth|acct|coa|disconnect] OR <ipaddr> <port>\n");
2657  return 0;
2658  }
2659 
2660  if (argc == 1) {
2661  if (strcmp(argv[0], "auth") == 0) {
2662  return command_print_stats(listener,
2663  &proxy_auth_stats, 1, 1);
2664  }
2665 
2666 #ifdef WITH_ACCOUNTING
2667  if (strcmp(argv[0], "acct") == 0) {
2668  return command_print_stats(listener,
2669  &proxy_acct_stats, 0, 1);
2670  }
2671 #endif
2672 
2673 #ifdef WITH_ACCOUNTING
2674  if (strcmp(argv[0], "coa") == 0) {
2675  return command_print_stats(listener,
2676  &proxy_coa_stats, 0, 1);
2677  }
2678 #endif
2679 
2680 #ifdef WITH_ACCOUNTING
2681  if (strcmp(argv[0], "disconnect") == 0) {
2682  return command_print_stats(listener,
2683  &proxy_dsc_stats, 0, 1);
2684  }
2685 #endif
2686 
2687  cprintf_error(listener, "Should specify [auth|acct|coa|disconnect]\n");
2688  return 0;
2689  }
2690 
2691  home = get_home_server(listener, argc, argv, NULL);
2692  if (!home) return 0;
2693 
2694  command_print_stats(listener, &home->stats,
2695  (home->type == HOME_TYPE_AUTH), 1);
2696  cprintf(listener, "outstanding\t%d\n", home->currently_outstanding);
2697  return CMD_OK;
2698 }
2699 #endif
2700 
2701 static int command_stats_client(rad_listen_t *listener, int argc, char *argv[])
2702 {
2703  bool auth = true;
2704  fr_stats_t *stats;
2705  RADCLIENT *client, fake;
2706 
2707  if (argc < 1) {
2708  cprintf_error(listener, "Must specify [auth/acct]\n");
2709  return 0;
2710  }
2711 
2712  if (argc == 1) {
2713  /*
2714  * Global statistics.
2715  */
2716  fake.auth = radius_auth_stats;
2717 #ifdef WITH_ACCOUNTING
2718  fake.acct = radius_acct_stats;
2719 #endif
2720 #ifdef WITH_COA
2721  fake.coa = radius_coa_stats;
2722  fake.dsc = radius_dsc_stats;
2723 #endif
2724  client = &fake;
2725 
2726  } else {
2727  /*
2728  * Per-client statistics.
2729  */
2730  client = get_client(listener, argc - 1, argv + 1);
2731  if (!client) return 0;
2732  }
2733 
2734  if (strcmp(argv[0], "auth") == 0) {
2735  auth = true;
2736  stats = &client->auth;
2737 
2738  } else if (strcmp(argv[0], "acct") == 0) {
2739 #ifdef WITH_ACCOUNTING
2740  auth = false;
2741  stats = &client->acct;
2742 #else
2743  cprintf_error(listener, "This server was built without accounting support.\n");
2744  return 0;
2745 #endif
2746 
2747  } else if (strcmp(argv[0], "coa") == 0) {
2748 #ifdef WITH_COA
2749  auth = false;
2750  stats = &client->coa;
2751 #else
2752  cprintf_error(listener, "This server was built without CoA support.\n");
2753  return 0;
2754 #endif
2755 
2756  } else if (strcmp(argv[0], "disconnect") == 0) {
2757 #ifdef WITH_COA
2758  auth = false;
2759  stats = &client->dsc;
2760 #else
2761  cprintf_error(listener, "This server was built without CoA support.\n");
2762  return 0;
2763 #endif
2764 
2765  } else {
2766  cprintf_error(listener, "Unknown statistics type\n");
2767  return 0;
2768  }
2769 
2770  /*
2771  * Global results for all client.
2772  */
2773  if (argc == 1) {
2774 #ifdef WITH_ACCOUNTING
2775  if (!auth) {
2776  return command_print_stats(listener,
2777  &radius_acct_stats, auth, 0);
2778  }
2779 #endif
2780  return command_print_stats(listener, &radius_auth_stats, auth, 0);
2781  }
2782 
2783  return command_print_stats(listener, stats, auth, 0);
2784 }
2785 
2786 
2787 static int command_stats_socket(rad_listen_t *listener, int argc, char *argv[])
2788 {
2789  bool auth = true;
2790  rad_listen_t *sock;
2791 
2792  sock = get_socket(listener, argc, argv, NULL);
2793  if (!sock) return 0;
2794 
2795  if (sock->type != RAD_LISTEN_AUTH) auth = false;
2796 
2797  return command_print_stats(listener, &sock->stats, auth, 0);
2798 }
2799 #endif /* WITH_STATS */
2800 
2801 
2802 #ifdef WITH_DYNAMIC_CLIENTS
2803 static int command_add_client_file(rad_listen_t *listener, int argc, char *argv[])
2804 {
2805  RADCLIENT *c;
2806 
2807  if (argc < 1) {
2808  cprintf_error(listener, "<file> is required\n");
2809  return 0;
2810  }
2811 
2812  /*
2813  * Read the file and generate the client.
2814  */
2815  c = client_read(argv[0], false, false);
2816  if (!c) {
2817  cprintf_error(listener, "Unknown error reading client file.\n");
2818  return 0;
2819  }
2820 
2821  if (!client_add(NULL, c)) {
2822  cprintf_error(listener, "Unknown error inserting new client.\n");
2823  client_free(c);
2824  return 0;
2825  }
2826 
2827  return CMD_OK;
2828 }
2829 
2830 
2831 static int command_del_client(rad_listen_t *listener, int argc, char *argv[])
2832 {
2833  RADCLIENT *client;
2834 
2835  client = get_client(listener, argc, argv);
2836  if (!client) return 0;
2837 
2838  if (!client->dynamic) {
2839  cprintf_error(listener, "Client %s was not dynamically defined.\n", argv[0]);
2840  return 0;
2841  }
2842 
2843  /*
2844  * DON'T delete it. Instead, mark it as "dead now". The
2845  * next time we receive a packet for the client, it will
2846  * be deleted.
2847  *
2848  * If we don't receive a packet from it, the client
2849  * structure will stick around for a while. Oh well...
2850  */
2851  client->lifetime = 1;
2852 
2853  return CMD_OK;
2854 }
2855 
2856 
2858  { "ipaddr", FR_WRITE,
2859  "del client ipaddr <ipaddr> [udp|tcp] [listen <ipaddr> <port>] - Delete a dynamically created client",
2860  command_del_client, NULL },
2861 
2862  { NULL, 0, NULL, NULL, NULL }
2863 };
2864 
2865 
2867  { "client", FR_WRITE,
2868  "del client <command> - Delete client configuration commands",
2869  NULL, command_table_del_client },
2870 
2871  { NULL, 0, NULL, NULL, NULL }
2872 };
2873 
2874 
2876  { "file", FR_WRITE,
2877  "add client file <filename> - Add new client definition from <filename>",
2878  command_add_client_file, NULL },
2879 
2880  { NULL, 0, NULL, NULL, NULL }
2881 };
2882 
2883 
2885  { "client", FR_WRITE,
2886  "add client <command> - Add client configuration commands",
2887  NULL, command_table_add_client },
2888 
2889  { NULL, 0, NULL, NULL, NULL }
2890 };
2891 #endif
2892 
2893 #ifdef WITH_PROXY
2895  { "state", FR_WRITE,
2896  "set home_server state <ipaddr> <port> [udp|tcp] [alive|dead] - set state for given home server",
2898 
2899  { NULL, 0, NULL, NULL, NULL }
2900 };
2901 #endif
2902 
2904  { "config", FR_WRITE,
2905  "set module config <module> variable value - set configuration for <module>",
2906  command_set_module_config, NULL },
2907 
2908  { "status", FR_WRITE,
2909  "set module status <module> [alive|...] - set the module status to be alive (operating normally), or force a particular code (ok,fail, etc.)",
2910  command_set_module_status, NULL },
2911 
2912  { NULL, 0, NULL, NULL, NULL }
2913 };
2914 
2915 
2917  { "module", FR_WRITE,
2918  "set module <command> - set module commands",
2919  NULL, command_table_set_module },
2920 #ifdef WITH_PROXY
2921  { "home_server", FR_WRITE,
2922  "set home_server <command> - set home server commands",
2923  NULL, command_table_set_home },
2924 #endif
2925 
2926  { NULL, 0, NULL, NULL, NULL }
2927 };
2928 
2929 
2930 #ifdef WITH_STATS
2932  { "client", FR_READ,
2933  "stats client [auth/acct] <ipaddr> [udp|tcp] [listen <ipaddr> <port>] "
2934  "- show statistics for given client, or for all clients (auth or acct)",
2935  command_stats_client, NULL },
2936 
2937 #ifdef WITH_DETAIL
2938  { "detail", FR_READ,
2939  "stats detail <filename> - show statistics for the given detail file",
2940  command_stats_detail, NULL },
2941 #endif
2942 
2943 #ifdef WITH_PROXY
2944  { "home_server", FR_READ,
2945  "stats home_server [<ipaddr>|auth|acct|coa|disconnect] <port> [udp|tcp] - show statistics for given home server (ipaddr and port), or for all home servers (auth or acct)",
2946  command_stats_home_server, NULL },
2947 #endif
2948 
2949 #ifdef HAVE_PTHREAD_H
2950  { "queue", FR_READ,
2951  "stats queue - show statistics for packet queues",
2952  command_stats_queue, NULL },
2953 #endif
2954 
2955  { "state", FR_READ,
2956  "stats state - show statistics for states",
2957  command_stats_state, NULL },
2958 
2959  { "socket", FR_READ,
2960  "stats socket <ipaddr> <port> [udp|tcp] "
2961  "- show statistics for given socket",
2962  command_stats_socket, NULL },
2963 
2964 #ifndef NDEBUG
2965  { "memory", FR_READ,
2966  "stats memory [blocks|full|total] - show statistics on used memory",
2967  command_stats_memory, NULL },
2968 #endif
2969 
2970  { NULL, 0, NULL, NULL, NULL }
2971 };
2972 #endif
2973 
2975 #ifdef WITH_DYNAMIC_CLIENTS
2976  { "add", FR_WRITE, NULL, NULL, command_table_add },
2977 #endif
2978  { "debug", FR_WRITE,
2979  "debug <command> - debugging commands",
2980  NULL, command_table_debug },
2981 #ifdef WITH_DYNAMIC_CLIENTS
2982  { "del", FR_WRITE, NULL, NULL, command_table_del },
2983 #endif
2984  { "hup", FR_WRITE,
2985  "hup [module] - sends a HUP signal to the server, or optionally to one module",
2986  command_hup, NULL },
2987  { "inject", FR_WRITE,
2988  "inject <command> - commands to inject packets into a running server",
2989  NULL, command_table_inject },
2990 
2991 #ifdef HAVE_GPERFTOOLS_PROFILER_H
2992  { "profiler", FR_WRITE,
2993  "profiler <command> - commands to alter the state of the gperftools profiler",
2994  NULL, command_table_profiler },
2995 #endif
2996  { "reconnect", FR_READ,
2997  "reconnect - reconnect to a running server",
2998  NULL, NULL }, /* just here for "help" */
2999  { "terminate", FR_WRITE,
3000  "terminate - terminates the server, and cause it to exit",
3001  command_terminate, NULL },
3002  { "set", FR_WRITE, NULL, NULL, command_table_set },
3003  { "show", FR_READ, NULL, NULL, command_table_show },
3004 #ifdef WITH_STATS
3005  { "stats", FR_READ, NULL, NULL, command_table_stats },
3006 #endif
3007 
3008  { NULL, 0, NULL, NULL, NULL }
3009 };
3010 
3011 
3013 {
3014  fr_command_socket_t *cmd = this->data;
3015 
3016  /*
3017  * If it's a TCP socket, don't do anything.
3018  */
3019  if (cmd->magic != COMMAND_SOCKET_MAGIC) {
3020  return;
3021  }
3022 
3023  if (!cmd->copy) return;
3024  unlink(cmd->copy);
3025 }
3026 
3027 
3028 /*
3029  * Parse the unix domain sockets.
3030  *
3031  * FIXME: TCP + SSL, after RadSec is in.
3032  */
3034 {
3035  fr_command_socket_t *sock;
3036 
3037  sock = this->data;
3038 
3039  if (cf_section_parse(cs, sock, command_config) < 0) return -1;
3040 
3041  /*
3042  * Can't get uid or gid of connecting user, so can't do
3043  * peercred authentication.
3044  */
3045 #ifndef HAVE_GETPEEREID
3046  if (sock->peercred && (sock->uid_name || sock->gid_name)) {
3047  ERROR("System does not support uid or gid authentication for sockets");
3048  return -1;
3049  }
3050 #endif
3051 
3052  sock->magic = COMMAND_SOCKET_MAGIC;
3053  sock->copy = NULL;
3054  if (sock->path) sock->copy = talloc_typed_strdup(sock, sock->path);
3055 
3056  if (sock->uid_name) {
3057  struct passwd *pwd;
3058 
3059  if (rad_getpwnam(cs, &pwd, sock->uid_name) < 0) {
3060  ERROR("Failed getting uid for %s: %s", sock->uid_name, fr_strerror());
3061  return -1;
3062  }
3063  sock->uid = pwd->pw_uid;
3064  talloc_free(pwd);
3065  } else {
3066  sock->uid = -1;
3067  }
3068 
3069  if (sock->gid_name) {
3070  if (rad_getgid(cs, &sock->gid, sock->gid_name) < 0) {
3071  ERROR("Failed getting gid for %s: %s", sock->gid_name, fr_strerror());
3072  return -1;
3073  }
3074  } else {
3075  sock->gid = -1;
3076  }
3077 
3078  if (!sock->mode_name) {
3079  sock->co.mode = FR_READ;
3080  } else {
3081  sock->co.mode = fr_str2int(mode_names, sock->mode_name, 0);
3082  if (!sock->co.mode) {
3083  ERROR("Invalid mode name \"%s\"",
3084  sock->mode_name);
3085  return -1;
3086  }
3087  }
3088 
3089  return 0;
3090 }
3091 
3093 {
3094  fr_command_socket_t *sock;
3095 
3096  sock = this->data;
3097 
3098  if (sock->peercred) {
3099  this->fd = fr_server_domain_socket_peercred(sock->path, sock->uid, sock->gid);
3100  } else {
3101  uid_t uid = sock->uid;
3102  gid_t gid = sock->gid;
3103 
3104  if (uid == ((uid_t)-1)) uid = 0;
3105  if (gid == ((gid_t)-1)) gid = 0;
3106 
3107  this->fd = fr_server_domain_socket_perm(sock->path, uid, gid);
3108  }
3109 
3110  if (this->fd < 0) {
3111  ERROR("Failed creating control socket \"%s\": %s", sock->path, fr_strerror());
3112  if (sock->copy) talloc_free(sock->copy);
3113  sock->copy = NULL;
3114  return -1;
3115  }
3116 
3117  return 0;
3118 }
3119 
3121 {
3122  int rcode;
3123  CONF_PAIR const *cp;
3124  listen_socket_t *sock;
3125 
3126  cp = cf_pair_find(cs, "socket");
3127  if (cp) return command_socket_parse_unix(cs, this);
3128 
3129  rcode = common_socket_parse(cs, this);
3130  if (rcode < 0) return -1;
3131 
3132 #ifdef WITH_TLS
3133  if (this->tls) {
3134  cf_log_err_cs(cs,
3135  "TLS is not supported for control sockets");
3136  return -1;
3137  }
3138 #endif
3139 
3140  sock = this->data;
3141  if (sock->proto != IPPROTO_TCP) {
3142  cf_log_err_cs(cs,
3143  "UDP is not supported for control sockets");
3144  return -1;
3145  }
3146 
3147  return 0;
3148 }
3149 
3151 {
3152  CONF_PAIR const *cp;
3153 
3154  cp = cf_pair_find(cs, "socket");
3155  if (cp) return command_socket_open_unix(cs, this);
3156 
3157  return common_socket_open(cs, this);
3158 }
3159 
3160 static int command_socket_print(rad_listen_t const *this, char *buffer, size_t bufsize)
3161 {
3162  fr_command_socket_t *sock = this->data;
3163 
3164  if (sock->magic != COMMAND_SOCKET_MAGIC) {
3165  return common_socket_print(this, buffer, bufsize);
3166  }
3167 
3168  snprintf(buffer, bufsize, "command file %s", sock->path);
3169  return 1;
3170 }
3171 
3172 
3173 /*
3174  * String split routine. Splits an input string IN PLACE
3175  * into pieces, based on spaces.
3176  */
3177 static int dict_str_to_argvX(char *str, char **argv, int max_argc)
3178 {
3179  int argc = 0;
3180 
3181  while (*str) {
3182  if (argc >= max_argc) return argc;
3183 
3184  /*
3185  * Chop out comments early.
3186  */
3187  if (*str == '#') {
3188  *str = '\0';
3189  break;
3190  }
3191 
3192  while ((*str == ' ') ||
3193  (*str == '\t') ||
3194  (*str == '\r') ||
3195  (*str == '\n')) *(str++) = '\0';
3196 
3197  if (!*str) return argc;
3198 
3199  argv[argc++] = str;
3200 
3201  if ((*str == '\'') || (*str == '"')) {
3202  char quote = *str;
3203  char *p = str + 1;
3204 
3205  while (true) {
3206  if (!*p) return -1;
3207 
3208  if (*p == quote) {
3209  str = p + 1;
3210  break;
3211  }
3212 
3213  /*
3214  * Handle \" and nothing else.
3215  */
3216  if (*p == '\\') {
3217  p += 2;
3218  continue;
3219  }
3220 
3221  p++;
3222  }
3223  }
3224 
3225  while (*str &&
3226  (*str != ' ') &&
3227  (*str != '\t') &&
3228  (*str != '\r') &&
3229  (*str != '\n')) str++;
3230  }
3231 
3232  return argc;
3233 }
3234 
3235 static void print_help(rad_listen_t *listener, int argc, char *argv[],
3236  fr_command_table_t *table, int recursive)
3237 {
3238  int i;
3239 
3240  /* this should never happen, but if it does then just return gracefully */
3241  if (!table) return;
3242 
3243  for (i = 0; table[i].command != NULL; i++) {
3244  if (argc > 0) {
3245  if (strcmp(table[i].command, argv[0]) == 0) {
3246  if (table[i].table) {
3247  print_help(listener, argc - 1, argv + 1, table[i].table, recursive);
3248  } else {
3249  if (table[i].help) {
3250  cprintf(listener, "%s\n", table[i].help);
3251  }
3252  }
3253  return;
3254  }
3255 
3256  continue;
3257  }
3258 
3259  if (table[i].help) {
3260  cprintf(listener, "%s\n",
3261  table[i].help);
3262  } else {
3263  cprintf(listener, "%s <command> - do sub-command of %s\n",
3264  table[i].command, table[i].command);
3265  }
3266 
3267  if (recursive && table[i].table) {
3268  print_help(listener, 0, NULL, table[i].table, recursive);
3269  }
3270  }
3271 }
3272 
3273 #define MAX_ARGV (16)
3274 
3275 /*
3276  * Check if an incoming request is "ok"
3277  *
3278  * It takes packets, not requests. It sees if the packet looks
3279  * OK. If so, it does a number of sanity checks on it.
3280  */
3282 {
3283  int i;
3284  uint32_t status;
3285  ssize_t r, len;
3286  int argc;
3287  fr_channel_type_t channel;
3288  char *my_argv[MAX_ARGV], **argv;
3289  fr_command_table_t *table;
3290  uint8_t *command;
3291 
3292  r = fr_channel_drain(listener->fd, &channel, co->buffer, sizeof(co->buffer) - 1, &command, co->offset);
3293 
3294  if (r <= 0) {
3295  do_close:
3296  command_close_socket(listener);
3297  return 0;
3298  }
3299 
3300  /*
3301  * We need more data. Go read it.
3302  */
3303  if (channel == FR_CHANNEL_WANT_MORE) {
3304  co->offset = r;
3305  return 0;
3306  }
3307 
3308  status = 0;
3309  command[r] = '\0';
3310  DEBUG("radmin> %s", command);
3311 
3312  argc = dict_str_to_argvX((char *) command, my_argv, MAX_ARGV);
3313  if (argc == 0) goto do_next; /* empty strings are OK */
3314 
3315  if (argc < 0) {
3316  cprintf_error(listener, "Failed parsing command '%s'.\n",
3317  command);
3318  goto do_next;
3319  }
3320 
3321  argv = my_argv;
3322 
3323  for (len = 0; len <= co->offset; len++) {
3324  if (command[len] < 0x20) {
3325  command[len] = '\0';
3326  break;
3327  }
3328  }
3329 
3330  /*
3331  * Hard-code exit && quit.
3332  */
3333  if ((strcmp(argv[0], "exit") == 0) ||
3334  (strcmp(argv[0], "quit") == 0)) goto do_close;
3335 
3336  table = command_table;
3337  retry:
3338  len = 0;
3339  for (i = 0; table[i].command != NULL; i++) {
3340  if (strcmp(table[i].command, argv[0]) == 0) {
3341  /*
3342  * Check permissions.
3343  */
3344  if (((co->mode & FR_WRITE) == 0) &&
3345  ((table[i].mode & FR_WRITE) != 0)) {
3346  cprintf_error(listener, "You do not have write permission. See \"mode = rw\" in the \"listen\" section for this socket.\n");
3347  goto do_next;
3348  }
3349 
3350  if (table[i].table) {
3351  /*
3352  * This is the last argument, but
3353  * there's a sub-table. Print help.
3354  *
3355  */
3356  if (argc == 1) {
3357  table = table[i].table;
3358  goto do_help;
3359  }
3360 
3361  argc--;
3362  argv++;
3363  table = table[i].table;
3364  goto retry;
3365  }
3366 
3367  if ((argc == 2) && (strcmp(argv[1], "?") == 0)) goto do_help;
3368 
3369  if (!table[i].func) {
3370  cprintf_error(listener, "Invalid command\n");
3371  goto do_next;
3372  }
3373 
3374  status = table[i].func(listener, argc - 1, argv + 1);
3375  goto do_next;
3376  }
3377  }
3378 
3379  /*
3380  * No such command
3381  */
3382  if (!len) {
3383  if ((strcmp(argv[0], "help") == 0) ||
3384  (strcmp(argv[0], "?") == 0)) {
3385  int recursive;
3386 
3387  do_help:
3388  if ((argc > 1) && (strcmp(argv[1], "-r") == 0)) {
3389  recursive = true;
3390  argc--;
3391  argv++;
3392  } else {
3393  recursive = false;
3394  }
3395 
3396  print_help(listener, argc - 1, argv + 1, table, recursive);
3397  goto do_next;
3398  }
3399 
3400  cprintf_error(listener, "Unknown command \"%s\"\n",
3401  argv[0]);
3402  }
3403 
3404  do_next:
3405  r = fr_channel_write(listener->fd, FR_CHANNEL_CMD_STATUS, &status, sizeof(status));
3406  if (r <= 0) goto do_close;
3407 
3408  return 0;
3409 }
3410 
3411 
3412 /*
3413  * Write 32-bit magic number && version information.
3414  */
3415 static int command_write_magic(int newfd, listen_socket_t *sock)
3416 {
3417  ssize_t r;
3418  uint32_t magic;
3419  fr_channel_type_t channel;
3420  char buffer[16];
3421 
3422  r = fr_channel_read(newfd, &channel, buffer, 8);
3423  if (r <= 0) {
3424  do_close:
3425  ERROR("Cannot talk to socket: %s",
3426  fr_syserror(errno));
3427  return -1;
3428  }
3429 
3430  magic = htonl(0xf7eead16);
3431  if ((r != 8) || (channel != FR_CHANNEL_INIT_ACK) ||
3432  (memcmp(&magic, &buffer, sizeof(magic)) != 0)) {
3433  ERROR("Incompatible versions");
3434  return -1;
3435  }
3436 
3437  r = fr_channel_write(newfd, FR_CHANNEL_INIT_ACK, buffer, 8);
3438  if (r <= 0) goto do_close;
3439 
3440  /*
3441  * Write an initial challenge
3442  */
3443  if (sock) {
3444  int i;
3445  fr_cs_buffer_t *co;
3446 
3447  co = talloc_zero(sock, fr_cs_buffer_t);
3448  sock->packet = (void *) co;
3449 
3450  for (i = 0; i < 16; i++) {
3451  co->buffer[i] = fr_rand();
3452  }
3453 
3454  r = fr_channel_write(newfd, FR_CHANNEL_AUTH_CHALLENGE, co->buffer, 16);
3455  if (r <= 0) goto do_close;
3456  }
3457 
3458  return 0;
3459 }
3460 
3461 
3463 {
3464  ssize_t r;
3465  listen_socket_t *sock = this->data;
3466  fr_cs_buffer_t *co = (void *) sock->packet;
3467  fr_channel_type_t channel;
3468 
3469  rad_assert(co != NULL);
3470 
3471  if (!co->auth) {
3472  uint8_t expected[16];
3473 
3474  r = fr_channel_read(this->fd, &channel, co->buffer, 16);
3475  if ((r != 16) || (channel != FR_CHANNEL_AUTH_RESPONSE)) {
3476  do_close:
3477  command_close_socket(this);
3478  return 0;
3479  }
3480 
3481  fr_hmac_md5(expected, (void const *) sock->client->secret,
3482  strlen(sock->client->secret),
3483  (uint8_t *) co->buffer, 16);
3484 
3485  if (fr_radius_digest_cmp(expected,
3486  (uint8_t *) co->buffer + 16, 16 != 0)) {
3487  ERROR("radmin failed challenge: Closing socket");
3488  goto do_close;
3489  }
3490 
3491  co->auth = true;
3492  co->offset = 0;
3493  }
3494 
3495  return command_domain_recv_co(this, co);
3496 }
3497 
3498 /*
3499  * Should never be called. The functions should just call write().
3500  */
3501 static int command_tcp_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
3502 {
3503  return 0;
3504 }
3505 
3506 static int command_domain_recv(rad_listen_t *listener)
3507 {
3508  fr_command_socket_t *sock = listener->data;
3509 
3510  return command_domain_recv_co(listener, &sock->co);
3511 }
3512 
3514 {
3515  int newfd;
3516  rad_listen_t *this;
3517  socklen_t salen;
3518  struct sockaddr_storage src;
3519  fr_command_socket_t *sock = listener->data;
3520 
3521  salen = sizeof(src);
3522 
3523  DEBUG2(" ... new connection request on command socket");
3524 
3525  newfd = accept(listener->fd, (struct sockaddr *) &src, &salen);
3526  if (newfd < 0) {
3527  /*
3528  * Non-blocking sockets must handle this.
3529  */
3530  if (errno == EWOULDBLOCK) {
3531  return 0;
3532  }
3533 
3534  DEBUG2(" ... failed to accept connection");
3535  return 0;
3536  }
3537 
3538 #ifdef HAVE_GETPEEREID
3539  /*
3540  * Perform user authentication.
3541  */
3542  if (sock->peercred && (sock->uid_name || sock->gid_name)) {
3543  uid_t uid;
3544  gid_t gid;
3545 
3546  if (getpeereid(newfd, &uid, &gid) < 0) {
3547  ERROR("Failed getting peer credentials for %s: %s",
3548  sock->path, fr_syserror(errno));
3549  close(newfd);
3550  return 0;
3551  }
3552 
3553  /*
3554  * Only do UID checking if the caller is
3555  * non-root. The superuser can do anything, so
3556  * we might as well let them.
3557  */
3558  if (uid != 0) do {
3559  /*
3560  * Allow entry if UID or GID matches.
3561  */
3562  if (sock->uid_name && (sock->uid == uid)) break;
3563  if (sock->gid_name && (sock->gid == gid)) break;
3564 
3565  if (sock->uid_name && (sock->uid != uid)) {
3566  ERROR("Unauthorized connection to %s from uid %ld",
3567 
3568  sock->path, (long int) uid);
3569  close(newfd);
3570  return 0;
3571  }
3572 
3573  if (sock->gid_name && (sock->gid != gid)) {
3574  ERROR("Unauthorized connection to %s from gid %ld",
3575  sock->path, (long int) gid);
3576  close(newfd);
3577  return 0;
3578  }
3579 
3580  } while (0);
3581  }
3582 #endif
3583 
3584  if (command_write_magic(newfd, NULL) < 0) {
3585  close(newfd);
3586  return 0;
3587  }
3588 
3589  /*
3590  * Add the new listener.
3591  */
3592  this = listen_alloc(listener, listener->type, listener->proto);
3593  if (!this) return 0;
3594 
3595  /*
3596  * Copy everything, including the pointer to the socket
3597  * information.
3598  */
3599  sock = this->data;
3600  memcpy(this, listener, sizeof(*this));
3601  this->status = RAD_LISTEN_STATUS_INIT;
3602  this->next = NULL;
3603  this->data = sock; /* fix it back */
3604 
3605  sock->magic = COMMAND_SOCKET_MAGIC;
3606  sock->user[0] = '\0';
3607  sock->path = ((fr_command_socket_t *) listener->data)->path;
3608  sock->co.offset = 0;
3609  sock->co.mode = ((fr_command_socket_t *) listener->data)->co.mode;
3610 
3611  this->fd = newfd;
3612  this->recv = command_domain_recv;
3613 
3614  /*
3615  * Tell the event loop that we have a new FD
3616  */
3617  radius_update_listener(this);
3618 
3619  return 0;
3620 }
3621 
3622 
3623 /*
3624  * Send an authentication response packet
3625  */
3627  UNUSED REQUEST *request)
3628 {
3629  return 0;
3630 }
3631 
3632 
3634  UNUSED REQUEST *request)
3635 {
3636  return 0;
3637 }
3638 
3639 
3641  UNUSED REQUEST *request)
3642 {
3643  return 0;
3644 }
3645 
3646 #endif /* WITH_COMMAND_SOCKET */
struct fr_command_socket_t fr_command_socket_t
void rad_suid_down(void)
Definition: util.c:1474
fr_log_t debug_log
Definition: mainconfig.c:49
char const * name
Name the server may be referenced by for querying stats or when specifying home servers for a pool...
Definition: realms.h:71
static int command_stats_socket(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2787
PUBLIC int vsnprintf(char *string, size_t length, char *format, va_list args)
Definition: snprintf.c:503
#define PW_TYPE_FILE_INPUT
File matching value must exist, and must be readable.
Definition: conffile.h:204
#define COMMAND_SOCKET_MAGIC
Definition: command.c:82
static int command_set_home_server_state(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1803
int rad_seuid(uid_t uid)
Alter the effective user id.
Definition: util.c:1491
static int sockfd
Definition: radclient.c:59
#define FR_COND_ONE_PASS
Definition: parser.h:96
fr_stats_t coa
Change of Authorization stats.
Definition: clients.h:64
128 Bit IPv6 Address.
Definition: radius.h:40
static int command_show_config(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:869
time_t last_packet
Definition: stats.h:53
off_t offset
Definition: detail.h:71
int id
Packet ID (used to link requests/responses).
Definition: libradius.h:154
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:265
static void command_socket_free(rad_listen_t *this)
Definition: command.c:3012
int cf_pair_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, FR_TOKEN dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
Definition: conffile.c:1968
void * data
Pointer to a static variable to write the parsed value to.
Definition: conffile.h:278
static int command_show_module_status(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1091
RADCLIENT * client
Definition: listen.h:158
#define FR_MAX_PACKET_CODE
Definition: libradius.h:370
static int command_show_debug_condition(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1633
packetmethod methods[MOD_COUNT]
Pointers to the various section functions.
Definition: modules.h:143
bfd_auth_t auth
Definition: proto_bfd.c:209
fr_uint_t total_packets_dropped
Definition: stats.h:49
Send log messages to a FILE*, via fopencookie()
Definition: log.h:62
Main server configuration.
Definition: radiusd.h:108
static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
Definition: command.c:3120
uint32_t ping_interval
Definition: realms.h:122
static fr_command_table_t command_table_set[]
Definition: command.c:2916
RAD_LISTEN_TYPE type
Definition: listen.h:76
fr_stats_t proxy_acct_stats
Definition: stats.c:53
static FR_NAME_NUMBER state_names[]
Definition: command.c:2582
static int command_socket_open_unix(UNUSED CONF_SECTION *cs, rad_listen_t *this)
Definition: command.c:3092
char const * name
Name of the CONF_ITEM to parse.
Definition: conffile.h:268
module_entry_t * entry
Definition: modpriv.h:67
static int command_stats_memory(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2549
void exec_trigger(REQUEST *request, CONF_SECTION *cs, char const *name, bool quench) CC_HINT(nonnull(3))
Execute a trigger - call an executable to process an event.
Definition: exec.c:686
void mark_home_server_dead(home_server_t *home, struct timeval *when)
Definition: process.c:3652
fr_stats_t stats
Definition: realms.h:143
char const * nas_type
Type of client (arbitrary).
Definition: clients.h:47
Metadata exported by the module.
Definition: modules.h:134
void * cookie
for fopencookie()
Definition: log.h:75
uint32_t lifetime
How long before the client is removed.
Definition: clients.h:80
int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
Definition: listen.c:1274
#define RLM_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition: modules.h:76
uint16_t my_port
Definition: listen.h:122
int fr_inet_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
Wrappers for IPv4/IPv6 host to IP address lookup.
Definition: inet.c:127
int rad_accounting(REQUEST *)
Definition: acct.c:38
uint64_t fr_state_entries_created(fr_state_tree_t *state)
Return number of entries created.
Definition: state.c:624
rad_listen_t * next
Definition: listen.h:70
char const * fr_packet_codes[FR_MAX_PACKET_CODE]
Definition: radius.c:101
static fr_command_table_t command_table_debug[]
Definition: command.c:2164
int type
A PW_TYPE value, may be or'd with one or more PW_TYPE_* flags.
Definition: conffile.h:269
time_t last_packet_recv
Definition: realms.h:107
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: radius.c:1621
module_t const * module
Definition: modpriv.h:54
fr_ipaddr_t src_ipaddr
Src IP address of packet.
Definition: libradius.h:149
static int command_tcp_recv(rad_listen_t *this)
Definition: command.c:3462
fr_stats_t radius_coa_stats
Definition: stats.c:46
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition: inet.h:47
int rad_segid(gid_t gid)
Alter the effective user id.
Definition: util.c:1512
static char const * name
struct fr_cs_buffer_t fr_cs_buffer_t
int(* cookie_write)(void *, char const *, int)
write function
Definition: log.h:79
static fr_command_table_t command_table_set_home[]
Definition: command.c:2894
fr_stats_t dsc
Disconnect-Request stats.
Definition: clients.h:65
static void command_debug_off(void)
Definition: command.c:713
int fd
Definition: listen.h:77
static int command_show_module_flags(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1060
bool client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
Add a client to a RADCLIENT_LIST.
Definition: client.c:192
static fr_command_table_t command_table[]
Definition: command.c:2974
int fr_socket_client_unix(char const *path, bool async)
static int command_show_home_servers(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1155
#define UNUSED
Definition: libradius.h:134
#define PU
Definition: command.c:2478
fr_ipaddr_t src_ipaddr
Definition: command.c:99
static int command_stats_client(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2701
char const * radlog_dir
Definition: radiusd.c:59
char const * filename
Definition: detail.h:59
int(* fr_command_func_t)(rad_listen_t *, int, char *argv[])
Definition: command.c:56
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
module_instance_t * module_find(CONF_SECTION *modules, char const *askedname)
Find an existing module instance.
Definition: modules.c:623
void * request_data_reference(REQUEST *request, void *unique_ptr, int unique_int)
Get opaque data from a request without removing it.
Definition: request.c:484
home_server_t * home_server_bynumber(int number)
Definition: realms.c:2692
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:538
char const * secret
Secret PSK.
Definition: clients.h:43
int rad_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
Resolve a gid to a group database entry.
Definition: util.c:1118
RADCLIENT RADCLIENT * client_find(RADCLIENT_LIST const *clients, fr_ipaddr_t const *ipaddr, int proto)
Definition: client.c:431
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
#define CMD_OK
Definition: command.c:62
fr_stats_t radius_dsc_stats
Definition: stats.c:47
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
fr_stats_t auth
Authentication stats.
Definition: clients.h:59
static int command_terminate(UNUSED rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:850
size_t offset
Relative offset of field or structure to write the parsed value to.
Definition: conffile.h:272
static int dict_str_to_argvX(char *str, char **argv, int max_argc)
Definition: command.c:3177
fr_log_t default_log
Definition: log.c:216
void rad_mode_to_str(char out[10], mode_t mode)
Convert mode_t into humanly readable permissions flags.
Definition: util.c:949
int fr_log_talloc_report(TALLOC_CTX *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition: debug.c:810
unsigned int number
Monotonically increasing request number. Reset on server restart.
Definition: radiusd.h:213
ssize_t fr_channel_read(int fd, fr_channel_type_t *pchannel, void *buffer, size_t buflen)
Definition: channel.c:125
CONF_SECTION * cs
Definition: modpriv.h:72
rad_listen_send_t send
Definition: listen.h:96
#define RLM_TYPE_HUP_SAFE
Will be restarted on HUP.
Definition: modules.h:79
fr_cond_t * debug_condition
Condition used to mark packets up for checking.
Definition: mainconfig.c:48
#define COMMAND_BUFFER_SIZE
Definition: command.c:72
uint16_t dst_port
DST Port of packet.
Definition: libradius.h:152
uint16_t src_port
Src port of packet.
Definition: libradius.h:151
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
Definition: libradius.h:150
static void command_close_socket(rad_listen_t *this)
Definition: command.c:699
fr_uint_t elapsed[8]
Definition: stats.h:54
fr_ipaddr_t my_ipaddr
Definition: listen.h:121
rad_listen_t * listener_find_byipaddr(fr_ipaddr_t const *ipaddr, uint16_t port, int proto)
Find a listener associated with an IP address/port/transport proto.
Definition: listen.c:3302
static int command_debug_file(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1353
#define PW_TYPE_SUBSECTION
Definition: conffile.h:188
int fr_debug_lvl
Definition: misc.c:40
static int command_domain_accept(rad_listen_t *listener)
Definition: command.c:3513
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
int module_hup_module(CONF_SECTION *cs, module_instance_t *node, time_t when)
Definition: modules.c:1624
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
char const * radiusd_version
Definition: radiusd.c:63
fr_stats_t proxy_dsc_stats
Definition: stats.c:57
CONF_PAIR * cf_pair_find(CONF_SECTION const *, char const *name)
Definition: conffile.c:3478
char const * cf_pair_value(CONF_PAIR const *pair)
Definition: conffile.c:3506
char const * command
Definition: command.c:65
static int command_uptime(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:858
int rad_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
Resolve a uid to a passwd entry.
Definition: util.c:984
static char const * proto
Definition: radclient.c:63
static void cprint_conf_parser(rad_listen_t *listener, int indent, CONF_SECTION *cs, void const *base)
Definition: command.c:899
Authentication and accounting server.
Definition: realms.h:38
char const * mode_name
Definition: command.c:91
const FR_NAME_NUMBER mod_rcode_table[]
Definition: modcall.c:186
int af
Address family.
Definition: inet.h:42
fr_channel_type_t
Definition: channel.h:32
int rad_getgid(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition: util.c:1248
#define rad_assert(expr)
Definition: rad_assert.h:38
RFC2865 - Access-Request.
Definition: radius.h:92
char const * help
Definition: command.c:67
static int command_write_magic(int newfd, listen_socket_t *sock)
Definition: command.c:3415
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
Definition: token.c:451
char user[256]
Definition: command.c:93
const CONF_PARSER * cf_section_parse_table(CONF_SECTION *cs)
Definition: conffile.c:4138
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
#define pthread_mutex_unlock(_x)
Definition: rlm_eap.h:78
#define FR_WRITE
Definition: command.c:59
static char const tabs[]
Definition: command.c:894
static fr_command_table_t command_table_show[]
Definition: command.c:2298
int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
Replace pair in a given section with a new pair, of the given value.
Definition: conffile.c:768
static int command_domain_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: command.c:3626
RADCLIENT * client_read(char const *filename, int in_server, int flag)
Definition: client.c:1449
static int command_debug_level(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1277
#define DEBUG(fmt,...)
Definition: log.h:175
int(* RAD_REQUEST_FUNP)(REQUEST *)
Definition: process.h:51
void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *text, size_t text_len, uint8_t const *key, size_t key_len) CC_BOUNDED(__minbytes__
bool debug_memory
Cleanup the server properly on exit, freeing up any memory we allocated.
Definition: radiusd.h:156
static int command_socket_decode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: command.c:3640
static rc_stats_t stats
Definition: radclient.c:47
CONF_SECTION * cf_subsection_find_next(CONF_SECTION const *section, CONF_SECTION const *subsection, char const *name1)
Definition: conffile.c:3799
static char spaces[]
Definition: proto.c:28
static FR_NAME_NUMBER mode_names[]
Definition: command.c:117
int rad_authenticate(REQUEST *)
Definition: auth.c:348
#define DEBUG2(fmt,...)
Definition: log.h:176
RFC2866 - Accounting-Request.
Definition: radius.h:95
static int command_del_client(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2831
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *item)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: conffile.c:181
RADIUS_PACKET * fr_radius_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new RADIUS_PACKET.
Definition: radius.c:1651
int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables)
Parse a configuration section into user-supplied variables.
Definition: conffile.c:2234
rad_listen_t * inject_listener
Definition: command.c:102
union fr_ipaddr_t::@1 ipaddr
unsigned int code
Packet code (type).
Definition: libradius.h:155
fr_stats_t stats
Definition: listen.h:106
static fr_command_table_t command_table_del_client[]
Definition: command.c:2857
fr_cs_buffer_t co
Definition: command.c:105
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition: clients.h:36
static int command_show_version(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1271
static rad_listen_t * listen_alloc(TALLOC_CTX *ctx, RAD_LISTEN_TYPE type, fr_protocol_t *proto)
Definition: listen.c:2898
int common_socket_open(CONF_SECTION *cs, rad_listen_t *this)
Definition: listen.c:1599
fr_stats_t proxy_auth_stats
Definition: stats.c:51
static int command_show_modules(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1124
Definition: log.h:68
char const * path
Definition: command.c:85
static fr_command_table_t command_table_set_module[]
Definition: command.c:2903
static int command_tcp_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: command.c:3501
static int command_socket_open(CONF_SECTION *cs, rad_listen_t *this)
Definition: command.c:3150
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
Resolve a username to a passwd entry.
Definition: util.c:1051
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
static int command_socket_encode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: command.c:3633
uint32_t fr_state_entries_tracked(fr_state_tree_t *state)
Return number of entries we're currently tracking.
Definition: state.c:640
void void cf_log_err_cs(CONF_SECTION const *cs, char const *fmt,...) CC_HINT(format(printf
bool cf_item_is_pair(CONF_ITEM const *item)
Definition: conffile.c:3928
static fr_command_table_t command_table_show_module[]
Definition: command.c:2227
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:272
A truth value.
Definition: radius.h:56
CoA destination (NAS or Proxy)
Definition: realms.h:41
static int command_show_home_server_state(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1835
Configuration AVP similar to a VALUE_PAIR.
Definition: conffile.c:82
void rad_suid_up(void)
Definition: util.c:1471
static int fr_server_domain_socket_perm(UNUSED char const *path, UNUSED uid_t uid, UNUSED gid_t gid)
Definition: command.c:327
rlm_rcode_t code
Definition: modpriv.h:76
static fr_command_table_t command_table_show_debug[]
Definition: command.c:2211
bool memory_report
Print a memory report on what's left unfreed.
Definition: radiusd.h:158
32 Bit unsigned integer.
Definition: radius.h:34
fr_ipaddr_t dst_ipaddr
Definition: command.c:100
static int null_socket_dencode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
Definition: command.c:1871
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
ssize_t next
Definition: command.c:78
CONF_SECTION * cf_section_sub_find(CONF_SECTION const *, char const *name)
Find a sub-section in a section.
Definition: conffile.c:3708
char const * file
Path to log file.
Definition: log.h:73
fr_uint_t total_responses
Definition: stats.h:43
static int command_stats_state(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:2519
char buffer[COMMAND_BUFFER_SIZE]
Definition: command.c:79
char const * cf_section_name1(CONF_SECTION const *cs)
Definition: conffile.c:3592
10 how many components there are.
Definition: modules.h:53
static rad_listen_t * get_socket(rad_listen_t *listener, int argc, char *argv[], int *last)
Definition: command.c:1928
int request_receive(TALLOC_CTX *ctx, rad_listen_t *listener, RADIUS_PACKET *packet, RADCLIENT *client, RAD_REQUEST_FUNP fun)
Definition: process.c:1523
static char const * method_names[MOD_COUNT]
Definition: command.c:1017
static fr_command_table_t command_table_add[]
Definition: command.c:2884
Log to a file on disk.
Definition: log.h:59
Describes a host allowed to send packets to the server.
Definition: clients.h:35
static fr_command_table_t command_table_inject[]
Definition: command.c:2148
unsigned int state
Definition: proto_bfd.c:200
static char const * elapsed_names[8]
Definition: command.c:2463
char const * gid_name
Definition: command.c:90
uint32_t dynamic
Whether the client was dynamically defined.
Definition: clients.h:81
uint8_t data[]
Definition: eap_pwd.h:625
fr_uint_t total_dup_requests
Definition: stats.h:42
static int command_show_module_config(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:993
static int command_stats_detail(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2595
Module failed, don't reply.
Definition: radiusd.h:90
static int command_domain_recv(rad_listen_t *listener)
Definition: command.c:3506
fr_stats_t radius_acct_stats
Definition: stats.c:43
rad_listen_decode_t decode
Definition: listen.h:98
static fr_ipaddr_t server_ipaddr
Definition: radclient.c:51
RADCLIENT * client_findbynumber(RADCLIENT_LIST const *clients, int number)
Definition: client.c:402
static int command_show_debug_file(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1650
CONF_SECTION * config
Root of the server config.
Definition: radiusd.h:110
char const * filename_work
Definition: detail.h:60
static home_server_t * get_home_server(rad_listen_t *listener, int argc, char *argv[], int *last)
Definition: command.c:1747
#define PW_TYPE_FILE_OUTPUT
File matching value must exist, and must be writeable.
Definition: conffile.h:205
static const void * fake
Definition: rlm_sql_null.c:33
static int command_show_module_methods(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1029
void * insthandle
Definition: modpriv.h:68
static fr_command_table_t command_table_show_home[]
Definition: command.c:2256
static fr_command_table_t command_table_show_client[]
Definition: command.c:2247
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
size_t fr_cond_snprint(char *buffer, size_t bufsize, fr_cond_t const *c)
Definition: parser.c:50
void thread_pool_queue_stats(int array[RAD_LISTEN_MAX], int pps[2])
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
Definition: cursor.c:263
static int command_add_client_file(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2803
int fr_pair_list_afrom_file(TALLOC_CTX *ctx, VALUE_PAIR **out, FILE *fp, bool *pfiledone)
Definition: pair.c:1333
void fr_radius_free(RADIUS_PACKET **)
Free a RADIUS_PACKET.
Definition: radius.c:1727
void radius_signal_self(int flag)
Definition: process.c:5132
int state
Definition: realms.h:113
fr_uint_t total_access_accepts
Definition: stats.h:44
ssize_t fr_channel_write(int fd, fr_channel_type_t channel, void const *buffer, size_t buflen)
Definition: channel.c:205
int type
One or more of the RLM_TYPE_* constants.
Definition: modules.h:137
void void void fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
Definition: log.c:359
fr_uint_t total_access_challenges
Definition: stats.h:46
fr_command_table_t * table
Definition: command.c:69
ssize_t fr_channel_drain(int fd, fr_channel_type_t *pchannel, void *inbuf, size_t buflen, uint8_t **outbuf, size_t have_read)
Definition: channel.c:61
ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, fr_cond_t **head, char const **error, int flag)
Tokenize a conditional check.
Definition: parser.c:1711
int request_data_add(REQUEST *request, void *unique_ptr, int unique_int, void *opaque, bool free_on_replace, bool free_on_parent, bool persist)
Add opaque data to a REQUEST.
Definition: request.c:279
fr_uint_t total_timeouts
Definition: stats.h:52
static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
Definition: command.c:3033
#define WARN(fmt,...)
Definition: log.h:144
static char debug_log_file_buffer[1024]
Definition: command.c:125
int status
Definition: listen.h:79
static int command_show_clients(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1239
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
static int command_set_module_config(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2332
RADIUS_PACKET * packet
Definition: listen.h:160
int fr_radius_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL digest.
Definition: radius.c:578
uint32_t currently_outstanding
Definition: realms.h:104
#define FR_READ
Definition: command.c:58
#define CMD_FAIL
Definition: command.c:61
rad_listen_t * listen
Head of a linked list of listeners.
Definition: radiusd.h:147
static int command_set_module_status(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2419
RADCLIENT * inject_client
Definition: command.c:103
fr_uint_t total_invalid_requests
Definition: stats.h:41
RADCLIENT * client_listener_find(rad_listen_t *listener, fr_ipaddr_t const *ipaddr, uint16_t src_port)
Definition: listen.c:344
size_t fr_pair_snprint(char *out, size_t outlen, VALUE_PAIR const *vp)
Print one attribute and value to a string.
Definition: pair.c:2189
static bool filedone
Definition: unittest.c:46
Discard log messages.
Definition: log.h:63
static int command_hup(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:804
uint16_t dst_port
Definition: command.c:101
fr_uint_t total_malformed_requests
Definition: stats.h:47
#define MAX_ARGV
Definition: command.c:3273
static int command_socket_print(rad_listen_t const *this, char *buffer, size_t bufsize)
Definition: command.c:3160
#define pthread_mutex_lock(_x)
Definition: rlm_eap.h:77
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
uint64_t fr_state_entries_timeout(fr_state_tree_t *state)
Return number of entries that timed out.
Definition: state.c:632
fr_stats_t acct
Accounting stats.
Definition: clients.h:61
IPv4/6 prefix.
Definition: inet.h:41
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
Definition: token.c:506
static int command_stats_home_server(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2651
static int command_inject_file(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:2025
fr_stats_t proxy_coa_stats
Definition: stats.c:56
static int command_domain_recv_co(rad_listen_t *listener, fr_cs_buffer_t *co)
Definition: command.c:3281
static int fr_server_domain_socket_peercred(char const *path, uid_t UNUSED uid, UNUSED gid_t gid)
Initialise a socket for use with peercred authentication.
Definition: command.c:164
void rad_mode_to_oct(char out[5], mode_t mode)
Definition: util.c:962
void * data
Definition: listen.h:103
log_dst_t dst
Log destination.
Definition: log.h:72
home_server_t * home_server_find(fr_ipaddr_t *ipaddr, uint16_t port, int proto)
Definition: realms.c:2660
detail_state_t state
Definition: detail.h:72
String of printable characters.
Definition: radius.h:33
static int command_print_stats(rad_listen_t *listener, fr_stats_t *stats, int auth, int server)
Definition: command.c:2482
Log to stdout.
Definition: log.h:58
static int command_inject_to(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1973
fr_uint_t total_access_rejects
Definition: stats.h:45
static ssize_t CC_HINT(format(printf, 2, 3))
Definition: command.c:762
fr_stats_t radius_auth_stats
Definition: stats.c:41
char const * server
Virtual server client is associated with.
Definition: clients.h:52
fr_uint_t total_unknown_types
Definition: stats.h:51
Accounting server.
Definition: realms.h:37
void radius_update_listener(rad_listen_t *listener)
Definition: process.c:336
time_t fr_start_time
Definition: process.c:52
static int r
Definition: rbmonkey.c:66
char const * fr_inet_ntoh(fr_ipaddr_t const *src, char *out, size_t outlen)
Perform reverse resolution of an IP address.
Definition: inet.c:226
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
Definition: missing.c:588
fr_command_func_t func
Definition: command.c:68
32 Bit IPv4 Address.
Definition: radius.h:35
home_type_t type
Auth, Acct, CoA etc.
Definition: realms.h:82
uint32_t magic
Definition: command.c:84
RADCLIENT_LIST * listener_find_client_list(fr_ipaddr_t const *ipaddr, uint16_t port, int proto)
Find client list associated with a listener.
Definition: listen.c:3264
void revive_home_server(void *ctx, struct timeval *now)
static int command_inject_from(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1992
uint16_t port
Definition: realms.h:79
static fr_command_table_t command_table_del[]
Definition: command.c:2866
#define RDEBUG(fmt,...)
Definition: log.h:243
static int command_show_debug_level(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
Definition: command.c:1660
static int command_debug_condition(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1393
fr_uint_t total_bad_authenticators
Definition: stats.h:48
int proto
TCP or UDP.
Definition: realms.h:91
int common_socket_print(rad_listen_t const *this, char *buffer, size_t bufsize)
Definition: listen.c:1021
static fr_command_table_t command_table_add_client[]
Definition: command.c:2875
#define ERROR(fmt,...)
Definition: log.h:145
fr_state_tree_t * global_state
Definition: state.c:87
fr_protocol_t * proto
Definition: listen.h:71
static void print_help(rad_listen_t *listener, int argc, char *argv[], fr_command_table_t *table, int recursive)
Definition: command.c:3235
fr_uint_t total_requests
Definition: stats.h:40
Authentication server.
Definition: realms.h:36
fr_ipaddr_t ipaddr
IP address of home server.
Definition: realms.h:78
ssize_t offset
Definition: command.c:77
char const * uid_name
Definition: command.c:89
char const * cf_section_name2(CONF_SECTION const *cs)
Definition: conffile.c:3601
static fr_command_table_t command_table_stats[]
Definition: command.c:2931
rad_listen_encode_t encode
Definition: listen.h:97
static RADCLIENT * get_client(rad_listen_t *listener, int argc, char *argv[])
Definition: command.c:1669
char const * shortname
Client nickname.
Definition: clients.h:41
static int null_socket_send(UNUSED rad_listen_t *listener, REQUEST *request)
Definition: command.c:1876
static const CONF_PARSER command_config[]
Definition: command.c:108
static uint16_t server_port
Definition: radclient.c:49
void hup_logfile(void)
Definition: mainconfig.c:1074
void client_free(RADCLIENT *client)
Definition: client.c:62
CONF_ITEM * cf_reference_item(CONF_SECTION const *parentcs, CONF_SECTION *outercs, char const *ptr)
Definition: conffile.c:906