The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
radmin.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: c9c54a2c6f284dc31dfb0cb6632bfa7c6374cd4b $
19 *
20 * @file src/listen/control/radmin.c
21 * @brief Control a running radiusd process.
22 *
23 * @copyright 2012-2016 The FreeRADIUS server project
24 * @copyright 2016 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25 * @copyright 2012 Alan DeKok (aland@deployingradius.com)
26 */
27RCSID("$Id: c9c54a2c6f284dc31dfb0cb6632bfa7c6374cd4b $")
28
29#include <assert.h>
30
31#include <pwd.h>
32#include <grp.h>
33#include <fcntl.h>
34
35#ifdef HAVE_GETOPT_H
36# include <getopt.h>
37#endif
38
39#ifdef HAVE_SYS_STAT_H
40# include <sys/stat.h>
41#endif
42
43#ifdef HAVE_LIBREADLINE
44
45# include <stdio.h>
46
47DIAG_OFF(strict-prototypes)
48#if defined(HAVE_READLINE_READLINE_H)
49# include <readline/readline.h>
50# define USE_READLINE (1)
51#elif defined(HAVE_READLINE_H)
52# include <readline.h>
53# define USE_READLINE (1)
54#endif /* !defined(HAVE_READLINE_H) */
55DIAG_ON(strict-prototypes)
56
57#ifdef HAVE_READLINE_HISTORY
58# if defined(HAVE_READLINE_HISTORY_H)
59# include <readline/history.h>
60# define USE_READLINE_HISTORY (1)
61# elif defined(HAVE_HISTORY_H)
62# include <history.h>
63# define USE_READLINE_HISTORY (1)
64#endif /* defined(HAVE_READLINE_HISTORY_H) */
65#endif /* HAVE_READLINE_HISTORY */
66#endif /* HAVE_LIBREADLINE */
67
68#define LOG_PREFIX "radmin"
69
70#include <freeradius-devel/server/cf_parse.h>
71#include <freeradius-devel/server/cf_file.h>
72#include <freeradius-devel/server/main_config.h>
73#include <freeradius-devel/server/radmin.h>
74
75#include <freeradius-devel/util/conf.h>
76#include <freeradius-devel/util/md5.h>
77#include <freeradius-devel/util/skip.h>
78#include <freeradius-devel/util/socket.h>
79
80#ifdef USE_READLINE_HISTORY
81#ifndef READLINE_MAX_HISTORY_LINES
82# define READLINE_MAX_HISTORY_LINES 1000
83#endif
84#endif
85
86#include "conduit.h"
87
88/*
89 * For configuration file stuff.
90 */
91static char const *progname = "radmin";
92static char const *radmin_version = RADIUSD_VERSION_BUILD("radmin");
93
94typedef enum {
95 RADMIN_CONN_NONE = 0, //!< Don't know, never connected.
96 RADMIN_CONN_UNIX, //!< Connect via unix socket.
97 RADMIN_CONN_TCP //!< Connect via TCP.
99
100/** A connection to a server
101 *
102 */
103typedef struct {
104 fr_event_list_t *event_list; //!< Event list this fd is serviced by.
105 int fd; //!< Control socket descriptor.
106
107 char *last_command; //!< Last command we executed on this connection.
108 char *server; //!< Path or FQDN of server we're connected to.
109 char *secret; //!< We use to authenticate ourselves to the server.
110
111 bool nonblock; //!< Whether this connection should operate in
112 //!< non-blocking mode.
113 bool connected; //!< Whether this connection is currently connected.
115 radmin_conn_type_t type; //!< Type of connection.
117
118/** Radmin state
119 *
120 * Many of the readline functions don't take callbacks, so we need
121 * to use a global structure to communicate radmin state.
122 */
123typedef struct {
124 fr_event_list_t *event_list; //!< Our main event list.
125
126 radmin_conn_t *active_conn; //!< Connection to remote entity.
128
129/** Main radmin state
130 *
131 */
132//static radmin_state_t state;
133
134static bool echo = false;
135static char const *secret = NULL;
136static bool unbuffered = false;
137static bool use_readline = true;
138
140 .dst = L_DST_NULL,
141 .colourise = false,
142 .timestamp = L_TIMESTAMP_ON,
143 .fd = -1,
144 .file = NULL,
145};
146static int sockfd = -1;
147static char io_buffer[65536];
148
149#ifdef USE_READLINE
150#define CMD_MAX_EXPANSIONS (128)
151static int radmin_num_expansions = 0;
152static char *radmin_expansions[CMD_MAX_EXPANSIONS] = {0};
153#endif
154
155#define MAX_STACK (64)
156static int stack_depth;
157static char cmd_buffer[65536];
158static char *stack[MAX_STACK];
159
160static fr_cmd_t *local_cmds = NULL;
161
162static NEVER_RETURNS void usage(int status)
163{
164 FILE *output = status ? stderr : stdout;
165 fprintf(output, "Usage: %s [ args ]\n", progname);
166 fprintf(output, " -d <confdir> Configuration file directory. (defaults to " CONFDIR ").");
167 fprintf(output, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
168 fprintf(output, " -e command Execute 'command' and then exit.\n");
169 fprintf(output, " -E Echo commands as they are being executed.\n");
170 fprintf(output, " -f socket_file Open socket_file directly, without reading radius.conf\n");
171 fprintf(output, " -h Print usage help information.\n");
172 fprintf(output, " -i input_file Read commands from 'input_file'.\n");
173 fprintf(output, " -l <log_file> Commands which are executed will be written to this file.\n");
174 fprintf(output, " -n name Read ${confdir}/name.conf instead of ${confdir}/radiusd.conf\n");
175 fprintf(output, " -q Reduce output verbosity\n");
176 fprintf(output, " -s <server> Look in named server for name of control socket.\n");
177 fprintf(output, " -S <secret> Use argument as shared secret for authentication to the server.\n");
178 fprintf(output, " -x Increase output verbosity\n");
179 fr_exit_now(status);
180}
181
182static int client_socket(char const *server)
183{
184 int fd;
185 uint16_t port;
186 fr_ipaddr_t ipaddr;
187 char *p, buffer[1024];
188
189 strlcpy(buffer, server, sizeof(buffer));
190
191 p = strchr(buffer, ':');
192 if (!p) {
193 port = FR_RADMIN_PORT;
194 } else {
195 port = atoi(p + 1);
196 *p = '\0';
197 }
198
199 if (fr_inet_hton(&ipaddr, AF_INET, buffer, false) < 0) {
200 fprintf(stderr, "%s: Failed looking up host %s: %s\n",
201 progname, buffer, fr_syserror(errno));
202 fr_exit_now(EXIT_FAILURE);
203 }
204
205 fd = fr_socket_client_tcp(NULL, NULL, &ipaddr, port, false);
206 if (fd < 0) {
207 fprintf(stderr, "%s: Failed opening socket %s: %s\n",
208 progname, server, fr_syserror(errno));
209 fr_exit_now(EXIT_FAILURE);
210 }
211
212 return fd;
213}
214
215static ssize_t do_challenge(int fd)
216{
217 ssize_t r;
218 fr_conduit_type_t conduit;
219 uint8_t challenge[16];
220
221 challenge[0] = 0x00;
222
223 /*
224 * When connecting over a socket, the server challenges us.
225 */
226 r = fr_conduit_read(fd, &conduit, challenge, sizeof(challenge));
227 if (r <= 0) return r;
228
229 if ((r != 16) || (conduit != FR_CONDUIT_AUTH_CHALLENGE)) {
230 fprintf(stderr, "%s: Failed to read challenge.\n",
231 progname);
232 fr_exit_now(EXIT_FAILURE);
233 }
234
235 if (!secret) return -1;
236
237 fr_hmac_md5(challenge, (uint8_t const *) secret, strlen(secret),
238 challenge, sizeof(challenge));
239
240 r = fr_conduit_write(fd, FR_CONDUIT_AUTH_RESPONSE, challenge, sizeof(challenge));
241 if (r <= 0) return r;
242
243 /*
244 * If the server doesn't like us, it just closes the
245 * socket. So we don't look for an ACK.
246 */
247
248 return r;
249}
250
251
252/*
253 * Returns -1 on failure. 0 on connection failed. +1 on OK.
254 */
255static ssize_t flush_conduits(int fd, char *buffer, size_t bufsize)
256{
257 ssize_t r;
258#ifdef USE_READLINE
259 char *p, *str;
260#endif
261 uint32_t status;
262 fr_conduit_type_t conduit;
263
264 while (true) {
265 uint32_t notify;
266
267 r = fr_conduit_read(fd, &conduit, buffer, bufsize - 1);
268 if (r <= 0) return r;
269
270 buffer[r] = '\0'; /* for C strings */
271
272 switch (conduit) {
274 fprintf(stdout, "%s", buffer);
275 break;
276
278 fprintf(stderr, "ERROR: %s", buffer);
279 break;
280
282 if (r < 4) return 1;
283
284 memcpy(&status, buffer, sizeof(status));
285 status = ntohl(status);
286 return status;
287
289 if (r < 4) return -1;
290
291 memcpy(&notify, buffer, sizeof(notify));
292 notify = ntohl(notify);
293
294 if (notify == FR_NOTIFY_UNBUFFERED) unbuffered = true;
295 if (notify == FR_NOTIFY_BUFFERED) unbuffered = false;
296
297 break;
298
299#ifdef USE_READLINE
301 str = buffer;
302
303 for (p = buffer; p < (buffer + r); p++) {
304 if (*p == '\n') {
305 size_t len;
306
307 len = p - str;
308
309 MEM(radmin_expansions[radmin_num_expansions] = malloc(len + 1));
310 memcpy(radmin_expansions[radmin_num_expansions], str, len);
311 radmin_expansions[radmin_num_expansions][len] = '\0';
312 radmin_num_expansions++;
313
314 str = p + 1;
315 }
316
317 if (radmin_num_expansions >= CMD_MAX_EXPANSIONS) break;
318 }
319 break;
320#endif
321
322 default:
323 fprintf(stderr, "Unexpected response %02x\n", conduit);
324 return -1;
325 }
326 }
327
328 /* never gets here */
329}
330
331
332/*
333 * Returns -1 on failure. 0 on connection failed. +1 on OK.
334 */
335static ssize_t run_command(int fd, char const *command,
336 char *buffer, size_t bufsize)
337{
338 ssize_t r;
339 char const *p = command;
340
342 if (!*p) return FR_CONDUIT_SUCCESS;
343
344 if (echo) {
345 fprintf(stdout, "%s\n", command);
346 }
347
348 /*
349 * Write the text to the socket.
350 */
351 r = fr_conduit_write(fd, FR_CONDUIT_STDIN, p, strlen(p));
352 if (r <= 0) return r;
353
354 return flush_conduits(fd, buffer, bufsize);
355}
356
357static int do_connect(int *out, char const *file, char const *server)
358{
359 int fd;
360 ssize_t r;
361 fr_conduit_type_t conduit;
362 char buffer[65536];
363
364 uint32_t magic;
365
366 /*
367 * Close stale file descriptors
368 */
369 if (*out != -1) {
370 close(*out);
371 *out = -1;
372 }
373
374 if (file) {
375 /*
376 * FIXME: Get destination from command line, if possible?
377 */
378 fd = fr_socket_client_unix(file, false);
379 if (fd < 0) {
380 fr_perror("radmin");
381 if (errno == ENOENT) {
382 fprintf(stderr, "Perhaps you need to run the commands:");
383 fprintf(stderr, "\tcd " CONFDIR "\n");
384 fprintf(stderr, "\tln -s sites-available/control-socket "
385 "sites-enabled/control-socket\n");
386 fprintf(stderr, "and then re-start the server?\n");
387 }
388 return -1;
389 }
390 } else {
391 fd = client_socket(server);
392 }
393
394 /*
395 * Only works for BSD, but Linux allows us
396 * to mask SIGPIPE, so that's fine.
397 */
398#ifdef SO_NOSIGPIPE
399 {
400 int set = 1;
401
402 setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
403 }
404#endif
405
406 /*
407 * Set up the initial header data.
408 */
409 magic = FR_CONDUIT_MAGIC;
410 magic = htonl(magic);
411 memcpy(buffer, &magic, sizeof(magic));
412 memset(buffer + sizeof(magic), 0, sizeof(magic));
413
415 if (r <= 0) {
416 do_close:
417 fprintf(stderr, "%s: Error in socket: %s\n",
418 progname, fr_syserror(errno));
419 close(fd);
420 return -1;
421 }
422
423 r = fr_conduit_read(fd, &conduit, buffer + 8, 8);
424 if (r <= 0) goto do_close;
425
426 if ((r != 8) || (conduit != FR_CONDUIT_INIT_ACK) ||
427 (memcmp(buffer, buffer + 8, 8) != 0)) {
428 fprintf(stderr, "%s: Incompatible versions\n", progname);
429 close(fd);
430 return -1;
431 }
432
433 if (secret) {
434 r = do_challenge(fd);
435 if (r <= 0) goto do_close;
436 }
437
438 *out = fd;
439
440 return 0;
441}
442
443
444static char readline_buffer[1024];
445
446/*
447 * Wrapper around readline which does the "right thing" depending
448 * on whether we're reading from a file or not. It also ignores
449 * blank lines and comments, which the main readline() API
450 * doesn't do.
451 */
452static char *my_readline(char const *prompt, FILE *fp_in, FILE *fp_out)
453{
454 char *line, *p;
455
456#ifdef USE_READLINE
457 if (use_readline) return readline(prompt);
458#endif
459
460 if (prompt && *prompt) puts(prompt);
461 fflush(fp_out);
462
463 line = fgets((char *) readline_buffer, sizeof(readline_buffer), fp_in);
464 if (!line) return NULL;
465
466 p = strchr(line, '\n');
467 if (!p) {
468 fprintf(stderr, "Input line too long\n");
469 return NULL;
470 }
471 *p = '\0';
472
474
475 /*
476 * Comments: keep going.
477 */
478 if (line[0] == '#') {
479 *line = '\0';
480 return line;
481 }
482
483 /*
484 * Strip off CR / LF
485 */
486 for (p = line; *p != '\0'; p++) {
487 if ((p[0] == '\r') ||
488 (p[0] == '\n')) {
489 p[0] = '\0';
490 break;
491 }
492 }
493
494 return line;
495}
496
497#ifdef USE_READLINE
498static void radmin_free(char *line)
499{
500 /*
501 * Was read from stdin, so "line" == "readline_buffer"
502 */
503 if (!use_readline) return;
504
505 free(line);
506}
507#else
508#define radmin_free(_x)
509#endif
510
511/*
512 * Copies the (possible partial) command to the command buffer,
513 * so that we can send the full command over to the server.
514 */
515static ssize_t cmd_copy(char const *cmd)
516{
517 size_t len;
518 char *p = stack[stack_depth];
519
520 if (stack_depth > 0) *(p++) = ' ';
521
522 /*
523 * No input, allow a trailing space so that tab
524 * completion works.
525 */
526 if (!*cmd) {
527 return p - cmd_buffer;
528 }
529
530 len = strlcpy(p, cmd, cmd_buffer + sizeof(cmd_buffer) - p);
531 if ((p + len) >= (cmd_buffer + sizeof(cmd_buffer))) {
532 fprintf(stderr, "Command too long\n");
533 return -1;
534 }
535
536 /*
537 * Trash trailing spaces.
538 */
539 for (p += len;
540 p > cmd_buffer;
541 p--) {
542 if (!isspace((uint8_t) p[-1])) break;
543 p[-1] = '\0';
544 }
545
546 return p - cmd_buffer;
547}
548
549#ifdef USE_READLINE
550static int radmin_help(UNUSED int count, UNUSED int key)
551{
552 ssize_t len;
553
554 printf("\n");
555
556 len = cmd_copy(rl_line_buffer);
557 if (len < 0) return 0;
558
559 /*
560 * Special-case help for local commands.
561 */
562 if ((len >= 5) && strncmp(cmd_buffer, "local", 5) == 0) {
564 rl_on_new_line();
565 return 0;
566 }
567
568 if (len > 0) {
570 } else {
571 /*
572 * Don't write zero bytes to the other side...
573 */
574 (void) fr_conduit_write(sockfd, FR_CONDUIT_HELP, " ", 1);
575 }
576
577 (void) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
578
579 rl_on_new_line();
580 return 0;
581}
582
583static char *
584radmin_expansion_walk(UNUSED const char *text, int state)
585{
586 static int current;
587 char *name;
588
589 if (!state) {
590 current = 0;
591 }
592
593 /*
594 * fr_command_completions() takes care of comparing things to
595 * suppress expansions which don't match "text"
596 */
597 if (current >= radmin_num_expansions) return NULL;
598
599 name = radmin_expansions[current];
600
601 radmin_expansions[current++] = NULL;
602
603 return name;
604}
605
606static char **
607radmin_completion(const char *text, int start, UNUSED int end)
608{
609 ssize_t len;
610
611 rl_attempted_completion_over = 1;
612
613 radmin_num_expansions = 0;
614
615 len = cmd_copy(rl_line_buffer);
616 if (len < 0) return NULL;
617
618 /*
619 * Handle local commands specially.
620 */
621 if (strncmp(cmd_buffer, "local", 5) == 0) {
622 int num;
623 char **expansions = &radmin_expansions[0];
624 char const **expansions_const;
625
626 memcpy(&expansions_const, &expansions, sizeof(expansions)); /* const issues */
628 CMD_MAX_EXPANSIONS, expansions_const);
629 if (num <= 0) return NULL;
630
631 radmin_num_expansions = num;
632 return rl_completion_matches(text, radmin_expansion_walk);
633 }
634
635 start += len;
636
637 if (start > 65535) return NULL;
638
639 io_buffer[0] = (start >> 8) & 0xff;
640 io_buffer[1] = start & 0xff;
641
642 /*
643 * Note that "text" is the PARTIAL thing we're trying to complete.
644 * And "start" is the OFFSET from rl_line_buffer where we want to
645 * do the completion. It's all rather idiotic.
646 */
647 memcpy(io_buffer + 2, cmd_buffer, len);
648
650
651 (void) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
652
653 return rl_completion_matches(text, radmin_expansion_walk);
654}
655
656#endif
657
658#ifndef USE_READLINE_HISTORY
659# define add_history(line)
660# define write_history(history_file)
661#endif
662
663static int check_server(CONF_SECTION *subcs, uid_t uid, gid_t gid, char const **file_p, char const **server_p)
664{
665 int rcode;
666 char const *value, *file = NULL;
667 CONF_SECTION *cs;
668 CONF_PAIR *cp;
669 char const *uid_name = NULL;
670 char const *gid_name = NULL;
671 char const *server;
672 struct passwd *pwd;
673 struct group *grp;
674
675 cp = cf_pair_find(subcs, "namespace");
676 if (!cp) return 0;
677
678 value = cf_pair_value(cp);
679 if (!value) return 0;
680
681 if (strcmp(value, "control") != 0) return 0;
682
683 server = cf_section_name2(subcs);
684 *server_p = server; /* need this for error messages */
685
686 /* listen {} */
687 cs = cf_section_find(subcs, "listen", NULL);
688 if (!cs) {
689 fprintf(stderr, "%s: Failed parsing 'listen{}' section in 'server %s {...}'\n", progname, server);
690 return -1;
691 }
692
693 /* transport = <transport> */
694 cp = cf_pair_find(cs, "transport");
695 if (!cp) return 0;
696
697 value = cf_pair_value(cp);
698 if (!value) return 0;
699
700 /* <transport> { ... } */
701 subcs = cf_section_find(cs, value, NULL);
702 if (!subcs) {
703 fprintf(stderr, "%s: Failed parsing the '%s {}' section in 'server %s {...}'\n",
704 progname, value, server);
705 return -1;
706 }
707
708 /*
709 * Now find the socket name (sigh)
710 */
711 rcode = cf_pair_parse(NULL, subcs, "filename",
713 if (rcode < 0) {
714 fprintf(stderr, "%s: Failed parsing listen section 'socket'\n", progname);
715 return -1;
716 }
717
718 if (!file) {
719 fprintf(stderr, "%s: No path given for socket\n", progname);
720 return -1;
721 }
722
723 *file_p = file;
724
725 /*
726 * If we're root, just use the first one we find
727 */
728 if (uid == 0) return 1;
729
730 /*
731 * Check UID and GID.
732 */
733 rcode = cf_pair_parse(NULL, subcs, "uid",
735 if (rcode < 0) {
736 fprintf(stderr, "%s: Failed parsing listen section 'uid'\n", progname);
737 return -1;
738 }
739
740 if (!uid_name || !*uid_name) return 1;
741
742 pwd = getpwnam(uid_name);
743 if (!pwd) {
744 fprintf(stderr, "%s: Failed getting UID for user %s: %s\n", progname, uid_name,
745 fr_syserror(errno));
746 return -1;
747 }
748
749 if (uid != pwd->pw_uid) return 0;
750
751 rcode = cf_pair_parse(NULL, subcs, "gid",
753 if (rcode < 0) {
754 fprintf(stderr, "%s: Failed parsing listen section 'gid'\n", progname);
755 return -1;
756 }
757
758 if (!gid_name || !*gid_name) return 1;
759
760 grp = getgrnam(gid_name);
761 if (!grp) {
762 fprintf(stderr, "%s: Failed resolving gid of group %s: %s\n",
763 progname, gid_name, fr_syserror(errno));
764 return -1;
765 }
766
767 if (gid != grp->gr_gid) return 0;
768
769 return 1;
770}
771
772static int cmd_test(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
773{
774 fprintf(fp, "We're testing stuff!\n");
775
776 return 0;
777}
778
779/*
780 * Local radmin commands
781 */
783 {
784 .parent = "local",
785 .name = "test",
786 .func = cmd_test,
787 .help = "Test stuff",
788 .read_only = true
789 },
790
792};
793
795
796static int local_command(char *line)
797{
798 int argc, ret;
799
801 if (argc < 0) {
802 fr_perror("Failed parsing local command");
803 return -1;
804 }
805
806 if (!local_info.runnable) {
807 return 0;
808 }
809
810 ret = fr_command_run(stderr, stdout, &local_info, false);
811 fflush(stdout);
812 fflush(stderr);
813
814 /*
815 * reset "info" to be a top-level context again.
816 */
817 (void) fr_command_clear(0, &local_info);
818
819 if (ret < 0) return ret;
820
821 return 1;
822
823}
824
825
826#define MAX_COMMANDS (256)
827
828int main(int argc, char **argv)
829{
830 int c;
831 bool quiet = false;
832 char *line = NULL;
833 ssize_t result;
834 char const *file = NULL;
835 char const *name = "radiusd";
836 char const *input_file = NULL;
837 FILE *inputfp = stdin;
838 char const *server = NULL;
839 fr_dict_t *dict = NULL;
840
841 char const *confdir = RADIUS_DIR;
842 char const *dict_dir = DICTDIR;
843#ifdef USE_READLINE_HISTORY
844 char history_file[PATH_MAX];
845#endif
846
847 TALLOC_CTX *autofree;
848
849 char *commands[MAX_COMMANDS];
850 int num_commands = 0;
851
852 int exit_status = EXIT_SUCCESS;
853
854 char const *prompt = "radmin> ";
855 char prompt_buffer[1024];
856
857 /*
858 * Must be called first, so the handler is called last
859 */
861
863
864#ifndef NDEBUG
865 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
866 fr_perror("radmin");
867 fr_exit_now(EXIT_FAILURE);
868 }
869#endif
870
871 talloc_set_log_stderr();
872
873 if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) {
874 progname = argv[0];
875 } else {
876 progname++;
877 }
878
880 secret = NULL;
881
882 while ((c = getopt(argc, argv, "d:D:hi:e:Ef:n:qs:S:x")) != -1) switch (c) {
883 case 'd':
884 if (file) {
885 fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
886 fr_exit_now(EXIT_FAILURE);
887 }
888 confdir = optarg;
889 break;
890
891 case 'D':
892 dict_dir = optarg;
893 break;
894
895 case 'e':
896 if (num_commands >= MAX_COMMANDS) {
897 fprintf(stderr, "%s: Too many '-e'\n", progname);
898 fr_exit_now(EXIT_FAILURE);
899 }
900
901 commands[num_commands++] = optarg;
902 break;
903
904 case 'E':
905 echo = true;
906 break;
907
908 case 'f':
909 confdir = NULL;
910 file = optarg;
911 break;
912
913 default:
914 case 'h':
915 usage(0); /* never returns */
916
917 case 'i':
918 /*
919 * optarg check is to quiet clang scan
920 */
921 if (optarg && (strcmp(optarg, "-") != 0)) input_file = optarg;
922 quiet = true;
923 break;
924
925 case 'l':
926 radmin_log.file = optarg;
927 break;
928
929 case 'n':
930 name = optarg;
931 break;
932
933 case 'q':
934 quiet = true;
935 if (fr_debug_lvl > 0) fr_debug_lvl--;
936 break;
937
938 case 's':
939 if (file) {
940 fprintf(stderr, "%s: -s and -f cannot be used together.\n", progname);
941 usage(1);
942 }
943 server = optarg;
944 break;
945
946 case 'S':
947 secret = talloc_strdup(autofree, optarg);
948 break;
949
950 case 'x':
951 fr_debug_lvl++;
952 break;
953 }
954
955 /*
956 * Mismatch between the binary and the libraries it depends on
957 */
959 fr_perror("radmin");
960 fr_exit_now(EXIT_FAILURE);
961 }
962
963 if (confdir) {
964 int rcode;
965 uid_t uid;
966 gid_t gid;
967 CONF_SECTION *cs, *subcs;
968 CONF_PAIR *cp;
969
970 file = NULL; /* MUST read it from the conf_file now */
971
972 snprintf(io_buffer, sizeof(io_buffer), "%s/%s.conf", confdir, name);
973
974 /*
975 * Need to read in the dictionaries, else we may get
976 * validation errors when we try and parse the config.
977 */
978 if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
979 fr_perror("radmin");
980 fr_exit_now(64);
981 }
982
984 fr_perror("radmin");
985 fr_exit_now(64);
986 }
987
988 if (fr_dict_read(dict, confdir, FR_DICTIONARY_FILE) == -1) {
989 fr_perror("radmin");
990 fr_exit_now(64);
991 }
992
993 cs = cf_section_alloc(autofree, NULL, "main", NULL);
994 if (!cs) fr_exit_now(EXIT_FAILURE);
995
996 if ((cf_file_read(cs, io_buffer, true) < 0) || (cf_section_pass2(cs) < 0)) {
997 fprintf(stderr, "%s: Errors reading or parsing %s\n", progname, io_buffer);
998 error:
999 fr_exit_now(EXIT_FAILURE);
1000 }
1001
1002 uid = getuid();
1003 gid = getgid();
1004
1005 /*
1006 * We are looking for: server whatever { namespace="control" ... }
1007 */
1008 if (server) {
1009 subcs = cf_section_find(cs, "server", server);
1010 if (!subcs) {
1011 fprintf(stderr, "%s: Could not find virtual server %s {}\n", progname, server);
1012 goto error;
1013 }
1014
1015 rcode = check_server(subcs, uid, gid, &file, &server);
1016 if (rcode < 0) goto error;
1017 if (rcode == 0) file = NULL;
1018
1019 } else {
1020 for (subcs = cf_section_find_next(cs, NULL, "server", CF_IDENT_ANY);
1021 subcs != NULL;
1022 subcs = cf_section_find_next(cs, subcs, "server", CF_IDENT_ANY)) {
1023 rcode = check_server(subcs, uid, gid, &file, &server);
1024 if (rcode < 0) goto error;
1025 if (rcode == 1) break;
1026 }
1027 }
1028
1029 if (!file) {
1030 fprintf(stderr, "%s: Could not find control socket in %s (server %s {})\n", progname, io_buffer, server);
1031 goto error;
1032 }
1033
1034 /*
1035 * Log the commands we've run.
1036 */
1037 if (!radmin_log.file) {
1038 subcs = cf_section_find(cs, "log", NULL);
1039 if (subcs) {
1040 cp = cf_pair_find(subcs, "radmin");
1041 if (cp) {
1043
1044 if (!radmin_log.file) {
1045 fprintf(stderr, "%s: Invalid value for 'radmin' log destination", progname);
1046 goto error;
1047 }
1048 }
1049 }
1050 }
1051
1052 if (radmin_log.file) {
1053 radmin_log.fd = open(radmin_log.file, O_APPEND | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1054 if (radmin_log.fd < 0) {
1055 fprintf(stderr, "%s: Failed opening %s: %s\n", progname, radmin_log.file, fr_syserror(errno));
1056 goto error;
1057 }
1058
1060 }
1061 }
1062
1063 if (input_file) {
1064 inputfp = fopen(input_file, "r");
1065 if (!inputfp) {
1066 fprintf(stderr, "%s: Failed opening %s: %s\n", progname, input_file, fr_syserror(errno));
1067 goto error;
1068 }
1069 }
1070
1071 if (!file) {
1072 fprintf(stderr, "%s: Failed to find socket file name\n",
1073 progname);
1074 goto error;
1075 }
1076
1077 /*
1078 * Check if stdin is a TTY only if input is from stdin
1079 */
1080 if (input_file || !isatty(STDIN_FILENO)) {
1081 use_readline = false;
1082 quiet = true;
1083 }
1084
1085 if (use_readline) {
1086#ifdef USE_READLINE_HISTORY
1087 char const *home = getenv("HOME");
1088
1089 if (home) {
1090 using_history();
1091 stifle_history(READLINE_MAX_HISTORY_LINES);
1092 snprintf(history_file, sizeof(history_file), "%s/%s", home, ".radmin_history");
1093 read_history(history_file);
1094 }
1095#endif
1096#ifdef USE_READLINE
1097 rl_attempted_completion_function = radmin_completion;
1098#endif
1099 } else {
1100 prompt = NULL;
1101 }
1102
1103 /*
1104 * Prevent SIGPIPEs from terminating the process
1105 */
1106 signal(SIGPIPE, SIG_IGN);
1107
1108 if (do_connect(&sockfd, file, server) < 0) fr_exit_now(EXIT_FAILURE);
1109
1110 /*
1111 * Register local commands.
1112 */
1113 if (fr_command_add_multi(autofree, &local_cmds, NULL, NULL, cmd_table) < 0) {
1114 fprintf(stderr, "%s: Failed registering local commands: %s\n",
1116 goto error;
1117 }
1118
1120
1121 /*
1122 * Run commands from the command-line.
1123 */
1124 if (num_commands > 0) {
1125 int i;
1126
1127 for (i = 0; i < num_commands; i++) {
1128 result = run_command(sockfd, commands[i], io_buffer, sizeof(io_buffer));
1129 if (result < 0) fr_exit_now(EXIT_FAILURE);
1130
1131 if (result == FR_CONDUIT_FAIL) {
1132 exit_status = EXIT_FAILURE;
1133 goto exit;
1134 }
1135 }
1136
1137 if (unbuffered) {
1138 while (true) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
1139 }
1140
1141 /*
1142 * We're done all of the commands, exit now.
1143 */
1144 goto exit;
1145 }
1146
1147 if (!quiet) {
1148 printf("%s - FreeRADIUS Server administration tool.\n", radmin_version);
1149 printf("Copyright 2008-2019 The FreeRADIUS server project and contributors.\n");
1150 printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
1151 printf("PARTICULAR PURPOSE.\n");
1152 printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
1153 printf("GNU General Public License v2.\n");
1154 }
1155
1156 /*
1157 * FIXME: Do login?
1158 */
1159
1160#ifdef USE_READLINE
1161 (void) rl_bind_key('?', radmin_help);
1162#endif
1163
1164 stack_depth = 0;
1165 stack[0] = cmd_buffer;
1166
1167 while (1) {
1168 int retries;
1169 ssize_t len;
1170
1171 line = my_readline(prompt, inputfp, stdout);
1172
1173 if (!line) break;
1174
1175 if (!*line) goto next;
1176
1177 /*
1178 * Radmin supports a number of commands which are
1179 * valid in any context.
1180 */
1181 if (strcmp(line, "reconnect") == 0) {
1182 if (do_connect(&sockfd, file, server) < 0) {
1184 fr_exit_now(EXIT_FAILURE);
1185 }
1186 goto next;
1187 }
1188
1189 if (!secret && !stack_depth && (strncmp(line, "secret ", 7) == 0)) {
1191 if (!secret) {
1193 fr_exit_now(EXIT_FAILURE);
1194 }
1195
1196 if (do_challenge(sockfd) < 0) {
1198 fr_exit_now(EXIT_FAILURE);
1199 }
1200 goto next;
1201 }
1202
1203 /*
1204 * Quit the program
1205 */
1206 if (strcmp(line, "quit") == 0) {
1208 break;
1209 }
1210
1211 /*
1212 * Exit the current context.
1213 */
1214 if (strcmp(line, "exit") == 0) {
1215 if (!stack_depth) {
1217 break;
1218 }
1219
1220 stack_depth--;
1221 *stack[stack_depth] = '\0';
1222
1223 if (stack_depth == 0) {
1224 prompt = "radmin> ";
1225 } else {
1226 snprintf(prompt_buffer, sizeof(prompt_buffer), "... %s> ",
1227 stack[stack_depth - 1]);
1228 prompt = prompt_buffer;
1229 }
1230
1231 goto next;
1232 }
1233
1234 /*
1235 * Radmin also supports local commands which
1236 * modifies it's behavior. These commands MUST
1237 */
1238 if (!stack_depth && (strncmp(line, "local", 5) == 0)) {
1239 if (!isspace((uint8_t) line[5])) {
1240 fprintf(stderr, "'local' commands MUST be specified all on one line");
1241 goto next;
1242 }
1243
1244 /*
1245 * Parse and run the local command.
1246 */
1248 goto next;
1249 }
1250
1251 /*
1252 * Any other input is sent to the server.
1253 */
1254 retries = 0;
1255
1256 /*
1257 * If required, log commands to a radmin log file.
1258 */
1259 if (radmin_log.dst == L_DST_FILES) {
1260 fr_log(&radmin_log, L_INFO, __FILE__, __LINE__, "%s", line);
1261 }
1262
1263 len = cmd_copy(line);
1264 if (len < 0) {
1265 exit_status = EXIT_FAILURE;
1267 break;
1268 }
1269
1270 retry:
1271
1272 result = run_command(sockfd, cmd_buffer, io_buffer, sizeof(io_buffer));
1273 if (result < 0) {
1274 if (!quiet) fprintf(stderr, "... reconnecting ...\n");
1275
1276 if (do_connect(&sockfd, file, server) < 0) {
1278 fr_exit_now(EXIT_FAILURE);
1279 }
1280
1281 retries++;
1282 if (retries < 2) goto retry;
1283
1284 fprintf(stderr, "Failed to connect to server\n");
1286 fr_exit_now(EXIT_FAILURE);
1287
1288 } else if (result == FR_CONDUIT_FAIL) {
1289 fprintf(stderr, "Failed running command\n");
1290 exit_status = EXIT_FAILURE;
1291
1292 } else if (result == FR_CONDUIT_PARTIAL) {
1293 char *p;
1294
1295 if (stack_depth >= (MAX_STACK - 1)) {
1296 fprintf(stderr, "Too many sub-contexts running command\n");
1297 exit_status = EXIT_FAILURE;
1299 break;
1300 }
1301
1302 /*
1303 * Point the stack to the last entry.
1304 */
1305 p = stack[stack_depth];
1306 p += strlen(p);
1307 stack_depth++;
1308 stack[stack_depth] = p;
1309
1310 snprintf(prompt_buffer, sizeof(prompt_buffer), "... %s> ",
1311 stack[stack_depth - 1]);
1312 prompt = prompt_buffer;
1313
1314 } else {
1315 /*
1316 * Add only successful commands to the history.
1317 *
1318 * Don't add exit / quit / secret / etc.
1319 */
1320 if (use_readline) {
1322 write_history(history_file);
1323 }
1324 }
1325
1326 /*
1327 * SUCCESS and PARTIAL end up here too.
1328 */
1329 next:
1331 }
1332
1333exit:
1334 fr_dict_free(&dict, __FILE__);
1335
1336 if (inputfp != stdin) fclose(inputfp);
1337
1338 if (radmin_log.dst == L_DST_FILES) close(radmin_log.fd);
1339
1340 if (sockfd >= 0) close(sockfd);
1341
1342 if (!quiet) fprintf(stdout, "\n");
1343
1344 /*
1345 * Ensure our atexit handlers run before any other
1346 * atexit handlers registered by third party libraries.
1347 */
1349
1350 return exit_status;
1351}
static int const char char buffer[256]
Definition acutest.h:576
int const char * file
Definition acutest.h:702
int const char int line
Definition acutest.h:702
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition atexit.c:159
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition atexit.c:285
static TALLOC_CTX * autofree
Definition fuzzer.c:44
static char * readline(char const *prompt)
Definition radmin.c:82
#define CMD_MAX_EXPANSIONS
Definition radmin.c:152
static fr_cmd_table_t cmd_table[]
Definition radmin.c:891
#define radmin_free(_x)
Definition radmin.c:136
static char readline_buffer[1024]
Definition radmin.c:80
#define RCSID(id)
Definition build.h:488
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:316
#define DIAG_ON(_x)
Definition build.h:463
#define UNUSED
Definition build.h:318
#define DIAG_OFF(_x)
Definition build.h:462
int cf_file_read(CONF_SECTION *cs, char const *filename, bool root)
Definition cf_file.c:3642
int cf_section_pass2(CONF_SECTION *cs)
Definition cf_file.c:987
int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, fr_token_t dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
Definition cf_parse.c:783
#define FR_ITEM_POINTER(_type, _res_p)
Definition cf_parse.h:355
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:72
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1184
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1027
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1419
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition cf_util.c:1048
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1574
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:143
#define CF_IDENT_ANY
Definition cf_util.h:75
int fr_command_clear(int new_argc, fr_cmd_info_t *info)
Clear out any value boxes etc.
Definition command.c:2377
int fr_command_str_to_argv(fr_cmd_t *head, fr_cmd_info_t *info, char const *text)
Split a string in-place, updating argv[].
Definition command.c:2149
int fr_command_run(FILE *fp, FILE *fp_err, fr_cmd_info_t *info, bool read_only)
Run a particular command.
Definition command.c:1481
void fr_command_info_init(TALLOC_CTX *ctx, fr_cmd_info_t *info)
Initialize an fr_cmd_info_t structure.
Definition command.c:2405
int fr_command_print_help(FILE *fp, fr_cmd_t *head, char const *text)
Do readline-style help completions.
Definition command.c:2796
int fr_command_complete(fr_cmd_t *head, char const *text, int start, int max_expansions, char const **expansions)
Do readline-style command completions.
Definition command.c:2653
int fr_command_add_multi(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
Add multiple commands to the global command tree.
Definition command.c:993
char const * parent
e.g. "show module"
Definition command.h:52
bool runnable
is the command runnable?
Definition command.h:41
#define CMD_TABLE_END
Definition command.h:62
ssize_t fr_conduit_write(int fd, fr_conduit_type_t conduit, void const *out, size_t outlen)
Definition conduit.c:227
ssize_t fr_conduit_read(int fd, fr_conduit_type_t *pconduit, void *out, size_t outlen)
Definition conduit.c:145
API to provide distinct communication conduits for the radmin protocol.
#define FR_CONDUIT_MAGIC
Definition conduit.h:32
@ FR_CONDUIT_FAIL
Definition conduit.h:54
@ FR_CONDUIT_PARTIAL
Definition conduit.h:55
@ FR_CONDUIT_SUCCESS
Definition conduit.h:56
@ FR_NOTIFY_BUFFERED
Definition conduit.h:61
@ FR_NOTIFY_UNBUFFERED
Definition conduit.h:62
fr_conduit_type_t
Definition conduit.h:34
@ FR_CONDUIT_STDOUT
Definition conduit.h:36
@ FR_CONDUIT_AUTH_RESPONSE
Definition conduit.h:41
@ FR_CONDUIT_HELP
Definition conduit.h:43
@ FR_CONDUIT_NOTIFY
Definition conduit.h:42
@ FR_CONDUIT_STDIN
Definition conduit.h:35
@ FR_CONDUIT_STDERR
Definition conduit.h:37
@ FR_CONDUIT_CMD_STATUS
Definition conduit.h:38
@ FR_CONDUIT_INIT_ACK
Definition conduit.h:39
@ FR_CONDUIT_COMPLETE
Definition conduit.h:44
@ FR_CONDUIT_AUTH_CHALLENGE
Definition conduit.h:40
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1056
#define MEM(x)
Definition debug.h:46
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:236
static int retries
Definition dhcpclient.c:52
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:113
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent))
(Re-)Initialize the special internal dictionary
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename))
Read supplementary attribute definitions into an existing dictionary.
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition dict_util.c:4329
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir))
Initialise the global protocol hashes.
Definition dict_util.c:4713
Test enumeration values.
Definition dict_test.h:92
free(array)
int fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen, uint8_t const *key, size_t key_len)
Calculate HMAC using internal MD5 implementation.
Definition hmac_md5.c:119
int fr_inet_hton(fr_ipaddr_t *out, int af, char const *hostname, bool fallback)
Wrappers for IPv4/IPv6 host to IP address lookup.
Definition inet.c:255
IPv4/6 prefix.
Stores all information relating to an event list.
Definition event.c:377
int fr_debug_lvl
Definition log.c:40
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition log.c:577
@ L_DST_NULL
Discard log messages.
Definition log.h:80
@ L_DST_FILES
Log to a file on disk.
Definition log.h:76
@ L_TIMESTAMP_ON
Always log timestamps.
Definition log.h:87
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition log.h:67
@ L_INFO
Informational message.
Definition log.h:52
char * last_command
Last command we executed on this connection.
Definition radmin.c:107
static char io_buffer[65536]
Definition radmin.c:147
fr_event_list_t * event_list
Event list this fd is serviced by.
Definition radmin.c:104
static ssize_t do_challenge(int fd)
Definition radmin.c:215
static fr_cmd_t * local_cmds
Definition radmin.c:160
static int stack_depth
Definition radmin.c:156
static int client_socket(char const *server)
Definition radmin.c:182
static bool echo
Main radmin state.
Definition radmin.c:134
int main(int argc, char **argv)
Definition radmin.c:828
fr_event_list_t * event_list
Our main event list.
Definition radmin.c:124
static char * my_readline(char const *prompt, FILE *fp_in, FILE *fp_out)
Definition radmin.c:452
static int do_connect(int *out, char const *file, char const *server)
Definition radmin.c:357
static char const * radmin_version
Definition radmin.c:92
#define MAX_COMMANDS
Definition radmin.c:826
radmin_conn_type_t type
Type of connection.
Definition radmin.c:115
static int local_command(char *line)
Definition radmin.c:796
static ssize_t flush_conduits(int fd, char *buffer, size_t bufsize)
Definition radmin.c:255
static fr_log_t radmin_log
Definition radmin.c:139
static char const * secret
Definition radmin.c:135
bool nonblock
Whether this connection should operate in non-blocking mode.
Definition radmin.c:111
static bool use_readline
Definition radmin.c:137
#define write_history(history_file)
Definition radmin.c:660
radmin_conn_type_t
Definition radmin.c:94
@ RADMIN_CONN_UNIX
Connect via unix socket.
Definition radmin.c:96
@ RADMIN_CONN_TCP
Connect via TCP.
Definition radmin.c:97
@ RADMIN_CONN_NONE
Don't know, never connected.
Definition radmin.c:95
static ssize_t cmd_copy(char const *cmd)
Definition radmin.c:515
#define add_history(line)
Definition radmin.c:659
static char const * progname
Definition radmin.c:91
static fr_cmd_info_t local_info
Definition radmin.c:794
int fd
Control socket descriptor.
Definition radmin.c:105
char * secret
We use to authenticate ourselves to the server.
Definition radmin.c:109
static char * stack[MAX_STACK]
Definition radmin.c:158
static int cmd_test(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
Definition radmin.c:772
bool connected
Whether this connection is currently connected.
Definition radmin.c:113
static bool unbuffered
Definition radmin.c:136
static int sockfd
Definition radmin.c:146
char * server
Path or FQDN of server we're connected to.
Definition radmin.c:108
static char cmd_buffer[65536]
Definition radmin.c:157
#define MAX_STACK
Definition radmin.c:155
static ssize_t run_command(int fd, char const *command, char *buffer, size_t bufsize)
Definition radmin.c:335
static int check_server(CONF_SECTION *subcs, uid_t uid, gid_t gid, char const **file_p, char const **server_p)
Definition radmin.c:663
fr_cs_buffer_t co
Definition radmin.c:114
radmin_conn_t * active_conn
Connection to remote entity.
Definition radmin.c:126
A connection to a server.
Definition radmin.c:103
Radmin state.
Definition radmin.c:123
unsigned short uint16_t
@ FR_TYPE_STRING
String of printable characters.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
#define FR_RADMIN_PORT
Definition radmin.h:39
static char const * name
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
Definition skip.h:36
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition socket.c:708
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition socket.c:543
return count
Definition module.c:155
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
Definition log.h:93
fr_log_dst_t dst
Log destination.
Definition log.h:94
int fd
File descriptor to write messages to.
Definition log.h:109
char const * file
Path to log file.
Definition log.h:110
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:48
#define talloc_strdup(_ctx, _str)
Definition talloc.h:142
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
static fr_table_ptr_sorted_t commands[]
#define FR_DICTIONARY_FILE
Definition conf.h:7
#define FR_DICTIONARY_INTERNAL_DIR
Definition conf.h:8
#define RADIUS_DIR
Definition conf.h:3
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:732
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
static size_t char ** out
Definition value.h:1030