The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
proto_control_unix.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: 0a936b3d2ba4a7796620cec864d73c701d38bf58 $
19  * @file proto_control_unix.c
20  * @brief Control handler for Unix sockets.
21  *
22  * @copyright 2018 The FreeRADIUS server project.
23  * @copyright 2018 Alan DeKok (aland@deployingradius.com)
24  */
25 #include <freeradius-devel/server/main_config.h>
26 
27 #include <freeradius-devel/io/application.h>
28 #include <freeradius-devel/io/listen.h>
29 #include <freeradius-devel/io/schedule.h>
30 #include <freeradius-devel/server/protocol.h>
31 #include <freeradius-devel/util/perm.h>
32 #include <freeradius-devel/util/trie.h>
33 #include <freeradius-devel/util/file.h>
34 
35 #include <netdb.h>
36 
37 #include "proto_control.h"
38 
39 #include <freeradius-devel/bio/fd.h>
40 
41 #ifdef HAVE_SYS_STAT_H
42 #endif
43 
44 #include <fcntl.h>
45 #include <libgen.h>
46 
47 typedef struct {
48  char const *name; //!< socket name
49 
50  int sockfd;
51 
53 
54  fr_stats_t stats; //!< statistics for this socket
55 
56  fr_io_address_t *connection; //!< for connected sockets.
57 
58 
59  fr_io_data_read_t read; //!< function to process data *after* reading
60  FILE *stdout_fp;
61  FILE *stderr_fp;
62 
64  FILE *misc;
65  fr_cmd_info_t *info; //!< for running commands
66 
67  fr_client_t radclient; //!< for faking out clients
69 
70 typedef struct {
71  CONF_SECTION *cs; //!< our configuration
72 
73  char const *filename; //!< filename of control socket
74  char const *uid_name; //!< name of UID to require
75  char const *gid_name; //!< name of GID to require
76  uid_t uid; //!< UID value
77  gid_t gid; //!< GID value
78 
79  uint32_t recv_buff; //!< How big the kernel's receive buffer should be.
80 
81  uint32_t max_packet_size; //!< for message ring buffer.
82 
83  char const *mode_name;
84  bool read_only;
85 
86  bool recv_buff_is_set; //!< Whether we were provided with a receive
87  //!< buffer value.
88  char const *peer_uid_name; //!< name of UID to require
89  char const *peer_gid_name; //!< name of GID to require
90  uid_t peer_uid; //!< UID value
91  gid_t peer_gid; //!< GID value
92 
94 
95 static const conf_parser_t peercred_config[] = {
96  { FR_CONF_OFFSET("uid", proto_control_unix_t, peer_uid_name) },
97  { FR_CONF_OFFSET("gid", proto_control_unix_t, peer_gid_name) },
98 
100 };
101 
104  .dflt = "${run_dir}/radiusd.sock}" },
105  { FR_CONF_OFFSET("uid", proto_control_unix_t, uid_name) },
106  { FR_CONF_OFFSET("gid", proto_control_unix_t, gid_name) },
107  { FR_CONF_OFFSET("mode", proto_control_unix_t, mode_name) },
108 
109  { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, proto_control_unix_t, recv_buff) },
110 
111  { FR_CONF_OFFSET("max_packet_size", proto_control_unix_t, max_packet_size), .dflt = "4096" } ,
112 
113  { FR_CONF_POINTER("peercred", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) peercred_config },
114 
116 };
117 
118 #define FR_READ (1)
119 #define FR_WRITE (2)
120 
122  { L("read-only"), FR_READ },
123  { L("read-write"), FR_READ | FR_WRITE },
124  { L("ro"), FR_READ },
125  { L("rw"), FR_READ | FR_WRITE }
126 };
128 
129 #undef INT
130 #define INT size_t
131 #define SINT ssize_t
132 
133 static SINT write_stdout(void *instance, char const *buffer, INT buffer_size)
134 {
135  proto_control_unix_thread_t *thread = talloc_get_type_abort(instance, proto_control_unix_thread_t);
136 
137  return fr_conduit_write(thread->sockfd, FR_CONDUIT_STDOUT, buffer, buffer_size);
138 }
139 
140 static SINT write_stderr(void *instance, char const *buffer, INT buffer_size)
141 {
142  proto_control_unix_thread_t *thread = talloc_get_type_abort(instance, proto_control_unix_thread_t)
143 ;
144  return fr_conduit_write(thread->sockfd, FR_CONDUIT_STDERR, buffer, buffer_size);
145 }
146 
147 static SINT write_misc(void *instance, char const *buffer, INT buffer_size)
148 {
149  proto_control_unix_thread_t *thread = talloc_get_type_abort(instance, proto_control_unix_thread_t);
150 
151  return fr_conduit_write(thread->sockfd, thread->misc_conduit, buffer, buffer_size);
152 }
153 
154 
155 /*
156  * Run a command.
157  */
158 static ssize_t mod_read_command(fr_listen_t *li, UNUSED void **packet_ctx, UNUSED fr_time_t *recv_time_p, uint8_t *buffer, UNUSED size_t buffer_len, UNUSED size_t *leftover)
159 {
161  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
163  uint32_t status;
164  uint8_t *cmd = buffer + sizeof(*hdr);
165  int rcode;
166  char string[1024];
167 
168  hdr->length = ntohl(hdr->length);
169  if (hdr->length >= sizeof(string)) goto fail;
170 
171  /*
172  * If the write gives us nothing, send an empty SUCCESS back.
173  */
174  if (!hdr->length) {
175  status = FR_CONDUIT_SUCCESS;
176  goto done;
177  }
178 
179  /*
180  * fr_command_run() expects a zero-terminated string...
181  */
182  memcpy(string, cmd, hdr->length);
183  string[hdr->length] = '\0';
184 
185  /*
186  * Content is the string we need help for.
187  */
188  if (htons(hdr->conduit) == FR_CONDUIT_HELP) {
189  fr_radmin_help(thread->stdout_fp, string);
190  // @todo - have in-band signalling saying that the help is done?
191  // we want to be able to say that *this* help is done.
192  // the best way to do that is to have a token, and every command
193  // from the other end sends a token, and we echo it back here...
194  // Or, since we currently can't do streaming commands, it's OK?
195  // Or, we assume that origin 0 is for interactive commands,
196  // and that the other origins are for streaming output...
197  status = FR_CONDUIT_SUCCESS;
198  goto done;
199  }
200 
201  if (htons(hdr->conduit) == FR_CONDUIT_COMPLETE) {
202  uint16_t start;
203 
204  if (hdr->length < 2) goto fail;
205 
206  start = (string[0] << 8) | string[1];
207 
209 
210  fr_radmin_complete(thread->misc, string + 2, start);
212  status = FR_CONDUIT_SUCCESS;
213  goto done;
214  }
215 
216  if (htons(hdr->conduit) != FR_CONDUIT_STDIN) {
217  DEBUG("ERROR: Ignoring data which is from wrong input");
218  return 0;
219  }
220 
221  DEBUG("radmin-remote> %.*s", (int) hdr->length, cmd);
222 
223  rcode = fr_radmin_run(thread->info, thread->stdout_fp, thread->stderr_fp, string, inst->read_only);
224  if (rcode < 0) {
225 fail:
226  status = FR_CONDUIT_FAIL;
227 
228  } else if (rcode == 0) {
229  /*
230  * The other end should keep track of it's
231  * context, and send us full lines.
232  */
233  (void) fr_command_clear(0, thread->info);
234  status = FR_CONDUIT_PARTIAL;
235  } else {
236  status = FR_CONDUIT_SUCCESS;
237  }
238 
239 done:
240  status = htonl(status);
241  (void) fr_conduit_write(thread->sockfd, FR_CONDUIT_CMD_STATUS, &status, sizeof(status));
242 
243  return 0;
244 }
245 
246 /*
247  * Process an initial connection request.
248  */
249 static ssize_t mod_read_init(fr_listen_t *li, UNUSED void **packet_ctx, UNUSED fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, UNUSED size_t *leftover)
250 {
251  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
253  uint32_t magic;
254 
255  if (htons(hdr->conduit) != FR_CONDUIT_INIT_ACK) {
256  DEBUG("ERROR: Connection is missing initial ACK packet.");
257  return -1;
258  }
259 
260  if (buffer_len < sizeof(*hdr)) {
261  DEBUG("ERROR: Initial ACK is malformed");
262  return -1;
263  }
264 
265  if (htonl(hdr->length) != 8) {
266  DEBUG("ERROR: Initial ACK has wrong length (%lu).", (size_t) htonl(hdr->length));
267  return -1;
268  }
269 
270  memcpy(&magic, buffer + sizeof(*hdr), sizeof(magic));
271  magic = htonl(magic);
272  if (magic != FR_CONDUIT_MAGIC) {
273  DEBUG("ERROR: Connection from incompatible version of radmin.");
274  return -1;
275  }
276 
277  /*
278  * Next 4 bytes are zero, we ignore them.
279  */
280  if (write(thread->sockfd, buffer, buffer_len) < (ssize_t) buffer_len) {
281  DEBUG("ERROR: Blocking write to socket... oops");
282  return -1;
283  }
284 
285  thread->read = mod_read_command;
286 
287  return 0;
288 }
289 
290 static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
291 {
292  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
293  ssize_t data_size;
294 
295  fr_conduit_type_t conduit;
296  bool want_more;
297 
298  /*
299  * Read data into the buffer.
300  */
301  data_size = fr_conduit_read_async(thread->sockfd, &conduit, buffer, buffer_len, leftover, &want_more);
302  if (data_size < 0) {
303  DEBUG2("proto_control_unix got read error %zd: %s", data_size, fr_syserror(errno));
304  return data_size;
305  }
306 
307  /*
308  * Note that we return ERROR for all bad packets, as
309  * there's no point in reading packets from a TCP
310  * connection which isn't sending us properly formatted
311  * packets.
312  */
313 
314  /*
315  * Not enough for a full packet, ask the caller to read more.
316  */
317  if (want_more) {
318  return 0;
319  }
320 
321  // @todo - maybe convert timestamp?
322  *recv_time_p = fr_time();
323  *leftover = 0;
324 
325  /*
326  * Print out what we received.
327  */
328  DEBUG3("proto_control_unix - Received command packet length %d on %s",
329  (int) data_size, thread->name);
330 
331  /*
332  * Run the state machine to process the rest of the packet.
333  */
334  return thread->read(li, packet_ctx, recv_time_p, buffer, (size_t) data_size, leftover);
335 }
336 
337 
338 static ssize_t mod_write(fr_listen_t *li, UNUSED void *packet_ctx, UNUSED fr_time_t request_time,
339  uint8_t *buffer, size_t buffer_len, size_t written)
340 {
341  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
342  ssize_t data_size;
343 
344  /*
345  * @todo - share a stats interface with the parent? or
346  * put the stats in the listener, so that proto_control
347  * can update them, too.. <sigh>
348  */
349  thread->stats.total_responses++;
350 
351  /*
352  * Only write replies if they're RADIUS packets.
353  * sometimes we want to NOT send a reply...
354  */
355  data_size = write(thread->sockfd, buffer + written, buffer_len - written);
356 
357  /*
358  * This socket is dead. That's an error...
359  */
360  if (data_size <= 0) return data_size;
361 
362  return data_size + written;
363 }
364 
365 
366 static int mod_connection_set(fr_listen_t *li, fr_io_address_t *connection)
367 {
368  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
369 
370  thread->connection = connection;
371 
372  // @todo - set name to path + peer ID of other end?
373 
374  return 0;
375 }
376 
377 static void mod_network_get(UNUSED void *instance, int *ipproto, bool *dynamic_clients, fr_trie_t const **trie)
378 {
379  *ipproto = IPPROTO_TCP;
380  *dynamic_clients = false;
381  *trie = NULL;
382 }
383 
384 /** Open a UNIX listener for control sockets
385  *
386  */
387 static int mod_open(fr_listen_t *li)
388 {
390  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
391 
392  CONF_ITEM *ci;
393  CONF_SECTION *server_cs;
394 
395  fr_bio_fd_info_t const *info;
396  fr_bio_fd_config_t cfg;
397 
398  fr_assert(!thread->connection);
399 
400  cfg = (fr_bio_fd_config_t) {
402  .socket_type = SOCK_STREAM,
403  .path = inst->filename,
404  .uid = inst->uid,
405  .gid = inst->gid,
406  .perm = 0x700,
407  .async = true,
408  };
409 
410  thread->fd_bio = fr_bio_fd_alloc(thread, NULL, &cfg, 0);
411  if (!thread->fd_bio) {
412  PERROR("Failed allocating UNIX path %s", inst->filename);
413  return -1;
414  }
415 
416  info = fr_bio_fd_info(thread->fd_bio);
417  fr_assert(info != NULL);
418 
419  li->fd = thread->sockfd = info->socket.fd;
420 
421  ci = cf_parent(inst->cs); /* listen { ... } */
422  fr_assert(ci != NULL);
423  ci = cf_parent(ci);
424  fr_assert(ci != NULL);
425 
426  server_cs = cf_item_to_section(ci);
427 
428  thread->name = talloc_typed_asprintf(thread, "control_unix from filename %s", inst->filename);
429 
430  /*
431  * Set up the fake client
432  */
433  thread->radclient.longname = inst->filename;
434  thread->radclient.ipaddr.af = AF_INET;
435  thread->radclient.src_ipaddr.af = AF_INET;
436 
437  thread->radclient.server_cs = server_cs;
438  fr_assert(thread->radclient.server_cs != NULL);
440 
441  return 0;
442 }
443 
444 #if !defined(HAVE_GETPEEREID) && defined(SO_PEERCRED)
445 static int getpeereid(int s, uid_t *euid, gid_t *egid)
446 {
447  struct ucred cr;
448  socklen_t cl = sizeof(cr);
449 
450  if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cl) < 0) {
451  return -1;
452  }
453 
454  *euid = cr.uid;
455  *egid = cr.gid;
456  return 0;
457 }
458 
459 /* we now have getpeereid() in this file */
460 #define HAVE_GETPEEREID (1)
461 
462 #endif /* HAVE_GETPEEREID */
463 
465 {
466  if (thread->stdout_fp) fclose(thread->stdout_fp);
467  if (thread->stderr_fp) fclose(thread->stderr_fp);
468  if (thread->misc) fclose(thread->misc);
469 
470  return 0;
471 }
472 
473 /** Set the file descriptor for this socket.
474  *
475  */
476 static int mod_fd_set(fr_listen_t *li, int fd)
477 {
479  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
480 
482 
483 #ifdef HAVE_GETPEEREID
484  /*
485  * Perform user authentication.
486  *
487  * @todo - this really belongs in the accept() callback,
488  * so that we don't create an entirely new listener and
489  * then close it.
490  */
491  if (inst->peer_uid || inst->peer_gid) {
492  uid_t uid;
493  gid_t gid;
494 
495  if (getpeereid(fd, &uid, &gid) < 0) {
496  ERROR("Failed getting peer credentials for %s: %s",
497  inst->filename, fr_syserror(errno));
498  return -1;
499  }
500 
501  /*
502  * Only do UID checking if the caller is
503  * non-root. The superuser can do anything, so
504  * we might as well let them do anything.
505  */
506  if (uid != 0) do {
507  /*
508  * Allow entry if UID or GID matches.
509  */
510  if (inst->peer_uid_name && (inst->peer_uid == uid)) break;
511  if (inst->peer_gid_name && (inst->peer_gid == gid)) break;
512 
513  if (inst->peer_uid_name && (inst->peer_uid != uid)) {
514  ERROR("Unauthorized connection to %s from uid %ld",
515  inst->filename, (long int) uid);
516  return -1;
517  }
518 
519  if (inst->peer_gid_name && (inst->peer_gid != gid)) {
520  ERROR("Unauthorized connection to %s from gid %ld",
521  inst->filename, (long int) gid);
522  return -1;
523  }
524 
525  } while (0);
526 
527  thread->name = talloc_typed_asprintf(thread, "proto unix filename %s from peer UID %u GID %u",
528  inst->filename,
529  (unsigned int) uid, (unsigned int) gid);
530  } else
531 #endif
532 
533 
534  thread->name = talloc_typed_asprintf(thread, "proto unix filename %s", inst->filename);
535 
536  thread->sockfd = fd;
537  thread->read = mod_read_init;
538 
539  /*
540  * These must be set separately as they have different prototypes.
541  */
542  io.read = NULL;
543  io.seek = NULL;
544  io.close = NULL;
545  io.write = write_stdout;
546 
547  thread->stdout_fp = fopencookie(thread, "w", io);
548 
549  io.write = write_stderr;
550  thread->stderr_fp = fopencookie(thread, "w", io);
551 
552  io.write = write_misc;
553  thread->misc = fopencookie(thread, "w", io);
554 
555  talloc_set_destructor(thread, _close_cookies);
556 
557  /*
558  * @todo - if we move to a binary protocol, then we
559  * should change this to a small (i.e. 1K) buffer. The
560  * data should be sent over to the remote side as quickly
561  * as possible.
562  */
563  (void) setvbuf(thread->stdout_fp, NULL, _IOLBF, 0);
564  (void) setvbuf(thread->stderr_fp, NULL, _IOLBF, 0);
565  (void) setvbuf(thread->misc, NULL, _IOLBF, 0);
566 
567  thread->info = talloc_zero(thread, fr_cmd_info_t);
568  fr_command_info_init(thread, thread->info);
569 
570  return 0;
571 }
572 
573 static char const *mod_name(fr_listen_t *li)
574 {
575  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
576 
577  return thread->name;
578 }
579 
580 
581 static int mod_bootstrap(module_inst_ctx_t const *mctx)
582 {
583  proto_control_unix_t *inst = talloc_get_type_abort(mctx->inst->data, proto_control_unix_t);
584  CONF_SECTION *conf = mctx->inst->conf;
585 
586  inst->cs = conf;
587 
588  if (inst->recv_buff_is_set) {
589  FR_INTEGER_BOUND_CHECK("recv_buff", inst->recv_buff, >=, 32);
590  FR_INTEGER_BOUND_CHECK("recv_buff", inst->recv_buff, <=, INT_MAX);
591  }
592 
593  if (inst->uid_name) {
594  struct passwd *pwd;
595 
596  if (fr_perm_getpwnam(conf, &pwd, inst->uid_name) < 0) {
597  PERROR("Failed getting uid for %s", inst->uid_name);
598  return -1;
599  }
600  inst->uid = pwd->pw_uid;
601  talloc_free(pwd);
602 
603  } else if (main_config->server_uid) {
604  inst->uid = main_config->server_uid;
605 
606  } else {
607  inst->uid = getuid();
608  }
609 
610  if (inst->gid_name) {
611  if (fr_perm_gid_from_str(conf, &inst->gid, inst->gid_name) < 0) {
612  PERROR("Failed getting gid for %s", inst->gid_name);
613  return -1;
614  }
615 
616  } else if (main_config->server_gid) {
617  inst->gid = main_config->server_gid;
618 
619  } else {
620  inst->gid = getgid();
621  }
622 
623  /*
624  * And for peer creds
625  */
626  if (inst->peer_uid_name) {
627  struct passwd *pwd;
628 
629  if (fr_perm_getpwnam(conf, &pwd, inst->peer_uid_name) < 0) {
630  PERROR("Failed getting peer uid for %s", inst->peer_uid_name);
631  return -1;
632  }
633  inst->peer_uid = pwd->pw_uid;
634  talloc_free(pwd);
635  }
636 
637  if (inst->peer_gid_name) {
638  if (fr_perm_gid_from_str(conf, &inst->peer_gid, inst->peer_gid_name) < 0) {
639  PERROR("Failed getting peer gid for %s", inst->peer_gid_name);
640  return -1;
641  }
642  }
643 
644  if (!inst->mode_name) {
645  inst->read_only = true;
646  } else {
647  int mode;
648 
649  mode = fr_table_value_by_str(mode_names, inst->mode_name, 0);
650  if (!mode) {
651  ERROR("Invalid mode name \"%s\"",
652  inst->mode_name);
653  return -1;
654  }
655 
656  if ((mode & FR_WRITE) == 0) {
657  inst->read_only = true;
658  } else {
659  inst->read_only = false;
660  }
661  }
662 
663  FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, >=, 20);
664  FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, <=, 65536);
665 
666  return 0;
667 }
668 
670 {
671  proto_control_unix_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_control_unix_thread_t);
672 
673  return &thread->radclient;
674 }
675 
678  .common = {
679  .magic = MODULE_MAGIC_INIT,
680  .name = "control_unix",
681  .config = unix_listen_config,
682  .inst_size = sizeof(proto_control_unix_t),
683  .thread_inst_size = sizeof(proto_control_unix_thread_t),
684  .bootstrap = mod_bootstrap,
685  },
686  .default_message_size = 4096,
687 
688  .open = mod_open,
689  .read = mod_read,
690  .write = mod_write,
691  .fd_set = mod_fd_set,
692  .connection_set = mod_connection_set,
693  .network_get = mod_network_get,
694  .client_find = mod_client_find,
695  .get_name = mod_name,
696 };
static int const char char buffer[256]
Definition: acutest.h:574
module_t common
Common fields to all loadable modules.
Definition: app_io.h:34
Public structure describing an I/O path for a protocol.
Definition: app_io.h:33
int fr_radmin_run(fr_cmd_info_t *info, FILE *fp, FILE *fp_err, char *str, bool read_only)
Run a command from an input string.
Definition: radmin.c:1135
void fr_radmin_complete(FILE *fp, const char *text, int start)
Definition: radmin.c:1171
void fr_radmin_help(FILE *fp, char const *text)
Definition: radmin.c:1166
Definition: base.h:103
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition: cf_parse.h:486
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition: cf_parse.h:310
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
Definition: cf_parse.h:282
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:406
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:400
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
Common header for all CONF_* types.
Definition: cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
#define cf_parent(_cf)
Definition: cf_util.h:98
int fr_command_clear(int new_argc, fr_cmd_info_t *info)
Clear out any value boxes etc.
Definition: command.c:2369
void fr_command_info_init(TALLOC_CTX *ctx, fr_cmd_info_t *info)
Initialize an fr_cmd_info_t structure.
Definition: command.c:2397
ssize_t fr_conduit_write(int fd, fr_conduit_type_t conduit, void const *out, size_t outlen)
Definition: conduit.c:225
ssize_t fr_conduit_read_async(int fd, fr_conduit_type_t *pconduit, void *out, size_t outlen, size_t *leftover, bool *want_more)
Definition: conduit.c:72
#define FR_CONDUIT_MAGIC
Definition: conduit.h:32
uint16_t conduit
Definition: conduit.h:77
@ FR_CONDUIT_FAIL
Definition: conduit.h:54
@ FR_CONDUIT_PARTIAL
Definition: conduit.h:55
@ FR_CONDUIT_SUCCESS
Definition: conduit.h:56
uint32_t length
Definition: conduit.h:78
fr_conduit_type_t
Definition: conduit.h:34
@ FR_CONDUIT_STDOUT
Definition: conduit.h:36
@ FR_CONDUIT_HELP
Definition: conduit.h:43
@ 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
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
Definition: fd.c:1167
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_cb_funcs_t *cb, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
Definition: fd.c:1018
fr_socket_t socket
as connected socket
Definition: fd.h:108
@ FR_BIO_FD_ACCEPT
returns new fd in buffer on fr_bio_read()
Definition: fd.h:65
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition: fd.h:77
Configuration for sockets.
Definition: fd.h:76
Run-time status of the socket.
Definition: fd.h:107
FILE * fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs)
Definition: fopencookie.c:99
cookie_close_function_t close
Definition: fopencookie.h:55
cookie_seek_function_t seek
Definition: fopencookie.h:54
cookie_read_function_t read
Definition: fopencookie.h:52
cookie_write_function_t write
Definition: fopencookie.h:53
int af
Address family.
Definition: inet.h:64
IPv4/6 prefix.
Definition: merged_model.c:272
ssize_t(* fr_io_data_read_t)(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time, uint8_t *buffer, size_t buffer_len, size_t *leftover)
Read from a socket.
Definition: base.h:176
void const * app_io_instance
I/O path configuration context.
Definition: listen.h:32
void * thread_instance
thread / socket context
Definition: listen.h:33
int fd
file descriptor for this socket - set by open
Definition: listen.h:28
char const * server
Name of the virtual server client is associated with.
Definition: client.h:101
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition: client.h:80
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
Definition: client.h:81
char const * longname
Client identifier.
Definition: client.h:84
CONF_SECTION * server_cs
Virtual server that the client is associated with.
Definition: client.h:102
Describes a host allowed to send packets to the server.
Definition: client.h:77
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
talloc_free(reap)
main_config_t const * main_config
Main server configuration.
Definition: main_config.c:69
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
int fr_perm_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
Resolve a username to a passwd entry.
Definition: perm.c:138
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition: perm.c:345
fr_client_t radclient
for faking out clients
char const * name
socket name
static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
static const conf_parser_t peercred_config[]
char const * filename
filename of control socket
static int _close_cookies(proto_control_unix_thread_t *thread)
gid_t peer_gid
GID value.
char const * gid_name
name of GID to require
bool recv_buff_is_set
Whether we were provided with a receive buffer value.
fr_cmd_info_t * info
for running commands
fr_io_data_read_t read
function to process data after reading
static int mod_bootstrap(module_inst_ctx_t const *mctx)
uint32_t recv_buff
How big the kernel's receive buffer should be.
fr_io_address_t * connection
for connected sockets.
fr_app_io_t proto_control_unix
static int mod_open(fr_listen_t *li)
Open a UNIX listener for control sockets.
uid_t peer_uid
UID value.
static char const * mod_name(fr_listen_t *li)
static SINT write_stdout(void *instance, char const *buffer, INT buffer_size)
char const * peer_uid_name
name of UID to require
CONF_SECTION * cs
our configuration
char const * peer_gid_name
name of GID to require
static ssize_t mod_read_init(fr_listen_t *li, UNUSED void **packet_ctx, UNUSED fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, UNUSED size_t *leftover)
static void mod_network_get(UNUSED void *instance, int *ipproto, bool *dynamic_clients, fr_trie_t const **trie)
#define FR_WRITE
static ssize_t mod_write(fr_listen_t *li, UNUSED void *packet_ctx, UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len, size_t written)
#define FR_READ
static SINT write_misc(void *instance, char const *buffer, INT buffer_size)
#define SINT
static int mod_connection_set(fr_listen_t *li, fr_io_address_t *connection)
static SINT write_stderr(void *instance, char const *buffer, INT buffer_size)
static int mod_fd_set(fr_listen_t *li, int fd)
Set the file descriptor for this socket.
fr_stats_t stats
statistics for this socket
uint32_t max_packet_size
for message ring buffer.
static fr_client_t * mod_client_find(fr_listen_t *li, UNUSED fr_ipaddr_t const *ipaddr, UNUSED int ipproto)
static size_t mode_names_len
static ssize_t mod_read_command(fr_listen_t *li, UNUSED void **packet_ctx, UNUSED fr_time_t *recv_time_p, uint8_t *buffer, UNUSED size_t buffer_len, UNUSED size_t *leftover)
static fr_table_num_sorted_t mode_names[]
static const conf_parser_t unix_listen_config[]
char const * uid_name
name of UID to require
#define INT
static int ipproto
Definition: radclient-ng.c:94
static bool done
Definition: radclient.c:80
#define DEBUG2(fmt,...)
Definition: radclient.h:43
static rs_t * conf
Definition: radsniff.c:53
fr_uint_t total_responses
Definition: stats.h:43
fr_assert(0)
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition: table.h:134
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:45
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:380
#define talloc_get_type_abort_const
Definition: talloc.h:270
"server local" time.
Definition: time.h:69
int fd
File descriptor if this is a live socket.
Definition: socket.h:81