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