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