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