The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_linelog.c
Go to the documentation of this file.
1/*
2 * rlm_linelog.c
3 *
4 * Version: $Id: 87d3742995e3e1d649773e8e690b358547fd547b $
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * @copyright 2004,2006 The FreeRADIUS server project
21 * @copyright 2004 Alan DeKok (aland@freeradius.org)
22 */
23RCSID("$Id: 87d3742995e3e1d649773e8e690b358547fd547b $")
24
25#include <freeradius-devel/server/base.h>
26#include <freeradius-devel/server/module_rlm.h>
27#include <freeradius-devel/server/tmpl_dcursor.h>
28#include <freeradius-devel/unlang/tmpl.h>
29
30#include <freeradius-devel/util/iovec.h>
31#include <freeradius-devel/util/perm.h>
32#include <freeradius-devel/util/print.h>
33
34#include <freeradius-devel/unlang/xlat_func.h>
35
36#ifdef HAVE_FCNTL_H
37# include <fcntl.h>
38#endif
39
40#ifdef HAVE_UNISTD_H
41#endif
42
43#ifdef HAVE_GRP_H
44#endif
45
46#ifdef HAVE_SYSLOG_H
47# include <syslog.h>
48# ifndef LOG_INFO
49# define LOG_INFO (0)
50# endif
51#endif
52
53
54#include "file.h"
55
56static int linelog_escape_func(fr_value_box_t *vb, UNUSED void *uctx);
57static int call_env_filename_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
58 call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule);
59
61 { L("file"), LINELOG_DST_FILE },
62 { L("files"), LINELOG_DST_FILE },
63 { L("request"), LINELOG_DST_REQUEST },
64 { L("stderr"), LINELOG_DST_STDERR },
65 { L("stdout"), LINELOG_DST_STDOUT },
66 { L("syslog"), LINELOG_DST_SYSLOG },
67 { L("tcp"), LINELOG_DST_TCP },
68 { L("udp"), LINELOG_DST_UDP },
69 { L("unix"), LINELOG_DST_UNIX }
70};
72
73typedef struct {
74 int sockfd; //!< File descriptor associated with socket
76
77
78static const conf_parser_t file_config[] = {
79 { FR_CONF_OFFSET("permissions", rlm_linelog_t, file.permissions), .dflt = "0600", .func = cf_parse_permissions },
80 { FR_CONF_OFFSET("group", rlm_linelog_t, file.group_str) },
81 { FR_CONF_OFFSET("escape_filenames", rlm_linelog_t, file.escape), .dflt = "no" },
82 { FR_CONF_OFFSET("fsync", rlm_linelog_t, file.fsync), .dflt = "no" },
83 { FR_CONF_OFFSET("max_idle", rlm_linelog_t, file.max_idle), .dflt = "30s" },
84 { FR_CONF_OFFSET("buffer_count", rlm_linelog_t, file.buffer_count), .dflt = "0" },
85 { FR_CONF_OFFSET_IS_SET("buffer_delay", FR_TYPE_TIME_DELTA, 0, rlm_linelog_t, file.buffer_delay), .dflt = "1s" },
86 { FR_CONF_OFFSET_IS_SET("buffer_expiry", FR_TYPE_TIME_DELTA, CONF_FLAG_HIDDEN, rlm_linelog_t, file.buffer_expiry), .dflt = "30s" },
87
89};
90
91static const conf_parser_t syslog_config[] = {
92 { FR_CONF_OFFSET("facility", rlm_linelog_t, syslog.facility) },
93 { FR_CONF_OFFSET("severity", rlm_linelog_t, syslog.severity), .dflt = "info" },
95};
96
97static const conf_parser_t unix_config[] = {
98 { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_SOCKET, rlm_linelog_t, unix_sock.path) },
100};
101
102static const conf_parser_t udp_config[] = {
104 { FR_CONF_OFFSET("port", linelog_net_t, port) },
105 { FR_CONF_OFFSET("timeout", linelog_net_t, timeout), .dflt = "1s" },
107};
108
109static const conf_parser_t tcp_config[] = {
111 { FR_CONF_OFFSET("port", linelog_net_t, port) },
112 { FR_CONF_OFFSET("timeout", linelog_net_t, timeout), .dflt = "1s" },
114};
115
116static const conf_parser_t module_config[] = {
117 { FR_CONF_OFFSET_FLAGS("destination", CONF_FLAG_REQUIRED, rlm_linelog_t, log_dst_str) },
118
119 { FR_CONF_OFFSET("delimiter", rlm_linelog_t, delimiter), .dflt = "\n" },
120
121 { FR_CONF_OFFSET("triggers", rlm_linelog_t, triggers) },
122
123 /*
124 * Log destinations
125 */
126 { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) file_config },
127 { FR_CONF_POINTER("syslog", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) syslog_config },
128 { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) unix_config },
131
132 /*
133 * Deprecated config items
134 */
135 { FR_CONF_DEPRECATED("permissions", rlm_linelog_t, file.permissions) },
136 { FR_CONF_DEPRECATED("group", rlm_linelog_t, file.group_str) },
137
138 { FR_CONF_DEPRECATED("syslog_facility", rlm_linelog_t, syslog.facility) },
139 { FR_CONF_DEPRECATED("syslog_severity", rlm_linelog_t, syslog.severity) },
141};
142
143#define LINELOG_BOX_ESCAPE { \
144 .func = linelog_escape_func, \
145 .safe_for = (fr_value_box_safe_for_t) linelog_escape_func, \
146 .always_escape = false, \
147 }
148
164
178
180{
181 if (shutdown(conn->sockfd, SHUT_RDWR) < 0) DEBUG3("Shutdown failed: %s", fr_syserror(errno));
182 if (close(conn->sockfd) < 0) DEBUG3("Closing socket failed: %s", fr_syserror(errno));
183
184 return 0;
185}
186
187static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
188{
189 rlm_linelog_t const *inst = talloc_get_type_abort(instance, rlm_linelog_t);
190 linelog_conn_t *conn;
191 int sockfd = -1;
192
193 switch (inst->log_dst) {
194 case LINELOG_DST_UNIX:
195 DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path);
196 sockfd = fr_socket_client_unix(inst->unix_sock.path, true);
197 if (sockfd < 0) {
198 PERROR("Failed opening UNIX socket");
199 return NULL;
200 }
201 break;
202
203 case LINELOG_DST_TCP:
204 DEBUG2("Opening TCP connection to %pV:%u", fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port);
205
206 sockfd = fr_socket_client_tcp(NULL, NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true);
207 if (sockfd < 0) {
208 PERROR("Failed opening TCP socket");
209 return NULL;
210 }
211 break;
212
213 case LINELOG_DST_UDP:
214 DEBUG2("Opening UDP connection to %pV:%u", fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port);
215
216 sockfd = fr_socket_client_udp(NULL, NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true);
217 if (sockfd < 0) {
218 PERROR("Failed opening UDP socket");
219 return NULL;
220 }
221 break;
222
223 /*
224 * Are not connection oriented destinations
225 */
227 case LINELOG_DST_FILE:
232 fr_assert(0);
233 return NULL;
234 }
235
236 if (errno == EINPROGRESS) {
237 if (fr_time_delta_ispos(timeout)) {
238 DEBUG2("Waiting for connection to complete...");
239 } else {
240 DEBUG2("Blocking until connection complete...");
241 }
242 if (fr_socket_wait_for_connect(sockfd, timeout) < 0) {
243 PERROR("Failed connecting to log destination");
244 close(sockfd);
245 return NULL;
246 }
247 }
248 DEBUG2("Connection successful");
249
250 /*
251 * Set blocking operation as we have no timeout set
252 */
253 if (!fr_time_delta_ispos(timeout) && (fr_blocking(sockfd) < 0)) {
254 ERROR("Failed setting nonblock flag on fd");
255 close(sockfd);
256 return NULL;
257 }
258
259 conn = talloc_zero(ctx, linelog_conn_t);
260 conn->sockfd = sockfd;
261 talloc_set_destructor(conn, _mod_conn_free);
262
263 return conn;
264}
265
266/** Escape unprintable characters
267 *
268 * - Newline is escaped as ``\\n``.
269 * - Return is escaped as ``\\r``.
270 * - All other unprintables are escaped as @verbatim <oct><oct><oct> @endverbatim.
271 *
272 * @param vb Value box to escape.
273 * @param uctx unused.
274 */
275/*
276 * Escape unprintable characters.
277 */
278static int linelog_escape_func(fr_value_box_t *vb, UNUSED void *uctx)
279{
280 char *escaped;
281
282 if (vb->vb_length == 0) return 0;
283
284 MEM(escaped = fr_asprint(vb, vb->vb_strvalue, vb->vb_length, 0));
286
287 return 0;
288}
289
290static void linelog_hexdump(request_t *request, struct iovec *vector_p, size_t vector_len, char const *msg)
291{
292 fr_dbuff_t *agg;
293
294 FR_DBUFF_TALLOC_THREAD_LOCAL(&agg, 1024, SIZE_MAX);
295 fr_concatv(agg, vector_p, vector_len);
296
297 RHEXDUMP3(fr_dbuff_start(agg), fr_dbuff_used(agg), "%s", msg);
298}
299
300static int linelog_write(rlm_linelog_t const *inst, linelog_call_env_t const *call_env, request_t *request, struct iovec *vector_p, size_t vector_len, bool with_delim)
301{
302 int ret = 0;
303 linelog_conn_t *conn;
305
306 /*
307 * Reserve a handle, write out the data, close the handle
308 */
309 switch (inst->log_dst) {
310 case LINELOG_DST_FILE:
311 {
312 int fd = -1;
313 char const *path;
314 off_t offset;
315 char *p;
316
317 if (!call_env->filename) {
318 RERROR("Missing filename");
319 return -1;
320 }
321
322 path = call_env->filename->vb_strvalue;
323
324 /* check path and eventually create subdirs */
325 p = strrchr(path, '/');
326 if (p) {
327 *p = '\0';
328 if (fr_mkdir(NULL, path, -1, 0700, NULL, NULL) < 0) {
329 RERROR("Failed to create directory %pV: %s", call_env->filename, fr_syserror(errno));
330 return -1;
331 }
332 *p = '/';
333 }
334
335 fd = exfile_open(inst->file.ef, path, inst->file.permissions, 0, &offset);
336 if (fd < 0) {
337 RERROR("Failed to open %pV: %s", call_env->filename, fr_syserror(errno));
338
339 /* coverity[missing_unlock] */
340 return -1;
341 }
342
343 if (inst->file.group_str && (chown(path, -1, inst->file.group) == -1)) {
344 RPWARN("Unable to change system group of \"%pV\": %s", call_env->filename, fr_strerror());
345 }
346
347 /*
348 * If a header format is defined and we are at the beginning
349 * of the file then expand the format and write it out before
350 * writing the actual log entries.
351 */
352 if (call_env->log_head && (offset == 0)) {
353 struct iovec head_vector_s[2];
354 size_t head_vector_len;
355
356 memcpy(&head_vector_s[0].iov_base, &call_env->log_head->vb_strvalue, sizeof(head_vector_s[0].iov_base));
357 head_vector_s[0].iov_len = call_env->log_head->vb_length;
358
359 if (!with_delim) {
360 head_vector_len = 1;
361 } else {
362 memcpy(&head_vector_s[1].iov_base, &(inst->delimiter),
363 sizeof(head_vector_s[1].iov_base));
364 head_vector_s[1].iov_len = inst->delimiter_len;
365 head_vector_len = 2;
366 }
367
368 if (RDEBUG_ENABLED3) linelog_hexdump(request, head_vector_s, head_vector_len, "linelog header");
369
370 if (writev(fd, &head_vector_s[0], head_vector_len) < 0) {
371 write_fail:
372 RERROR("Failed writing to \"%pV\": %s", call_env->filename, fr_syserror(errno));
373 exfile_close(inst->file.ef, fd);
374
375 /* Assert on the extra fatal errors */
376 fr_assert((errno != EINVAL) && (errno != EFAULT));
377
378 return -1;
379 }
380 if (inst->file.fsync && (fsync(fd) < 0)) {
381 RERROR("Failed syncing \"%pV\" to persistent storage: %s", call_env->filename, fr_syserror(errno));
382 exfile_close(inst->file.ef, fd);
383 return -1;
384 }
385 }
386
387 if (RDEBUG_ENABLED3) linelog_hexdump(request, vector_p, vector_len, "linelog data");
388
389 ret = writev(fd, vector_p, vector_len);
390 if (ret < 0) goto write_fail;
391
392 exfile_close(inst->file.ef, fd);
393 }
394 break;
395
397 {
398 size_t i;
399
400 ret = 0;
401 for (i = 0; i < vector_len; i++) {
402 RINFO("%.*s", (int)vector_p[i].iov_len, (char *)vector_p[i].iov_base);
403 ret += vector_p[i].iov_len;
404 }
405 }
406 break;
407
408 case LINELOG_DST_UNIX:
409 if (fr_time_delta_ispos(inst->unix_sock.timeout)) {
410 timeout = inst->unix_sock.timeout;
411 }
412 goto do_write;
413
414 case LINELOG_DST_UDP:
415 if (fr_time_delta_ispos(inst->udp.timeout)) {
416 timeout = inst->udp.timeout;
417 }
418 goto do_write;
419
420 case LINELOG_DST_TCP:
421 {
422 int i, num;
423 if (fr_time_delta_ispos(inst->tcp.timeout)) {
424 timeout = inst->tcp.timeout;
425 }
426
427 do_write:
428 num = fr_pool_state(inst->pool)->num;
429 conn = fr_pool_connection_get(inst->pool, request);
430 if (!conn) return -1;
431
432 for (i = num; i >= 0; i--) {
433 ssize_t wrote;
434 char discard[64];
435
436 if (RDEBUG_ENABLED3) linelog_hexdump(request, vector_p, vector_len, "linelog data");
437 wrote = fr_writev(conn->sockfd, vector_p, vector_len, timeout);
438 if (wrote < 0) switch (errno) {
439 /* Errors that indicate we should reconnect */
440 case EDESTADDRREQ:
441 case EPIPE:
442 case EBADF:
443 case ECONNRESET:
444 case ENETDOWN:
445 case ENETUNREACH:
446 case EADDRNOTAVAIL: /* Which is OSX for outbound interface is down? */
447 RWARN("Failed writing to socket: %s. Will reconnect and try again...",
448 fr_syserror(errno));
449 conn = fr_pool_connection_reconnect(inst->pool, request, conn);
450 if (!conn) {
451 ret = -1;
452 goto done;
453 }
454 continue;
455
456 /* Assert on the extra fatal errors */
457 case EINVAL:
458 case EFAULT:
459 fr_assert(0);
461
462 /* Normal errors that just cause the module to fail */
463 default:
464 RERROR("Failed writing to socket: %s", fr_syserror(errno));
465 ret = -1;
466 goto done;
467 }
468 RDEBUG2("Wrote %zi bytes", wrote);
469 ret = wrote;
470
471 /* Drain the receive buffer */
472 while (read(conn->sockfd, discard, sizeof(discard)) > 0);
473 break;
474 }
475 done:
476 fr_pool_connection_release(inst->pool, request, conn);
477 }
478 break;
479
480#ifdef HAVE_SYSLOG_H
482 {
483 size_t i;
484
485 ret = 0;
486 for (i = 0; i < vector_len; i++) {
487 syslog(inst->syslog.priority, "%.*s", (int)vector_p[i].iov_len, (char *)vector_p[i].iov_base);
488 ret += vector_p[i].iov_len;
489 }
490 }
491 break;
492#endif
493
496 {
497 int fd = inst->log_dst == LINELOG_DST_STDOUT ? STDOUT_FILENO : STDERR_FILENO;
498 if ((ret = writev(fd, vector_p, vector_len)) < 0) {
499 RERROR("Failed writing to \"%s\": %s",
501 fr_syserror(errno));
502 }
503 }
504 break;
505
507 fr_assert(0);
508 ret = -1;
509 break;
510 }
511
512 return ret;
513}
514
516 xlat_ctx_t const *xctx, request_t *request,
517 fr_value_box_list_t *args)
518{
520 linelog_call_env_t const *call_env = talloc_get_type_abort(xctx->env_data, linelog_call_env_t);
521
522 struct iovec vector[2];
523 size_t i = 0;
524 bool with_delim;
525 fr_value_box_t *msg, *wrote;
526 ssize_t slen;
527
528 XLAT_ARGS(args, &msg);
529
530 vector[i].iov_base = UNCONST(char *, msg->vb_strvalue);
531 vector[i].iov_len = msg->vb_length;
532 i++;
533
534 with_delim = (inst->log_dst != LINELOG_DST_SYSLOG) && (inst->delimiter_len > 0);
535 if (with_delim) {
536 memcpy(&vector[i].iov_base, &(inst->delimiter), sizeof(vector[i].iov_base));
537 vector[i].iov_len = inst->delimiter_len;
538 i++;
539 }
540
541 if (inst->file.buffer_write) {
542 rlm_linelog_file_entry_t *entry = NULL;
543
544 switch(file_enqueue_write(&entry, xctx->mctx, call_env, request, vector, i)) {
546 return XLAT_ACTION_FAIL;
547
549 break;
550
553 }
554
555 slen = entry->data_len;
556 } else {
557 slen = linelog_write(inst, call_env, request, vector, i, with_delim);
558 }
559
560 if (slen < 0) return XLAT_ACTION_FAIL;
561
562 MEM(wrote = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL));
563 wrote->vb_size = (size_t)slen;
564
565 fr_dcursor_insert(out, wrote);
566
567 return XLAT_ACTION_DONE;
568}
569
570typedef struct {
571 fr_value_box_list_t expanded; //!< The result of expanding the fmt tmpl
572 bool with_delim; //!< Whether to add a delimiter
574
576{
578 linelog_call_env_t const *call_env = talloc_get_type_abort(mctx->env_data, linelog_call_env_t);
579 rlm_linelog_rctx_t *rctx = talloc_get_type_abort(mctx->rctx, rlm_linelog_rctx_t);
580 struct iovec *vector;
581 struct iovec *vector_p;
582 size_t vector_len;
583
584 vector_len = fr_value_box_list_num_elements(&rctx->expanded);
585 if (vector_len == 0) {
586 RDEBUG2("No data to write");
588 }
589
590 /*
591 * Add extra space for the delimiter
592 */
593 if (rctx->with_delim) vector_len *= 2;
594
595 MEM(vector = vector_p = talloc_array(rctx, struct iovec, vector_len));
597 switch(vb->type) {
598 default:
599 if (unlikely(fr_value_box_cast_in_place(rctx, vb, FR_TYPE_STRING, vb->enumv) < 0)) {
600 REDEBUG("Failed casting value to string");
602 }
604
605 case FR_TYPE_STRING:
606 vector_p->iov_base = UNCONST(char *, vb->vb_strvalue);
607 vector_p->iov_len = vb->vb_length;
608 vector_p++;
609 break;
610
611 case FR_TYPE_OCTETS:
612 vector_p->iov_base = UNCONST(char *, vb->vb_octets);
613 vector_p->iov_len = vb->vb_length;
614 vector_p++;
615 break;
616 }
617
618 /*
619 * Don't add the delim for the last element
620 */
621 if (rctx->with_delim) {
622 memcpy(&vector_p->iov_base, &(inst->delimiter), sizeof(vector_p->iov_base));
623 vector_p->iov_len = inst->delimiter_len;
624 vector_p++;
625 }
626 }
627
628 if (inst->file.buffer_write) {
629 rlm_linelog_file_entry_t *entry = NULL;
630
631 switch(file_enqueue_write(&entry, mctx, call_env, request, vector, vector_len)) {
634
637
640 }
641 }
642
643 RETURN_UNLANG_RCODE(linelog_write(inst, call_env, request, vector, vector_len, rctx->with_delim) < 0 ? RLM_MODULE_FAIL : RLM_MODULE_OK);
644}
645
646/** Write a linelog message
647 *
648 * Write a log message to syslog or a flat file.
649 *
650 * @param[in] p_result the result of the module call:
651 * - #RLM_MODULE_NOOP if no message to log.
652 * - #RLM_MODULE_FAIL if we failed writing the message.
653 * - #RLM_MODULE_OK on success.
654 * @param[in] mctx module calling context.
655 * @param[in] request The current request.
656 */
657static unlang_action_t CC_HINT(nonnull) mod_do_linelog(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
658{
660 linelog_call_env_t const *call_env = talloc_get_type_abort(mctx->env_data, linelog_call_env_t);
661 CONF_SECTION *conf = mctx->mi->conf;
662
663 char buff[4096];
664 char *p = buff;
665 tmpl_t *empty, *vpt = NULL, *vpt_p = NULL;
666 ssize_t slen;
667 bool with_delim;
668
669 TALLOC_CTX *frame_ctx = unlang_interpret_frame_talloc_ctx(request);
670
671 if (!call_env->log_src && !call_env->log_ref) {
672 cf_log_err(conf, "A 'format', or 'reference' configuration item must be set to call this module");
674 }
675
676 buff[0] = '.'; /* force to be in current section (by default) */
677 buff[1] = '\0';
678 buff[2] = '\0';
679
680 /*
681 * Expand log_ref to a config path, using the module
682 * configuration section as the root.
683 */
684 if (call_env->log_ref) {
685 CONF_ITEM *ci;
686 CONF_PAIR *cp;
687 char const *tmpl_str;
688
689 if (call_env->log_ref->vb_length >= (sizeof(buff) - 2)) {
690 REDEBUG("Invalid log_ref - too long (%zu >= %zu)",
691 call_env->log_ref->vb_length, sizeof(buff) - 2);
693 }
694
695 memcpy(buff + 1, call_env->log_ref->vb_strvalue, call_env->log_ref->vb_length);
696 buff[call_env->log_ref->vb_length + 1] = '\0';
697
698 if (buff[1] == '.') p++;
699
700 /*
701 * Don't go back up.
702 */
703 if (buff[2] == '.') {
704 REDEBUG("Invalid path \"%s\"", p);
706 }
707
708 ci = cf_reference_item(NULL, inst->cs, p);
709 if (!ci) {
710 RPDEBUG2("Failed finding reference '%s'", p);
711 goto default_msg;
712 }
713
714 if (!cf_item_is_pair(ci)) {
715 REDEBUG("Path \"%s\" resolves to a section (should be a pair)", p);
717 }
718
719 cp = cf_item_to_pair(ci);
720 tmpl_str = cf_pair_value(cp);
721 if (!tmpl_str || (tmpl_str[0] == '\0')) {
722 RDEBUG2("Path \"%s\" resolves to an empty config pair", p);
723 empty = talloc(frame_ctx, tmpl_t);
724 vpt_p = tmpl_init_shallow(empty, TMPL_TYPE_DATA, T_DOUBLE_QUOTED_STRING, "", 0, NULL);
725 fr_value_box_init_null(&empty->data.literal);
726 fr_value_box_strdup_shallow(&empty->data.literal, NULL, "", false);
727 goto build_vector;
728 }
729
730 /*
731 * Alloc a template from the value of the CONF_PAIR
732 * using request as the context (which will hopefully avoid an alloc).
733 */
734 slen = tmpl_afrom_substr(frame_ctx, &vpt,
735 &FR_SBUFF_IN(tmpl_str, talloc_strlen(tmpl_str)),
737 NULL,
738 &(tmpl_rules_t){
739 .attr = {
740 .list_def = request_attr_request,
741 .dict_def = request->local_dict,
742 .allow_unknown = true,
743 .allow_unresolved = false,
744 },
745 .xlat = {
746 .runtime_el = unlang_interpret_event_list(request),
747 },
748 .at_runtime = true,
749 .literals_safe_for = FR_VALUE_BOX_SAFE_FOR_ANY,
750 });
751 if (!vpt) {
752 REMARKER(tmpl_str, -slen, "%s", fr_strerror());
754 }
755 if (tmpl_resolve(vpt, NULL) < 0) {
756 RPERROR("Runtime resolution of tmpl failed");
759 }
760 vpt_p = vpt;
761 } else {
762 default_msg:
763 /*
764 * Use the default format string
765 */
766 if (!call_env->log_src) {
767 RDEBUG2("No default message configured");
769 }
770 /*
771 * Use the pre-parsed format template
772 */
773 RDEBUG2("Using default message");
774 vpt_p = call_env->log_src;
775 }
776
777build_vector:
778 with_delim = (inst->log_dst != LINELOG_DST_SYSLOG) && (inst->delimiter_len > 0);
779
780 /*
781 * Log all the things!
782 */
783 switch (vpt_p->type) {
784 case TMPL_TYPE_ATTR:
785 {
786 #define VECTOR_INCREMENT 20
787 fr_dcursor_t cursor;
789 fr_pair_t *vp;
790 int alloced = VECTOR_INCREMENT, i;
791 struct iovec *vector = NULL, *vector_p;
792 size_t vector_len;
794
795 MEM(vector = talloc_array(frame_ctx, struct iovec, alloced));
796 for (vp = tmpl_dcursor_init(NULL, NULL, &cc, &cursor, request, vpt_p), i = 0;
797 vp;
798 vp = fr_dcursor_next(&cursor), i++) {
799 /* need extra for line terminator */
800 if ((with_delim && ((i + 1) >= alloced)) ||
801 (i >= alloced)) {
802 alloced += VECTOR_INCREMENT;
803 MEM(vector = talloc_realloc(frame_ctx, vector, struct iovec, alloced));
804 }
805
806 switch (vp->vp_type) {
807 case FR_TYPE_OCTETS:
808 case FR_TYPE_STRING:
809 vector[i].iov_len = vp->vp_length;
810 vector[i].iov_base = vp->vp_ptr;
811 break;
812
813 default:
814 vector[i].iov_len = fr_value_box_aprint(vector, &p, &vp->data, NULL);
815 vector[i].iov_base = p;
816 break;
817 }
818
819 /*
820 * Add the line delimiter string
821 */
822 if (with_delim) {
823 i++;
824 memcpy(&vector[i].iov_base, &(inst->delimiter), sizeof(vector[i].iov_base));
825 vector[i].iov_len = inst->delimiter_len;
826 }
827 }
829 vector_p = vector;
830 vector_len = i;
831
832 if (vector_len == 0) {
833 RDEBUG2("No data to write");
834 rcode = RLM_MODULE_NOOP;
835
836 } else if (inst->file.buffer_write) {
838 rlm_linelog_file_entry_t *entry = NULL;
839
840 ret = file_enqueue_write(&entry, mctx, call_env, request, vector_p, vector_len);
841
843 talloc_free(vector);
844
845 switch (ret) {
848
851
854 }
855 } else {
856 rcode = linelog_write(inst, call_env, request, vector_p, vector_len, with_delim) < 0 ? RLM_MODULE_FAIL : RLM_MODULE_OK;
857 }
858
860 talloc_free(vector);
861
862 RETURN_UNLANG_RCODE(rcode);
863 }
864
865 /*
866 * Log a format string. We need to yield as this might contain asynchronous expansions.
867 */
868 default:
869 {
870 rlm_linelog_rctx_t *rctx;
871
872 MEM(rctx = talloc(frame_ctx, rlm_linelog_rctx_t));
873 fr_value_box_list_init(&rctx->expanded);
874 rctx->with_delim = with_delim;
875
876 return unlang_module_yield_to_tmpl(rctx, &rctx->expanded, request, vpt_p, NULL, mod_do_linelog_resume, NULL, 0, rctx);
877 }
878 }
879}
880
881/*
882 * Custom call env parser for filenames - sets the correct escaping function
883 */
884static int call_env_filename_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
885 call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
886{
888 tmpl_t *parsed;
889 CONF_PAIR const *to_parse = cf_item_to_pair(ci);
890 tmpl_rules_t our_rules;
891
892 /*
893 * If we're not logging to a file destination, do nothing
894 */
896
897 our_rules = *t_rules;
900 .safe_for = (inst->file.escape) ? (fr_value_box_safe_for_t)rad_filename_box_escape :
902 .always_escape = false,
903 };
905 our_rules.literals_safe_for = our_rules.escape.box_escape.safe_for;
906
907 if (tmpl_afrom_substr(ctx, &parsed,
910 &our_rules) < 0) return -1;
911
912 *(void **)out = parsed;
913 return 0;
914}
915
916static int mod_detach(module_detach_ctx_t const *mctx)
917{
918 rlm_linelog_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_linelog_t);
919
920 fr_pool_free(inst->pool);
921
922 return 0;
923}
924
925/*
926 * Instantiate the module.
927 */
928static int mod_instantiate(module_inst_ctx_t const *mctx)
929{
930 rlm_linelog_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_linelog_t);
931 CONF_SECTION *cs, *conf = mctx->mi->conf;
932 char prefix[100];
933
935 if (inst->log_dst == LINELOG_DST_INVALID) {
936 cf_log_err(conf, "Invalid log destination \"%s\"", inst->log_dst_str);
937 return -1;
938 }
939
940 snprintf(prefix, sizeof(prefix), "rlm_linelog (%s)", mctx->mi->name);
941
942 /*
943 * Setup the logging destination
944 */
945 switch (inst->log_dst) {
946 case LINELOG_DST_FILE:
947 {
948 cs = cf_section_find(conf, "file", CF_IDENT_ANY);
949 if (!cs) {
950 no_filename:
951 cf_log_err(conf, "No value provided for 'file.filename'");
952 return -1;
953 }
954 if (!cf_pair_find(cs, "filename")) goto no_filename;
955
956 inst->file.ef = module_rlm_exfile_init(inst, conf, 256, inst->file.max_idle, true,
957 inst->triggers, NULL, NULL);
958 if (!inst->file.ef) {
959 cf_log_err(conf, "Failed creating log file context");
960 return -1;
961 }
962
963 if (inst->file.group_str) {
964 char *endptr;
965
966 inst->file.group = strtol(inst->file.group_str, &endptr, 10);
967 if (*endptr != '\0') {
968 if (fr_perm_gid_from_str(inst, &(inst->file.group), inst->file.group_str) < 0) {
969 cf_log_err(conf, "Unable to find system group \"%s\"",
970 inst->file.group_str);
971 return -1;
972 }
973 }
974 }
975
976 FR_TIME_DELTA_COND_CHECK("buffer_delay", inst->file.buffer_delay,
977 fr_time_delta_lt(inst->file.buffer_delay, fr_time_delta_wrap(0)), fr_time_delta_wrap(0));
978
979 if ((inst->file.buffer_count != 0) || (fr_time_delta_unwrap(inst->file.buffer_delay) != 0)) {
980 inst->file.buffer_write = true;
981
982 if (inst->file.buffer_delay_is_set && !inst->file.buffer_expiry_is_set) {
983 /*
984 * If only delay is set, set expiry to double that value
985 */
986 inst->file.buffer_expiry = fr_time_delta_mul(inst->file.buffer_delay, 2);
987 }
988
989 FR_INTEGER_BOUND_CHECK("buffer_count", inst->file.buffer_count, >=, 10);
990 FR_INTEGER_BOUND_CHECK("buffer_count", inst->file.buffer_count, <=, 100000);
991
992 FR_TIME_DELTA_COND_CHECK("buffer_delay", inst->file.buffer_delay,
994
995 FR_TIME_DELTA_COND_CHECK("buffer_delay", inst->file.buffer_delay,
997
998 } else {
999 inst->file.buffer_write = false;
1000 }
1001 }
1002 break;
1003
1004 case LINELOG_DST_SYSLOG:
1005 {
1006 int num;
1007
1008#ifndef HAVE_SYSLOG_H
1009 cf_log_err(conf, "Syslog output is not supported on this system");
1010 return -1;
1011#else
1012 if (inst->syslog.facility) {
1013 num = fr_table_value_by_str(syslog_facility_table, inst->syslog.facility, -1);
1014 if (num < 0) {
1015 cf_log_err(conf, "Invalid syslog facility \"%s\"", inst->syslog.facility);
1016 return -1;
1017 }
1018 inst->syslog.priority |= num;
1019 }
1020
1021 num = fr_table_value_by_str(syslog_severity_table, inst->syslog.severity, -1);
1022 if (num < 0) {
1023 cf_log_err(conf, "Invalid syslog severity \"%s\"", inst->syslog.severity);
1024 return -1;
1025 }
1026 inst->syslog.priority |= num;
1027#endif
1028 }
1029 break;
1030
1031 case LINELOG_DST_UNIX:
1032#ifndef HAVE_SYS_UN_H
1033 cf_log_err(conf, "Unix sockets are not supported on this system");
1034 return -1;
1035#else
1037 inst, mod_conn_create, NULL, prefix, NULL, NULL);
1038 if (!inst->pool) return -1;
1039#endif
1040 break;
1041
1042 case LINELOG_DST_UDP:
1044 inst, mod_conn_create, NULL, prefix, NULL, NULL);
1045 if (!inst->pool) return -1;
1046 break;
1047
1048 case LINELOG_DST_TCP:
1050 inst, mod_conn_create, NULL, prefix, NULL, NULL);
1051 if (!inst->pool) return -1;
1052 break;
1053
1055 case LINELOG_DST_STDOUT:
1056 case LINELOG_DST_STDERR:
1057 break;
1058
1060 fr_assert(0);
1061 break;
1062 }
1063
1064 inst->delimiter_len = talloc_strlen(inst->delimiter);
1065 inst->cs = conf;
1066
1067 return 0;
1068}
1069
1070static int mod_bootstrap(module_inst_ctx_t const *mctx)
1071{
1072 xlat_t *xlat;
1073
1074 static xlat_arg_parser_t const linelog_xlat_args[] = {
1075 { .required = true, .concat = true, .type = FR_TYPE_STRING },
1077 };
1078
1079 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, NULL, linelog_xlat, FR_TYPE_SIZE);
1080 xlat_func_args_set(xlat, linelog_xlat_args);
1082
1083 return 0;
1084}
1085
1086/** Initialise thread specific data strcuture
1087 */
1089{
1090 rlm_linelog_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_linelog_t);
1091
1092 if (inst->log_dst == LINELOG_DST_FILE && inst->file.buffer_write) {
1093 rlm_linelog_thread_t *thread = talloc_get_type_abort(mctx->thread, rlm_linelog_thread_t);
1094 file_thread_init(thread, mctx->el->tl);
1095 }
1096
1097 return 0;
1098}
1099
1100/*
1101 * Externally visible module definition.
1102 */
1105 .common = {
1106 .magic = MODULE_MAGIC_INIT,
1107 .name = "linelog",
1108 .inst_size = sizeof(rlm_linelog_t),
1110 .bootstrap = mod_bootstrap,
1111 .instantiate = mod_instantiate,
1112 .detach = mod_detach,
1114 .thread_instantiate = mod_thread_instantiate,
1115 },
1116 .method_group = {
1117 .bindings = (module_method_binding_t[]){
1118 { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_do_linelog, .method_env = &linelog_method_env },
1120 }
1121 }
1122};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
int const char * file
Definition acutest.h:702
log_entry msg
Definition acutest.h:794
va_list args
Definition acutest.h:770
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:186
#define RCSID(id)
Definition build.h:512
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:343
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
#define NUM_ELEMENTS(_t)
Definition build.h:358
#define CALL_ENV_TERMINATOR
Definition call_env.h:236
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
Definition call_env.h:240
call_env_parser_t const * env
Parsing rules for call method env.
Definition call_env.h:247
#define FR_CALL_ENV_SUBSECTION(_name, _name2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
Definition call_env.h:402
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
Definition call_env.h:76
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
Definition call_env.h:85
@ CALL_ENV_FLAG_NONE
Definition call_env.h:74
@ CALL_ENV_FLAG_BARE_WORD_ATTRIBUTE
bare words are treated as an attribute, but strings may be xlats.
Definition call_env.h:92
module_instance_t const * mi
Module instance that the callenv is registered to.
Definition call_env.h:229
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
Definition call_env.h:340
#define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field)
Specify a call_env_parser_t which writes out the result of the parsing phase to the field specified.
Definition call_env.h:389
Per method call config.
Definition call_env.h:180
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3852
int cf_parse_permissions(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving permissions to a mode-t.
Definition cf_parse.c:1789
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:669
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:623
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
Definition cf_parse.h:409
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:529
#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:280
#define FR_TIME_DELTA_COND_CHECK(_name, _var, _cond, _new)
Definition cf_parse.h:531
#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:334
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
Definition cf_parse.h:294
#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:268
#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:309
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:429
@ CONF_FLAG_FILE_SOCKET
File matching value must exist, and must be a unix socket.
Definition cf_parse.h:439
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:423
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition cf_parse.h:455
#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:238
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:72
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:633
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1029
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1422
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition cf_util.c:1625
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:665
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1581
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:287
#define CF_IDENT_ANY
Definition cf_util.h:75
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition dbuff.h:775
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:906
#define FR_DBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Create a function local and thread local extensible dbuff.
Definition dbuff.h:564
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition dcursor.h:288
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
Definition dcursor.h:435
#define MEM(x)
Definition debug.h:36
#define ERROR(fmt,...)
Definition dhcpclient.c:40
static int sockfd
Definition dhcpclient.c:55
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, int flags, off_t *offset)
Open a new log file, or maybe an existing one.
Definition exfile.c:529
int exfile_close(exfile_t *ef, int fd)
Close the log file.
Definition exfile.c:596
talloc_free(hp)
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition interpret.c:2033
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:2409
ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t timeout)
Write out a vector to a file descriptor.
Definition iovec.c:68
fr_slen_t fr_concatv(fr_dbuff_t *out, struct iovec vector[], int iovcnt)
Concatenate an iovec into a dbuff.
Definition iovec.c:38
fr_table_num_sorted_t const syslog_severity_table[]
Syslog severity table.
Definition log.c:151
fr_table_num_sorted_t const syslog_facility_table[]
Syslog facility table.
Definition log.c:66
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG3(_fmt,...)
Definition log.h:266
#define RPDEBUG2(fmt,...)
Definition log.h:359
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition log.h:347
#define RWARN(fmt,...)
Definition log.h:309
#define RERROR(fmt,...)
Definition log.h:310
#define RPWARN(fmt,...)
Definition log.h:313
#define RPERROR(fmt,...)
Definition log.h:314
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:510
#define RINFO(fmt,...)
Definition log.h:308
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition log.h:717
int rad_filename_box_escape(fr_value_box_t *vb, UNUSED void *uxtc)
Definition util.c:253
int rad_filename_box_make_safe(fr_value_box_t *vb, UNUSED void *uxtc)
Definition util.c:131
ssize_t fr_mkdir(int *fd_out, char const *path, ssize_t len, mode_t mode, fr_mkdir_func_t func, void *uctx)
Create directories that are missing in the specified path.
Definition file.c:218
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ 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.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
long long int off_t
unsigned long int size_t
int fr_blocking(UNUSED int fd)
Definition misc.c:298
void * env_data
Per call environment data.
Definition module_ctx.h:44
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * rctx
Resume ctx that a module previously set.
Definition module_ctx.h:45
fr_event_list_t * el
Event list to register any IO handlers and timers against.
Definition module_ctx.h:68
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
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 detach calls.
Definition module_ctx.h:56
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
exfile_t * module_rlm_exfile_init(TALLOC_CTX *ctx, CONF_SECTION *module, uint32_t max_entries, fr_time_delta_t max_idle, bool locking, bool triggers, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific exfile handle.
Definition module_rlm.c:103
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition module_rlm.c:232
fr_pool_t * module_rlm_connection_pool_init(CONF_SECTION *module, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific connection pool.
Definition module_rlm.c:283
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
linelog_buffer_action_t file_enqueue_write(rlm_linelog_file_entry_t **entry_p, module_ctx_t const *mctx, linelog_call_env_t const *call_env, request_t *request, struct iovec *vector_p, size_t vector_len)
Definition file.c:272
void file_batching_mod_handle_signal(module_ctx_t const *mctx, request_t *request, fr_signal_t action)
Definition file.c:87
void file_thread_init(rlm_linelog_thread_t *thread, fr_timer_list_t *tl)
Definition file.c:360
void file_batching_xlat_handle_signal(xlat_ctx_t const *xctx, request_t *request, fr_signal_t action)
Definition file.c:92
unlang_action_t file_batching_mod_resume(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition file.c:46
xlat_action_t file_batching_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Definition file.c:58
size_t data_len
How much data this entry holds in the sbuff.
Definition file.h:38
linelog_buffer_action_t
Definition file.h:59
@ LINELOG_BUFFER_WRITE_YIELD
Writing buffered data yielded.
Definition file.h:61
@ LINELOG_BUFFER_WRITE_DONE
Writing buffered data completed.
Definition file.h:62
@ LINELOG_BUFFER_WRITE_FAIL
Writing buffered data failed.
Definition file.h:60
Definition file.h:34
linelog module thread specific structure
Definition file.h:27
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition perm.c:475
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
Definition pool.c:1410
void fr_pool_free(fr_pool_t *pool)
Delete a connection pool.
Definition pool.c:1332
fr_pool_state_t const * fr_pool_state(fr_pool_t *pool)
Get the number of connections currently in the pool.
Definition pool.c:1176
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
Definition pool.c:1395
void * fr_pool_connection_reconnect(fr_pool_t *pool, request_t *request, void *conn)
Reconnect a suspected inviable connection.
Definition pool.c:1503
uint32_t num
Number of connections in the pool.
Definition pool.h:67
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
Definition print.c:438
static const conf_parser_t config[]
Definition base.c:163
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define DEBUG2(fmt,...)
static bool done
Definition radclient.c:80
static rs_t * conf
Definition radsniff.c:52
#define RETURN_UNLANG_RCODE(_rcode)
Definition rcode.h:61
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
#define RETURN_UNLANG_OK
Definition rcode.h:64
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:54
#define RETURN_UNLANG_NOOP
Definition rcode.h:69
fr_dict_attr_t const * request_attr_request
Definition request.c:43
static int mod_detach(module_detach_ctx_t const *mctx)
static int call_env_filename_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
module_rlm_t rlm_linelog
static const conf_parser_t file_config[]
Definition rlm_linelog.c:78
static const call_env_method_t linelog_xlat_method_env
static unlang_action_t mod_do_linelog_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
#define LINELOG_BOX_ESCAPE
static unlang_action_t mod_do_linelog(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Write a linelog message.
static const conf_parser_t syslog_config[]
Definition rlm_linelog.c:91
static xlat_action_t linelog_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
static int _mod_conn_free(linelog_conn_t *conn)
static int mod_bootstrap(module_inst_ctx_t const *mctx)
fr_value_box_list_t expanded
The result of expanding the fmt tmpl.
#define VECTOR_INCREMENT
static const conf_parser_t udp_config[]
static void linelog_hexdump(request_t *request, struct iovec *vector_p, size_t vector_len, char const *msg)
static int linelog_write(rlm_linelog_t const *inst, linelog_call_env_t const *call_env, request_t *request, struct iovec *vector_p, size_t vector_len, bool with_delim)
int sockfd
File descriptor associated with socket.
Definition rlm_linelog.c:74
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Initialise thread specific data strcuture.
static void * mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
static fr_table_num_sorted_t const linefr_log_dst_table[]
Definition rlm_linelog.c:60
static const call_env_method_t linelog_method_env
static const conf_parser_t module_config[]
static int linelog_escape_func(fr_value_box_t *vb, UNUSED void *uctx)
Escape unprintable characters.
static const conf_parser_t unix_config[]
Definition rlm_linelog.c:97
static size_t linefr_log_dst_table_len
Definition rlm_linelog.c:71
static int mod_instantiate(module_inst_ctx_t const *mctx)
bool with_delim
Whether to add a delimiter.
static const conf_parser_t tcp_config[]
tmpl_t * log_src
Source of log messages.
Definition rlm_linelog.h:92
@ LINELOG_DST_FILE
Log to a file.
Definition rlm_linelog.h:28
@ LINELOG_DST_STDERR
Log to stderr.
Definition rlm_linelog.h:35
@ LINELOG_DST_UNIX
Log via Unix socket.
Definition rlm_linelog.h:31
@ LINELOG_DST_STDOUT
Log to stdout.
Definition rlm_linelog.h:34
@ LINELOG_DST_TCP
Log via TCP.
Definition rlm_linelog.h:33
@ LINELOG_DST_INVALID
Definition rlm_linelog.h:27
@ LINELOG_DST_REQUEST
Log to the request->log.
Definition rlm_linelog.h:29
@ LINELOG_DST_UDP
Log via UDP.
Definition rlm_linelog.h:32
@ LINELOG_DST_SYSLOG
Log to syslog.
Definition rlm_linelog.h:30
fr_value_box_t * log_head
Header to add to each new log file.
Definition rlm_linelog.h:97
fr_value_box_t * log_ref
Path to a CONF_PAIR (to use as the source of log messages).
Definition rlm_linelog.h:94
fr_value_box_t * filename
File name, if output is to a file.
Definition rlm_linelog.h:99
linelog module instance
Definition rlm_linelog.h:47
#define FR_SBUFF_IN(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:39
#define MODULE_THREAD_INST(_ctype)
Definition module.h:258
char const * name
Instance name e.g. user_database.
Definition module.h:357
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:293
void * boot
Data allocated during the boostrap phase.
Definition module.h:296
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:152
Named methods exported by a module.
Definition module.h:174
tmpl_escape_t escape
How escaping should be handled during evaluation.
Definition tmpl.h:353
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
fr_value_box_safe_for_t literals_safe_for
safe_for value assigned to literal values in xlats, execs, and data.
Definition tmpl.h:351
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition tmpl.h:142
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition tmpl.h:138
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
static fr_slen_t vpt
Definition tmpl.h:1269
tmpl_t * tmpl_init_shallow(tmpl_t *vpt, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len, tmpl_rules_t const *t_rules))
Initialise a tmpl without copying the input name string.
Optional arguments passed to vp_tmpl functions.
Definition tmpl.h:336
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:41
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:613
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:708
int fr_socket_wait_for_connect(int sockfd, fr_time_delta_t timeout)
Wait for a socket to be connected, with an optional timeout.
Definition socket.c:782
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition socket.c:543
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition module.c:431
unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt, unlang_tmpl_args_t *args, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Push a pre-compiled tmpl and resumption state onto the stack for evaluation.
Definition module.c:216
eap_aka_sim_process_conf_t * inst
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
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
#define talloc_get_type_abort_const
Definition talloc.h:117
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
#define fr_time_delta_lt(_a, _b)
Definition time.h:285
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_time_delta_ispos(_a)
Definition time.h:290
static fr_time_delta_t fr_time_delta_mul(fr_time_delta_t a, int64_t b)
Definition time.h:273
#define USEC
Definition time.h:380
#define fr_time_delta_gt(_a, _b)
Definition time.h:283
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
void tmpl_dcursor_clear(tmpl_dcursor_ctx_t *cc)
Clear any temporary state allocations.
#define tmpl_dcursor_init(_err, _ctx, _cc, _cursor, _request, _vpt)
Maintains state between cursor calls.
fr_value_box_escape_t box_escape
How to escape when returned from evaluation.
Definition tmpl_escape.h:81
@ TMPL_ESCAPE_PRE_CONCAT
Pre-concatenation escaping is useful for DSLs where elements of the expansion are static,...
Definition tmpl_escape.h:61
tmpl_escape_mode_t mode
Whether to apply escape function after concatenation, i.e.
Definition tmpl_escape.h:83
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition xlat.c:543
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
Definition xlat.h:383
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumed by an xlat function.
Definition xlat.h:145
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:553
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
Definition value.c:611
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
Definition value.c:4196
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
Definition value.c:4745
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
Definition value.c:4729
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:644
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define fr_box_ipaddr(_val)
Definition value.h:317
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:616
fr_value_box_safe_for_t safe_for
Definition value.h:678
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
Definition value.h:162
int nonnull(2, 5))
fr_value_box_escape_func_t func
Definition value.h:677
#define fr_value_box_list_foreach(_list_head, _iter)
Definition value.h:224
static size_t char ** out
Definition value.h:1030
#define FR_VALUE_BOX_SAFE_FOR_ANY
Definition value.h:173
void * env_data
Expanded call env data.
Definition xlat_ctx.h:53
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition xlat_ctx.h:52
An xlat calling ctx.
Definition xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.
Definition xlat_func.c:380