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: 1428871c9b2f77511ee413a11045012fb7e74223 $
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: 1428871c9b2f77511ee413a11045012fb7e74223 $")
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 = "";
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 raddb_dir Configuration files are in \"raddbdir/*\".\n");
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 raddb/name.conf instead of raddb/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 fr_hmac_md5(challenge, (uint8_t const *) secret, strlen(secret),
237 challenge, sizeof(challenge));
238
239 r = fr_conduit_write(fd, FR_CONDUIT_AUTH_RESPONSE, challenge, sizeof(challenge));
240 if (r <= 0) return r;
241
242 /*
243 * If the server doesn't like us, it just closes the
244 * socket. So we don't look for an ACK.
245 */
246
247 return r;
248}
249
250
251/*
252 * Returns -1 on failure. 0 on connection failed. +1 on OK.
253 */
254static ssize_t flush_conduits(int fd, char *buffer, size_t bufsize)
255{
256 ssize_t r;
257#ifdef USE_READLINE
258 char *p, *str;
259#endif
260 uint32_t status;
261 fr_conduit_type_t conduit;
262
263 while (true) {
264 uint32_t notify;
265
266 r = fr_conduit_read(fd, &conduit, buffer, bufsize - 1);
267 if (r <= 0) return r;
268
269 buffer[r] = '\0'; /* for C strings */
270
271 switch (conduit) {
273 fprintf(stdout, "%s", buffer);
274 break;
275
277 fprintf(stderr, "ERROR: %s", buffer);
278 break;
279
281 if (r < 4) return 1;
282
283 memcpy(&status, buffer, sizeof(status));
284 status = ntohl(status);
285 return status;
286
288 if (r < 4) return -1;
289
290 memcpy(&notify, buffer, sizeof(notify));
291 notify = ntohl(notify);
292
293 if (notify == FR_NOTIFY_UNBUFFERED) unbuffered = true;
294 if (notify == FR_NOTIFY_BUFFERED) unbuffered = false;
295
296 break;
297
298#ifdef USE_READLINE
300 str = buffer;
301
302 for (p = buffer; p < (buffer + r); p++) {
303 if (*p == '\n') {
304 size_t len;
305
306 len = p - str;
307
308 MEM(radmin_expansions[radmin_num_expansions] = malloc(len + 1));
309 memcpy(radmin_expansions[radmin_num_expansions], str, len);
310 radmin_expansions[radmin_num_expansions][len] = '\0';
311 radmin_num_expansions++;
312
313 str = p + 1;
314 }
315
316 if (radmin_num_expansions >= CMD_MAX_EXPANSIONS) break;
317 }
318 break;
319#endif
320
321 default:
322 fprintf(stderr, "Unexpected response %02x\n", conduit);
323 return -1;
324 }
325 }
326
327 /* never gets here */
328}
329
330
331/*
332 * Returns -1 on failure. 0 on connection failed. +1 on OK.
333 */
334static ssize_t run_command(int fd, char const *command,
335 char *buffer, size_t bufsize)
336{
337 ssize_t r;
338 char const *p = command;
339
341 if (!*p) return FR_CONDUIT_SUCCESS;
342
343 if (echo) {
344 fprintf(stdout, "%s\n", command);
345 }
346
347 /*
348 * Write the text to the socket.
349 */
350 r = fr_conduit_write(fd, FR_CONDUIT_STDIN, p, strlen(p));
351 if (r <= 0) return r;
352
353 return flush_conduits(fd, buffer, bufsize);
354}
355
356static int do_connect(int *out, char const *file, char const *server)
357{
358 int fd;
359 ssize_t r;
360 fr_conduit_type_t conduit;
361 char buffer[65536];
362
363 uint32_t magic;
364
365 /*
366 * Close stale file descriptors
367 */
368 if (*out != -1) {
369 close(*out);
370 *out = -1;
371 }
372
373 if (file) {
374 /*
375 * FIXME: Get destination from command line, if possible?
376 */
377 fd = fr_socket_client_unix(file, false);
378 if (fd < 0) {
379 fr_perror("radmin");
380 if (errno == ENOENT) {
381 fprintf(stderr, "Perhaps you need to run the commands:");
382 fprintf(stderr, "\tcd /etc/raddb\n");
383 fprintf(stderr, "\tln -s sites-available/control-socket "
384 "sites-enabled/control-socket\n");
385 fprintf(stderr, "and then re-start the server?\n");
386 }
387 return -1;
388 }
389 } else {
390 fd = client_socket(server);
391 }
392
393 /*
394 * Only works for BSD, but Linux allows us
395 * to mask SIGPIPE, so that's fine.
396 */
397#ifdef SO_NOSIGPIPE
398 {
399 int set = 1;
400
401 setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
402 }
403#endif
404
405 /*
406 * Set up the initial header data.
407 */
408 magic = FR_CONDUIT_MAGIC;
409 magic = htonl(magic);
410 memcpy(buffer, &magic, sizeof(magic));
411 memset(buffer + sizeof(magic), 0, sizeof(magic));
412
414 if (r <= 0) {
415 do_close:
416 fprintf(stderr, "%s: Error in socket: %s\n",
417 progname, fr_syserror(errno));
418 close(fd);
419 return -1;
420 }
421
422 r = fr_conduit_read(fd, &conduit, buffer + 8, 8);
423 if (r <= 0) goto do_close;
424
425 if ((r != 8) || (conduit != FR_CONDUIT_INIT_ACK) ||
426 (memcmp(buffer, buffer + 8, 8) != 0)) {
427 fprintf(stderr, "%s: Incompatible versions\n", progname);
428 close(fd);
429 return -1;
430 }
431
432 if (secret) {
433 r = do_challenge(fd);
434 if (r <= 0) goto do_close;
435 }
436
437 *out = fd;
438
439 return 0;
440}
441
442
443static char *readline_buffer[1024];
444
445/*
446 * Wrapper around readline which does the "right thing" depending
447 * on whether we're reading from a file or not. It also ignores
448 * blank lines and comments, which the main readline() API
449 * doesn't do.
450 */
451static char *my_readline(char const *prompt, FILE *fp_in, FILE *fp_out)
452{
453 char *line, *p;
454
455#ifdef USE_READLINE
456 if (use_readline) return readline(prompt);
457#endif
458
459 if (prompt && *prompt) puts(prompt);
460 fflush(fp_out);
461
462 line = fgets((char *) readline_buffer, sizeof(readline_buffer), fp_in);
463 if (!line) return NULL;
464
465 p = strchr(line, '\n');
466 if (!p) {
467 fprintf(stderr, "Input line too long\n");
468 return NULL;
469 }
470 *p = '\0';
471
473
474 /*
475 * Comments: keep going.
476 */
477 if (line[0] == '#') {
478 *line = '\0';
479 return line;
480 }
481
482 /*
483 * Strip off CR / LF
484 */
485 for (p = line; *p != '\0'; p++) {
486 if ((p[0] == '\r') ||
487 (p[0] == '\n')) {
488 p[0] = '\0';
489 break;
490 }
491 }
492
493 return line;
494}
495
496#ifdef USE_READLINE
497static void radmin_free(char *line)
498{
499 /*
500 * Was read from stdin, so "line" == "readline_buffer"
501 */
502 if (!use_readline) return;
503
504 free(line);
505}
506#else
507#define radmin_free(_x)
508#endif
509
510/*
511 * Copies the (possible partial) command to the command buffer,
512 * so that we can send the full command over to the server.
513 */
514static ssize_t cmd_copy(char const *cmd)
515{
516 size_t len;
517 char *p = stack[stack_depth];
518
519 if (stack_depth > 0) *(p++) = ' ';
520
521 /*
522 * No input, allow a trailing space so that tab
523 * completion works.
524 */
525 if (!*cmd) {
526 return p - cmd_buffer;
527 }
528
529 len = strlcpy(p, cmd, cmd_buffer + sizeof(cmd_buffer) - p);
530 if ((p + len) >= (cmd_buffer + sizeof(cmd_buffer))) {
531 fprintf(stderr, "Command too long\n");
532 return -1;
533 }
534
535 /*
536 * Trash trailing spaces.
537 */
538 for (p += len;
539 p > cmd_buffer;
540 p--) {
541 if (!isspace((uint8_t) p[-1])) break;
542 p[-1] = '\0';
543 }
544
545 return p - cmd_buffer;
546}
547
548#ifdef USE_READLINE
549static int radmin_help(UNUSED int count, UNUSED int key)
550{
551 ssize_t len;
552
553 printf("\n");
554
555 len = cmd_copy(rl_line_buffer);
556 if (len < 0) return 0;
557
558 /*
559 * Special-case help for local commands.
560 */
561 if ((len >= 5) && strncmp(cmd_buffer, "local", 5) == 0) {
563 rl_on_new_line();
564 return 0;
565 }
566
567 if (len > 0) {
569 } else {
570 /*
571 * Don't write zero bytes to the other side...
572 */
573 (void) fr_conduit_write(sockfd, FR_CONDUIT_HELP, " ", 1);
574 }
575
576 (void) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
577
578 rl_on_new_line();
579 return 0;
580}
581
582static char *
583radmin_expansion_walk(UNUSED const char *text, int state)
584{
585 static int current;
586 char *name;
587
588 if (!state) {
589 current = 0;
590 }
591
592 /*
593 * fr_command_completions() takes care of comparing things to
594 * suppress expansions which don't match "text"
595 */
596 if (current >= radmin_num_expansions) return NULL;
597
598 name = radmin_expansions[current];
599
600 radmin_expansions[current++] = NULL;
601
602 return name;
603}
604
605static char **
606radmin_completion(const char *text, int start, UNUSED int end)
607{
608 ssize_t len;
609
610 rl_attempted_completion_over = 1;
611
612 radmin_num_expansions = 0;
613
614 len = cmd_copy(rl_line_buffer);
615 if (len < 0) return NULL;
616
617 /*
618 * Handle local commands specially.
619 */
620 if (strncmp(cmd_buffer, "local", 5) == 0) {
621 int num;
622 char **expansions = &radmin_expansions[0];
623 char const **expansions_const;
624
625 memcpy(&expansions_const, &expansions, sizeof(expansions)); /* const issues */
627 CMD_MAX_EXPANSIONS, expansions_const);
628 if (num <= 0) return NULL;
629
630 radmin_num_expansions = num;
631 return rl_completion_matches(text, radmin_expansion_walk);
632 }
633
634 start += len;
635
636 if (start > 65535) return NULL;
637
638 io_buffer[0] = (start >> 8) & 0xff;
639 io_buffer[1] = start & 0xff;
640
641 /*
642 * Note that "text" is the PARTIAL thing we're trying to complete.
643 * And "start" is the OFFSET from rl_line_buffer where we want to
644 * do the completion. It's all rather idiotic.
645 */
646 memcpy(io_buffer + 2, cmd_buffer, len);
647
649
650 (void) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
651
652 return rl_completion_matches(text, radmin_expansion_walk);
653}
654
655#endif
656
657#ifndef USE_READLINE_HISTORY
658# define add_history(line)
659# define write_history(history_file)
660#endif
661
662static int check_server(CONF_SECTION *subcs, uid_t uid, gid_t gid, char const **file_p, char const **server_p)
663{
664 int rcode;
665 char const *value, *file = NULL;
666 CONF_SECTION *cs;
667 CONF_PAIR *cp;
668 char const *uid_name = NULL;
669 char const *gid_name = NULL;
670 char const *server;
671 struct passwd *pwd;
672 struct group *grp;
673
674 cp = cf_pair_find(subcs, "namespace");
675 if (!cp) return 0;
676
677 value = cf_pair_value(cp);
678 if (!value) return 0;
679
680 if (strcmp(value, "control") != 0) return 0;
681
682 server = cf_section_name2(subcs);
683 *server_p = server; /* need this for error messages */
684
685 /* listen {} */
686 cs = cf_section_find(subcs, "listen", NULL);
687 if (!cs) {
688 fprintf(stderr, "%s: Failed parsing 'listen{}' section in 'server %s {...}'\n", progname, server);
689 return -1;
690 }
691
692 /* transport = <transport> */
693 cp = cf_pair_find(cs, "transport");
694 if (!cp) return 0;
695
696 value = cf_pair_value(cp);
697 if (!value) return 0;
698
699 /* <transport> { ... } */
700 subcs = cf_section_find(cs, value, NULL);
701 if (!subcs) {
702 fprintf(stderr, "%s: Failed parsing the '%s {}' section in 'server %s {...}'\n",
703 progname, cf_section_name1(subcs), server);
704 return -1;
705 }
706
707 /*
708 * Now find the socket name (sigh)
709 */
710 rcode = cf_pair_parse(NULL, subcs, "filename",
712 if (rcode < 0) {
713 fprintf(stderr, "%s: Failed parsing listen section 'socket'\n", progname);
714 return -1;
715 }
716
717 if (!file) {
718 fprintf(stderr, "%s: No path given for socket\n", progname);
719 return -1;
720 }
721
722 *file_p = file;
723
724 /*
725 * If we're root, just use the first one we find
726 */
727 if (uid == 0) return 1;
728
729 /*
730 * Check UID and GID.
731 */
732 rcode = cf_pair_parse(NULL, subcs, "uid",
734 if (rcode < 0) {
735 fprintf(stderr, "%s: Failed parsing listen section 'uid'\n", progname);
736 return -1;
737 }
738
739 if (!uid_name || !*uid_name) return 1;
740
741 pwd = getpwnam(uid_name);
742 if (!pwd) {
743 fprintf(stderr, "%s: Failed getting UID for user %s: %s\n", progname, uid_name,
744 fr_syserror(errno));
745 return -1;
746 }
747
748 if (uid != pwd->pw_uid) return 0;
749
750 rcode = cf_pair_parse(NULL, subcs, "gid",
752 if (rcode < 0) {
753 fprintf(stderr, "%s: Failed parsing listen section 'gid'\n", progname);
754 return -1;
755 }
756
757 if (!gid_name || !*gid_name) return 1;
758
759 grp = getgrnam(gid_name);
760 if (!grp) {
761 fprintf(stderr, "%s: Failed resolving gid of group %s: %s\n",
762 progname, gid_name, fr_syserror(errno));
763 return -1;
764 }
765
766 if (gid != grp->gr_gid) return 0;
767
768 return 1;
769}
770
771static int cmd_test(FILE *fp, UNUSED FILE *fp_err, UNUSED void *ctx, UNUSED fr_cmd_info_t const *info)
772{
773 fprintf(fp, "We're testing stuff!\n");
774
775 return 0;
776}
777
778/*
779 * Local radmin commands
780 */
782 {
783 .parent = "local",
784 .name = "test",
785 .func = cmd_test,
786 .help = "Test stuff",
787 .read_only = true
788 },
789
791};
792
794
795static int local_command(char *line)
796{
797 int argc, ret;
798
800 if (argc < 0) {
801 fr_perror("Failed parsing local command");
802 return -1;
803 }
804
805 if (!local_info.runnable) {
806 return 0;
807 }
808
809 ret = fr_command_run(stderr, stdout, &local_info, false);
810 fflush(stdout);
811 fflush(stderr);
812
813 /*
814 * reset "info" to be a top-level context again.
815 */
816 (void) fr_command_clear(0, &local_info);
817
818 if (ret < 0) return ret;
819
820 return 1;
821
822}
823
824
825#define MAX_COMMANDS (256)
826
827int main(int argc, char **argv)
828{
829 int c;
830 bool quiet = false;
831 char *line = NULL;
832 ssize_t result;
833 char const *file = NULL;
834 char const *name = "radiusd";
835 char const *input_file = NULL;
836 FILE *inputfp = stdin;
837 char const *server = NULL;
838 fr_dict_t *dict = NULL;
839
840 char const *raddb_dir = RADIUS_DIR;
841 char const *dict_dir = DICTDIR;
842#ifdef USE_READLINE_HISTORY
843 char history_file[PATH_MAX];
844#endif
845
846 TALLOC_CTX *autofree;
847
848 char *commands[MAX_COMMANDS];
849 int num_commands = 0;
850
851 int exit_status = EXIT_SUCCESS;
852
853 char const *prompt = "radmin> ";
854 char prompt_buffer[1024];
855
856 /*
857 * Must be called first, so the handler is called last
858 */
860
862
863#ifndef NDEBUG
864 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
865 fr_perror("radmin");
866 fr_exit_now(EXIT_FAILURE);
867 }
868#endif
869
870 talloc_set_log_stderr();
871
872 if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) {
873 progname = argv[0];
874 } else {
875 progname++;
876 }
877
879 secret = NULL;
880
881 while ((c = getopt(argc, argv, "d:D:hi:e:Ef:n:qs:S:x")) != -1) switch (c) {
882 case 'd':
883 if (file) {
884 fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
885 fr_exit_now(EXIT_FAILURE);
886 }
887 raddb_dir = optarg;
888 break;
889
890 case 'D':
891 dict_dir = optarg;
892 break;
893
894 case 'e':
895 if (num_commands >= MAX_COMMANDS) {
896 fprintf(stderr, "%s: Too many '-e'\n", progname);
897 fr_exit_now(EXIT_FAILURE);
898 }
899
900 commands[num_commands++] = optarg;
901 break;
902
903 case 'E':
904 echo = true;
905 break;
906
907 case 'f':
908 raddb_dir = NULL;
909 file = optarg;
910 break;
911
912 default:
913 case 'h':
914 usage(0); /* never returns */
915
916 case 'i':
917 /*
918 * optarg check is to quiet clang scan
919 */
920 if (optarg && (strcmp(optarg, "-") != 0)) input_file = optarg;
921 quiet = true;
922 break;
923
924 case 'l':
925 radmin_log.file = optarg;
926 break;
927
928 case 'n':
929 name = optarg;
930 break;
931
932 case 'q':
933 quiet = true;
934 if (fr_debug_lvl > 0) fr_debug_lvl--;
935 break;
936
937 case 's':
938 if (file) {
939 fprintf(stderr, "%s: -s and -f cannot be used together.\n", progname);
940 usage(1);
941 }
942 server = optarg;
943 break;
944
945 case 'S':
946 secret = optarg;
947 break;
948
949 case 'x':
950 fr_debug_lvl++;
951 break;
952 }
953
954 /*
955 * Mismatch between the binary and the libraries it depends on
956 */
958 fr_perror("radmin");
959 fr_exit_now(EXIT_FAILURE);
960 }
961
962 if (raddb_dir) {
963 int rcode;
964 uid_t uid;
965 gid_t gid;
966 CONF_SECTION *cs, *subcs;
967 CONF_PAIR *cp;
968
969 file = NULL; /* MUST read it from the conf_file now */
970
971 snprintf(io_buffer, sizeof(io_buffer), "%s/%s.conf", raddb_dir, name);
972
973 /*
974 * Need to read in the dictionaries, else we may get
975 * validation errors when we try and parse the config.
976 */
977 if (!fr_dict_global_ctx_init(NULL, true, dict_dir)) {
978 fr_perror("radmin");
979 fr_exit_now(64);
980 }
981
983 fr_perror("radmin");
984 fr_exit_now(64);
985 }
986
987 if (fr_dict_read(dict, raddb_dir, FR_DICTIONARY_FILE) == -1) {
988 fr_perror("radmin");
989 fr_exit_now(64);
990 }
991
992 cs = cf_section_alloc(autofree, NULL, "main", NULL);
993 if (!cs) fr_exit_now(EXIT_FAILURE);
994
995 if ((cf_file_read(cs, io_buffer) < 0) || (cf_section_pass2(cs) < 0)) {
996 fprintf(stderr, "%s: Errors reading or parsing %s\n", progname, io_buffer);
997 error:
998 fr_exit_now(EXIT_FAILURE);
999 }
1000
1001 uid = getuid();
1002 gid = getgid();
1003
1004 /*
1005 * We are looking for: server whatever { namespace="control" ... }
1006 */
1007 if (server) {
1008 subcs = cf_section_find(cs, "server", server);
1009 if (subcs) {
1010 fprintf(stderr, "%s: Could not find virtual server %s {}\n", progname, server);
1011 goto error;
1012 }
1013
1014 rcode = check_server(subcs, uid, gid, &file, &server);
1015 if (rcode < 0) goto error;
1016 if (rcode == 0) file = NULL;
1017
1018 } else {
1019 for (subcs = cf_section_find_next(cs, NULL, "server", CF_IDENT_ANY);
1020 subcs != NULL;
1021 subcs = cf_section_find_next(cs, subcs, "server", CF_IDENT_ANY)) {
1022 rcode = check_server(subcs, uid, gid, &file, &server);
1023 if (rcode < 0) goto error;
1024 if (rcode == 1) break;
1025 }
1026 }
1027
1028 if (!file) {
1029 fprintf(stderr, "%s: Could not find control socket in %s (server %s {})\n", progname, io_buffer, server);
1030 goto error;
1031 }
1032
1033 /*
1034 * Log the commands we've run.
1035 */
1036 if (!radmin_log.file) {
1037 subcs = cf_section_find(cs, "log", NULL);
1038 if (subcs) {
1039 cp = cf_pair_find(subcs, "radmin");
1040 if (cp) {
1042
1043 if (!radmin_log.file) {
1044 fprintf(stderr, "%s: Invalid value for 'radmin' log destination", progname);
1045 goto error;
1046 }
1047 }
1048 }
1049 }
1050
1051 if (radmin_log.file) {
1052 radmin_log.fd = open(radmin_log.file, O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
1053 if (radmin_log.fd < 0) {
1054 fprintf(stderr, "%s: Failed opening %s: %s\n", progname, radmin_log.file, fr_syserror(errno));
1055 goto error;
1056 }
1057
1059 }
1060 }
1061
1062 if (input_file) {
1063 inputfp = fopen(input_file, "r");
1064 if (!inputfp) {
1065 fprintf(stderr, "%s: Failed opening %s: %s\n", progname, input_file, fr_syserror(errno));
1066 goto error;
1067 }
1068 }
1069
1070 if (!file) {
1071 fprintf(stderr, "%s: Failed to find socket file name\n",
1072 progname);
1073 goto error;
1074 }
1075
1076 /*
1077 * Check if stdin is a TTY only if input is from stdin
1078 */
1079 if (input_file || !isatty(STDIN_FILENO)) {
1080 use_readline = false;
1081 quiet = true;
1082 }
1083
1084 if (use_readline) {
1085#ifdef USE_READLINE_HISTORY
1086 using_history();
1087 stifle_history(READLINE_MAX_HISTORY_LINES);
1088 snprintf(history_file, sizeof(history_file), "%s/%s", getenv("HOME"), ".radmin_history");
1089 read_history(history_file);
1090#endif
1091#ifdef USE_READLINE
1092 rl_attempted_completion_function = radmin_completion;
1093#endif
1094 } else {
1095 prompt = NULL;
1096 }
1097
1098 /*
1099 * Prevent SIGPIPEs from terminating the process
1100 */
1101 signal(SIGPIPE, SIG_IGN);
1102
1103 if (do_connect(&sockfd, file, server) < 0) fr_exit_now(EXIT_FAILURE);
1104
1105 /*
1106 * Register local commands.
1107 */
1108 if (fr_command_add_multi(autofree, &local_cmds, NULL, NULL, cmd_table) < 0) {
1109 fprintf(stderr, "%s: Failed registering local commands: %s\n",
1111 goto error;
1112 }
1113
1115
1116 /*
1117 * Run commands from the command-line.
1118 */
1119 if (num_commands > 0) {
1120 int i;
1121
1122 for (i = 0; i < num_commands; i++) {
1123 result = run_command(sockfd, commands[i], io_buffer, sizeof(io_buffer));
1124 if (result < 0) fr_exit_now(EXIT_FAILURE);
1125
1126 if (result == FR_CONDUIT_FAIL) {
1127 exit_status = EXIT_FAILURE;
1128 goto exit;
1129 }
1130 }
1131
1132 if (unbuffered) {
1133 while (true) flush_conduits(sockfd, io_buffer, sizeof(io_buffer));
1134 }
1135
1136 /*
1137 * We're done all of the commands, exit now.
1138 */
1139 goto exit;
1140 }
1141
1142 if (!quiet) {
1143 printf("%s - FreeRADIUS Server administration tool.\n", radmin_version);
1144 printf("Copyright 2008-2019 The FreeRADIUS server project and contributors.\n");
1145 printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
1146 printf("PARTICULAR PURPOSE.\n");
1147 printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
1148 printf("GNU General Public License v2.\n");
1149 }
1150
1151 /*
1152 * FIXME: Do login?
1153 */
1154
1155#ifdef USE_READLINE
1156 (void) rl_bind_key('?', radmin_help);
1157#endif
1158
1159 stack_depth = 0;
1160 stack[0] = cmd_buffer;
1161
1162 while (1) {
1163 int retries;
1164 ssize_t len;
1165
1166 line = my_readline(prompt, inputfp, stdout);
1167
1168 if (!line) break;
1169
1170 if (!*line) goto next;
1171
1172 /*
1173 * Radmin supports a number of commands which are
1174 * valid in any context.
1175 */
1176 if (strcmp(line, "reconnect") == 0) {
1177 if (do_connect(&sockfd, file, server) < 0) {
1179 fr_exit_now(EXIT_FAILURE);
1180 }
1181 goto next;
1182 }
1183
1184 if (!secret && !stack_depth && (strncmp(line, "secret ", 7) == 0)) {
1185 secret = line + 7;
1187 goto next;
1188 }
1189
1190 /*
1191 * Quit the program
1192 */
1193 if (strcmp(line, "quit") == 0) {
1195 break;
1196 }
1197
1198 /*
1199 * Exit the current context.
1200 */
1201 if (strcmp(line, "exit") == 0) {
1202 if (!stack_depth) {
1204 break;
1205 }
1206
1207 stack_depth--;
1208 *stack[stack_depth] = '\0';
1209
1210 if (stack_depth == 0) {
1211 prompt = "radmin> ";
1212 } else {
1213 snprintf(prompt_buffer, sizeof(prompt_buffer), "... %s> ",
1214 stack[stack_depth - 1]);
1215 prompt = prompt_buffer;
1216 }
1217
1218 goto next;
1219 }
1220
1221 /*
1222 * Radmin also supports local commands which
1223 * modifies it's behavior. These commands MUST
1224 */
1225 if (!stack_depth && (strncmp(line, "local", 5) == 0)) {
1226 if (!isspace((uint8_t) line[5])) {
1227 fprintf(stderr, "'local' commands MUST be specified all on one line");
1228 goto next;
1229 }
1230
1231 /*
1232 * Parse and run the local command.
1233 */
1235 goto next;
1236 }
1237
1238 /*
1239 * Any other input is sent to the server.
1240 */
1241 retries = 0;
1242
1243 /*
1244 * If required, log commands to a radmin log file.
1245 */
1246 if (radmin_log.dst == L_DST_FILES) {
1247 fr_log(&radmin_log, L_INFO, __FILE__, __LINE__, "%s", line);
1248 }
1249
1250 len = cmd_copy(line);
1251 if (len < 0) {
1252 exit_status = EXIT_FAILURE;
1254 break;
1255 }
1256
1257 retry:
1258
1259 result = run_command(sockfd, cmd_buffer, io_buffer, sizeof(io_buffer));
1260 if (result < 0) {
1261 if (!quiet) fprintf(stderr, "... reconnecting ...\n");
1262
1263 if (do_connect(&sockfd, file, server) < 0) {
1265 fr_exit_now(EXIT_FAILURE);
1266 }
1267
1268 retries++;
1269 if (retries < 2) goto retry;
1270
1271 fprintf(stderr, "Failed to connect to server\n");
1273 fr_exit_now(EXIT_FAILURE);
1274
1275 } else if (result == FR_CONDUIT_FAIL) {
1276 fprintf(stderr, "Failed running command\n");
1277 exit_status = EXIT_FAILURE;
1278
1279 } else if (result == FR_CONDUIT_PARTIAL) {
1280 char *p;
1281
1282 if (stack_depth >= (MAX_STACK - 1)) {
1283 fprintf(stderr, "Too many sub-contexts running command\n");
1284 exit_status = EXIT_FAILURE;
1286 break;
1287 }
1288
1289 /*
1290 * Point the stack to the last entry.
1291 */
1292 p = stack[stack_depth];
1293 p += strlen(p);
1294 stack_depth++;
1295 stack[stack_depth] = p;
1296
1297 snprintf(prompt_buffer, sizeof(prompt_buffer), "... %s> ",
1298 stack[stack_depth - 1]);
1299 prompt = prompt_buffer;
1300
1301 } else {
1302 /*
1303 * Add only successful commands to the history.
1304 *
1305 * Don't add exit / quit / secret / etc.
1306 */
1307 if (use_readline) {
1309 write_history(history_file);
1310 }
1311 }
1312
1313 /*
1314 * SUCCESS and PARTIAL end up here too.
1315 */
1316 next:
1318 }
1319
1320exit:
1321 fr_dict_free(&dict, __FILE__);
1322
1323 if (inputfp != stdin) fclose(inputfp);
1324
1326
1327 if (sockfd >= 0) close(sockfd);
1328
1329 if (!quiet) fprintf(stdout, "\n");
1330
1331 /*
1332 * Ensure our atexit handlers run before any other
1333 * atexit handlers registered by third party libraries.
1334 */
1336
1337 return exit_status;
1338}
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: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:45
static char * readline(char const *prompt)
Definition radmin.c:81
#define CMD_MAX_EXPANSIONS
Definition radmin.c:151
#define radmin_free(_x)
Definition radmin.c:135
static char readline_buffer[1024]
Definition radmin.c:79
#define RCSID(id)
Definition build.h:485
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:315
#define DIAG_ON(_x)
Definition build.h:460
#define UNUSED
Definition build.h:317
#define DIAG_OFF(_x)
Definition build.h:459
int cf_file_read(CONF_SECTION *cs, char const *filename)
Definition cf_file.c:3234
int cf_section_pass2(CONF_SECTION *cs)
Definition cf_file.c:767
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:730
#define FR_ITEM_POINTER(_type, _res_p)
Definition cf_parse.h:360
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
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
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1170
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:1438
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:1593
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#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: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:2810
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:2667
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: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:1242
#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:234
static int retries
Definition dhcpclient.c:53
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:114
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:4436
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name, char const *dependent)
(Re-)Initialize the special internal 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:4068
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
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:581
@ 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:827
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:451
static int do_connect(int *out, char const *file, char const *server)
Definition radmin.c:356
static char const * radmin_version
Definition radmin.c:93
#define MAX_COMMANDS
Definition radmin.c:825
radmin_conn_type_t type
Type of connection.
Definition radmin.c:116
static int local_command(char *line)
Definition radmin.c:795
static ssize_t flush_conduits(int fd, char *buffer, size_t bufsize)
Definition radmin.c:254
static fr_log_t radmin_log
Definition radmin.c:140
static char const * secret
Definition radmin.c:136
static fr_cmd_table_t cmd_table[]
Definition radmin.c:781
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:659
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:514
#define add_history(line)
Definition radmin.c:658
static char const * progname
Definition radmin.c:92
static fr_cmd_info_t local_info
Definition radmin.c:793
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:771
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:334
static int check_server(CONF_SECTION *subcs, uid_t uid, gid_t gid, char const **file_p, char const **server_p)
Definition radmin.c:662
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
static rc_request_t * current
#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:37
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:727
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition socket.c:562
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
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
close(uq->fd)
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:1020