All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
radmin.c
Go to the documentation of this file.
1 /*
2  * radmin.c RADIUS Administration tool.
3  *
4  * Version: $Id: d705b0373e8056c409aa5a075b2cd5bb29d51e04 $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2012 The FreeRADIUS server project
21  * Copyright 2012 Alan DeKok <aland@deployingradius.com>
22  */
23 
24 RCSID("$Id: d705b0373e8056c409aa5a075b2cd5bb29d51e04 $")
25 
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/md5.h>
28 #include <freeradius-devel/channel.h>
29 
30 #include <pwd.h>
31 #include <grp.h>
32 
33 #ifdef HAVE_GETOPT_H
34 # include <getopt.h>
35 #endif
36 
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
39 #endif
40 
41 #ifdef HAVE_LIBREADLINE
42 
43 #if defined(HAVE_READLINE_READLINE_H)
44 # include <readline/readline.h>
45 # define USE_READLINE (1)
46 #elif defined(HAVE_READLINE_H)
47 # include <readline.h>
48 # define USE_READLINE (1)
49 #endif /* !defined(HAVE_READLINE_H) */
50 
51 #ifdef HAVE_READLINE_HISTORY
52 # if defined(HAVE_READLINE_HISTORY_H)
53 # include <readline/history.h>
54 # define USE_READLINE_HISTORY (1)
55 # elif defined(HAVE_HISTORY_H)
56 # include <history.h>
57 # define USE_READLINE_HISTORY (1)
58 #endif /* defined(HAVE_READLINE_HISTORY_H) */
59 
60 #endif /* HAVE_READLINE_HISTORY */
61 
62 #endif /* HAVE_LIBREADLINE */
63 
64 /*
65  * For configuration file stuff.
66  */
67 static char const *progname = "radmin";
68 static char const *radmin_version = "radmin version " RADIUSD_VERSION_STRING
69 #ifdef RADIUSD_VERSION_COMMIT
70 " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")"
71 #endif
72 ", built on " __DATE__ " at " __TIME__;
73 
74 
75 /*
76  * The rest of this is because the conffile.c, etc. assume
77  * they're running inside of the server. And we don't (yet)
78  * have a "libfreeradius-server", or "libfreeradius-util".
79  */
81 
82 static bool echo = false;
83 static char const *secret = "testing123";
84 static bool unbuffered = false;
85 
86 #include <sys/wait.h>
87 pid_t rad_fork(void)
88 {
89  return fork();
90 }
91 
92 #ifdef HAVE_PTHREAD_H
93 pid_t rad_waitpid(pid_t pid, int *status)
94 {
95  return waitpid(pid, status, 0);
96 }
97 #endif
98 
99 static void NEVER_RETURNS usage(int status)
100 {
101  FILE *output = status ? stderr : stdout;
102  fprintf(output, "Usage: %s [ args ]\n", progname);
103  fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
104  fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
105  fprintf(output, " -e command Execute 'command' and then exit.\n");
106  fprintf(output, " -E Echo commands as they are being executed.\n");
107  fprintf(output, " -f socket_file Open socket_file directly, without reading radius.conf\n");
108  fprintf(output, " -h Print usage help information.\n");
109  fprintf(output, " -i input_file Read commands from 'input_file'.\n");
110  fprintf(output, " -n name Read raddb/name.conf instead of raddb/radiusd.conf\n");
111  fprintf(output, " -q Quiet mode.\n");
112 
113  exit(status);
114 }
115 
116 static int client_socket(char const *server)
117 {
118  int sockfd;
119  uint16_t port;
120  fr_ipaddr_t ipaddr;
121  char *p, buffer[1024];
122 
123  strlcpy(buffer, server, sizeof(buffer));
124 
125  p = strchr(buffer, ':');
126  if (!p) {
127  port = PW_RADMIN_PORT;
128  } else {
129  port = atoi(p + 1);
130  *p = '\0';
131  }
132 
133  if (fr_inet_hton(&ipaddr, AF_INET, buffer, false) < 0) {
134  fprintf(stderr, "%s: Failed looking up host %s: %s\n",
135  progname, buffer, fr_syserror(errno));
136  exit(1);
137  }
138 
139  sockfd = fr_socket_client_tcp(NULL, &ipaddr, port, false);
140  if (sockfd < 0) {
141  fprintf(stderr, "%s: Failed opening socket %s: %s\n",
142  progname, server, fr_syserror(errno));
143  exit(1);
144  }
145 
146  return sockfd;
147 }
148 
149 static ssize_t do_challenge(int sockfd)
150 {
151  ssize_t r;
152  fr_channel_type_t channel;
153  uint8_t challenge[16];
154 
155  challenge[0] = 0;
156 
157  /*
158  * When connecting over a socket, the server challenges us.
159  */
160  r = fr_channel_read(sockfd, &channel, challenge, sizeof(challenge));
161  if (r <= 0) return r;
162 
163  if ((r != 16) || (channel != FR_CHANNEL_AUTH_CHALLENGE)) {
164  fprintf(stderr, "%s: Failed to read challenge.\n",
165  progname);
166  exit(1);
167  }
168 
169  fr_hmac_md5(challenge, (uint8_t const *) secret, strlen(secret),
170  challenge, sizeof(challenge));
171 
172  r = fr_channel_write(sockfd, FR_CHANNEL_AUTH_RESPONSE, challenge, sizeof(challenge));
173  if (r <= 0) return r;
174 
175  /*
176  * If the server doesn't like us, he just closes the
177  * socket. So we don't look for an ACK.
178  */
179 
180  return r;
181 }
182 
183 
184 /*
185  * Returns -1 on failure. 0 on connection failed. +1 on OK.
186  */
187 static ssize_t flush_channels(int sockfd, char *buffer, size_t bufsize)
188 {
189  ssize_t r;
190  uint32_t status;
191  fr_channel_type_t channel;
192 
193  while (true) {
194  uint32_t notify;
195 
196  r = fr_channel_read(sockfd, &channel, buffer, bufsize - 1);
197  if (r <= 0) return r;
198 
199  buffer[r] = '\0'; /* for C strings */
200 
201  switch (channel) {
202  case FR_CHANNEL_STDOUT:
203  fprintf(stdout, "%s", buffer);
204  break;
205 
206  case FR_CHANNEL_STDERR:
207  fprintf(stderr, "ERROR: %s", buffer);
208  break;
209 
211  if (r < 4) return 1;
212 
213  memcpy(&status, buffer, sizeof(status));
214  status = ntohl(status);
215  return status;
216 
217  case FR_CHANNEL_NOTIFY:
218  if (r < 4) return -1;
219 
220  memcpy(&notify, buffer, sizeof(notify));
221  notify = ntohl(notify);
222 
223  if (notify == FR_NOTIFY_UNBUFFERED) unbuffered = true;
224  if (notify == FR_NOTIFY_BUFFERED) unbuffered = false;
225 
226  break;
227 
228  default:
229  fprintf(stderr, "Unexpected response\n");
230  return -1;
231  }
232  }
233 
234  /* never gets here */
235 }
236 
237 
238 /*
239  * Returns -1 on failure. 0 on connection failed. +1 on OK.
240  */
241 static ssize_t run_command(int sockfd, char const *command,
242  char *buffer, size_t bufsize)
243 {
244  ssize_t r;
245 
246  if (echo) {
247  fprintf(stdout, "%s\n", command);
248  }
249 
250  /*
251  * Write the text to the socket.
252  */
253  r = fr_channel_write(sockfd, FR_CHANNEL_STDIN, command, strlen(command));
254  if (r <= 0) return r;
255 
256  return flush_channels(sockfd, buffer, bufsize);
257 }
258 
259 static int do_connect(int *out, char const *file, char const *server)
260 {
261  int sockfd;
262  ssize_t r;
263  fr_channel_type_t channel;
264  char buffer[65536];
265 
266  uint32_t magic;
267 
268  /*
269  * Close stale file descriptors
270  */
271  if (*out != -1) {
272  close(*out);
273  *out = -1;
274  }
275 
276  if (file) {
277  /*
278  * FIXME: Get destination from command line, if possible?
279  */
280  sockfd = fr_socket_client_unix(file, false);
281  if (sockfd < 0) {
282  fr_perror("radmin");
283  if (errno == ENOENT) {
284  fprintf(stderr, "Perhaps you need to run the commands:");
285  fprintf(stderr, "\tcd /etc/raddb\n");
286  fprintf(stderr, "\tln -s sites-available/control-socket "
287  "sites-enabled/control-socket\n");
288  fprintf(stderr, "and then re-start the server?\n");
289  }
290  return -1;
291  }
292  } else {
293  sockfd = client_socket(server);
294  }
295 
296  /*
297  * Only works for BSD, but Linux allows us
298  * to mask SIGPIPE, so that's fine.
299  */
300 #ifdef SO_NOSIGPIPE
301  {
302  int set = 1;
303 
304  setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
305  }
306 #endif
307 
308  /*
309  * Set up the initial header data.
310  */
311  magic = 0xf7eead16;
312  magic = htonl(magic);
313  memcpy(buffer, &magic, sizeof(magic));
314  memset(buffer + sizeof(magic), 0, sizeof(magic));
315 
316  r = fr_channel_write(sockfd, FR_CHANNEL_INIT_ACK, buffer, 8);
317  if (r <= 0) {
318  do_close:
319  fprintf(stderr, "%s: Error in socket: %s\n",
320  progname, fr_syserror(errno));
321  close(sockfd);
322  return -1;
323  }
324 
325  r = fr_channel_read(sockfd, &channel, buffer + 8, 8);
326  if (r <= 0) goto do_close;
327 
328  if ((r != 8) || (channel != FR_CHANNEL_INIT_ACK) ||
329  (memcmp(buffer, buffer + 8, 8) != 0)) {
330  fprintf(stderr, "%s: Incompatible versions\n", progname);
331  close(sockfd);
332  return -1;
333  }
334 
335  if (server && secret) {
336  r = do_challenge(sockfd);
337  if (r <= 0) goto do_close;
338  }
339 
340  *out = sockfd;
341 
342  return 0;
343 }
344 
345 #define MAX_COMMANDS (4)
346 
347 int main(int argc, char **argv)
348 {
349  int argval;
350  bool quiet = false;
351  int sockfd = -1;
352  char *line = NULL;
353  ssize_t len;
354  char const *file = NULL;
355  char const *name = "radiusd";
356  char *p, buffer[65536];
357  char const *input_file = NULL;
358  FILE *inputfp = stdin;
359  char const *server = NULL;
360  fr_dict_t *dict = NULL;
361 
362  char const *radius_dir = RADIUS_DIR;
363  char const *dict_dir = DICTDIR;
364 
365  char *commands[MAX_COMMANDS];
366  int num_commands = -1;
367 
368  int exit_status = EXIT_SUCCESS;
369 
370 #ifndef NDEBUG
371  if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) {
372  fr_perror("radmin");
373  exit(EXIT_FAILURE);
374  }
375 #endif
376 
377  talloc_set_log_stderr();
378 
379  if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) {
380  progname = argv[0];
381  } else {
382  progname++;
383  }
384 
385  while ((argval = getopt(argc, argv, "d:D:hi:e:Ef:n:qs:S")) != EOF) {
386  switch (argval) {
387  case 'd':
388  if (file) {
389  fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
390  exit(1);
391  }
392  if (server) {
393  fprintf(stderr, "%s: -d and -s cannot be used together.\n", progname);
394  exit(1);
395  }
396  radius_dir = optarg;
397  break;
398 
399  case 'D':
400  dict_dir = optarg;
401  break;
402 
403  case 'e':
404  num_commands++; /* starts at -1 */
405  if (num_commands >= MAX_COMMANDS) {
406  fprintf(stderr, "%s: Too many '-e'\n",
407  progname);
408  exit(1);
409  }
410 
411  commands[num_commands] = optarg;
412  break;
413 
414  case 'E':
415  echo = true;
416  break;
417 
418  case 'f':
419  radius_dir = NULL;
420  file = optarg;
421  break;
422 
423  default:
424  case 'h':
425  usage(0); /* never returns */
426 
427  case 'i':
428  if (strcmp(optarg, "-") != 0) {
429  input_file = optarg;
430  }
431  quiet = true;
432  break;
433 
434  case 'n':
435  name = optarg;
436  break;
437 
438  case 'q':
439  quiet = true;
440  break;
441 
442  case 's':
443  if (file) {
444  fprintf(stderr, "%s: -s and -f cannot be used together.\n", progname);
445  usage(1);
446  }
447  radius_dir = NULL;
448  server = optarg;
449  break;
450 
451  case 'S':
452  secret = NULL;
453  break;
454  }
455  }
456 
457  /*
458  * Mismatch between the binary and the libraries it depends on
459  */
461  fr_perror("radmin");
462  exit(1);
463  }
464 
465  if (radius_dir) {
466  int rcode;
467  CONF_SECTION *cs, *subcs;
468  uid_t uid;
469  gid_t gid;
470  char const *uid_name = NULL;
471  char const *gid_name = NULL;
472  struct passwd *pwd;
473  struct group *grp;
474 
475  file = NULL; /* MUST read it from the conffile now */
476 
477  snprintf(buffer, sizeof(buffer), "%s/%s.conf", radius_dir, name);
478 
479  /*
480  * Need to read in the dictionaries, else we may get
481  * validation errors when we try and parse the config.
482  */
483  if (fr_dict_init(NULL, &dict, dict_dir, RADIUS_DICTIONARY, "radius") < 0) {
484  fr_perror("radmin");
485  exit(64);
486  }
487 
488  if (fr_dict_read(dict, radius_dir, RADIUS_DICTIONARY) == -1) {
489  fr_perror("radmin");
490  exit(64);
491  }
492 
493  cs = cf_section_alloc(NULL, "main", NULL);
494  if (!cs) exit(1);
495 
496  if (cf_file_read(cs, buffer) < 0) {
497  fprintf(stderr, "%s: Errors reading or parsing %s\n", progname, buffer);
498  talloc_free(cs);
499  usage(1);
500  }
501 
502  uid = getuid();
503  gid = getgid();
504 
505  subcs = NULL;
506  while ((subcs = cf_subsection_find_next(cs, subcs, "listen")) != NULL) {
507  char const *value;
508  CONF_PAIR *cp = cf_pair_find(subcs, "type");
509 
510  if (!cp) continue;
511 
512  value = cf_pair_value(cp);
513  if (!value) continue;
514 
515  if (strcmp(value, "control") != 0) continue;
516 
517  /*
518  * Now find the socket name (sigh)
519  */
520  rcode = cf_pair_parse(subcs, "socket",
522  if (rcode < 0) {
523  fprintf(stderr, "%s: Failed parsing listen section 'socket'\n", progname);
524  exit(1);
525  }
526 
527  if (!file) {
528  fprintf(stderr, "%s: No path given for socket\n", progname);
529  usage(1);
530  }
531 
532  /*
533  * If we're root, just use the first one we find
534  */
535  if (uid == 0) break;
536 
537  /*
538  * Check UID and GID.
539  */
540  rcode = cf_pair_parse(subcs, "uid",
542  if (rcode < 0) {
543  fprintf(stderr, "%s: Failed parsing listen section 'uid'\n", progname);
544  exit(1);
545  }
546 
547  if (!uid_name) break;
548 
549  pwd = getpwnam(uid_name);
550  if (!pwd) {
551  fprintf(stderr, "%s: Failed getting UID for user %s: %s\n", progname, uid_name, strerror(errno));
552  exit(1);
553  }
554 
555  if (uid != pwd->pw_uid) continue;
556 
557  rcode = cf_pair_parse(subcs, "gid",
559  if (rcode < 0) {
560  fprintf(stderr, "%s: Failed parsing listen section 'gid'\n", progname);
561  exit(1);
562  }
563 
564  if (!gid_name) break;
565 
566  grp = getgrnam(gid_name);
567  if (!grp) {
568  fprintf(stderr, "%s: Failed getting GID for group %s: %s\n", progname, gid_name, strerror(errno));
569  exit(1);
570  }
571 
572  if (gid != grp->gr_gid) continue;
573 
574  break;
575  }
576 
577  if (!file) {
578  fprintf(stderr, "%s: Could not find control socket in %s\n", progname, buffer);
579  exit(1);
580  }
581  }
582 
583  if (input_file) {
584  inputfp = fopen(input_file, "r");
585  if (!inputfp) {
586  fprintf(stderr, "%s: Failed opening %s: %s\n", progname, input_file, fr_syserror(errno));
587  exit(1);
588  }
589  }
590 
591  if (!file && !server) {
592  fprintf(stderr, "%s: Must use one of '-d' or '-f' or '-s'\n",
593  progname);
594  exit(1);
595  }
596 
597  /*
598  * Check if stdin is a TTY only if input is from stdin
599  */
600  if (input_file && !quiet && !isatty(STDIN_FILENO)) quiet = true;
601 
602 #ifdef USE_READLINE
603  if (!quiet) {
604 #ifdef USE_READLINE_HISTORY
605  using_history();
606 #endif
607  rl_bind_key('\t', rl_insert);
608  }
609 #endif
610 
611  /*
612  * Prevent SIGPIPEs from terminating the process
613  */
614  signal(SIGPIPE, SIG_IGN);
615 
616  if (do_connect(&sockfd, file, server) < 0) exit(1);
617 
618  /*
619  * Run commans from the command-line.
620  */
621  if (num_commands >= 0) {
622  int i;
623 
624  for (i = 0; i <= num_commands; i++) {
625  len = run_command(sockfd, commands[i], buffer, sizeof(buffer));
626  if (len < 0) exit(1);
627 
628  if (len == FR_CHANNEL_FAIL) exit_status = EXIT_FAILURE;
629  }
630 
631  if (unbuffered) {
632  while (true) flush_channels(sockfd, buffer, sizeof(buffer));
633  }
634 
635  exit(exit_status);
636  }
637 
638  if (!quiet) {
639  printf("%s - FreeRADIUS Server administration tool.\n", radmin_version);
640  printf("Copyright (C) 2008-2015 The FreeRADIUS server project and contributors.\n");
641  printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
642  printf("PARTICULAR PURPOSE.\n");
643  printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
644  printf("GNU General Public License v2.\n");
645  }
646 
647  /*
648  * FIXME: Do login?
649  */
650 
651  while (1) {
652  int retries;
653 
654 #ifndef USE_READLINE
655  if (!quiet) {
656  printf("radmin> ");
657  fflush(stdout);
658  }
659 #else
660  if (!quiet) {
661  line = readline("radmin> ");
662 
663  if (!line) break;
664 
665  if (!*line) {
666  free(line);
667  continue;
668  }
669 
670 #ifdef USE_READLINE_HISTORY
671  add_history(line);
672 #endif
673  } else /* quiet, or no readline */
674 #endif
675  {
676  line = fgets(buffer, sizeof(buffer), inputfp);
677  if (!line) break;
678 
679  p = strchr(buffer, '\n');
680  if (!p) {
681  fprintf(stderr, "%s: Input line too long\n",
682  progname);
683  exit(1);
684  }
685 
686  *p = '\0';
687 
688  /*
689  * Strip off leading spaces.
690  */
691  for (p = line; *p != '\0'; p++) {
692  if ((p[0] == ' ') ||
693  (p[0] == '\t')) {
694  line = p + 1;
695  continue;
696  }
697 
698  if (p[0] == '#') {
699  line = NULL;
700  break;
701  }
702 
703  break;
704  }
705 
706  /*
707  * Comments: keep going.
708  */
709  if (!line) continue;
710 
711  /*
712  * Strip off CR / LF
713  */
714  for (p = line; *p != '\0'; p++) {
715  if ((p[0] == '\r') ||
716  (p[0] == '\n')) {
717  p[0] = '\0';
718  break;
719  }
720  }
721  }
722 
723  if (strcmp(line, "reconnect") == 0) {
724  if (do_connect(&sockfd, file, server) < 0) exit(1);
725  line = NULL;
726  continue;
727  }
728 
729  if (memcmp(line, "secret ", 7) == 0) {
730  if (!secret) {
731  secret = line + 7;
732  do_challenge(sockfd);
733  }
734  line = NULL;
735  continue;
736  }
737 
738  /*
739  * Exit, done, etc.
740  */
741  if ((strcmp(line, "exit") == 0) ||
742  (strcmp(line, "quit") == 0)) {
743  break;
744  }
745 
746  if (server && !secret) {
747  fprintf(stderr, "ERROR: You must enter 'secret <SECRET>' before running any commands\n");
748  line = NULL;
749  continue;
750  }
751 
752  retries = 0;
753  retry:
754  len = run_command(sockfd, line, buffer, sizeof(buffer));
755  if (len < 0) {
756  if (!quiet) fprintf(stderr, "... reconnecting ...\n");
757 
758  if (do_connect(&sockfd, file, server) < 0) {
759  exit(1);
760  }
761 
762  retries++;
763  if (retries < 2) goto retry;
764 
765  fprintf(stderr, "Failed to connect to server\n");
766  exit(1);
767 
768  } else if (len == FR_CHANNEL_SUCCESS) {
769  break;
770 
771  } else if (len == FR_CHANNEL_FAIL) {
772  exit_status = EXIT_FAILURE;
773  }
774  }
775 
776  fprintf(stdout, "\n");
777 
778  if (inputfp != stdin) fclose(inputfp);
779 
780  talloc_free(dict);
781 
782  return exit_status;
783 }
784 
static ssize_t flush_channels(int sockfd, char *buffer, size_t bufsize)
Definition: radmin.c:187
static char const * dict_dir
Definition: radwho.c:53
static int sockfd
Definition: radclient.c:59
int cf_pair_parse(CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, FR_TOKEN dflt_quote)
Parses a CONF_PAIR into a C data type, with a default value.
Definition: conffile.c:1968
static char const * radius_dir
Path to raddb directory.
Definition: mainconfig.c:88
int fr_socket_client_tcp(fr_ipaddr_t *src_ipaddr, fr_ipaddr_t *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition: socket.c:167
Main server configuration.
Definition: radiusd.h:108
int fr_dict_read(fr_dict_t *dict, char const *dir, char const *filename)
Definition: dict.c:2291
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:127
static char const * name
int fr_socket_client_unix(char const *path, bool async)
int cf_file_read(CONF_SECTION *cs, char const *file)
Definition: conffile.c:3421
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
int main(int argc, char **argv)
Definition: radmin.c:347
#define rad_waitpid(a, b)
Definition: radiusd.h:564
#define MAX_COMMANDS
Definition: radmin.c:345
ssize_t fr_channel_read(int fd, fr_channel_type_t *pchannel, void *buffer, size_t buflen)
Definition: channel.c:125
static char const * progname
Definition: radmin.c:67
static int client_socket(char const *server)
Definition: radmin.c:116
CONF_PAIR * cf_pair_find(CONF_SECTION const *, char const *name)
Definition: conffile.c:3478
char const * cf_pair_value(CONF_PAIR const *pair)
Definition: conffile.c:3506
int fr_fault_setup(char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition: debug.c:890
fr_channel_type_t
Definition: channel.h:32
Vendors and attribute names.
Definition: dict.c:61
main_config_t main_config
Main server configuration.
Definition: radmin.c:80
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition: version.c:38
static void NEVER_RETURNS usage(int status)
Definition: radmin.c:99
pid_t rad_fork(void)
Definition: radmin.c:87
void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *text, size_t text_len, uint8_t const *key, size_t key_len) CC_BOUNDED(__minbytes__
static int do_connect(int *out, char const *file, char const *server)
Definition: radmin.c:259
CONF_SECTION * cf_subsection_find_next(CONF_SECTION const *section, CONF_SECTION const *subsection, char const *name1)
Definition: conffile.c:3799
#define STRINGIFY(x)
Definition: build.h:34
void void fr_perror(char const *,...) CC_HINT(format(printf
static char const * secret
Definition: radmin.c:83
#define RADIUS_DICTIONARY
Definition: conf.h:7
static int retries
Definition: radclient.c:42
Configuration AVP similar to a VALUE_PAIR.
Definition: conffile.c:82
static bool echo
Definition: radmin.c:82
#define PW_RADMIN_PORT
Definition: radiusd.h:624
static ssize_t run_command(int sockfd, char const *command, char *buffer, size_t bufsize)
Definition: radmin.c:241
#define FR_ITEM_POINTER(_t, _p)
Definition: conffile.h:176
ssize_t fr_channel_write(int fd, fr_channel_type_t channel, void const *buffer, size_t buflen)
Definition: channel.c:205
CONF_SECTION * cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2)
Allocate a CONF_SECTION.
Definition: conffile.c:626
static ssize_t do_challenge(int sockfd)
Definition: radmin.c:149
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
IPv4/6 prefix.
Definition: inet.h:41
#define NEVER_RETURNS
Definition: libradius.h:133
String of printable characters.
Definition: radius.h:33
static bool unbuffered
Definition: radmin.c:84
#define RCSID(id)
Definition: build.h:135
static int r
Definition: rbmonkey.c:66
#define RADIUS_DIR
Definition: conf.h:3
int fr_dict_init(TALLOC_CTX *ctx, fr_dict_t **out, char const *dir, char const *fn, char const *name)
(re)initialize a protocol dictionary
Definition: dict.c:2148
#define RADIUSD_MAGIC_NUMBER
Definition: libradius.h:51
static char const * radmin_version
Definition: radmin.c:68