The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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 */
26RCSID("$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
54typedef 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.
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
70typedef 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.
75
76/** logtee module instance
77 */
78typedef 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.
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.
110
111/** Per-thread instance data
112 *
113 * Contains buffers and connection handles specific to the thread.
114 */
115typedef 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
132static 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
140static const conf_parser_t unix_config[] = {
141 { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_logtee_t, unix_sock.path) },
143};
144
145static 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
151static 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
158static 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
199static void logtee_fd_idle(rlm_logtee_thread_t *t);
200
202
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
208static 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 */
213static 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 */
230static 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 */
263static 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
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 */
354static 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) {
377 } else {
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 */
390CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function*/
391static 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 */
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 */
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 */
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
502finish:
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 */
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 */
598static 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
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 */
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:576
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:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define CC_NO_UBSAN(_sanitize)
Definition build.h:426
#define UNUSED
Definition build.h:315
#define NUM_ELEMENTS(_t)
Definition build.h:337
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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:492
fr_token_t quote
Quoting around the default value. Only used for templates.
Definition cf_parse.h:634
#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:323
#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:418
@ CONF_FLAG_FILE_OUTPUT
File matching value must exist, and must be writable.
Definition cf_parse.h:426
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition cf_parse.h:424
@ CONF_FLAG_XLAT
string will be dynamically expanded.
Definition cf_parse.h:429
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
#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:579
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 int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
Definition dcursor.h:480
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
Definition dcursor.h:234
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
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
#define MEM(x)
Definition debug.h:36
#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:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
#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
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
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
Standard thread safe circular buffer.
Definition fring.c:36
IPv4/6 prefix.
#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
size_t(* xlat_escape_legacy_t)(request_t *request, char *out, size_t outlen, char const *in, void *arg)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
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 fr_assert(_expr)
Definition rad_assert.h:38
#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
static connection_state_t _logtee_conn_init(void **h_out, connection_t *conn, void *uctx)
Initialise a new outbound connection.
Definition rlm_logtee.c:391
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
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.
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.
void connection_signal_init(connection_t *conn)
Asynchronously signal a halted connection to start.
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.
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
size_t inst_size
Size of the module's instance data.
Definition module.h:203
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
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))