"Fossies" - the Fresh Open Source Software Archive

Member "freeradius-server-3.0.23/src/main/command.c" (10 Jun 2021, 82314 Bytes) of package /linux/misc/freeradius-server-3.0.23.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "command.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.0.22_vs_3.0.23.

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