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: 1c373916d2d1fc60836177b635694370b12e7f44 $
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: 1c373916d2d1fc60836177b635694370b12e7f44 $")
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  fr_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 static fr_connection_state_t _logtee_conn_init(void **h_out, fr_connection_t *conn, void *uctx)
391 {
392  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
393  rlm_logtee_t const *inst = t->inst;
394  int fd = -1;
395  int *fd_s;
396 
397  switch (inst->log_dst) {
398  case LOGTEE_DST_UNIX:
399  DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path);
400  fd = fr_socket_client_unix(inst->unix_sock.path, true);
401  if (fd < 0) return FR_CONNECTION_STATE_FAILED;
402  break;
403 
404  case LOGTEE_DST_TCP:
405  DEBUG2("Opening TCP connection to %pV:%u",
406  fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port);
407  fd = fr_socket_client_tcp(NULL, NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true);
408  if (fd < 0) return FR_CONNECTION_STATE_FAILED;
409  break;
410 
411  case LOGTEE_DST_UDP:
412  DEBUG2("Opening UDP connection to %pV:%u",
413  fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port);
414  fd = fr_socket_client_udp(NULL, NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true);
415  if (fd < 0) return FR_CONNECTION_STATE_FAILED;
416  break;
417 
418  /*
419  * Are not connection oriented destinations
420  */
421  case LOGTEE_DST_INVALID:
422  case LOGTEE_DST_FILE:
423  fr_assert(0);
425  }
426 
427  /*
428  * Avoid pointer/integer assignments
429  */
430  MEM(fd_s = talloc(conn, int));
431  *fd_s = fd;
432  *h_out = fd_s;
433 
434  fr_connection_signal_on_fd(conn, fd);
435 
437 }
438 
439 /** Logging callback to write log messages to a destination
440  *
441  * This allows the logging destination to be customised on a per request basis.
442  *
443  * @note Function does not write log output immediately
444  *
445  * @param[in] type What type of message this is (error, warn, info, debug).
446  * @param[in] lvl At what logging level this message should be output.
447  * @param[in] request The current request.
448  * @param[in] file src file the log message was generated in.
449  * @param[in] line number the log message was generated on.
450  * @param[in] fmt sprintf style fmt string.
451  * @param[in] ap Arguments for the fmt string.
452  * @param[in] uctx Context data for the log function.
453  */
454 static void logtee_it(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request,
455  UNUSED char const *file, UNUSED int line,
456  char const *fmt, va_list ap, void *uctx)
457 {
458  rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
459  rlm_logtee_t const *inst = t->inst;
460  char *msg, *exp;
461  fr_dcursor_t cursor;
462  fr_pair_t *vp;
463  log_dst_t *dst;
464 
465  fr_assert(t->msg->vp_length == 0); /* Should have been cleared before returning */
466 
467  /*
468  * None of this should involve mallocs unless msg > 1k
469  */
470  msg = talloc_typed_vasprintf(t->msg, fmt, ap);
472 
473  t->type->vp_uint32 = (uint32_t) type;
474  t->lvl->vp_uint32 = (uint32_t) lvl;
475 
476  fr_pair_dcursor_init(&cursor, &request->request_pairs);
477  fr_dcursor_prepend(&cursor, t->msg);
478  fr_dcursor_prepend(&cursor, t->type);
479  fr_dcursor_prepend(&cursor, t->lvl);
480  fr_dcursor_head(&cursor);
481 
482  /*
483  * Now expand our fmt string to encapsulate the
484  * message and any metadata
485  *
486  * Fixme: Would be better to call tmpl_expand
487  * into a variable length ring buffer.
488  */
489  dst = request->log.dst;
490  request->log.dst = NULL;
491  if (tmpl_aexpand(t, &exp, request, inst->log_fmt, NULL, NULL) < 0) goto finish;
492  request->log.dst = dst;
493 
494  fr_fring_overwrite(t->fring, exp); /* Insert it into the buffer */
495 
496  if (!t->pending) {
497  t->pending = true;
498  logtee_fd_active(t); /* Listen for when the fd is writable */
499  }
500 
501 finish:
502  /*
503  * Don't free, we reuse the fr_pair_ts for the next message
504  */
505  vp = fr_dcursor_remove(&cursor);
506  if (!fr_cond_assert(vp == t->lvl)) fr_dcursor_append(&cursor, vp);
507 
508  vp = fr_dcursor_remove(&cursor);
509  if (!fr_cond_assert(vp == t->type)) fr_dcursor_append(&cursor, vp);
510 
511  vp = fr_dcursor_remove(&cursor);
512  if (!fr_cond_assert(vp == t->msg)) fr_dcursor_append(&cursor, vp);
513 
514  fr_value_box_clear(&t->msg->data); /* Clear message data */
515 }
516 
517 /** Add our logging destination to the linked list of logging destinations (if it doesn't already exist)
518  *
519  * @param[in] p_result the result of the module call:
520  * - #RLM_MODULE_NOOP if log destination already exists.
521  * - #RLM_MODULE_OK if we added a new destination.
522  * @param[in] mctx Module calling ctx.
523  * @param[in] request request to add our log destination to.
524  */
525 static unlang_action_t mod_insert_logtee(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
526 {
527  log_dst_t *dst, **last = NULL;
528 
529  for (dst = request->log.dst; dst; dst = dst->next) {
530  if (dst->uctx == mctx->thread) {
532  }
533 
534  last = &(dst->next);
535  }
536 
537  if (!last) RETURN_MODULE_NOOP;
538 
539  dst = talloc_zero(request, log_dst_t);
540  dst->func = logtee_it;
541  dst->uctx = mctx->thread;
542 
543  *last = dst;
544 
546 }
547 
548 /** Create thread-specific connections and buffers
549  *
550  * @param[in] mctx specific data.
551  * @return
552  * - 0 on success.
553  * - -1 on failure.
554  */
556 {
557  rlm_logtee_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_logtee_t);
558  rlm_logtee_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_logtee_thread_t);
559 
560  MEM(t->fring = fr_fring_alloc(t, inst->buffer_depth, false));
561 
562  t->inst = inst;
563  t->el = mctx->el;
564 
565  /*
566  * Pre-allocate temporary attributes
567  */
568  MEM(t->msg_pool = talloc_pool(t, 1024));
572 
573  /*
574  * This opens the outbound connection
575  */
576  t->conn = fr_connection_alloc(t, t->el,
578  .init = _logtee_conn_init,
579  .open = _logtee_conn_open,
580  .close = _logtee_conn_close
581  },
583  .connection_timeout = inst->connection_timeout,
584  .reconnection_delay = inst->reconnection_delay
585  },
586  inst->name, t);
587  if (t->conn == NULL) return -1;
588 
590 
591  return 0;
592 }
593 
594 /*
595  * Instantiate the module.
596  */
597 static int mod_instantiate(module_inst_ctx_t const *mctx)
598 {
599  rlm_logtee_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_logtee_t);
600  CONF_SECTION *conf = mctx->inst->conf;
601  char prefix[100];
602 
603  /*
604  * Escape filenames only if asked.
605  */
606  if (inst->file.escape) {
607  inst->file.escape_func = rad_filename_escape;
608  } else {
609  inst->file.escape_func = rad_filename_make_safe;
610  }
611 
613  if (inst->log_dst == LOGTEE_DST_INVALID) {
614  cf_log_err(conf, "Invalid log destination \"%s\"", inst->log_dst_str);
615  return -1;
616  }
617 
618  snprintf(prefix, sizeof(prefix), "rlm_logtee (%s)", inst->name);
619 
620  FR_SIZE_BOUND_CHECK("buffer_depth", inst->buffer_depth, >=, (size_t)1);
621  FR_SIZE_BOUND_CHECK("buffer_depth", inst->buffer_depth, <=, (size_t)1000000); /* 1 Million messages */
622 
623  /*
624  * Setup the logging destination
625  */
626  switch (inst->log_dst) {
627  case LOGTEE_DST_FILE:
628  cf_log_err(conf, "Teeing to files NYI");
629  return -1;
630 
631  case LOGTEE_DST_UNIX:
632 #ifndef HAVE_SYS_UN_H
633  cf_log_err(conf, "Unix sockets are not supported on this system");
634  return -1;
635 #endif
636 
637  case LOGTEE_DST_UDP:
638  break;
639 
640  case LOGTEE_DST_TCP:
641  break;
642 
643  case LOGTEE_DST_INVALID:
644  fr_assert(0);
645  break;
646  }
647 
648  inst->delimiter_len = talloc_array_length(inst->delimiter) - 1;
649 
650  return 0;
651 }
652 
653 
654 /*
655  * Externally visible module definition.
656  */
657 extern module_rlm_t rlm_logtee;
659  .common = {
660  .magic = MODULE_MAGIC_INIT,
661  .name = "logtee",
662  .inst_size = sizeof(rlm_logtee_t),
663  .thread_inst_size = sizeof(rlm_logtee_thread_t),
664  .config = module_config,
665  .instantiate = mod_instantiate,
666  .thread_instantiate = mod_thread_instantiate,
667  },
668  .method_names = (module_method_name_t[]){
669  { .name1 = CF_IDENT_ANY, .name2 = CF_IDENT_ANY, .method = mod_insert_logtee },
671  }
672 };
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:444
#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_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:476
#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:406
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition: cf_parse.h:414
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:412
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition: cf_parse.h:417
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:400
#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:563
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define CF_IDENT_ANY
Definition: cf_util.h:78
fr_connection_state_t
Definition: connection.h:45
@ FR_CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
Definition: connection.h:50
@ FR_CONNECTION_STATE_FAILED
Connection has failed.
Definition: connection.h:54
@ FR_CONNECTION_STATE_CONNECTED
File descriptor is open (ready for writing).
Definition: connection.h:52
@ FR_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:479
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:405
static int fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
Insert a single item at the start of the list.
Definition: dcursor.h:375
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
Definition: dcursor.h:233
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
#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:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
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
#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
size_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:94
size_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:214
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:63
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
void * thread
Thread instance data.
Definition: module_ctx.h:62
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:59
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:51
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:58
Specifies a module method identifier.
Definition: module_method.c:36
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
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:278
#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:555
static fr_connection_state_t _logtee_conn_init(void **h_out, fr_connection_t *conn, void *uctx)
Initialise a new outbound connection.
Definition: rlm_logtee.c:390
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
static fr_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
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 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:525
fr_event_list_t * el
This thread's event list.
Definition: rlm_logtee.c:117
fr_ipaddr_t dst_ipaddr
Network server.
Definition: rlm_logtee.c:71
static const conf_parser_t module_config[]
Definition: rlm_logtee.c:158
module_rlm_t rlm_logtee
Definition: rlm_logtee.c:658
fr_connection_t * conn
Connection to our log destination.
Definition: rlm_logtee.c:118
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:597
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
void fr_connection_signal_init(fr_connection_t *conn)
Asynchronously signal a halted connection to start.
Definition: connection.c:1106
int fr_connection_signal_on_fd(fr_connection_t *conn, int fd)
Setup the connection to change states to connected or failed based on I/O events.
Definition: connection.c:1400
fr_connection_t * fr_connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, fr_connection_funcs_t const *funcs, fr_connection_conf_t const *conf, char const *log_prefix, void const *uctx)
Allocate a new connection.
Definition: connection.c:1507
void fr_connection_signal_reconnect(fr_connection_t *conn, fr_connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
Definition: connection.c:1166
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
#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:1054
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:134
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:45
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:407
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:590
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3672
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:4202
#define fr_box_ipaddr(_val)
Definition: value.h:287
int nonnull(2, 5))
int format(printf, 5, 0))