The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_logtee.c
Go to the documentation of this file.
1 /*
2  * This program is 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 (at
5  * 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: 6893a40d066975062bf3ea885e90d3b7659add3d $
19  * @file rlm_logtee.c
20  * @brief Add an additional log destination for any given request.
21  *
22  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  *
24  * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  */
26 RCSID("$Id: 6893a40d066975062bf3ea885e90d3b7659add3d $")
27 
28 #include <freeradius-devel/server/base.h>
29 #include <freeradius-devel/server/module_rlm.h>
30 #include <freeradius-devel/util/debug.h>
31 #include <freeradius-devel/server/connection.h>
32 
33 #ifdef HAVE_FCNTL_H
34 # include <fcntl.h>
35 #endif
36 
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 
41 #ifdef HAVE_GRP_H
42 # include <grp.h>
43 #endif
44 
45 #ifdef HAVE_SYSLOG_H
46 # include <syslog.h>
47 # ifndef LOG_INFO
48 # define LOG_INFO (0)
49 # endif
50 #endif
51 
52 #include <sys/uio.h>
53 
54 typedef enum {
56  LOGTEE_DST_FILE, //!< Log to a file.
57  LOGTEE_DST_UNIX, //!< Log via Unix socket.
58  LOGTEE_DST_UDP, //!< Log via UDP.
59  LOGTEE_DST_TCP, //!< Log via TCP.
60 } logtee_dst_t;
61 
63  { L("file"), LOGTEE_DST_FILE },
64  { L("tcp"), LOGTEE_DST_TCP },
65  { L("udp"), LOGTEE_DST_UDP },
66  { L("unix"), LOGTEE_DST_UNIX }
67 };
69 
70 typedef struct {
71  fr_ipaddr_t dst_ipaddr; //!< Network server.
72  fr_ipaddr_t src_ipaddr; //!< Send requests from a given src_ipaddr.
73  uint16_t port; //!< Network port.
74 } logtee_net_t;
75 
76 /** logtee module instance
77  */
78 typedef struct {
79  char const *name; //!< Module instance name.
80 
81  char const *delimiter; //!< Line termination string (usually \n).
82  size_t delimiter_len; //!< Length of line termination string.
83 
84  tmpl_t *log_fmt; //!< Source of log messages.
85 
86  logtee_dst_t log_dst; //!< Logging destination.
87  char const *log_dst_str; //!< Logging destination string.
88 
89  size_t buffer_depth; //!< How big our circular buffer should be.
90 
91  struct {
92  char const *name; //!< File to write to.
93  uint32_t permissions; //!< Permissions to use when creating new files.
94  char const *group_str; //!< Group to set on new files.
95  gid_t group; //!< Resolved gid.
96  bool escape; //!< Do filename escaping, yes / no.
97  xlat_escape_legacy_t escape_func; //!< Escape function.
98  } file;
99 
100  struct {
101  char const *path; //!< Where the UNIX socket lives.
102  } unix_sock; // Lowercase unix is a macro on some systems?!
103 
104  logtee_net_t tcp; //!< TCP server.
105  logtee_net_t udp; //!< UDP server.
106 
107  fr_time_delta_t connection_timeout; //!< How long to wait to open a socket.
108  fr_time_delta_t reconnection_delay; //!< How long to wait to retry.
109 } rlm_logtee_t;
110 
111 /** Per-thread instance data
112  *
113  * Contains buffers and connection handles specific to the thread.
114  */
115 typedef struct {
116  rlm_logtee_t const *inst; //!< Instance of logtee.
117  fr_event_list_t *el; //!< This thread's event list.
118  connection_t *conn; //!< Connection to our log destination.
119 
120  fr_fring_t *fring; //!< Circular buffer used to batch up messages.
121 
122  bool pending; //!< We have pending messages to write.
123 
124  TALLOC_CTX *msg_pool; //!< A 1k talloc pool to hold the log message whilst
125  //!< it's being expanded.
126  fr_pair_t *msg; //!< Temporary value pair holding the message value.
127  fr_pair_t *type; //!< Temporary value pair holding the message type.
128  fr_pair_t *lvl; //!< Temporary value pair holding the log lvl.
130 
131 
132 static const conf_parser_t file_config[] = {
134  { FR_CONF_OFFSET("permissions", rlm_logtee_t, file.permissions), .dflt = "0600" },
135  { FR_CONF_OFFSET("group", rlm_logtee_t, file.group_str) },
136  { FR_CONF_OFFSET("escape_filenames", rlm_logtee_t, file.escape), .dflt = "no" },
138 };
139 
140 static const conf_parser_t unix_config[] = {
141  { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_logtee_t, unix_sock.path) },
143 };
144 
145 static const conf_parser_t udp_config[] = {
146  { FR_CONF_OFFSET_TYPE_FLAGS("server", FR_TYPE_COMBO_IP_ADDR, 0, logtee_net_t, dst_ipaddr) },
147  { FR_CONF_OFFSET("port", logtee_net_t, port) },
149 };
150 
151 static const conf_parser_t tcp_config[] = {
152  { FR_CONF_OFFSET_TYPE_FLAGS("server", FR_TYPE_COMBO_IP_ADDR, 0, logtee_net_t, dst_ipaddr) },
153  { FR_CONF_OFFSET("port", logtee_net_t, port) },
154 
156 };
157 
158 static const conf_parser_t module_config[] = {
159  { FR_CONF_OFFSET_FLAGS("destination", CONF_FLAG_REQUIRED, rlm_logtee_t, log_dst_str) },
160  { FR_CONF_OFFSET_TYPE_FLAGS("buffer_depth", FR_TYPE_SIZE, 0, rlm_logtee_t, buffer_depth), .dflt = "10000" },
161 
162  { FR_CONF_OFFSET("delimiter", rlm_logtee_t, delimiter), .dflt = "\n" },
163  { FR_CONF_OFFSET("format", rlm_logtee_t, log_fmt), .dflt = "%n - %s", .quote = T_DOUBLE_QUOTED_STRING },
164 
165  /*
166  * Log destinations
167  */
168  { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) file_config },
169  { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) unix_config },
172 
173  { FR_CONF_OFFSET("connection_timeout", rlm_logtee_t, connection_timeout), .dflt = "1.0" },
174  { FR_CONF_OFFSET("reconnection_delay", rlm_logtee_t, reconnection_delay), .dflt = "1.0" },
175 
177 };
178 
180 
183  { .out = &dict_freeradius, .proto = "freeradius" },
184  { NULL }
185 };
186 
190 
193  { .out = &attr_log_level, .name = "Log-Level", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
194  { .out = &attr_log_message, .name = "Log-Message", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
195  { .out = &attr_log_type, .name = "Log-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
196  { NULL }
197 };
198 
199 static void logtee_fd_idle(rlm_logtee_thread_t *t);
200 
201 static void logtee_fd_active(rlm_logtee_thread_t *t);
202 
203 static void logtee_it(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request,
204  char const *file, int line,
205  char const *fmt, va_list ap, void *uctx)
206  CC_HINT(format (printf, 6, 0)) CC_HINT(nonnull (3, 6));
207 
208 static unlang_action_t mod_insert_logtee(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request) CC_HINT(nonnull);
209 
210 /** Connection errored
211  *
212  */
213 static void _logtee_conn_error(UNUSED fr_event_list_t *el, int sock, UNUSED int flags, int fd_errno, void *uctx)
214 {
215  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
216 
217  ERROR("Connection failed (%i): %s", sock, fr_syserror(fd_errno));
218 
219  /*
220  * Something bad happened... Fix it...
221  */
223 }
224 
225 /** Drain any data we received
226  *
227  * We don't care about this data, we just don't want the kernel to
228  * signal the other side that our read buffer's full.
229  */
230 static void _logtee_conn_read(UNUSED fr_event_list_t *el, int sock, UNUSED int flags, void *uctx)
231 {
232  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
233  ssize_t slen;
234  uint8_t buffer[1024];
235 
236  slen = read(sock, buffer, sizeof(buffer));
237  if (slen < 0) {
238  switch (errno) {
239  case EAGAIN: /* We drained all the data */
240  case EINTR:
241  return;
242 
243  case ECONNRESET: /* Connection was reset */
244  case ETIMEDOUT:
245  case EIO:
246  case ENXIO:
248  return;
249 
250  /*
251  * Shouldn't be any other errors
252  * If there are, investigate why we get them...
253  */
254  default:
255  fr_assert(0);
256  }
257  }
258 }
259 
260 /** There's space available to write data, so do that...
261  *
262  */
263 static void _logtee_conn_writable(UNUSED fr_event_list_t *el, int sock, UNUSED int flags, void *uctx)
264 {
265  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
266  char *msg;
267 
268  /*
269  * Fixme in general...
270  */
271  while ((msg = fr_fring_next(t->fring))) {
272  ssize_t slen;
273 
274  slen = write(sock, msg, talloc_array_length(msg) - 1) ;
275  write_error:
276  if (slen < 0) {
277  switch (errno) {
278  case EAGAIN:
279 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
280  case EWOULDBLOCK:
281 #endif
282  case EINTR:
283  case ENOBUFS:
284  return;
285 
286  case ECONNRESET:
287  case EDESTADDRREQ:
288  case EIO:
289  case ENXIO:
290  case EPIPE:
291  case ENETDOWN:
293  return;
294 
295  /*
296  * Shouldn't be any other errors
297  * If there are, investigate why we get them...
298  */
299  default:
300  fr_assert(0);
301  }
302  }
303 
304  slen = write(sock, t->inst->delimiter, t->inst->delimiter_len);
305  if (slen < 0) goto write_error;
306  }
307 
308  logtee_fd_idle(t);
309 }
310 
311 /** Set the socket to idle
312  *
313  * If the other side is sending back garbage, we want to drain it so our buffer doesn't fill up.
314  *
315  * @param[in] t Thread instance containing the connection.
316  */
318 {
319  int fd = *((int *)t->conn->h);
320 
321  DEBUG3("Marking socket (%i) as idle", fd);
322  if (fr_event_fd_insert(t->conn, NULL, t->el, fd,
324  NULL,
326  t) < 0) {
327  PERROR("Failed inserting FD event");
328  }
329 }
330 
331 /** Set the socket to active
332  *
333  * We have messages we want to send, so need to know when the socket is writable.
334  *
335  * @param[in] t Thread instance containing the connection.
336  */
338 {
339  int fd = *((int *)t->conn->h);
340 
341  DEBUG3("Marking socket (%i) as active - Draining requests", fd);
342  if (fr_event_fd_insert(t->conn, NULL, t->el, fd,
346  t) < 0) {
347  PERROR("Failed inserting FD event");
348  }
349 }
350 
351 /** Shutdown/close a file descriptor
352  *
353  */
354 static void _logtee_conn_close(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
355 {
356  int fd = *((int *)h);
357 
358  DEBUG3("Closing socket (%i)", fd);
359  if (shutdown(fd, SHUT_RDWR) < 0) DEBUG3("Shutdown on socket (%i) failed: %s", fd, fr_syserror(errno));
360  if (close(fd) < 0) DEBUG3("Closing socket (%i) failed: %s", fd, fr_syserror(errno));
361 }
362 
363 /** Process notification that fd is open
364  *
365  */
367 {
368  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
369 
370  DEBUG2("Socket connected");
371 
372  /*
373  * If we have data pending, add the writable event immediately
374  */
375  if (t->pending) {
376  logtee_fd_active(t);
377  } else {
378  logtee_fd_idle(t);
379  }
380 
382 }
383 
384 /** Initialise a new outbound connection
385  *
386  * @param[out] h_out Where to write the new file descriptor.
387  * @param[in] conn being initialised.
388  * @param[in] uctx A #rlm_logtee_thread_t.
389  */
390 CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function*/
391 static connection_state_t _logtee_conn_init(void **h_out, connection_t *conn, void *uctx)
392 {
393  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
394  rlm_logtee_t const *inst = t->inst;
395  int fd = -1;
396  int *fd_s;
397 
398  switch (inst->log_dst) {
399  case LOGTEE_DST_UNIX:
400  DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path);
401  fd = fr_socket_client_unix(inst->unix_sock.path, true);
402  if (fd < 0) return CONNECTION_STATE_FAILED;
403  break;
404 
405  case LOGTEE_DST_TCP:
406  DEBUG2("Opening TCP connection to %pV:%u",
407  fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port);
408  fd = fr_socket_client_tcp(NULL, NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true);
409  if (fd < 0) return CONNECTION_STATE_FAILED;
410  break;
411 
412  case LOGTEE_DST_UDP:
413  DEBUG2("Opening UDP connection to %pV:%u",
414  fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port);
415  fd = fr_socket_client_udp(NULL, NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true);
416  if (fd < 0) return CONNECTION_STATE_FAILED;
417  break;
418 
419  /*
420  * Are not connection oriented destinations
421  */
422  case LOGTEE_DST_INVALID:
423  case LOGTEE_DST_FILE:
424  fr_assert(0);
426  }
427 
428  /*
429  * Avoid pointer/integer assignments
430  */
431  MEM(fd_s = talloc(conn, int));
432  *fd_s = fd;
433  *h_out = fd_s;
434 
435  connection_signal_on_fd(conn, fd);
436 
438 }
439 
440 /** Logging callback to write log messages to a destination
441  *
442  * This allows the logging destination to be customised on a per request basis.
443  *
444  * @note Function does not write log output immediately
445  *
446  * @param[in] type What type of message this is (error, warn, info, debug).
447  * @param[in] lvl At what logging level this message should be output.
448  * @param[in] request The current request.
449  * @param[in] file src file the log message was generated in.
450  * @param[in] line number the log message was generated on.
451  * @param[in] fmt sprintf style fmt string.
452  * @param[in] ap Arguments for the fmt string.
453  * @param[in] uctx Context data for the log function.
454  */
455 static void logtee_it(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request,
456  UNUSED char const *file, UNUSED int line,
457  char const *fmt, va_list ap, void *uctx)
458 {
459  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
460  rlm_logtee_t const *inst = t->inst;
461  char *msg, *exp;
462  fr_dcursor_t cursor;
463  fr_pair_t *vp;
464  log_dst_t *dst;
465 
466  fr_assert(t->msg->vp_length == 0); /* Should have been cleared before returning */
467 
468  /*
469  * None of this should involve mallocs unless msg > 1k
470  */
471  msg = talloc_typed_vasprintf(t->msg, fmt, ap);
473 
474  t->type->vp_uint32 = (uint32_t) type;
475  t->lvl->vp_uint32 = (uint32_t) lvl;
476 
477  fr_pair_dcursor_init(&cursor, &request->request_pairs);
478  fr_dcursor_prepend(&cursor, t->msg);
479  fr_dcursor_prepend(&cursor, t->type);
480  fr_dcursor_prepend(&cursor, t->lvl);
481  fr_dcursor_head(&cursor);
482 
483  /*
484  * Now expand our fmt string to encapsulate the
485  * message and any metadata
486  *
487  * Fixme: Would be better to call tmpl_expand
488  * into a variable length ring buffer.
489  */
490  dst = request->log.dst;
491  request->log.dst = NULL;
492  if (tmpl_aexpand(t, &exp, request, inst->log_fmt, NULL, NULL) < 0) goto finish;
493  request->log.dst = dst;
494 
495  fr_fring_overwrite(t->fring, exp); /* Insert it into the buffer */
496 
497  if (!t->pending) {
498  t->pending = true;
499  logtee_fd_active(t); /* Listen for when the fd is writable */
500  }
501 
502 finish:
503  /*
504  * Don't free, we reuse the fr_pair_ts for the next message
505  */
506  vp = fr_dcursor_remove(&cursor);
507  if (!fr_cond_assert(vp == t->lvl)) fr_dcursor_append(&cursor, vp);
508 
509  vp = fr_dcursor_remove(&cursor);
510  if (!fr_cond_assert(vp == t->type)) fr_dcursor_append(&cursor, vp);
511 
512  vp = fr_dcursor_remove(&cursor);
513  if (!fr_cond_assert(vp == t->msg)) fr_dcursor_append(&cursor, vp);
514 
515  fr_value_box_clear(&t->msg->data); /* Clear message data */
516 }
517 
518 /** Add our logging destination to the linked list of logging destinations (if it doesn't already exist)
519  *
520  * @param[in] p_result the result of the module call:
521  * - #RLM_MODULE_NOOP if log destination already exists.
522  * - #RLM_MODULE_OK if we added a new destination.
523  * @param[in] mctx Module calling ctx.
524  * @param[in] request request to add our log destination to.
525  */
526 static unlang_action_t mod_insert_logtee(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
527 {
528  log_dst_t *dst, **last = NULL;
529 
530  for (dst = request->log.dst; dst; dst = dst->next) {
531  if (dst->uctx == mctx->thread) {
533  }
534 
535  last = &(dst->next);
536  }
537 
538  if (!last) RETURN_MODULE_NOOP;
539 
540  dst = talloc_zero(request, log_dst_t);
541  dst->func = logtee_it;
542  dst->uctx = mctx->thread;
543 
544  *last = dst;
545 
547 }
548 
549 /** Create thread-specific connections and buffers
550  *
551  * @param[in] mctx specific data.
552  * @return
553  * - 0 on success.
554  * - -1 on failure.
555  */
557 {
558  rlm_logtee_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_logtee_t);
559  rlm_logtee_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_logtee_thread_t);
560 
561  MEM(t->fring = fr_fring_alloc(t, inst->buffer_depth, false));
562 
563  t->inst = inst;
564  t->el = mctx->el;
565 
566  /*
567  * Pre-allocate temporary attributes
568  */
569  MEM(t->msg_pool = talloc_pool(t, 1024));
573 
574  /*
575  * This opens the outbound connection
576  */
577  t->conn = connection_alloc(t, t->el,
579  .init = _logtee_conn_init,
580  .open = _logtee_conn_open,
581  .close = _logtee_conn_close
582  },
584  .connection_timeout = inst->connection_timeout,
585  .reconnection_delay = inst->reconnection_delay
586  },
587  inst->name, t);
588  if (t->conn == NULL) return -1;
589 
591 
592  return 0;
593 }
594 
595 /*
596  * Instantiate the module.
597  */
598 static int mod_instantiate(module_inst_ctx_t const *mctx)
599 {
600  rlm_logtee_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_logtee_t);
601  CONF_SECTION *conf = mctx->mi->conf;
602  char prefix[100];
603 
604  /*
605  * Escape filenames only if asked.
606  */
607  if (inst->file.escape) {
608  inst->file.escape_func = rad_filename_escape;
609  } else {
610  inst->file.escape_func = rad_filename_make_safe;
611  }
612 
614  if (inst->log_dst == LOGTEE_DST_INVALID) {
615  cf_log_err(conf, "Invalid log destination \"%s\"", inst->log_dst_str);
616  return -1;
617  }
618 
619  snprintf(prefix, sizeof(prefix), "rlm_logtee (%s)", inst->name);
620 
621  FR_SIZE_BOUND_CHECK("buffer_depth", inst->buffer_depth, >=, (size_t)1);
622  FR_SIZE_BOUND_CHECK("buffer_depth", inst->buffer_depth, <=, (size_t)1000000); /* 1 Million messages */
623 
624  /*
625  * Setup the logging destination
626  */
627  switch (inst->log_dst) {
628  case LOGTEE_DST_FILE:
629  cf_log_err(conf, "Teeing to files NYI");
630  return -1;
631 
632  case LOGTEE_DST_UNIX:
633 #ifndef HAVE_SYS_UN_H
634  cf_log_err(conf, "Unix sockets are not supported on this system");
635  return -1;
636 #endif
637 
638  case LOGTEE_DST_UDP:
639  break;
640 
641  case LOGTEE_DST_TCP:
642  break;
643 
644  case LOGTEE_DST_INVALID:
645  fr_assert(0);
646  break;
647  }
648 
649  inst->delimiter_len = talloc_array_length(inst->delimiter) - 1;
650 
651  return 0;
652 }
653 
654 
655 /*
656  * Externally visible module definition.
657  */
658 extern module_rlm_t rlm_logtee;
660  .common = {
661  .magic = MODULE_MAGIC_INIT,
662  .name = "logtee",
663  .inst_size = sizeof(rlm_logtee_t),
664  .thread_inst_size = sizeof(rlm_logtee_thread_t),
665  .config = module_config,
666  .instantiate = mod_instantiate,
667  .thread_instantiate = mod_thread_instantiate,
668  },
669  .method_group = {
670  .bindings = (module_method_binding_t[]){
671  { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_insert_logtee },
673  }
674  }
675 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
static int const char char buffer[256]
Definition: acutest.h:574
int const char * file
Definition: acutest.h:702
log_entry msg
Definition: acutest.h:794
static int const char * fmt
Definition: acutest.h:573
int const char int line
Definition: acutest.h:702
#define RCSID(id)
Definition: build.h:481
#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:627
#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_SIZE_BOUND_CHECK(_name, _var, _op, _bound)
Definition: cf_parse.h:477
#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_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
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition: cf_parse.h:297
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:405
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition: cf_parse.h:413
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:411
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition: cf_parse.h:416
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:399
#define FR_CONF_OFFSET_TYPE_FLAGS(_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:241
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:289
#define CF_IDENT_ANY
Definition: cf_util.h:78
connection_state_t
Definition: connection.h:45
@ CONNECTION_STATE_FAILED
Connection has failed.
Definition: connection.h:54
@ CONNECTION_STATE_CONNECTED
File descriptor is open (ready for writing).
Definition: connection.h:52
@ CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
Definition: connection.h:50
@ CONNECTION_FAILED
Connection is being reconnected because it failed.
Definition: connection.h:84
Holds a complete set of functions for a connection.
Definition: connection.h:186
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
Definition: dcursor.h:480
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:406
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
static int fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
Insert a single item at the start of the list.
Definition: dcursor.h:376
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
Definition: dcursor.h:234
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:267
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:280
Specifies an attribute which must be present for the module to function.
Definition: dict.h:266
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:279
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
#define fr_event_fd_insert(...)
Definition: event.h:232
void * fr_fring_next(fr_fring_t *fring)
Remove an item from the buffer.
Definition: fring.c:177
fr_fring_t * fr_fring_alloc(TALLOC_CTX *ctx, uint32_t size, bool lock)
Initialise a ring buffer with fixed element size.
Definition: fring.c:78
int fr_fring_overwrite(fr_fring_t *fring, void *in)
Insert a new item into the circular buffer, freeing the tail if we hit it.
Definition: fring.c:120
Standard thread safe circular buffer.
Definition: fring.c:36
IPv4/6 prefix.
Definition: merged_model.c:272
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
void * uctx
Context to pass to the logging function.
Definition: log.h:72
log_dst_t * next
Next logging destination.
Definition: log.h:74
log_func_t func
Function to call to log to this destination.
Definition: log.h:71
Definition: log.h:70
ssize_t rad_filename_make_safe(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Ensures that a filename cannot walk up the directory structure.
Definition: util.c:96
ssize_t rad_filename_escape(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes the raw string such that it should be safe to use as part of a file path.
Definition: util.c:216
Stores all information relating to an event list.
Definition: event.c:411
fr_log_lvl_t
Definition: log.h:67
fr_log_type_t
Definition: log.h:54
unsigned short uint16_t
Definition: merged_model.c:31
size_t(* xlat_escape_legacy_t)(request_t *request, char *out, size_t outlen, char const *in, void *arg)
Definition: merged_model.c:213
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
Definition: merged_model.c:115
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
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
void * thread
Thread specific instance data.
Definition: module_ctx.h:43
fr_event_list_t * el
Event list to register any IO handlers and timers against.
Definition: module_ctx.h:68
void * thread
Thread instance data.
Definition: module_ctx.h:67
module_instance_t const * mi
Instance of the module being instantiated.
Definition: module_ctx.h:64
module_instance_t * mi
Instance of the module being instantiated.
Definition: module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:63
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:39
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:283
#define DEBUG2(fmt,...)
Definition: radclient.h:43
static rs_t * conf
Definition: radsniff.c:53
#define RETURN_MODULE_NOOP
Definition: rcode.h:62
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
static void logtee_it(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt, va_list ap, void *uctx))
static void logtee_fd_idle(rlm_logtee_thread_t *t)
Set the socket to idle.
Definition: rlm_logtee.c:317
fr_ipaddr_t src_ipaddr
Send requests from a given src_ipaddr.
Definition: rlm_logtee.c:72
static void _logtee_conn_error(UNUSED fr_event_list_t *el, int sock, UNUSED int flags, int fd_errno, void *uctx)
Connection errored.
Definition: rlm_logtee.c:213
logtee_dst_t log_dst
Logging destination.
Definition: rlm_logtee.c:86
static void logtee_fd_active(rlm_logtee_thread_t *t)
Set the socket to active.
Definition: rlm_logtee.c:337
static void _logtee_conn_close(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
Shutdown/close a file descriptor.
Definition: rlm_logtee.c:354
static fr_dict_attr_t const * attr_log_type
Definition: rlm_logtee.c:189
static const conf_parser_t file_config[]
Definition: rlm_logtee.c:132
char const * name
Module instance name.
Definition: rlm_logtee.c:79
char const * log_dst_str
Logging destination string.
Definition: rlm_logtee.c:87
static fr_dict_attr_t const * attr_log_message
Definition: rlm_logtee.c:188
static fr_dict_t const * dict_freeradius
Definition: rlm_logtee.c:179
char const * delimiter
Line termination string (usually ).
Definition: rlm_logtee.c:81
static fr_dict_attr_t const * attr_log_level
Definition: rlm_logtee.c:187
size_t buffer_depth
How big our circular buffer should be.
Definition: rlm_logtee.c:89
fr_pair_t * msg
Temporary value pair holding the message value.
Definition: rlm_logtee.c:126
fr_dict_attr_autoload_t rlm_logtee_dict_attr[]
Definition: rlm_logtee.c:192
static void _logtee_conn_writable(UNUSED fr_event_list_t *el, int sock, UNUSED int flags, void *uctx)
There's space available to write data, so do that...
Definition: rlm_logtee.c:263
static const conf_parser_t udp_config[]
Definition: rlm_logtee.c:145
tmpl_t * log_fmt
Source of log messages.
Definition: rlm_logtee.c:84
fr_fring_t * fring
Circular buffer used to batch up messages.
Definition: rlm_logtee.c:120
fr_time_delta_t connection_timeout
How long to wait to open a socket.
Definition: rlm_logtee.c:107
static fr_table_num_sorted_t const logtee_dst_table[]
Definition: rlm_logtee.c:62
fr_dict_autoload_t rlm_logtee_dict[]
Definition: rlm_logtee.c:182
fr_pair_t * type
Temporary value pair holding the message type.
Definition: rlm_logtee.c:127
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Create thread-specific connections and buffers.
Definition: rlm_logtee.c:556
bool pending
We have pending messages to write.
Definition: rlm_logtee.c:122
static size_t logtee_dst_table_len
Definition: rlm_logtee.c:68
fr_pair_t * lvl
Temporary value pair holding the log lvl.
Definition: rlm_logtee.c:128
logtee_dst_t
Definition: rlm_logtee.c:54
@ LOGTEE_DST_FILE
Log to a file.
Definition: rlm_logtee.c:56
@ LOGTEE_DST_INVALID
Definition: rlm_logtee.c:55
@ LOGTEE_DST_TCP
Log via TCP.
Definition: rlm_logtee.c:59
@ LOGTEE_DST_UNIX
Log via Unix socket.
Definition: rlm_logtee.c:57
@ LOGTEE_DST_UDP
Log via UDP.
Definition: rlm_logtee.c:58
logtee_net_t tcp
TCP server.
Definition: rlm_logtee.c:104
static connection_state_t _logtee_conn_open(UNUSED fr_event_list_t *el, UNUSED void *h, void *uctx)
Process notification that fd is open.
Definition: rlm_logtee.c:366
static unlang_action_t mod_insert_logtee(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Add our logging destination to the linked list of logging destinations (if it doesn't already exist)
Definition: rlm_logtee.c:526
fr_event_list_t * el
This thread's event list.
Definition: rlm_logtee.c:117
CC_NO_UBSAN(function)
Initialise a new outbound connection.
Definition: rlm_logtee.c:390
fr_ipaddr_t dst_ipaddr
Network server.
Definition: rlm_logtee.c:71
connection_t * conn
Connection to our log destination.
Definition: rlm_logtee.c:118
static const conf_parser_t module_config[]
Definition: rlm_logtee.c:158
module_rlm_t rlm_logtee
Definition: rlm_logtee.c:659
static const conf_parser_t unix_config[]
Definition: rlm_logtee.c:140
logtee_net_t udp
UDP server.
Definition: rlm_logtee.c:105
size_t delimiter_len
Length of line termination string.
Definition: rlm_logtee.c:82
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_logtee.c:598
fr_time_delta_t reconnection_delay
How long to wait to retry.
Definition: rlm_logtee.c:108
uint16_t port
Network port.
Definition: rlm_logtee.c:73
TALLOC_CTX * msg_pool
A 1k talloc pool to hold the log message whilst it's being expanded.
Definition: rlm_logtee.c:124
rlm_logtee_t const * inst
Instance of logtee.
Definition: rlm_logtee.c:116
static void _logtee_conn_read(UNUSED fr_event_list_t *el, int sock, UNUSED int flags, void *uctx)
Drain any data we received.
Definition: rlm_logtee.c:230
static const conf_parser_t tcp_config[]
Definition: rlm_logtee.c:151
logtee module instance
Definition: rlm_logtee.c:78
Per-thread instance data.
Definition: rlm_logtee.c:115
static char const * name
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition: section.h:40
void connection_signal_reconnect(connection_t *conn, connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
Definition: connection.c:1167
int connection_signal_on_fd(connection_t *conn, int fd)
Setup the connection to change states to connected or failed based on I/O events.
Definition: connection.c:1405
void connection_signal_init(connection_t *conn)
Asynchronously signal a halted connection to start.
Definition: connection.c:1107
connection_t * connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, connection_funcs_t const *funcs, connection_conf_t const *conf, char const *log_prefix, void const *uctx)
Allocate a new connection.
Definition: connection.c:1512
CONF_SECTION * conf
Module's instance configuration.
Definition: module.h:329
void * data
Module's instance data.
Definition: module.h:271
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition: module.h:151
Named methods exported by a module.
Definition: module.h:173
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
Definition: tmpl.h:1070
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
Definition: socket.c:634
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
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
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:653
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:49
char * talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition: talloc.c:519
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
close(uq->fd)
static fr_event_list_t * el
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:591
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3723
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
Definition: value.c:4253
#define fr_box_ipaddr(_val)
Definition: value.h:294
int nonnull(2, 5))
int format(printf, 5, 0))