close open FDs on error, and use error path in more situations
[freeradius.git] / src / main / command.c
1 /*
2  * command.c    Command socket processing.
3  *
4  * Version:     $Id$
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 int command_show_module_config(rad_listen_t *listener, int argc, char *argv[])
930 {
931         CONF_SECTION *cs;
932         module_instance_t *mi;
933
934         if (argc != 1) {
935                 cprintf_error(listener, "No module name was given\n");
936                 return CMD_FAIL;
937         }
938
939         cs = cf_section_find("modules");
940         if (!cs) return CMD_FAIL;
941
942         mi = module_find(cs, argv[0]);
943         if (!mi) {
944                 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
945                 return CMD_FAIL;
946         }
947
948         cprint_conf_parser(listener, 0, mi->cs, mi->insthandle);
949
950         return CMD_OK;
951 }
952
953 static char const *method_names[MOD_COUNT] = {
954         "authenticate",
955         "authorize",
956         "preacct",
957         "accounting",
958         "session",
959         "pre-proxy",
960         "post-proxy",
961         "post-auth"
962 };
963
964
965 static int command_show_module_methods(rad_listen_t *listener, int argc, char *argv[])
966 {
967         int i;
968         CONF_SECTION *cs;
969         module_instance_t const *mi;
970         module_t const *mod;
971
972         if (argc != 1) {
973                 cprintf_error(listener, "No module name was given\n");
974                 return CMD_FAIL;
975         }
976
977         cs = cf_section_find("modules");
978         if (!cs) return CMD_FAIL;
979
980         mi = module_find(cs, argv[0]);
981         if (!mi) {
982                 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
983                 return CMD_FAIL;
984         }
985
986         mod = mi->entry->module;
987
988         for (i = 0; i < MOD_COUNT; i++) {
989                 if (mod->methods[i]) cprintf(listener, "%s\n", method_names[i]);
990         }
991
992         return CMD_OK;
993 }
994
995
996 static int command_show_module_flags(rad_listen_t *listener, int argc, char *argv[])
997 {
998         CONF_SECTION *cs;
999         module_instance_t const *mi;
1000         module_t const *mod;
1001
1002         if (argc != 1) {
1003                 cprintf_error(listener, "No module name was given\n");
1004                 return CMD_FAIL;
1005         }
1006
1007         cs = cf_section_find("modules");
1008         if (!cs) return CMD_FAIL;
1009
1010         mi = module_find(cs, argv[0]);
1011         if (!mi) {
1012                 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1013                 return CMD_FAIL;
1014         }
1015
1016         mod = mi->entry->module;
1017
1018         if ((mod->type & RLM_TYPE_THREAD_UNSAFE) != 0)
1019                 cprintf(listener, "thread-unsafe\n");
1020
1021         if ((mod->type & RLM_TYPE_HUP_SAFE) != 0)
1022                 cprintf(listener, "reload-on-hup\n");
1023
1024         return CMD_OK;
1025 }
1026
1027 static int command_show_module_status(rad_listen_t *listener, int argc, char *argv[])
1028 {
1029         CONF_SECTION *cs;
1030         const module_instance_t *mi;
1031
1032         if (argc != 1) {
1033                 cprintf_error(listener, "No module name was given\n");
1034                 return CMD_FAIL;
1035         }
1036
1037         cs = cf_section_find("modules");
1038         if (!cs) return CMD_FAIL;
1039
1040         mi = module_find(cs, argv[0]);
1041         if (!mi) {
1042                 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
1043                 return CMD_FAIL;
1044         }
1045
1046         if (!mi->force) {
1047                 cprintf(listener, "alive\n");
1048         } else {
1049                 cprintf(listener, "%s\n", fr_int2str(mod_rcode_table, mi->code, "<invalid>"));
1050         }
1051
1052
1053         return CMD_OK;
1054 }
1055
1056
1057 /*
1058  *      Show all loaded modules
1059  */
1060 static int command_show_modules(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1061 {
1062         CONF_SECTION *cs, *subcs;
1063
1064         cs = cf_section_find("modules");
1065         if (!cs) return CMD_FAIL;
1066
1067         subcs = NULL;
1068         while ((subcs = cf_subsection_find_next(cs, subcs, NULL)) != NULL) {
1069                 char const *name1 = cf_section_name1(subcs);
1070                 char const *name2 = cf_section_name2(subcs);
1071
1072                 module_instance_t *mi;
1073
1074                 if (name2) {
1075                         mi = module_find(cs, name2);
1076                         if (!mi) continue;
1077
1078                         cprintf(listener, "%s (%s)\n", name2, name1);
1079                 } else {
1080                         mi = module_find(cs, name1);
1081                         if (!mi) continue;
1082
1083                         cprintf(listener, "%s\n", name1);
1084                 }
1085         }
1086
1087         return CMD_OK;
1088 }
1089
1090 #ifdef WITH_PROXY
1091 static int command_show_home_servers(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1092 {
1093         int i;
1094         home_server_t *home;
1095         char const *type, *state, *proto;
1096
1097         char buffer[256];
1098
1099         for (i = 0; i < 256; i++) {
1100                 home = home_server_bynumber(i);
1101                 if (!home) break;
1102
1103                 /*
1104                  *      Internal "virtual" home server.
1105                  */
1106                 if (home->ipaddr.af == AF_UNSPEC) continue;
1107
1108                 if (home->type == HOME_TYPE_AUTH) {
1109                         type = "auth";
1110
1111                 } else if (home->type == HOME_TYPE_ACCT) {
1112                         type = "acct";
1113
1114                 } else if (home->type == HOME_TYPE_AUTH_ACCT) {
1115                         type = "auth+acct";
1116
1117 #ifdef WITH_COA
1118                 } else if (home->type == HOME_TYPE_COA) {
1119                         type = "coa";
1120 #endif
1121
1122                 } else continue;
1123
1124                 if (home->proto == IPPROTO_UDP) {
1125                         proto = "udp";
1126                 }
1127 #ifdef WITH_TCP
1128                 else if (home->proto == IPPROTO_TCP) {
1129                         proto = "tcp";
1130                 }
1131 #endif
1132                 else proto = "??";
1133
1134                 if (home->state == HOME_STATE_ALIVE) {
1135                         state = "alive";
1136
1137                 } else if (home->state == HOME_STATE_ZOMBIE) {
1138                         state = "zombie";
1139
1140                 } else if (home->state == HOME_STATE_IS_DEAD) {
1141                         state = "dead";
1142
1143                 } else if (home->state == HOME_STATE_UNKNOWN) {
1144                         time_t now = time(NULL);
1145
1146                         /*
1147                          *      We've recently received a packet, so
1148                          *      the home server seems to be alive.
1149                          *
1150                          *      The *reported* state changes because
1151                          *      the internal state machine NEEDS THE
1152                          *      RIGHT STATE.  However, reporting that
1153                          *      to the admin will confuse them.
1154                          *      So... we lie.  No, that dress doesn't
1155                          *      make you look fat...
1156                          */
1157                         if ((home->last_packet_recv + (int)home->ping_interval) >= now) {
1158                                 state = "alive";
1159                         } else {
1160                                 state = "unknown";
1161                         }
1162
1163                 } else continue;
1164
1165                 cprintf(listener, "%s\t%d\t%s\t%s\t%s\t%d\n",
1166                         ip_ntoh(&home->ipaddr, buffer, sizeof(buffer)),
1167                         home->port, proto, type, state,
1168                         home->currently_outstanding);
1169         }
1170
1171         return CMD_OK;
1172 }
1173 #endif
1174
1175 static int command_show_clients(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1176 {
1177         int i;
1178         RADCLIENT *client;
1179         char buffer[256];
1180
1181         for (i = 0; i < 256; i++) {
1182                 client = client_findbynumber(NULL, i);
1183                 if (!client) break;
1184
1185                 ip_ntoh(&client->ipaddr, buffer, sizeof(buffer));
1186
1187                 if (((client->ipaddr.af == AF_INET) &&
1188                      (client->ipaddr.prefix != 32)) ||
1189                     ((client->ipaddr.af == AF_INET6) &&
1190                      (client->ipaddr.prefix != 128))) {
1191                         cprintf(listener, "%s/%d\n", buffer, client->ipaddr.prefix);
1192                 } else {
1193                         cprintf(listener, "%s\n", buffer);
1194                 }
1195         }
1196
1197         return CMD_OK;
1198 }
1199
1200
1201 static int command_show_version(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
1202 {
1203         cprintf(listener, "%s\n", radiusd_version);
1204         return CMD_OK;
1205 }
1206
1207 static int command_debug_level(rad_listen_t *listener, int argc, char *argv[])
1208 {
1209         int number;
1210
1211         if (argc == 0) {
1212                 cprintf_error(listener, "Must specify <number>\n");
1213                 return -1;
1214         }
1215
1216         number = atoi(argv[0]);
1217         if ((number < 0) || (number > 4)) {
1218                 cprintf_error(listener, "<number> must be between 0 and 4\n");
1219                 return -1;
1220         }
1221
1222         fr_debug_lvl = rad_debug_lvl = number;
1223
1224         return CMD_OK;
1225 }
1226
1227 static char debug_log_file_buffer[1024];
1228
1229 static int command_debug_file(rad_listen_t *listener, int argc, char *argv[])
1230 {
1231         if (rad_debug_lvl && default_log.dst == L_DST_STDOUT) {
1232                 cprintf_error(listener, "Cannot redirect debug logs to a file when already in debugging mode.\n");
1233                 return -1;
1234         }
1235
1236         if ((argc > 0) && (strchr(argv[0], FR_DIR_SEP) != NULL)) {
1237                 cprintf_error(listener, "Cannot direct debug logs to absolute path.\n");
1238         }
1239
1240         default_log.debug_file = NULL;
1241
1242         if (argc == 0) return CMD_OK;
1243
1244         /*
1245          *      This looks weird, but it's here to avoid locking
1246          *      a mutex for every log message.
1247          */
1248         memset(debug_log_file_buffer, 0, sizeof(debug_log_file_buffer));
1249
1250         /*
1251          *      Debug files always go to the logging directory.
1252          */
1253         snprintf(debug_log_file_buffer, sizeof(debug_log_file_buffer),
1254                  "%s/%s", radlog_dir, argv[0]);
1255
1256         default_log.debug_file = &debug_log_file_buffer[0];
1257
1258         return CMD_OK;
1259 }
1260
1261 extern fr_cond_t *debug_condition;
1262 static int command_debug_condition(rad_listen_t *listener, int argc, char *argv[])
1263 {
1264         int i;
1265         char const *error;
1266         ssize_t slen = 0;
1267         fr_cond_t *new_condition = NULL;
1268         char *p, buffer[1024];
1269
1270         /*
1271          *      Disable it.
1272          */
1273         if (argc == 0) {
1274                 TALLOC_FREE(debug_condition);
1275                 debug_condition = NULL;
1276                 return CMD_OK;
1277         }
1278
1279         if (!((argc == 1) &&
1280               ((argv[0][0] == '"') || (argv[0][0] == '\'')))) {
1281                 p = buffer;
1282                 *p = '\0';
1283                 for (i = 0; i < argc; i++) {
1284                         size_t len;
1285
1286                         len = strlcpy(p, argv[i], buffer + sizeof(buffer) - p);
1287                         p += len;
1288                         *(p++) = ' ';
1289                         *p = '\0';
1290                 }
1291
1292         } else {
1293                 /*
1294                  *      Backwards compatibility.  De-escape the string.
1295                  */
1296                 char quote;
1297                 char *q;
1298
1299                 p = argv[0];
1300                 q = buffer;
1301
1302                 quote = *(p++);
1303
1304                 while (true) {
1305                         if (!*p) {
1306                                 error = "Unexpected end of string";
1307                                 slen = -strlen(argv[0]);
1308                                 p = argv[0];
1309
1310                                 goto parse_error;
1311                         }
1312
1313                         if (*p == quote) {
1314                                 if (p[1]) {
1315                                         error = "Unexpected text after end of string";
1316                                         slen = -(p - argv[0]);
1317                                         p = argv[0];
1318
1319                                         goto parse_error;
1320                                 }
1321                                 *q = '\0';
1322                                 break;
1323                         }
1324
1325                         if (*p == '\\') {
1326                                 *(q++) = p[1];
1327                                 p += 2;
1328                                 continue;
1329                         }
1330
1331                         *(q++) = *(p++);
1332                 }
1333         }
1334
1335         p = buffer;
1336
1337         slen = fr_condition_tokenize(NULL, NULL, p, &new_condition, &error, FR_COND_ONE_PASS);
1338         if (slen <= 0) {
1339                 char *spaces, *text;
1340
1341         parse_error:
1342                 fr_canonicalize_error(NULL, &spaces, &text, slen, p);
1343
1344                 ERROR("Parse error in condition");
1345                 ERROR("%s", p);
1346                 ERROR("%s^ %s", spaces, error);
1347
1348                 cprintf_error(listener, "Parse error in condition \"%s\": %s\n", p, error);
1349
1350                 talloc_free(spaces);
1351                 talloc_free(text);
1352                 return CMD_FAIL;
1353         }
1354
1355         (void) modcall_pass2_condition(new_condition);
1356
1357         /*
1358          *      Delete old condition.
1359          *
1360          *      This is thread-safe because the condition is evaluated
1361          *      in the main server thread, along with this code.
1362          */
1363         TALLOC_FREE(debug_condition);
1364         debug_condition = new_condition;
1365
1366         return CMD_OK;
1367 }
1368
1369 static int command_show_debug_condition(rad_listen_t *listener,
1370                                         UNUSED int argc, UNUSED char *argv[])
1371 {
1372         char buffer[1024];
1373
1374         if (!debug_condition) {
1375                 cprintf(listener, "\n");
1376                 return CMD_OK;
1377         }
1378
1379         fr_cond_sprint(buffer, sizeof(buffer), debug_condition);
1380
1381         cprintf(listener, "%s\n", buffer);
1382         return CMD_OK;
1383 }
1384
1385
1386 static int command_show_debug_file(rad_listen_t *listener,
1387                                         UNUSED int argc, UNUSED char *argv[])
1388 {
1389         if (!default_log.debug_file) return CMD_FAIL;
1390
1391         cprintf(listener, "%s\n", default_log.debug_file);
1392         return CMD_OK;
1393 }
1394
1395
1396 static int command_show_debug_level(rad_listen_t *listener,
1397                                         UNUSED int argc, UNUSED char *argv[])
1398 {
1399         cprintf(listener, "%d\n", rad_debug_lvl);
1400         return CMD_OK;
1401 }
1402
1403
1404 static RADCLIENT *get_client(rad_listen_t *listener, int argc, char *argv[])
1405 {
1406         RADCLIENT *client;
1407         fr_ipaddr_t ipaddr;
1408         int myarg;
1409         int proto = IPPROTO_UDP;
1410         RADCLIENT_LIST *list = NULL;
1411
1412         if (argc < 1) {
1413                 cprintf_error(listener, "Must specify <ipaddr>\n");
1414                 return NULL;
1415         }
1416
1417         /*
1418          *      First arg is IP address.
1419          */
1420         if (ip_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1421                 cprintf_error(listener, "Failed parsing IP address; %s\n",
1422                         fr_strerror());
1423                 return NULL;
1424         }
1425         myarg = 1;
1426
1427         while (myarg < argc) {
1428                 if (strcmp(argv[myarg], "udp") == 0) {
1429                         proto = IPPROTO_UDP;
1430                         myarg++;
1431                         continue;
1432                 }
1433
1434 #ifdef WITH_TCP
1435                 if (strcmp(argv[myarg], "tcp") == 0) {
1436                         proto = IPPROTO_TCP;
1437                         myarg++;
1438                         continue;
1439                 }
1440 #endif
1441
1442                 if (strcmp(argv[myarg], "listen") == 0) {
1443                         uint16_t server_port;
1444                         fr_ipaddr_t server_ipaddr;
1445
1446                         if ((argc - myarg) < 2) {
1447                                 cprintf_error(listener, "Must specify listen <ipaddr> <port>\n");
1448                                 return NULL;
1449                         }
1450
1451                         if (ip_hton(&server_ipaddr, ipaddr.af, argv[myarg + 1], false) < 0) {
1452                                 cprintf_error(listener, "Failed parsing IP address; %s\n",
1453                                               fr_strerror());
1454                                 return NULL;
1455                         }
1456
1457                         server_port = atoi(argv[myarg + 2]);
1458
1459                         list = listener_find_client_list(&server_ipaddr, server_port, proto);
1460                         if (!list) {
1461                                 cprintf_error(listener, "No such listener %s %s\n", argv[myarg + 1], argv[myarg + 2]);
1462                                 return NULL;
1463                         }
1464                         myarg += 3;
1465                         continue;
1466                 }
1467
1468                 cprintf_error(listener, "Unknown argument %s.\n", argv[myarg]);
1469                 return NULL;
1470         }
1471
1472         client = client_find(list, &ipaddr, proto);
1473         if (!client) {
1474                 cprintf_error(listener, "No such client\n");
1475                 return NULL;
1476         }
1477
1478         return client;
1479 }
1480
1481 #ifdef WITH_PROXY
1482 static home_server_t *get_home_server(rad_listen_t *listener, int argc,
1483                                     char *argv[], int *last)
1484 {
1485         int myarg;
1486         home_server_t *home;
1487         uint16_t port;
1488         int proto = IPPROTO_UDP;
1489         fr_ipaddr_t ipaddr;
1490
1491         if (argc < 2) {
1492                 cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp]\n");
1493                 return NULL;
1494         }
1495
1496         if (ip_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1497                 cprintf_error(listener, "Failed parsing IP address; %s\n",
1498                         fr_strerror());
1499                 return NULL;
1500         }
1501
1502         port = atoi(argv[1]);
1503
1504         myarg = 2;
1505
1506         while (myarg < argc) {
1507                 if (strcmp(argv[myarg], "udp") == 0) {
1508                         proto = IPPROTO_UDP;
1509                         myarg++;
1510                         continue;
1511                 }
1512
1513 #ifdef WITH_TCP
1514                 if (strcmp(argv[myarg], "tcp") == 0) {
1515                         proto = IPPROTO_TCP;
1516                         myarg++;
1517                         continue;
1518                 }
1519 #endif
1520
1521                 /*
1522                  *      Unknown argument.  Leave it for the caller.
1523                  */
1524                 break;
1525         }
1526
1527         home = home_server_find(&ipaddr, port, proto);
1528         if (!home) {
1529                 cprintf_error(listener, "No such home server\n");
1530                 return NULL;
1531         }
1532
1533         if (last) *last = myarg;
1534
1535         return home;
1536 }
1537
1538 static int command_set_home_server_state(rad_listen_t *listener, int argc, char *argv[])
1539 {
1540         int last;
1541         home_server_t *home;
1542
1543         if (argc < 3) {
1544                 cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp] <state>\n");
1545                 return CMD_FAIL;
1546         }
1547
1548         home = get_home_server(listener, argc, argv, &last);
1549         if (!home) {
1550                 return CMD_FAIL;
1551         }
1552
1553         if (strcmp(argv[last], "alive") == 0) {
1554                 revive_home_server(home);
1555
1556         } else if (strcmp(argv[last], "dead") == 0) {
1557                 struct timeval now;
1558
1559                 gettimeofday(&now, NULL); /* we do this WAY too ofetn */
1560                 mark_home_server_dead(home, &now);
1561
1562         } else {
1563                 cprintf_error(listener, "Unknown state \"%s\"\n", argv[last]);
1564                 return CMD_FAIL;
1565         }
1566
1567         return CMD_OK;
1568 }
1569
1570 static int command_show_home_server_state(rad_listen_t *listener, int argc, char *argv[])
1571 {
1572         home_server_t *home;
1573
1574         home = get_home_server(listener, argc, argv, NULL);
1575         if (!home) return CMD_FAIL;
1576
1577         switch (home->state) {
1578         case HOME_STATE_ALIVE:
1579                 cprintf(listener, "alive\n");
1580                 break;
1581
1582         case HOME_STATE_IS_DEAD:
1583                 cprintf(listener, "dead\n");
1584                 break;
1585
1586         case HOME_STATE_ZOMBIE:
1587                 cprintf(listener, "zombie\n");
1588                 break;
1589
1590         case HOME_STATE_UNKNOWN:
1591                 cprintf(listener, "unknown\n");
1592                 break;
1593
1594         default:
1595                 cprintf(listener, "invalid\n");
1596                 break;
1597         }
1598
1599         return CMD_OK;
1600 }
1601 #endif
1602
1603 /*
1604  *      For encode/decode stuff
1605  */
1606 static int null_socket_dencode(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
1607 {
1608         return 0;
1609 }
1610
1611 static int null_socket_send(UNUSED rad_listen_t *listener, REQUEST *request)
1612 {
1613         vp_cursor_t cursor;
1614         char *output_file;
1615         FILE *fp;
1616
1617         output_file = request_data_reference(request, (void *)null_socket_send, 0);
1618         if (!output_file) {
1619                 ERROR("No output file for injected packet %d", request->number);
1620                 return 0;
1621         }
1622
1623         fp = fopen(output_file, "w");
1624         if (!fp) {
1625                 ERROR("Failed to send injected file to %s: %s", output_file, fr_syserror(errno));
1626                 return 0;
1627         }
1628
1629         if (request->reply->code != 0) {
1630                 char const *what = "reply";
1631                 VALUE_PAIR *vp;
1632                 char buffer[1024];
1633
1634                 if (request->reply->code < FR_MAX_PACKET_CODE) {
1635                         what = fr_packet_codes[request->reply->code];
1636                 }
1637
1638                 fprintf(fp, "%s\n", what);
1639
1640                 if (rad_debug_lvl) {
1641                         RDEBUG("Injected %s packet to host %s port 0 code=%d, id=%d", what,
1642                                inet_ntop(request->reply->src_ipaddr.af,
1643                                          &request->reply->src_ipaddr.ipaddr,
1644                                          buffer, sizeof(buffer)),
1645                                          request->reply->code, request->reply->id);
1646                 }
1647
1648                 RINDENT();
1649                 for (vp = fr_cursor_init(&cursor, &request->reply->vps);
1650                      vp;
1651                      vp = fr_cursor_next(&cursor)) {
1652                         vp_prints(buffer, sizeof(buffer), vp);
1653                         fprintf(fp, "%s\n", buffer);
1654                         RDEBUG("%s", buffer);
1655                 }
1656                 REXDENT();
1657         }
1658         fclose(fp);
1659
1660         return 0;
1661 }
1662
1663 static rad_listen_t *get_socket(rad_listen_t *listener, int argc,
1664                                char *argv[], int *last)
1665 {
1666         rad_listen_t *sock;
1667         uint16_t port;
1668         int proto = IPPROTO_UDP;
1669         fr_ipaddr_t ipaddr;
1670
1671         if (argc < 2) {
1672                 cprintf_error(listener, "Must specify <ipaddr> <port> [udp|tcp]\n");
1673                 return NULL;
1674         }
1675
1676         if (ip_hton(&ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1677                 cprintf_error(listener, "Failed parsing IP address; %s\n",
1678                         fr_strerror());
1679                 return NULL;
1680         }
1681
1682         port = atoi(argv[1]);
1683
1684         if (last) *last = 2;
1685         if (argc > 2) {
1686                 if (strcmp(argv[2], "udp") == 0) {
1687                         proto = IPPROTO_UDP;
1688                         if (last) *last = 3;
1689                 }
1690 #ifdef WITH_TCP
1691                 if (strcmp(argv[2], "tcp") == 0) {
1692                         proto = IPPROTO_TCP;
1693                         if (last) *last = 3;
1694                 }
1695 #endif
1696         }
1697
1698         sock = listener_find_byipaddr(&ipaddr, port, proto);
1699         if (!sock) {
1700                 cprintf_error(listener, "No such listen section\n");
1701                 return NULL;
1702         }
1703
1704         return sock;
1705 }
1706
1707
1708 static int command_inject_to(rad_listen_t *listener, int argc, char *argv[])
1709 {
1710         fr_command_socket_t *sock = listener->data;
1711         listen_socket_t *data;
1712         rad_listen_t *found;
1713
1714         found = get_socket(listener, argc, argv, NULL);
1715         if (!found) {
1716                 return 0;
1717         }
1718
1719         data = found->data;
1720         sock->inject_listener = found;
1721         sock->dst_ipaddr = data->my_ipaddr;
1722         sock->dst_port = data->my_port;
1723
1724         return CMD_OK;
1725 }
1726
1727 static int command_inject_from(rad_listen_t *listener, int argc, char *argv[])
1728 {
1729         RADCLIENT *client;
1730         fr_command_socket_t *sock = listener->data;
1731
1732         if (argc < 1) {
1733                 cprintf_error(listener, "No <ipaddr> was given\n");
1734                 return 0;
1735         }
1736
1737         if (!sock->inject_listener) {
1738                 cprintf_error(listener, "You must specify \"inject to\" before using \"inject from\"\n");
1739                 return 0;
1740         }
1741
1742         sock->src_ipaddr.af = AF_UNSPEC;
1743         if (ip_hton(&sock->src_ipaddr, AF_UNSPEC, argv[0], false) < 0) {
1744                 cprintf_error(listener, "Failed parsing IP address; %s\n",
1745                         fr_strerror());
1746                 return 0;
1747         }
1748
1749         client = client_listener_find(sock->inject_listener, &sock->src_ipaddr,
1750                                       0);
1751         if (!client) {
1752                 cprintf_error(listener, "No such client %s\n", argv[0]);
1753                 return 0;
1754         }
1755         sock->inject_client = client;
1756
1757         return CMD_OK;
1758 }
1759
1760 static int command_inject_file(rad_listen_t *listener, int argc, char *argv[])
1761 {
1762         static int inject_id = 0;
1763         int ret;
1764         bool filedone;
1765         fr_command_socket_t *sock = listener->data;
1766         rad_listen_t *fake;
1767         RADIUS_PACKET *packet;
1768         vp_cursor_t cursor;
1769         VALUE_PAIR *vp;
1770         FILE *fp;
1771         RAD_REQUEST_FUNP fun = NULL;
1772         char buffer[2048];
1773
1774         if (argc < 2) {
1775                 cprintf_error(listener, "You must specify <input-file> <output-file>\n");
1776                 return 0;
1777         }
1778
1779         if (!sock->inject_listener) {
1780                 cprintf_error(listener, "You must specify \"inject to\" before using \"inject file\"\n");
1781                 return 0;
1782         }
1783
1784         if (!sock->inject_client) {
1785                 cprintf_error(listener, "You must specify \"inject from\" before using \"inject file\"\n");
1786                 return 0;
1787         }
1788
1789         /*
1790          *      Output files always go to the logging directory.
1791          */
1792         snprintf(buffer, sizeof(buffer), "%s/%s", radlog_dir, argv[1]);
1793
1794         fp = fopen(argv[0], "r");
1795         if (!fp ) {
1796                 cprintf_error(listener, "Failed opening %s: %s\n",
1797                         argv[0], fr_syserror(errno));
1798                 return 0;
1799         }
1800
1801         ret = fr_pair_list_afrom_file(NULL, &vp, fp, &filedone);
1802         fclose(fp);
1803         if (ret < 0) {
1804                 cprintf_error(listener, "Failed reading attributes from %s: %s\n",
1805                         argv[0], fr_strerror());
1806                 return 0;
1807         }
1808
1809         fake = talloc(NULL, rad_listen_t);
1810         memcpy(fake, sock->inject_listener, sizeof(*fake));
1811
1812         /*
1813          *      Re-write the IO for the listener.
1814          */
1815         fake->encode = null_socket_dencode;
1816         fake->decode = null_socket_dencode;
1817         fake->send = null_socket_send;
1818
1819         packet = rad_alloc(NULL, false);
1820         packet->src_ipaddr = sock->src_ipaddr;
1821         packet->src_port = 0;
1822
1823         packet->dst_ipaddr = sock->dst_ipaddr;
1824         packet->dst_port = sock->dst_port;
1825         packet->vps = vp;
1826         packet->id = inject_id++;
1827
1828         if (fake->type == RAD_LISTEN_AUTH) {
1829                 packet->code = PW_CODE_ACCESS_REQUEST;
1830                 fun = rad_authenticate;
1831
1832         } else {
1833 #ifdef WITH_ACCOUNTING
1834                 packet->code = PW_CODE_ACCOUNTING_REQUEST;
1835                 fun = rad_accounting;
1836 #else
1837                 cprintf_error(listener, "This server was built without accounting support.\n");
1838                 rad_free(&packet);
1839                 free(fake);
1840                 return 0;
1841 #endif
1842         }
1843
1844         if (rad_debug_lvl) {
1845                 DEBUG("Injecting %s packet from host %s port 0 code=%d, id=%d",
1846                                 fr_packet_codes[packet->code],
1847                                 inet_ntop(packet->src_ipaddr.af,
1848                                           &packet->src_ipaddr.ipaddr,
1849                                           buffer, sizeof(buffer)),
1850                                 packet->code, packet->id);
1851
1852                 for (vp = fr_cursor_init(&cursor, &packet->vps);
1853                      vp;
1854                      vp = fr_cursor_next(&cursor)) {
1855                         vp_prints(buffer, sizeof(buffer), vp);
1856                         DEBUG("\t%s", buffer);
1857                 }
1858
1859                 WARN("INJECTION IS LEAKING MEMORY!");
1860         }
1861
1862         if (!request_receive(NULL, fake, packet, sock->inject_client, fun)) {
1863                 cprintf_error(listener, "Failed to inject request.  See log file for details\n");
1864                 rad_free(&packet);
1865                 free(fake);
1866                 return 0;
1867         }
1868
1869 #if 0
1870         /*
1871          *      Remember what the output file is, and remember to
1872          *      delete the fake listener when done.
1873          */
1874         request_data_add(request, null_socket_send, 0, talloc_typed_strdup(NULL, buffer), true);
1875         request_data_add(request, null_socket_send, 1, fake, true);
1876
1877 #endif
1878
1879         return CMD_OK;
1880 }
1881
1882
1883 static fr_command_table_t command_table_inject[] = {
1884         { "to", FR_WRITE,
1885           "inject to <ipaddr> <port> - Inject packets to the destination IP and port.",
1886           command_inject_to, NULL },
1887
1888         { "from", FR_WRITE,
1889           "inject from <ipaddr> - Inject packets as if they came from <ipaddr>",
1890           command_inject_from, NULL },
1891
1892         { "file", FR_WRITE,
1893           "inject file <input-file> <output-file> - Inject packet from <input-file>, with results sent to <output-file>",
1894           command_inject_file, NULL },
1895
1896         { NULL, 0, NULL, NULL, NULL }
1897 };
1898
1899 static fr_command_table_t command_table_debug[] = {
1900         { "condition", FR_WRITE,
1901           "debug condition [condition] - Enable debugging for requests matching [condition]",
1902           command_debug_condition, NULL },
1903
1904         { "level", FR_WRITE,
1905           "debug level <number> - Set debug level to <number>.  Higher is more debugging.",
1906           command_debug_level, NULL },
1907
1908         { "file", FR_WRITE,
1909           "debug file [filename] - Send all debugging output to [filename]",
1910           command_debug_file, NULL },
1911
1912         { NULL, 0, NULL, NULL, NULL }
1913 };
1914
1915 static fr_command_table_t command_table_show_debug[] = {
1916         { "condition", FR_READ,
1917           "show debug condition - Shows current debugging condition.",
1918           command_show_debug_condition, NULL },
1919
1920         { "level", FR_READ,
1921           "show debug level - Shows current debugging level.",
1922           command_show_debug_level, NULL },
1923
1924         { "file", FR_READ,
1925           "show debug file - Shows current debugging file.",
1926           command_show_debug_file, NULL },
1927
1928         { NULL, 0, NULL, NULL, NULL }
1929 };
1930
1931 static fr_command_table_t command_table_show_module[] = {
1932         { "config", FR_READ,
1933           "show module config <module> - show configuration for given module",
1934           command_show_module_config, NULL },
1935         { "flags", FR_READ,
1936           "show module flags <module> - show other module properties",
1937           command_show_module_flags, NULL },
1938         { "list", FR_READ,
1939           "show module list - shows list of loaded modules",
1940           command_show_modules, NULL },
1941         { "methods", FR_READ,
1942           "show module methods <module> - show sections where <module> may be used",
1943           command_show_module_methods, NULL },
1944         { "status", FR_READ,
1945           "show module status <module> - show the module status",
1946           command_show_module_status, NULL },
1947
1948         { NULL, 0, NULL, NULL, NULL }
1949 };
1950
1951 static fr_command_table_t command_table_show_client[] = {
1952         { "list", FR_READ,
1953           "show client list - shows list of global clients",
1954           command_show_clients, NULL },
1955
1956         { NULL, 0, NULL, NULL, NULL }
1957 };
1958
1959 #ifdef WITH_PROXY
1960 static fr_command_table_t command_table_show_home[] = {
1961         { "list", FR_READ,
1962           "show home_server list - shows list of home servers",
1963           command_show_home_servers, NULL },
1964         { "state", FR_READ,
1965           "show home_server state <ipaddr> <port> [udp|tcp] - shows state of given home server",
1966           command_show_home_server_state, NULL },
1967
1968         { NULL, 0, NULL, NULL, NULL }
1969 };
1970 #endif
1971
1972
1973 static fr_command_table_t command_table_show[] = {
1974         { "client", FR_READ,
1975           "show client <command> - do sub-command of client",
1976           NULL, command_table_show_client },
1977         { "config", FR_READ,
1978           "show config <path> - shows the value of configuration option <path>",
1979           command_show_config, NULL },
1980         { "debug", FR_READ,
1981           "show debug <command> - show debug properties",
1982           NULL, command_table_show_debug },
1983 #ifdef WITH_PROXY
1984         { "home_server", FR_READ,
1985           "show home_server <command> - do sub-command of home_server",
1986           NULL, command_table_show_home },
1987 #endif
1988         { "module", FR_READ,
1989           "show module <command> - do sub-command of module",
1990           NULL, command_table_show_module },
1991         { "uptime", FR_READ,
1992           "show uptime - shows time at which server started",
1993           command_uptime, NULL },
1994         { "version", FR_READ,
1995           "show version - Prints version of the running server",
1996           command_show_version, NULL },
1997         { NULL, 0, NULL, NULL, NULL }
1998 };
1999
2000
2001 static int command_set_module_config(rad_listen_t *listener, int argc, char *argv[])
2002 {
2003         int i, rcode;
2004         CONF_PAIR *cp;
2005         CONF_SECTION *cs;
2006         module_instance_t *mi;
2007         CONF_PARSER const *variables;
2008         void *data;
2009
2010         if (argc < 3) {
2011                 cprintf_error(listener, "No module name or variable was given\n");
2012                 return 0;
2013         }
2014
2015         cs = cf_section_find("modules");
2016         if (!cs) return 0;
2017
2018         mi = module_find(cs, argv[0]);
2019         if (!mi) {
2020                 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
2021                 return 0;
2022         }
2023
2024         if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) {
2025                 cprintf_error(listener, "Cannot change configuration of module as it is cannot be HUP'd.\n");
2026                 return 0;
2027         }
2028
2029         variables = cf_section_parse_table(mi->cs);
2030         if (!variables) {
2031                 cprintf_error(listener, "Cannot find configuration for module\n");
2032                 return 0;
2033         }
2034
2035         rcode = -1;
2036         for (i = 0; variables[i].name != NULL; i++) {
2037                 /*
2038                  *      FIXME: Recurse into sub-types somehow...
2039                  */
2040                 if (variables[i].type == PW_TYPE_SUBSECTION) continue;
2041
2042                 if (strcmp(variables[i].name, argv[1]) == 0) {
2043                         rcode = i;
2044                         break;
2045                 }
2046         }
2047
2048         if (rcode < 0) {
2049                 cprintf_error(listener, "No such variable \"%s\"\n", argv[1]);
2050                 return 0;
2051         }
2052
2053         i = rcode;              /* just to be safe */
2054
2055         /*
2056          *      It's not part of the dynamic configuration.  The module
2057          *      needs to re-parse && validate things.
2058          */
2059         if (variables[i].data) {
2060                 cprintf_error(listener, "Variable cannot be dynamically updated\n");
2061                 return 0;
2062         }
2063
2064         data = ((char *) mi->insthandle) + variables[i].offset;
2065
2066         cp = cf_pair_find(mi->cs, argv[1]);
2067         if (!cp) return 0;
2068
2069         /*
2070          *      Replace the OLD value in the configuration file with
2071          *      the NEW value.
2072          *
2073          *      FIXME: Parse argv[2] depending on it's data type!
2074          *      If it's a string, look for leading single/double quotes,
2075          *      end then call tokenize functions???
2076          */
2077         cf_pair_replace(mi->cs, cp, argv[2]);
2078
2079         rcode = cf_item_parse(mi->cs, argv[1], variables[i].type, data, argv[2]);
2080         if (rcode < 0) {
2081                 cprintf_error(listener, "Failed to parse value\n");
2082                 return 0;
2083         }
2084
2085         return CMD_OK;
2086 }
2087
2088 static int command_set_module_status(rad_listen_t *listener, int argc, char *argv[])
2089 {
2090         CONF_SECTION *cs;
2091         module_instance_t *mi;
2092
2093         if (argc < 2) {
2094                 cprintf_error(listener, "No module name or status was given\n");
2095                 return 0;
2096         }
2097
2098         cs = cf_section_find("modules");
2099         if (!cs) return 0;
2100
2101         mi = module_find(cs, argv[0]);
2102         if (!mi) {
2103                 cprintf_error(listener, "No such module \"%s\"\n", argv[0]);
2104                 return 0;
2105         }
2106
2107
2108         if (strcmp(argv[1], "alive") == 0) {
2109                 mi->force = false;
2110
2111         } else if (strcmp(argv[1], "dead") == 0) {
2112                 mi->code = RLM_MODULE_FAIL;
2113                 mi->force = true;
2114
2115         } else {
2116                 int rcode;
2117
2118                 rcode = fr_str2int(mod_rcode_table, argv[1], -1);
2119                 if (rcode < 0) {
2120                         cprintf_error(listener, "Unknown status \"%s\"\n", argv[1]);
2121                         return 0;
2122                 }
2123
2124                 mi->code = rcode;
2125                 mi->force = true;
2126         }
2127
2128         return CMD_OK;
2129 }
2130
2131 #ifdef WITH_STATS
2132 static char const *elapsed_names[8] = {
2133         "1us", "10us", "100us", "1ms", "10ms", "100ms", "1s", "10s"
2134 };
2135
2136 #undef PU
2137 #ifdef WITH_STATS_64BIT
2138 #ifdef PRIu64
2139 #define PU "%" PRIu64
2140 #else
2141 #define PU "%lu"
2142 #endif
2143 #else
2144 #ifdef PRIu32
2145 #define PU "%" PRIu32
2146 #else
2147 #define PU "%u"
2148 #endif
2149 #endif
2150
2151 static int command_print_stats(rad_listen_t *listener, fr_stats_t *stats,
2152                                int auth, int server)
2153 {
2154         int i;
2155
2156         cprintf(listener, "requests\t" PU "\n", stats->total_requests);
2157         cprintf(listener, "responses\t" PU "\n", stats->total_responses);
2158
2159         if (auth) {
2160                 cprintf(listener, "accepts\t\t" PU "\n",
2161                         stats->total_access_accepts);
2162                 cprintf(listener, "rejects\t\t" PU "\n",
2163                         stats->total_access_rejects);
2164                 cprintf(listener, "challenges\t" PU "\n",
2165                         stats->total_access_challenges);
2166         }
2167
2168         cprintf(listener, "dup\t\t" PU "\n", stats->total_dup_requests);
2169         cprintf(listener, "invalid\t\t" PU "\n", stats->total_invalid_requests);
2170         cprintf(listener, "malformed\t" PU "\n", stats->total_malformed_requests);
2171         cprintf(listener, "bad_authenticator\t" PU "\n", stats->total_bad_authenticators);
2172         cprintf(listener, "dropped\t\t" PU "\n", stats->total_packets_dropped);
2173         cprintf(listener, "unknown_types\t" PU "\n", stats->total_unknown_types);
2174
2175         if (server) {
2176                 cprintf(listener, "timeouts\t" PU "\n", stats->total_timeouts);
2177         }
2178
2179         cprintf(listener, "last_packet\t%" PRId64 "\n", (int64_t) stats->last_packet);
2180         for (i = 0; i < 8; i++) {
2181                 cprintf(listener, "elapsed.%s\t%u\n",
2182                         elapsed_names[i], stats->elapsed[i]);
2183         }
2184
2185         return CMD_OK;
2186 }
2187
2188
2189 #ifdef HAVE_PTHREAD_H
2190 static int command_stats_queue(rad_listen_t *listener, UNUSED int argc, UNUSED char *argv[])
2191 {
2192         int array[RAD_LISTEN_MAX], pps[2];
2193
2194         thread_pool_queue_stats(array, pps);
2195
2196         cprintf(listener, "queue_len_internal\t" PU "\n", array[0]);
2197         cprintf(listener, "queue_len_proxy\t\t" PU "\n", array[1]);
2198         cprintf(listener, "queue_len_auth\t\t" PU "\n", array[2]);
2199         cprintf(listener, "queue_len_acct\t\t" PU "\n", array[3]);
2200         cprintf(listener, "queue_len_detail\t" PU "\n", array[4]);
2201
2202         cprintf(listener, "queue_pps_in\t\t" PU "\n", pps[0]);
2203         cprintf(listener, "queue_pps_out\t\t" PU "\n", pps[1]);
2204
2205         return CMD_OK;
2206 }
2207 #endif
2208
2209 #ifndef NDEBUG
2210 static int command_stats_memory(rad_listen_t *listener, int argc, char *argv[])
2211 {
2212
2213         if (!main_config.debug_memory || !main_config.memory_report) {
2214                 cprintf(listener, "No memory debugging was enabled.\n");
2215                 return CMD_OK;
2216         }
2217
2218         if (argc == 0) goto fail;
2219
2220         if (strcmp(argv[0], "total") == 0) {
2221                 cprintf(listener, "%zd\n", talloc_total_size(NULL));
2222                 return CMD_OK;
2223         }
2224
2225         if (strcmp(argv[0], "blocks") == 0) {
2226                 cprintf(listener, "%zd\n", talloc_total_blocks(NULL));
2227                 return CMD_OK;
2228         }
2229
2230         if (strcmp(argv[0], "full") == 0) {
2231                 cprintf(listener, "see stdout of the server for the full report.\n");
2232                 fr_log_talloc_report(NULL);
2233                 return CMD_OK;
2234         }
2235
2236 fail:
2237         cprintf_error(listener, "Must use 'stats memory [blocks|full|total]'\n");
2238         return CMD_FAIL;
2239 }
2240 #endif
2241
2242 #ifdef WITH_DETAIL
2243 static FR_NAME_NUMBER state_names[] = {
2244         { "unopened", STATE_UNOPENED },
2245         { "unlocked", STATE_UNLOCKED },
2246         { "header", STATE_HEADER },
2247         { "reading", STATE_READING },
2248         { "queued", STATE_QUEUED },
2249         { "running", STATE_RUNNING },
2250         { "no-reply", STATE_NO_REPLY },
2251         { "replied", STATE_REPLIED },
2252
2253         { NULL, 0 }
2254 };
2255
2256 static int command_stats_detail(rad_listen_t *listener, int argc, char *argv[])
2257 {
2258         rad_listen_t *this;
2259         listen_detail_t *data, *needle;
2260         struct stat buf;
2261
2262         if (argc == 0) {
2263                 cprintf_error(listener, "Must specify <filename>\n");
2264                 return 0;
2265         }
2266
2267         data = NULL;
2268         for (this = main_config.listen; this != NULL; this = this->next) {
2269                 if (this->type != RAD_LISTEN_DETAIL) continue;
2270
2271                 needle = this->data;
2272                 if (!strcmp(argv[0], needle->filename)) {
2273                         data = needle;
2274                         break;
2275                 }
2276         }
2277
2278         if (!data) {
2279                 cprintf_error(listener, "No detail file listener\n");
2280                 return 0;
2281         }
2282
2283         cprintf(listener, "state\t%s\n",
2284                 fr_int2str(state_names, data->state, "?"));
2285
2286         if ((data->state == STATE_UNOPENED) ||
2287             (data->state == STATE_UNLOCKED)) {
2288                 return CMD_OK;
2289         }
2290
2291         /*
2292          *      Race conditions: file might not exist.
2293          */
2294         if (stat(data->filename_work, &buf) < 0) {
2295                 cprintf(listener, "packets\t0\n");
2296                 cprintf(listener, "tries\t0\n");
2297                 cprintf(listener, "offset\t0\n");
2298                 cprintf(listener, "size\t0\n");
2299                 return CMD_OK;
2300         }
2301
2302         cprintf(listener, "packets\t%d\n", data->packets);
2303         cprintf(listener, "tries\t%d\n", data->tries);
2304         cprintf(listener, "offset\t%u\n", (unsigned int) data->offset);
2305         cprintf(listener, "size\t%u\n", (unsigned int) buf.st_size);
2306
2307         return CMD_OK;
2308 }
2309 #endif
2310
2311 #ifdef WITH_PROXY
2312 static int command_stats_home_server(rad_listen_t *listener, int argc, char *argv[])
2313 {
2314         home_server_t *home;
2315
2316         if (argc == 0) {
2317                 cprintf_error(listener, "Must specify [auth|acct|coa|disconnect] OR <ipaddr> <port>\n");
2318                 return 0;
2319         }
2320
2321         if (argc == 1) {
2322                 if (strcmp(argv[0], "auth") == 0) {
2323                         return command_print_stats(listener,
2324                                                    &proxy_auth_stats, 1, 1);
2325                 }
2326
2327 #ifdef WITH_ACCOUNTING
2328                 if (strcmp(argv[0], "acct") == 0) {
2329                         return command_print_stats(listener,
2330                                                    &proxy_acct_stats, 0, 1);
2331                 }
2332 #endif
2333
2334 #ifdef WITH_ACCOUNTING
2335                 if (strcmp(argv[0], "coa") == 0) {
2336                         return command_print_stats(listener,
2337                                                    &proxy_coa_stats, 0, 1);
2338                 }
2339 #endif
2340
2341 #ifdef WITH_ACCOUNTING
2342                 if (strcmp(argv[0], "disconnect") == 0) {
2343                         return command_print_stats(listener,
2344                                                    &proxy_dsc_stats, 0, 1);
2345                 }
2346 #endif
2347
2348                 cprintf_error(listener, "Should specify [auth|acct|coa|disconnect]\n");
2349                 return 0;
2350         }
2351
2352         home = get_home_server(listener, argc, argv, NULL);
2353         if (!home) return 0;
2354
2355         command_print_stats(listener, &home->stats,
2356                             (home->type == HOME_TYPE_AUTH), 1);
2357         cprintf(listener, "outstanding\t%d\n", home->currently_outstanding);
2358         return CMD_OK;
2359 }
2360 #endif
2361
2362 static int command_stats_client(rad_listen_t *listener, int argc, char *argv[])
2363 {
2364         bool auth = true;
2365         fr_stats_t *stats;
2366         RADCLIENT *client, fake;
2367
2368         if (argc < 1) {
2369                 cprintf_error(listener, "Must specify [auth/acct]\n");
2370                 return 0;
2371         }
2372
2373         if (argc == 1) {
2374                 /*
2375                  *      Global statistics.
2376                  */
2377                 fake.auth = radius_auth_stats;
2378 #ifdef WITH_ACCOUNTING
2379                 fake.acct = radius_acct_stats;
2380 #endif
2381 #ifdef WITH_COA
2382                 fake.coa = radius_coa_stats;
2383                 fake.dsc = radius_dsc_stats;
2384 #endif
2385                 client = &fake;
2386
2387         } else {
2388                 /*
2389                  *      Per-client statistics.
2390                  */
2391                 client = get_client(listener, argc - 1, argv + 1);
2392                 if (!client) return 0;
2393         }
2394
2395         if (strcmp(argv[0], "auth") == 0) {
2396                 auth = true;
2397                 stats = &client->auth;
2398
2399         } else if (strcmp(argv[0], "acct") == 0) {
2400 #ifdef WITH_ACCOUNTING
2401                 auth = false;
2402                 stats = &client->acct;
2403 #else
2404                 cprintf_error(listener, "This server was built without accounting support.\n");
2405                 return 0;
2406 #endif
2407
2408         } else if (strcmp(argv[0], "coa") == 0) {
2409 #ifdef WITH_COA
2410                 auth = false;
2411                 stats = &client->coa;
2412 #else
2413                 cprintf_error(listener, "This server was built without CoA support.\n");
2414                 return 0;
2415 #endif
2416
2417         } else if (strcmp(argv[0], "disconnect") == 0) {
2418 #ifdef WITH_COA
2419                 auth = false;
2420                 stats = &client->dsc;
2421 #else
2422                 cprintf_error(listener, "This server was built without CoA support.\n");
2423                 return 0;
2424 #endif
2425
2426         } else {
2427                 cprintf_error(listener, "Unknown statistics type\n");
2428                 return 0;
2429         }
2430
2431         /*
2432          *      Global results for all client.
2433          */
2434         if (argc == 1) {
2435 #ifdef WITH_ACCOUNTING
2436                 if (!auth) {
2437                         return command_print_stats(listener,
2438                                                    &radius_acct_stats, auth, 0);
2439                 }
2440 #endif
2441                 return command_print_stats(listener, &radius_auth_stats, auth, 0);
2442         }
2443
2444         return command_print_stats(listener, stats, auth, 0);
2445 }
2446
2447
2448 static int command_stats_socket(rad_listen_t *listener, int argc, char *argv[])
2449 {
2450         bool auth = true;
2451         rad_listen_t *sock;
2452
2453         sock = get_socket(listener, argc, argv, NULL);
2454         if (!sock) return 0;
2455
2456         if (sock->type != RAD_LISTEN_AUTH) auth = false;
2457
2458         return command_print_stats(listener, &sock->stats, auth, 0);
2459 }
2460 #endif  /* WITH_STATS */
2461
2462
2463 #ifdef WITH_DYNAMIC_CLIENTS
2464 static int command_add_client_file(rad_listen_t *listener, int argc, char *argv[])
2465 {
2466         RADCLIENT *c;
2467
2468         if (argc < 1) {
2469                 cprintf_error(listener, "<file> is required\n");
2470                 return 0;
2471         }
2472
2473         /*
2474          *      Read the file and generate the client.
2475          */
2476         c = client_read(argv[0], false, false);
2477         if (!c) {
2478                 cprintf_error(listener, "Unknown error reading client file.\n");
2479                 return 0;
2480         }
2481
2482         if (!client_add(NULL, c)) {
2483                 cprintf_error(listener, "Unknown error inserting new client.\n");
2484                 client_free(c);
2485                 return 0;
2486         }
2487
2488         return CMD_OK;
2489 }
2490
2491
2492 static int command_del_client(rad_listen_t *listener, int argc, char *argv[])
2493 {
2494         RADCLIENT *client;
2495
2496         client = get_client(listener, argc, argv);
2497         if (!client) return 0;
2498
2499         if (!client->dynamic) {
2500                 cprintf_error(listener, "Client %s was not dynamically defined.\n", argv[0]);
2501                 return 0;
2502         }
2503
2504         /*
2505          *      DON'T delete it.  Instead, mark it as "dead now".  The
2506          *      next time we receive a packet for the client, it will
2507          *      be deleted.
2508          *
2509          *      If we don't receive a packet from it, the client
2510          *      structure will stick around for a while.  Oh well...
2511          */
2512         client->lifetime = 1;
2513
2514         return CMD_OK;
2515 }
2516
2517
2518 static fr_command_table_t command_table_del_client[] = {
2519         { "ipaddr", FR_WRITE,
2520           "del client ipaddr <ipaddr> [udp|tcp] [listen <ipaddr> <port>] - Delete a dynamically created client",
2521           command_del_client, NULL },
2522
2523         { NULL, 0, NULL, NULL, NULL }
2524 };
2525
2526
2527 static fr_command_table_t command_table_del[] = {
2528         { "client", FR_WRITE,
2529           "del client <command> - Delete client configuration commands",
2530           NULL, command_table_del_client },
2531
2532         { NULL, 0, NULL, NULL, NULL }
2533 };
2534
2535
2536 static fr_command_table_t command_table_add_client[] = {
2537         { "file", FR_WRITE,
2538           "add client file <filename> - Add new client definition from <filename>",
2539           command_add_client_file, NULL },
2540
2541         { NULL, 0, NULL, NULL, NULL }
2542 };
2543
2544
2545 static fr_command_table_t command_table_add[] = {
2546         { "client", FR_WRITE,
2547           "add client <command> - Add client configuration commands",
2548           NULL, command_table_add_client },
2549
2550         { NULL, 0, NULL, NULL, NULL }
2551 };
2552 #endif
2553
2554 #ifdef WITH_PROXY
2555 static fr_command_table_t command_table_set_home[] = {
2556         { "state", FR_WRITE,
2557           "set home_server state <ipaddr> <port> [udp|tcp] [alive|dead] - set state for given home server",
2558           command_set_home_server_state, NULL },
2559
2560         { NULL, 0, NULL, NULL, NULL }
2561 };
2562 #endif
2563
2564 static fr_command_table_t command_table_set_module[] = {
2565         { "config", FR_WRITE,
2566           "set module config <module> variable value - set configuration for <module>",
2567           command_set_module_config, NULL },
2568
2569         { "status", FR_WRITE,
2570           "set module status <module> [alive|...] - set the module status to be alive (operating normally), or force a particular code (ok,fail, etc.)",
2571           command_set_module_status, NULL },
2572
2573         { NULL, 0, NULL, NULL, NULL }
2574 };
2575
2576
2577 static fr_command_table_t command_table_set[] = {
2578         { "module", FR_WRITE,
2579           "set module <command> - set module commands",
2580           NULL, command_table_set_module },
2581 #ifdef WITH_PROXY
2582         { "home_server", FR_WRITE,
2583           "set home_server <command> - set home server commands",
2584           NULL, command_table_set_home },
2585 #endif
2586
2587         { NULL, 0, NULL, NULL, NULL }
2588 };
2589
2590
2591 #ifdef WITH_STATS
2592 static fr_command_table_t command_table_stats[] = {
2593         { "client", FR_READ,
2594           "stats client [auth/acct] <ipaddr> [udp|tcp] [listen <ipaddr> <port>] "
2595           "- show statistics for given client, or for all clients (auth or acct)",
2596           command_stats_client, NULL },
2597
2598 #ifdef WITH_DETAIL
2599         { "detail", FR_READ,
2600           "stats detail <filename> - show statistics for the given detail file",
2601           command_stats_detail, NULL },
2602 #endif
2603
2604 #ifdef WITH_PROXY
2605         { "home_server", FR_READ,
2606           "stats home_server [<ipaddr>|auth|acct|coa|disconnect] <port> [udp|tcp] - show statistics for given home server (ipaddr and port), or for all home servers (auth or acct)",
2607           command_stats_home_server, NULL },
2608 #endif
2609
2610 #ifdef HAVE_PTHREAD_H
2611         { "queue", FR_READ,
2612           "stats queue - show statistics for packet queues",
2613           command_stats_queue, NULL },
2614 #endif
2615
2616         { "socket", FR_READ,
2617           "stats socket <ipaddr> <port> [udp|tcp] "
2618           "- show statistics for given socket",
2619           command_stats_socket, NULL },
2620
2621 #ifndef NDEBUG
2622         { "memory", FR_READ,
2623           "stats memory [blocks|full|total] - show statistics on used memory",
2624           command_stats_memory, NULL },
2625 #endif
2626
2627         { NULL, 0, NULL, NULL, NULL }
2628 };
2629 #endif
2630
2631 static fr_command_table_t command_table[] = {
2632 #ifdef WITH_DYNAMIC_CLIENTS
2633         { "add", FR_WRITE, NULL, NULL, command_table_add },
2634 #endif
2635         { "debug", FR_WRITE,
2636           "debug <command> - debugging commands",
2637           NULL, command_table_debug },
2638 #ifdef WITH_DYNAMIC_CLIENTS
2639         { "del", FR_WRITE, NULL, NULL, command_table_del },
2640 #endif
2641         { "hup", FR_WRITE,
2642           "hup [module] - sends a HUP signal to the server, or optionally to one module",
2643           command_hup, NULL },
2644         { "inject", FR_WRITE,
2645           "inject <command> - commands to inject packets into a running server",
2646           NULL, command_table_inject },
2647         { "reconnect", FR_READ,
2648           "reconnect - reconnect to a running server",
2649           NULL, NULL },         /* just here for "help" */
2650         { "terminate", FR_WRITE,
2651           "terminate - terminates the server, and cause it to exit",
2652           command_terminate, NULL },
2653         { "set", FR_WRITE, NULL, NULL, command_table_set },
2654         { "show",  FR_READ, NULL, NULL, command_table_show },
2655 #ifdef WITH_STATS
2656         { "stats",  FR_READ, NULL, NULL, command_table_stats },
2657 #endif
2658
2659         { NULL, 0, NULL, NULL, NULL }
2660 };
2661
2662
2663 static void command_socket_free(rad_listen_t *this)
2664 {
2665         fr_command_socket_t *cmd = this->data;
2666
2667         /*
2668          *      If it's a TCP socket, don't do anything.
2669          */
2670         if (cmd->magic != COMMAND_SOCKET_MAGIC) {
2671                 return;
2672         }
2673
2674         if (!cmd->copy) return;
2675         unlink(cmd->copy);
2676 }
2677
2678
2679 /*
2680  *      Parse the unix domain sockets.
2681  *
2682  *      FIXME: TCP + SSL, after RadSec is in.
2683  */
2684 static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
2685 {
2686         fr_command_socket_t *sock;
2687
2688         if (check_config) return 0;
2689
2690         sock = this->data;
2691
2692         if (cf_section_parse(cs, sock, command_config) < 0) return -1;
2693
2694         /*
2695          *      Can't get uid or gid of connecting user, so can't do
2696          *      peercred authentication.
2697          */
2698 #ifndef HAVE_GETPEEREID
2699         if (sock->peercred && (sock->uid_name || sock->gid_name)) {
2700                 ERROR("System does not support uid or gid authentication for sockets");
2701                 return -1;
2702         }
2703 #endif
2704
2705         sock->magic = COMMAND_SOCKET_MAGIC;
2706         sock->copy = NULL;
2707         if (sock->path) sock->copy = talloc_typed_strdup(sock, sock->path);
2708
2709         if (sock->uid_name) {
2710                 struct passwd *pwd;
2711
2712                 if (rad_getpwnam(cs, &pwd, sock->uid_name) < 0) {
2713                         ERROR("Failed getting uid for %s: %s", sock->uid_name, fr_strerror());
2714                         return -1;
2715                 }
2716                 sock->uid = pwd->pw_uid;
2717                 talloc_free(pwd);
2718         } else {
2719                 sock->uid = -1;
2720         }
2721
2722         if (sock->gid_name) {
2723                 if (rad_getgid(cs, &sock->gid, sock->gid_name) < 0) {
2724                         ERROR("Failed getting gid for %s: %s", sock->gid_name, fr_strerror());
2725                         return -1;
2726                 }
2727         } else {
2728                 sock->gid = -1;
2729         }
2730
2731         if (!sock->mode_name) {
2732                 sock->co.mode = FR_READ;
2733         } else {
2734                 sock->co.mode = fr_str2int(mode_names, sock->mode_name, 0);
2735                 if (!sock->co.mode) {
2736                         ERROR("Invalid mode name \"%s\"",
2737                                sock->mode_name);
2738                         return -1;
2739                 }
2740         }
2741
2742         if (sock->peercred) {
2743                 this->fd = fr_server_domain_socket_peercred(sock->path, sock->uid, sock->gid);
2744         } else {
2745                 uid_t uid = sock->uid;
2746                 gid_t gid = sock->gid;
2747
2748                 if (uid == ((uid_t)-1)) uid = 0;
2749                 if (gid == ((gid_t)-1)) gid = 0;
2750
2751                 this->fd = fr_server_domain_socket_perm(sock->path, uid, gid);
2752         }
2753
2754         if (this->fd < 0) {
2755                 ERROR("Failed creating control socket \"%s\": %s", sock->path, fr_strerror());
2756                 if (sock->copy) talloc_free(sock->copy);
2757                 sock->copy = NULL;
2758                 return -1;
2759         }
2760
2761         return 0;
2762 }
2763
2764 static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
2765 {
2766         int rcode;
2767         CONF_PAIR const *cp;
2768         listen_socket_t *sock;
2769
2770         cp = cf_pair_find(cs, "socket");
2771         if (cp) return command_socket_parse_unix(cs, this);
2772
2773         rcode = common_socket_parse(cs, this);
2774         if (rcode < 0) return -1;
2775
2776 #ifdef WITH_TLS
2777         if (this->tls) {
2778                 cf_log_err_cs(cs,
2779                            "TLS is not supported for control sockets");
2780                 return -1;
2781         }
2782 #endif
2783
2784         sock = this->data;
2785         if (sock->proto != IPPROTO_TCP) {
2786                 cf_log_err_cs(cs,
2787                            "UDP is not supported for control sockets");
2788                 return -1;
2789         }
2790
2791         return 0;
2792 }
2793
2794 static int command_socket_print(rad_listen_t const *this, char *buffer, size_t bufsize)
2795 {
2796         fr_command_socket_t *sock = this->data;
2797
2798         if (sock->magic != COMMAND_SOCKET_MAGIC) {
2799                 return common_socket_print(this, buffer, bufsize);
2800         }
2801
2802         snprintf(buffer, bufsize, "command file %s", sock->path);
2803         return 1;
2804 }
2805
2806
2807 /*
2808  *      String split routine.  Splits an input string IN PLACE
2809  *      into pieces, based on spaces.
2810  */
2811 static int str2argvX(char *str, char **argv, int max_argc)
2812 {
2813         int argc = 0;
2814
2815         while (*str) {
2816                 if (argc >= max_argc) return argc;
2817
2818                 /*
2819                  *      Chop out comments early.
2820                  */
2821                 if (*str == '#') {
2822                         *str = '\0';
2823                         break;
2824                 }
2825
2826                 while ((*str == ' ') ||
2827                        (*str == '\t') ||
2828                        (*str == '\r') ||
2829                        (*str == '\n')) *(str++) = '\0';
2830
2831                 if (!*str) return argc;
2832
2833                 argv[argc++] = str;
2834
2835                 if ((*str == '\'') || (*str == '"')) {
2836                         char quote = *str;
2837                         char *p = str + 1;
2838
2839                         while (true) {
2840                                 if (!*p) return -1;
2841
2842                                 if (*p == quote) {
2843                                         str = p + 1;
2844                                         break;
2845                                 }
2846
2847                                 /*
2848                                  *      Handle \" and nothing else.
2849                                  */
2850                                 if (*p == '\\') {
2851                                         p += 2;
2852                                         continue;
2853                                 }
2854
2855                                 p++;
2856                         }
2857                 }
2858
2859                 while (*str &&
2860                        (*str != ' ') &&
2861                        (*str != '\t') &&
2862                        (*str != '\r') &&
2863                        (*str != '\n')) str++;
2864         }
2865
2866         return argc;
2867 }
2868
2869 static void print_help(rad_listen_t *listener, int argc, char *argv[],
2870                        fr_command_table_t *table, int recursive)
2871 {
2872         int i;
2873
2874         /* this should never happen, but if it does then just return gracefully */
2875         if (!table) return;
2876
2877         for (i = 0; table[i].command != NULL; i++) {
2878                 if (argc > 0) {
2879                         if (strcmp(table[i].command, argv[0]) == 0) {
2880                                 if (table[i].table) {
2881                                         print_help(listener, argc - 1, argv + 1, table[i].table, recursive);
2882                                 } else {
2883                                         if (table[i].help) {
2884                                                 cprintf(listener, "%s\n", table[i].help);
2885                                         }
2886                                 }
2887                                 return;
2888                         }
2889
2890                         continue;
2891                 }
2892
2893                 if (table[i].help) {
2894                         cprintf(listener, "%s\n",
2895                                 table[i].help);
2896                 } else {
2897                         cprintf(listener, "%s <command> - do sub-command of %s\n",
2898                                 table[i].command, table[i].command);
2899                 }
2900
2901                 if (recursive && table[i].table) {
2902                         print_help(listener, 0, NULL, table[i].table, recursive);
2903                 }
2904         }
2905 }
2906
2907 #define MAX_ARGV (16)
2908
2909 /*
2910  *      Check if an incoming request is "ok"
2911  *
2912  *      It takes packets, not requests.  It sees if the packet looks
2913  *      OK.  If so, it does a number of sanity checks on it.
2914  */
2915 static int command_domain_recv_co(rad_listen_t *listener, fr_cs_buffer_t *co)
2916 {
2917         int i;
2918         uint32_t status;
2919         ssize_t r, len;
2920         int argc;
2921         fr_channel_type_t channel;
2922         char *my_argv[MAX_ARGV], **argv;
2923         fr_command_table_t *table;
2924         uint8_t *command;
2925
2926         r = fr_channel_drain(listener->fd, &channel, co->buffer, sizeof(co->buffer) - 1, &command, co->offset);
2927
2928         if (r <= 0) {
2929         do_close:
2930                 command_close_socket(listener);
2931                 return 0;
2932         }
2933
2934         /*
2935          *      We need more data.  Go read it.
2936          */
2937         if (channel == FR_CHANNEL_WANT_MORE) {
2938                 co->offset = r;
2939                 return 0;
2940         }
2941
2942         status = 0;
2943         command[r] = '\0';
2944         DEBUG("radmin> %s", command);
2945
2946         argc = str2argvX((char *) command, my_argv, MAX_ARGV);
2947         if (argc == 0) goto do_next; /* empty strings are OK */
2948
2949         if (argc < 0) {
2950                 cprintf_error(listener, "Failed parsing command.\n");
2951                 goto do_next;
2952         }
2953
2954         argv = my_argv;
2955
2956         for (len = 0; len <= co->offset; len++) {
2957                 if (command[len] < 0x20) {
2958                         command[len] = '\0';
2959                         break;
2960                 }
2961         }
2962
2963         /*
2964          *      Hard-code exit && quit.
2965          */
2966         if ((strcmp(argv[0], "exit") == 0) ||
2967             (strcmp(argv[0], "quit") == 0)) goto do_close;
2968
2969         table = command_table;
2970  retry:
2971         len = 0;
2972         for (i = 0; table[i].command != NULL; i++) {
2973                 if (strcmp(table[i].command, argv[0]) == 0) {
2974                         /*
2975                          *      Check permissions.
2976                          */
2977                         if (((co->mode & FR_WRITE) == 0) &&
2978                             ((table[i].mode & FR_WRITE) != 0)) {
2979                                 cprintf_error(listener, "You do not have write permission.  See \"mode = rw\" in the \"listen\" section for this socket.\n");
2980                                 goto do_next;
2981                         }
2982
2983                         if (table[i].table) {
2984                                 /*
2985                                  *      This is the last argument, but
2986                                  *      there's a sub-table.  Print help.
2987                                  *
2988                                  */
2989                                 if (argc == 1) {
2990                                         table = table[i].table;
2991                                         goto do_help;
2992                                 }
2993
2994                                 argc--;
2995                                 argv++;
2996                                 table = table[i].table;
2997                                 goto retry;
2998                         }
2999
3000                         if ((argc == 2) && (strcmp(argv[1], "?") == 0)) goto do_help;
3001
3002                         if (!table[i].func) {
3003                                 cprintf_error(listener, "Invalid command\n");
3004                                 goto do_next;
3005                         }
3006
3007                         status = table[i].func(listener, argc - 1, argv + 1);
3008                         goto do_next;
3009                 }
3010         }
3011
3012         /*
3013          *      No such command
3014          */
3015         if (!len) {
3016                 if ((strcmp(argv[0], "help") == 0) ||
3017                     (strcmp(argv[0], "?") == 0)) {
3018                         int recursive;
3019
3020                 do_help:
3021                         if ((argc > 1) && (strcmp(argv[1], "-r") == 0)) {
3022                                 recursive = true;
3023                                 argc--;
3024                                 argv++;
3025                         } else {
3026                                 recursive = false;
3027                         }
3028
3029                         print_help(listener, argc - 1, argv + 1, table, recursive);
3030                         goto do_next;
3031                 }
3032
3033                 cprintf_error(listener, "Unknown command \"%s\"\n",
3034                               argv[0]);
3035         }
3036
3037  do_next:
3038         r = fr_channel_write(listener->fd, FR_CHANNEL_CMD_STATUS, &status, sizeof(status));
3039         if (r <= 0) goto do_close;
3040
3041         return 0;
3042 }
3043
3044
3045 /*
3046  *      Write 32-bit magic number && version information.
3047  */
3048 static int command_write_magic(int newfd,
3049 #ifndef WITH_TCP
3050                                UNUSED
3051 #endif
3052                                listen_socket_t *sock
3053         )
3054 {
3055         ssize_t r;
3056         uint32_t magic;
3057         fr_channel_type_t channel;
3058         char buffer[16];
3059
3060         r = fr_channel_read(newfd, &channel, buffer, 8);
3061         if (r <= 0) {
3062         do_close:
3063                 ERROR("Cannot talk to socket: %s",
3064                       fr_syserror(errno));
3065                 return -1;
3066         }
3067
3068         magic = htonl(0xf7eead16);
3069         if ((r != 8) || (channel != FR_CHANNEL_INIT_ACK) ||
3070             (memcmp(&magic, &buffer, sizeof(magic)) != 0)) {
3071                 ERROR("Incompatible versions");
3072                 return -1;
3073         }
3074
3075         r = fr_channel_write(newfd, FR_CHANNEL_INIT_ACK, buffer, 8);
3076         if (r <= 0) goto do_close;
3077
3078 #ifdef WITH_TCP
3079         /*
3080          *      Write an initial challenge
3081          */
3082         if (sock) {
3083                 int i;
3084                 fr_cs_buffer_t *co;
3085
3086                 co = talloc_zero(sock, fr_cs_buffer_t);
3087                 sock->packet = (void *) co;
3088
3089                 for (i = 0; i < 16; i++) {
3090                         co->buffer[i] = fr_rand();
3091                 }
3092
3093                 r = fr_channel_write(newfd, FR_CHANNEL_AUTH_CHALLENGE, co->buffer, 16);
3094                 if (r <= 0) goto do_close;
3095         }
3096 #endif
3097
3098         return 0;
3099 }
3100
3101 #ifdef WITH_TCP
3102 static int command_tcp_recv(rad_listen_t *this)
3103 {
3104         ssize_t r;
3105         listen_socket_t *sock = this->data;
3106         fr_cs_buffer_t *co = (void *) sock->packet;
3107         fr_channel_type_t channel;
3108
3109         if (!co) {
3110         do_close:
3111                 command_close_socket(this);
3112                 return 0;
3113         }
3114
3115         if (!co->auth) {
3116                 uint8_t expected[16];
3117
3118                 r = fr_channel_read(this->fd, &channel, co->buffer, 16);
3119                 if ((r != 16) || (channel != FR_CHANNEL_AUTH_RESPONSE)) {
3120                         goto do_close;
3121                 }
3122
3123                 fr_hmac_md5(expected, (void const *) sock->client->secret,
3124                             strlen(sock->client->secret),
3125                             (uint8_t *) co->buffer, 16);
3126
3127                 if (rad_digest_cmp(expected,
3128                                    (uint8_t *) co->buffer + 16, 16 != 0)) {
3129                         ERROR("radmin failed challenge: Closing socket");
3130                         goto do_close;
3131                 }
3132
3133                 co->auth = true;
3134                 co->offset = 0;
3135         }
3136
3137         return command_domain_recv_co(this, co);
3138 }
3139
3140
3141 /*
3142  *      Should never be called.  The functions should just call write().
3143  */
3144 static int command_tcp_send(UNUSED rad_listen_t *listener, UNUSED REQUEST *request)
3145 {
3146         return 0;
3147 }
3148 #endif
3149
3150 static int command_domain_recv(rad_listen_t *listener)
3151 {
3152         fr_command_socket_t *sock = listener->data;
3153
3154         return command_domain_recv_co(listener, &sock->co);
3155 }
3156
3157 static int command_domain_accept(rad_listen_t *listener)
3158 {
3159         int newfd;
3160         rad_listen_t *this;
3161         socklen_t salen;
3162         struct sockaddr_storage src;
3163         fr_command_socket_t *sock = listener->data;
3164
3165         salen = sizeof(src);
3166
3167         DEBUG2(" ... new connection request on command socket");
3168
3169         newfd = accept(listener->fd, (struct sockaddr *) &src, &salen);
3170         if (newfd < 0) {
3171                 /*
3172                  *      Non-blocking sockets must handle this.
3173                  */
3174                 if (errno == EWOULDBLOCK) {
3175                         return 0;
3176                 }
3177
3178                 DEBUG2(" ... failed to accept connection");
3179                 return 0;
3180         }
3181
3182 #ifdef HAVE_GETPEEREID
3183         /*
3184          *      Perform user authentication.
3185          */
3186         if (sock->peercred && (sock->uid_name || sock->gid_name)) {
3187                 uid_t uid;
3188                 gid_t gid;
3189
3190                 if (getpeereid(newfd, &uid, &gid) < 0) {
3191                         ERROR("Failed getting peer credentials for %s: %s",
3192                                sock->path, fr_syserror(errno));
3193                         close(newfd);
3194                         return 0;
3195                 }
3196
3197                 /*
3198                  *      Only do UID checking if the caller is
3199                  *      non-root.  The superuser can do anything, so
3200                  *      we might as well let them.
3201                  */
3202                 if (uid != 0) do {
3203                         /*
3204                          *      Allow entry if UID or GID matches.
3205                          */
3206                         if (sock->uid_name && (sock->uid == uid)) break;
3207                         if (sock->gid_name && (sock->gid == gid)) break;
3208
3209                         if (sock->uid_name && (sock->uid != uid)) {
3210                                 ERROR("Unauthorized connection to %s from uid %ld",
3211
3212                                        sock->path, (long int) uid);
3213                                 close(newfd);
3214                                 return 0;
3215                         }
3216
3217                         if (sock->gid_name && (sock->gid != gid)) {
3218                                 ERROR("Unauthorized connection to %s from gid %ld",
3219                                        sock->path, (long int) gid);
3220                                 close(newfd);
3221                                 return 0;
3222                         }
3223
3224                 } while (0);
3225         }
3226 #endif
3227
3228         if (command_write_magic(newfd, NULL) < 0) {
3229                 close(newfd);
3230                 return 0;
3231         }
3232
3233         /*
3234          *      Add the new listener.
3235          */
3236         this = listen_alloc(listener, listener->type);
3237         if (!this) return 0;
3238
3239         /*
3240          *      Copy everything, including the pointer to the socket
3241          *      information.
3242          */
3243         sock = this->data;
3244         memcpy(this, listener, sizeof(*this));
3245         this->status = RAD_LISTEN_STATUS_INIT;
3246         this->next = NULL;
3247         this->data = sock;      /* fix it back */
3248
3249         sock->magic = COMMAND_SOCKET_MAGIC;
3250         sock->user[0] = '\0';
3251         sock->path = ((fr_command_socket_t *) listener->data)->path;
3252         sock->co.offset = 0;
3253         sock->co.mode = ((fr_command_socket_t *) listener->data)->co.mode;
3254
3255         this->fd = newfd;
3256         this->recv = command_domain_recv;
3257
3258         /*
3259          *      Tell the event loop that we have a new FD
3260          */
3261         radius_update_listener(this);
3262
3263         return 0;
3264 }
3265
3266
3267 /*
3268  *      Send an authentication response packet
3269  */
3270 static int command_domain_send(UNUSED rad_listen_t *listener,
3271                                UNUSED REQUEST *request)
3272 {
3273         return 0;
3274 }
3275
3276
3277 static int command_socket_encode(UNUSED rad_listen_t *listener,
3278                                  UNUSED REQUEST *request)
3279 {
3280         return 0;
3281 }
3282
3283
3284 static int command_socket_decode(UNUSED rad_listen_t *listener,
3285                                  UNUSED REQUEST *request)
3286 {
3287         return 0;
3288 }
3289
3290 #endif /* WITH_COMMAND_SOCKET */