The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_linelog.c
Go to the documentation of this file.
1 /*
2  * rlm_linelog.c
3  *
4  * Version: $Id: d3b8ce762cfd1e4d8bfb428b6f9a6cbe7a235458 $
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  */
23 
24 RCSID("$Id: d3b8ce762cfd1e4d8bfb428b6f9a6cbe7a235458 $")
25 
26 #include <freeradius-devel/server/base.h>
27 #include <freeradius-devel/server/exfile.h>
28 #include <freeradius-devel/server/module_rlm.h>
29 #include <freeradius-devel/server/tmpl_dcursor.h>
30 #include <freeradius-devel/server/rcode.h>
31 #include <freeradius-devel/server/tmpl.h>
32 #include <freeradius-devel/unlang/call_env.h>
33 #include <freeradius-devel/unlang/tmpl.h>
34 #include <freeradius-devel/unlang/module.h>
35 
36 #include <freeradius-devel/util/debug.h>
37 #include <freeradius-devel/util/iovec.h>
38 #include <freeradius-devel/util/perm.h>
39 #include <freeradius-devel/util/print.h>
40 #include <freeradius-devel/util/value.h>
41 #include <freeradius-devel/util/types.h>
42 
43 #include <freeradius-devel/unlang/xlat_func.h>
44 
45 #ifdef HAVE_FCNTL_H
46 # include <fcntl.h>
47 #endif
48 
49 #ifdef HAVE_UNISTD_H
50 # include <unistd.h>
51 #endif
52 
53 #ifdef HAVE_GRP_H
54 # include <grp.h>
55 #endif
56 
57 #ifdef HAVE_SYSLOG_H
58 # include <syslog.h>
59 # ifndef LOG_INFO
60 # define LOG_INFO (0)
61 # endif
62 #endif
63 
64 #include <sys/uio.h>
65 
66 static int linelog_escape_func(fr_value_box_t *vb, UNUSED void *uctx);
67 static int call_env_filename_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
68  UNUSED char const *section_name1, UNUSED char const *section_name2,
69  void const *data, UNUSED call_env_parser_t const *rule);
70 typedef enum {
72  LINELOG_DST_FILE, //!< Log to a file.
73  LINELOG_DST_REQUEST, //!< Log to the request->log
74  LINELOG_DST_SYSLOG, //!< Log to syslog.
75  LINELOG_DST_UNIX, //!< Log via Unix socket.
76  LINELOG_DST_UDP, //!< Log via UDP.
77  LINELOG_DST_TCP, //!< Log via TCP.
78  LINELOG_DST_STDOUT, //!< Log to stdout.
79  LINELOG_DST_STDERR, //!< Log to stderr.
81 
83  { L("file"), LINELOG_DST_FILE },
84  { L("files"), LINELOG_DST_FILE },
85  { L("request"), LINELOG_DST_REQUEST },
86  { L("stderr"), LINELOG_DST_STDERR },
87  { L("stdout"), LINELOG_DST_STDOUT },
88  { L("syslog"), LINELOG_DST_SYSLOG },
89  { L("tcp"), LINELOG_DST_TCP },
90  { L("udp"), LINELOG_DST_UDP },
91  { L("unix"), LINELOG_DST_UNIX }
92 };
94 
95 typedef struct {
96  fr_ipaddr_t dst_ipaddr; //!< Network server.
97  fr_ipaddr_t src_ipaddr; //!< Send requests from a given src_ipaddr.
98  uint16_t port; //!< Network port.
99  fr_time_delta_t timeout; //!< How long to wait for read/write operations.
100 } linelog_net_t;
101 
102 /** linelog module instance
103  */
104 typedef struct {
105  fr_pool_t *pool; //!< Connection pool instance.
106 
107  char const *delimiter; //!< Line termination string (usually \n).
108  size_t delimiter_len; //!< Length of line termination string.
109 
110  linefr_log_dst_t log_dst; //!< Logging destination.
111  char const *log_dst_str; //!< Logging destination string.
112 
113  struct {
114  char const *facility; //!< Syslog facility string.
115  char const *severity; //!< Syslog severity string.
116  int priority; //!< Bitwise | of severity and facility.
117  } syslog;
118 
119  struct {
120  uint32_t permissions; //!< Permissions to use when creating new files.
121  char const *group_str; //!< Group to set on new files.
122  gid_t group; //!< Resolved gid.
123  exfile_t *ef; //!< Exclusive file access handle.
124  bool escape; //!< Do filename escaping, yes / no.
125  } file;
126 
127  struct {
128  char const *path; //!< Where the UNIX socket lives.
129  fr_time_delta_t timeout; //!< How long to wait for read/write operations.
130  } unix_sock; // Lowercase unix is a macro on some systems?!
131 
132  linelog_net_t tcp; //!< TCP server.
133  linelog_net_t udp; //!< UDP server.
134 
135  CONF_SECTION *cs; //!< #CONF_SECTION to use as the root for #log_ref lookups.
136 } rlm_linelog_t;
137 
138 typedef struct {
139  int sockfd; //!< File descriptor associated with socket
141 
142 
143 static const conf_parser_t file_config[] = {
144  { FR_CONF_OFFSET("permissions", rlm_linelog_t, file.permissions), .dflt = "0600" },
145  { FR_CONF_OFFSET("group", rlm_linelog_t, file.group_str) },
146  { FR_CONF_OFFSET("escape_filenames", rlm_linelog_t, file.escape), .dflt = "no" },
148 };
149 
150 static const conf_parser_t syslog_config[] = {
151  { FR_CONF_OFFSET("facility", rlm_linelog_t, syslog.facility) },
152  { FR_CONF_OFFSET("severity", rlm_linelog_t, syslog.severity), .dflt = "info" },
154 };
155 
156 static const conf_parser_t unix_config[] = {
157  { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_linelog_t, unix_sock.path) },
159 };
160 
161 static const conf_parser_t udp_config[] = {
162  { FR_CONF_OFFSET_TYPE_FLAGS("server", FR_TYPE_COMBO_IP_ADDR, 0, linelog_net_t, dst_ipaddr) },
163  { FR_CONF_OFFSET("port", linelog_net_t, port) },
164  { FR_CONF_OFFSET("timeout", linelog_net_t, timeout), .dflt = "1000" },
166 };
167 
168 static const conf_parser_t tcp_config[] = {
169  { FR_CONF_OFFSET_TYPE_FLAGS("server", FR_TYPE_COMBO_IP_ADDR, 0, linelog_net_t, dst_ipaddr) },
170  { FR_CONF_OFFSET("port", linelog_net_t, port) },
171  { FR_CONF_OFFSET("timeout", linelog_net_t, timeout), .dflt = "1000" },
173 };
174 
175 static const conf_parser_t module_config[] = {
176  { FR_CONF_OFFSET_FLAGS("destination", CONF_FLAG_REQUIRED, rlm_linelog_t, log_dst_str) },
177 
178  { FR_CONF_OFFSET("delimiter", rlm_linelog_t, delimiter), .dflt = "\n" },
179 
180  /*
181  * Log destinations
182  */
183  { FR_CONF_POINTER("file", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) file_config },
184  { FR_CONF_POINTER("syslog", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) syslog_config },
185  { FR_CONF_POINTER("unix", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) unix_config },
188 
189  /*
190  * Deprecated config items
191  */
192  { FR_CONF_DEPRECATED("permissions", rlm_linelog_t, file.permissions) },
193  { FR_CONF_DEPRECATED("group", rlm_linelog_t, file.group_str) },
194 
195  { FR_CONF_DEPRECATED("syslog_facility", rlm_linelog_t, syslog.facility) },
196  { FR_CONF_DEPRECATED("syslog_severity", rlm_linelog_t, syslog.severity) },
198 };
199 
200 typedef struct {
201  tmpl_t *log_src; //!< Source of log messages.
202 
203  fr_value_box_t *log_ref; //!< Path to a #CONF_PAIR (to use as the source of
204  ///< log messages).
205 
206  fr_value_box_t *log_head; //!< Header to add to each new log file.
207 
208  fr_value_box_t *filename; //!< File name, if output is to a file.
210 
213  .env = (call_env_parser_t[]) {
215  { FR_CALL_ENV_OFFSET("reference",FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, linelog_call_env_t, log_ref), .pair.escape.func = linelog_escape_func },
216  { FR_CALL_ENV_OFFSET("header", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, linelog_call_env_t, log_head), .pair.escape.func = linelog_escape_func },
218  ((call_env_parser_t[]) {
220  .pair.func = call_env_filename_parse },
222  })) },
224  }
225 };
226 
229  .env = (call_env_parser_t[]) {
230  { FR_CALL_ENV_OFFSET("header", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, linelog_call_env_t, log_head), .pair.escape.func = linelog_escape_func },
232  ((call_env_parser_t[]) {
234  .pair.func = call_env_filename_parse },
236  })) },
238  }
239 };
240 
242 {
243  if (shutdown(conn->sockfd, SHUT_RDWR) < 0) DEBUG3("Shutdown failed: %s", fr_syserror(errno));
244  if (close(conn->sockfd) < 0) DEBUG3("Closing socket failed: %s", fr_syserror(errno));
245 
246  return 0;
247 }
248 
249 static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
250 {
251  rlm_linelog_t const *inst = talloc_get_type_abort(instance, rlm_linelog_t);
252  linelog_conn_t *conn;
253  int sockfd = -1;
254 
255  switch (inst->log_dst) {
256  case LINELOG_DST_UNIX:
257  DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path);
258  sockfd = fr_socket_client_unix(inst->unix_sock.path, true);
259  if (sockfd < 0) {
260  PERROR("Failed opening UNIX socket");
261  return NULL;
262  }
263  break;
264 
265  case LINELOG_DST_TCP:
266  DEBUG2("Opening TCP connection to %pV:%u", fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port);
267 
268  sockfd = fr_socket_client_tcp(NULL, NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true);
269  if (sockfd < 0) {
270  PERROR("Failed opening TCP socket");
271  return NULL;
272  }
273  break;
274 
275  case LINELOG_DST_UDP:
276  DEBUG2("Opening UDP connection to %pV:%u", fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port);
277 
278  sockfd = fr_socket_client_udp(NULL, NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true);
279  if (sockfd < 0) {
280  PERROR("Failed opening UDP socket");
281  return NULL;
282  }
283  break;
284 
285  /*
286  * Are not connection oriented destinations
287  */
288  case LINELOG_DST_INVALID:
289  case LINELOG_DST_FILE:
290  case LINELOG_DST_REQUEST:
291  case LINELOG_DST_SYSLOG:
292  case LINELOG_DST_STDOUT:
293  case LINELOG_DST_STDERR:
294  fr_assert(0);
295  return NULL;
296  }
297 
298  if (errno == EINPROGRESS) {
300  DEBUG2("Waiting for connection to complete...");
301  } else {
302  DEBUG2("Blocking until connection complete...");
303  }
305  PERROR("Failed connecting to log destination");
306  close(sockfd);
307  return NULL;
308  }
309  }
310  DEBUG2("Connection successful");
311 
312  /*
313  * Set blocking operation as we have no timeout set
314  */
315  if (!fr_time_delta_ispos(timeout) && (fr_blocking(sockfd) < 0)) {
316  ERROR("Failed setting nonblock flag on fd");
317  close(sockfd);
318  return NULL;
319  }
320 
321  conn = talloc_zero(ctx, linelog_conn_t);
322  conn->sockfd = sockfd;
323  talloc_set_destructor(conn, _mod_conn_free);
324 
325  return conn;
326 }
327 
328 /** Escape unprintable characters
329  *
330  * - Newline is escaped as ``\\n``.
331  * - Return is escaped as ``\\r``.
332  * - All other unprintables are escaped as @verbatim <oct><oct><oct> @endverbatim.
333  *
334  * @param vb Value box to escape.
335  * @param uctx unused.
336  */
337 /*
338  * Escape unprintable characters.
339  */
340 static int linelog_escape_func(fr_value_box_t *vb, UNUSED void *uctx)
341 {
342  char *escaped;
343 
344  if (vb->vb_length == 0) return 0;
345 
346  MEM(escaped = fr_asprint(vb, vb->vb_strvalue, vb->vb_length, 0));
347  fr_value_box_strdup_shallow_replace(vb, escaped, talloc_strlen(escaped));
348 
349  return 0;
350 }
351 
352 static void linelog_hexdump(request_t *request, struct iovec *vector_p, size_t vector_len, char const *msg)
353 {
354  fr_dbuff_t *agg;
355 
356  FR_DBUFF_TALLOC_THREAD_LOCAL(&agg, 1024, SIZE_MAX);
357  fr_concatv(agg, vector_p, vector_len);
358 
359  RHEXDUMP3(fr_dbuff_start(agg), fr_dbuff_used(agg), "%s", msg);
360 }
361 
362 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)
363 {
364  int ret = 0;
365  linelog_conn_t *conn;
367 
368  /*
369  * Reserve a handle, write out the data, close the handle
370  */
371  switch (inst->log_dst) {
372  case LINELOG_DST_FILE:
373  {
374  int fd = -1;
375  char const *path;
376  off_t offset;
377  char *p;
378 
379  if (!call_env->filename) {
380  RERROR("Missing filename");
381  return -1;
382  }
383 
384  path = call_env->filename->vb_strvalue;
385 
386  /* check path and eventually create subdirs */
387  p = strrchr(path, '/');
388  if (p) {
389  *p = '\0';
390  if (fr_mkdir(NULL, path, -1, 0700, NULL, NULL) < 0) {
391  RERROR("Failed to create directory %pV: %s", call_env->filename, fr_syserror(errno));
392  return -1;
393  }
394  *p = '/';
395  }
396 
397  fd = exfile_open(inst->file.ef, path, inst->file.permissions, &offset);
398  if (fd < 0) {
399  RERROR("Failed to open %pV: %s", call_env->filename, fr_syserror(errno));
400  return -1;
401  }
402 
403  if (inst->file.group_str && (chown(path, -1, inst->file.group) == -1)) {
404  RPWARN("Unable to change system group of \"%pV\": %s", call_env->filename, fr_strerror());
405  }
406 
407  /*
408  * If a header format is defined and we are at the beginning
409  * of the file then expand the format and write it out before
410  * writing the actual log entries.
411  */
412  if (call_env->log_head && (offset == 0)) {
413  struct iovec head_vector_s[2];
414  size_t head_vector_len;
415 
416  memcpy(&head_vector_s[0].iov_base, &call_env->log_head->vb_strvalue, sizeof(head_vector_s[0].iov_base));
417  head_vector_s[0].iov_len = call_env->log_head->vb_length;
418 
419  if (!with_delim) {
420  head_vector_len = 1;
421  } else {
422  memcpy(&head_vector_s[1].iov_base, &(inst->delimiter),
423  sizeof(head_vector_s[1].iov_base));
424  head_vector_s[1].iov_len = inst->delimiter_len;
425  head_vector_len = 2;
426  }
427 
428  if (RDEBUG_ENABLED3) linelog_hexdump(request, head_vector_s, head_vector_len, "linelog header");
429 
430  if (writev(fd, &head_vector_s[0], head_vector_len) < 0) {
431  write_fail:
432  RERROR("Failed writing to \"%pV\": %s", call_env->filename, fr_syserror(errno));
433  exfile_close(inst->file.ef, fd);
434 
435  /* Assert on the extra fatal errors */
436  fr_assert((errno != EINVAL) && (errno != EFAULT));
437 
438  return -1;
439  }
440  }
441 
442  if (RDEBUG_ENABLED3) linelog_hexdump(request, vector_p, vector_len, "linelog data");
443 
444  ret = writev(fd, vector_p, vector_len);
445  if (ret < 0) goto write_fail;
446 
447  exfile_close(inst->file.ef, fd);
448  }
449  break;
450 
451  case LINELOG_DST_REQUEST:
452  {
453  size_t i;
454 
455  ret = 0;
456  for (i = 0; i < vector_len; i++) {
457  RINFO("%.*s", (int)vector_p[i].iov_len, (char *)vector_p[i].iov_base);
458  ret += vector_p[i].iov_len;
459  }
460  }
461  break;
462 
463  case LINELOG_DST_UNIX:
464  if (fr_time_delta_ispos(inst->unix_sock.timeout)) {
465  timeout = inst->unix_sock.timeout;
466  }
467  goto do_write;
468 
469  case LINELOG_DST_UDP:
470  if (fr_time_delta_ispos(inst->udp.timeout)) {
471  timeout = inst->udp.timeout;
472  }
473  goto do_write;
474 
475  case LINELOG_DST_TCP:
476  {
477  int i, num;
478  if (fr_time_delta_ispos(inst->tcp.timeout)) {
479  timeout = inst->tcp.timeout;
480  }
481 
482  do_write:
483  num = fr_pool_state(inst->pool)->num;
484  conn = fr_pool_connection_get(inst->pool, request);
485  if (!conn) return -1;
486 
487  for (i = num; i >= 0; i--) {
488  ssize_t wrote;
489  char discard[64];
490 
491  if (RDEBUG_ENABLED3) linelog_hexdump(request, vector_p, vector_len, "linelog data");
492  wrote = fr_writev(conn->sockfd, vector_p, vector_len, timeout);
493  if (wrote < 0) switch (errno) {
494  /* Errors that indicate we should reconnect */
495  case EDESTADDRREQ:
496  case EPIPE:
497  case EBADF:
498  case ECONNRESET:
499  case ENETDOWN:
500  case ENETUNREACH:
501  case EADDRNOTAVAIL: /* Which is OSX for outbound interface is down? */
502  RWARN("Failed writing to socket: %s. Will reconnect and try again...",
503  fr_syserror(errno));
504  conn = fr_pool_connection_reconnect(inst->pool, request, conn);
505  if (!conn) {
506  ret = -1;
507  goto done;
508  }
509  continue;
510 
511  /* Assert on the extra fatal errors */
512  case EINVAL:
513  case EFAULT:
514  fr_assert(0);
515  FALL_THROUGH;
516 
517  /* Normal errors that just cause the module to fail */
518  default:
519  RERROR("Failed writing to socket: %s", fr_syserror(errno));
520  ret = -1;
521  goto done;
522  }
523  RDEBUG2("Wrote %zi bytes", wrote);
524  ret = wrote;
525 
526  /* Drain the receive buffer */
527  while (read(conn->sockfd, discard, sizeof(discard)) > 0);
528  break;
529  }
530  done:
531  fr_pool_connection_release(inst->pool, request, conn);
532  }
533  break;
534 
535 #ifdef HAVE_SYSLOG_H
536  case LINELOG_DST_SYSLOG:
537  {
538  size_t i;
539 
540  ret = 0;
541  for (i = 0; i < vector_len; i++) {
542  syslog(inst->syslog.priority, "%.*s", (int)vector_p[i].iov_len, (char *)vector_p[i].iov_base);
543  ret += vector_p[i].iov_len;
544  }
545  }
546  break;
547 #endif
548 
549  case LINELOG_DST_STDOUT:
550  case LINELOG_DST_STDERR:
551  {
552  int fd = inst->log_dst == LINELOG_DST_STDOUT ? STDOUT_FILENO : STDERR_FILENO;
553  if ((ret = writev(fd, vector_p, vector_len)) < 0) {
554  RERROR("Failed writing to \"%s\": %s",
556  fr_syserror(errno));
557  }
558  }
559  break;
560 
561  case LINELOG_DST_INVALID:
562  fr_assert(0);
563  ret = -1;
564  break;
565  }
566 
567  return ret;
568 }
569 
570 static xlat_action_t linelog_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
571  xlat_ctx_t const *xctx, request_t *request,
572  fr_value_box_list_t *args)
573 {
575  linelog_call_env_t const *call_env = talloc_get_type_abort(xctx->env_data, linelog_call_env_t);
576 
577  struct iovec vector[2];
578  size_t i = 0;
579  bool with_delim;
580  fr_value_box_t *msg, *wrote;
581  ssize_t slen;
582 
583  XLAT_ARGS(args, &msg);
584 
585  vector[i].iov_base = UNCONST(char *, msg->vb_strvalue);
586  vector[i].iov_len = msg->vb_length;
587  i++;
588 
589  with_delim = (inst->log_dst != LINELOG_DST_SYSLOG) && (inst->delimiter_len > 0);
590  if (with_delim) {
591  memcpy(&vector[i].iov_base, &(inst->delimiter), sizeof(vector[i].iov_base));
592  vector[i].iov_len = inst->delimiter_len;
593  i++;
594  }
595  slen = linelog_write(inst, call_env, request, vector, i, with_delim);
596  if (slen < 0) return XLAT_ACTION_FAIL;
597 
598  MEM(wrote = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL));
599  wrote->vb_size = (size_t)slen;
600 
601  fr_dcursor_insert(out, wrote);
602 
603  return XLAT_ACTION_DONE;
604 }
605 
606 typedef struct {
607  fr_value_box_list_t expanded; //!< The result of expanding the fmt tmpl
608  bool with_delim; //!< Whether to add a delimiter
610 
611 static unlang_action_t CC_HINT(nonnull) mod_do_linelog_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
612 {
614  linelog_call_env_t const *call_env = talloc_get_type_abort(mctx->env_data, linelog_call_env_t);
615  rlm_linelog_rctx_t *rctx = talloc_get_type_abort(mctx->rctx, rlm_linelog_rctx_t);
616  struct iovec *vector;
617  struct iovec *vector_p;
618  size_t vector_len;
619 
620  vector_len = fr_value_box_list_num_elements(&rctx->expanded);
621  if (vector_len == 0) {
622  RDEBUG2("No data to write");
624  }
625 
626  /*
627  * Add extra space for the delimiter
628  */
629  if (rctx->with_delim) vector_len *= 2;
630 
631  MEM(vector = vector_p = talloc_array(rctx, struct iovec, vector_len));
632  fr_value_box_list_foreach(&rctx->expanded, vb) {
633  switch(vb->type) {
634  default:
635  if (unlikely(fr_value_box_cast_in_place(rctx, vb, FR_TYPE_STRING, vb->enumv) < 0)) {
636  REDEBUG("Failed casting value to string");
638  }
639  FALL_THROUGH;
640 
641  case FR_TYPE_STRING:
642  vector_p->iov_base = UNCONST(char *, vb->vb_strvalue);
643  vector_p->iov_len = vb->vb_length;
644  vector_p++;
645  break;
646 
647  case FR_TYPE_OCTETS:
648  vector_p->iov_base = UNCONST(char *, vb->vb_octets);
649  vector_p->iov_len = vb->vb_length;
650  vector_p++;
651  break;
652  }
653 
654  /*
655  * Don't add the delim for the last element
656  */
657  if (rctx->with_delim) {
658  memcpy(&vector_p->iov_base, &(inst->delimiter), sizeof(vector_p->iov_base));
659  vector_p->iov_len = inst->delimiter_len;
660  vector_p++;
661  }
662  }
663 
664  RETURN_MODULE_RCODE(linelog_write(inst, call_env, request, vector, vector_len, rctx->with_delim) < 0 ? RLM_MODULE_FAIL : RLM_MODULE_OK);
665 }
666 
667 /** Write a linelog message
668  *
669  * Write a log message to syslog or a flat file.
670  *
671  * @param[in] p_result the result of the module call:
672  * - #RLM_MODULE_NOOP if no message to log.
673  * - #RLM_MODULE_FAIL if we failed writing the message.
674  * - #RLM_MODULE_OK on success.
675  * @param[in] mctx module calling context.
676  * @param[in] request The current request.
677  */
678 static unlang_action_t CC_HINT(nonnull) mod_do_linelog(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
679 {
681  linelog_call_env_t const *call_env = talloc_get_type_abort(mctx->env_data, linelog_call_env_t);
682  CONF_SECTION *conf = mctx->inst->conf;
683 
684  char buff[4096];
685  char *p = buff;
686  tmpl_t *empty, *vpt = NULL, *vpt_p = NULL;
687  ssize_t slen;
688  bool with_delim;
689 
690  TALLOC_CTX *frame_ctx = unlang_interpret_frame_talloc_ctx(request);
691 
692  if (!call_env->log_src && !call_env->log_ref) {
693  cf_log_err(conf, "A 'format', or 'reference' configuration item must be set to call this module");
695  }
696 
697  buff[0] = '.'; /* force to be in current section (by default) */
698  buff[1] = '\0';
699  buff[2] = '\0';
700 
701  /*
702  * Expand log_ref to a config path, using the module
703  * configuration section as the root.
704  */
705  if (call_env->log_ref) {
706  CONF_ITEM *ci;
707  CONF_PAIR *cp;
708  char const *tmpl_str;
709 
710  memcpy(buff + 1, call_env->log_ref->vb_strvalue, call_env->log_ref->vb_length);
711  buff[call_env->log_ref->vb_length + 1] = '\0';
712 
713  if (buff[1] == '.') p++;
714 
715  /*
716  * Don't go back up.
717  */
718  if (buff[2] == '.') {
719  REDEBUG("Invalid path \"%s\"", p);
721  }
722 
723  ci = cf_reference_item(NULL, inst->cs, p);
724  if (!ci) {
725  RDEBUG2("Path \"%s\" doesn't exist", p);
726  goto default_msg;
727  }
728 
729  if (!cf_item_is_pair(ci)) {
730  REDEBUG("Path \"%s\" resolves to a section (should be a pair)", p);
732  }
733 
734  cp = cf_item_to_pair(ci);
735  tmpl_str = cf_pair_value(cp);
736  if (!tmpl_str || (tmpl_str[0] == '\0')) {
737  RDEBUG2("Path \"%s\" resolves to an empty config pair", p);
738  empty = talloc(frame_ctx, tmpl_t);
739  vpt_p = tmpl_init_shallow(empty, TMPL_TYPE_DATA, T_DOUBLE_QUOTED_STRING, "", 0, NULL);
740  fr_value_box_init_null(&empty->data.literal);
741  fr_value_box_strdup_shallow(&empty->data.literal, NULL, "", false);
742  goto build_vector;
743  }
744 
745  /*
746  * Alloc a template from the value of the CONF_PAIR
747  * using request as the context (which will hopefully avoid an alloc).
748  */
749  slen = tmpl_afrom_substr(frame_ctx, &vpt,
750  &FR_SBUFF_IN(tmpl_str, talloc_array_length(tmpl_str) - 1),
752  NULL,
753  &(tmpl_rules_t){
754  .attr = {
755  .list_def = request_attr_request,
756  .dict_def = request->dict,
757  .allow_unknown = true,
758  .allow_unresolved = false,
759  },
760  .xlat = {
761  .runtime_el = unlang_interpret_event_list(request),
762  },
763  .at_runtime = true
764  });
765  if (!vpt) {
766  REMARKER(tmpl_str, -slen, "%s", fr_strerror());
768  }
769  if (tmpl_resolve(vpt, NULL) < 0) {
770  RPERROR("Runtime resolution of tmpl failed");
771  talloc_free(vpt);
773  }
774  vpt_p = vpt;
775  } else {
776  default_msg:
777  /*
778  * Use the default format string
779  */
780  if (!call_env->log_src) {
781  RDEBUG2("No default message configured");
783  }
784  /*
785  * Use the pre-parsed format template
786  */
787  RDEBUG2("Using default message");
788  vpt_p = call_env->log_src;
789  }
790 
791 build_vector:
792  with_delim = (inst->log_dst != LINELOG_DST_SYSLOG) && (inst->delimiter_len > 0);
793 
794  /*
795  * Log all the things!
796  */
797  switch (vpt_p->type) {
798  case TMPL_TYPE_ATTR:
799  {
800  #define VECTOR_INCREMENT 20
801  fr_dcursor_t cursor;
803  fr_pair_t *vp;
804  int alloced = VECTOR_INCREMENT, i;
805  struct iovec *vector = NULL, *vector_p;
806  size_t vector_len;
807  rlm_rcode_t rcode = RLM_MODULE_OK;
808 
809  MEM(vector = talloc_array(frame_ctx, struct iovec, alloced));
810  for (vp = tmpl_dcursor_init(NULL, NULL, &cc, &cursor, request, vpt_p), i = 0;
811  vp;
812  vp = fr_dcursor_next(&cursor), i++) {
813  /* need extra for line terminator */
814  if ((with_delim && ((i + 1) >= alloced)) ||
815  (i >= alloced)) {
816  alloced += VECTOR_INCREMENT;
817  MEM(vector = talloc_realloc(frame_ctx, vector, struct iovec, alloced));
818  }
819 
820  switch (vp->vp_type) {
821  case FR_TYPE_OCTETS:
822  case FR_TYPE_STRING:
823  vector[i].iov_len = vp->vp_length;
824  vector[i].iov_base = vp->vp_ptr;
825  break;
826 
827  default:
828  vector[i].iov_len = fr_value_box_aprint(vector, &p, &vp->data, NULL);
829  vector[i].iov_base = p;
830  break;
831  }
832 
833  /*
834  * Add the line delimiter string
835  */
836  if (with_delim) {
837  i++;
838  memcpy(&vector[i].iov_base, &(inst->delimiter), sizeof(vector[i].iov_base));
839  vector[i].iov_len = inst->delimiter_len;
840  }
841  }
842  tmpl_dcursor_clear(&cc);
843  vector_p = vector;
844  vector_len = i;
845 
846  if (vector_len == 0) {
847  RDEBUG2("No data to write");
848  rcode = RLM_MODULE_NOOP;
849  } else {
850  rcode = linelog_write(inst, call_env, request, vector_p, vector_len, with_delim) < 0 ? RLM_MODULE_FAIL : RLM_MODULE_OK;
851  }
852 
853  talloc_free(vpt);
854  talloc_free(vector);
855 
856  RETURN_MODULE_RCODE(rcode);
857  }
858 
859  /*
860  * Log a format string. We need to yield as this might contain asynchronous expansions.
861  */
862  default:
863  {
864  rlm_linelog_rctx_t *rctx;
865 
866  MEM(rctx = talloc(frame_ctx, rlm_linelog_rctx_t));
867  fr_value_box_list_init(&rctx->expanded);
868  rctx->with_delim = with_delim;
869 
870  return unlang_module_yield_to_tmpl(rctx, &rctx->expanded, request, vpt_p, NULL, mod_do_linelog_resume, NULL, 0, rctx);
871  }
872  }
873 }
874 
875 /*
876  * Custom call env parser for filenames - sets the correct escaping function
877  */
878 static int call_env_filename_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci,
879  UNUSED char const *section_name1, UNUSED char const *section_name2,
880  void const *data, UNUSED call_env_parser_t const *rule)
881 {
883  tmpl_t *parsed;
884  CONF_PAIR const *to_parse = cf_item_to_pair(ci);
885  tmpl_rules_t our_rules;
886 
887  /*
888  * If we're not logging to a file destination, do nothing
889  */
891 
892  our_rules = *t_rules;
893  our_rules.escape.func = (inst->file.escape) ? rad_filename_box_escape : rad_filename_box_make_safe;
894  our_rules.escape.safe_for = (inst->file.escape) ? (fr_value_box_safe_for_t)rad_filename_box_escape :
896  our_rules.escape.mode = TMPL_ESCAPE_PRE_CONCAT;
897  our_rules.literals_safe_for = our_rules.escape.safe_for;
898 
899  if (tmpl_afrom_substr(ctx, &parsed,
900  &FR_SBUFF_IN(cf_pair_value(to_parse), talloc_array_length(cf_pair_value(to_parse)) - 1),
901  cf_pair_value_quote(to_parse), NULL, &our_rules) < 0) return -1;
902 
903  *(void **)out = parsed;
904  return 0;
905 }
906 
907 static int mod_detach(module_detach_ctx_t const *mctx)
908 {
909  rlm_linelog_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_linelog_t);
910 
911  fr_pool_free(inst->pool);
912 
913  return 0;
914 }
915 
916 /*
917  * Instantiate the module.
918  */
919 static int mod_instantiate(module_inst_ctx_t const *mctx)
920 {
921  rlm_linelog_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_linelog_t);
922  CONF_SECTION *cs, *conf = mctx->inst->conf;
923  char prefix[100];
924 
926  if (inst->log_dst == LINELOG_DST_INVALID) {
927  cf_log_err(conf, "Invalid log destination \"%s\"", inst->log_dst_str);
928  return -1;
929  }
930 
931  snprintf(prefix, sizeof(prefix), "rlm_linelog (%s)", mctx->inst->name);
932 
933  /*
934  * Setup the logging destination
935  */
936  switch (inst->log_dst) {
937  case LINELOG_DST_FILE:
938  {
939  cs = cf_section_find(conf, "file", CF_IDENT_ANY);
940  if (!cs) {
941  no_filename:
942  cf_log_err(conf, "No value provided for 'file.filename'");
943  return -1;
944  }
945  if (!cf_pair_find(cs, "filename")) goto no_filename;
946 
947  inst->file.ef = module_rlm_exfile_init(inst, conf, 256, fr_time_delta_from_sec(30), true, NULL, NULL);
948  if (!inst->file.ef) {
949  cf_log_err(conf, "Failed creating log file context");
950  return -1;
951  }
952 
953  if (inst->file.group_str) {
954  char *endptr;
955 
956  inst->file.group = strtol(inst->file.group_str, &endptr, 10);
957  if (*endptr != '\0') {
958  if (fr_perm_gid_from_str(inst, &(inst->file.group), inst->file.group_str) < 0) {
959  cf_log_err(conf, "Unable to find system group \"%s\"",
960  inst->file.group_str);
961  return -1;
962  }
963  }
964  }
965  }
966  break;
967 
968  case LINELOG_DST_SYSLOG:
969  {
970  int num;
971 
972 #ifndef HAVE_SYSLOG_H
973  cf_log_err(conf, "Syslog output is not supported on this system");
974  return -1;
975 #else
976  if (inst->syslog.facility) {
977  num = fr_table_value_by_str(syslog_facility_table, inst->syslog.facility, -1);
978  if (num < 0) {
979  cf_log_err(conf, "Invalid syslog facility \"%s\"", inst->syslog.facility);
980  return -1;
981  }
982  inst->syslog.priority |= num;
983  }
984 
985  num = fr_table_value_by_str(syslog_severity_table, inst->syslog.severity, -1);
986  if (num < 0) {
987  cf_log_err(conf, "Invalid syslog severity \"%s\"", inst->syslog.severity);
988  return -1;
989  }
990  inst->syslog.priority |= num;
991 #endif
992  }
993  break;
994 
995  case LINELOG_DST_UNIX:
996 #ifndef HAVE_SYS_UN_H
997  cf_log_err(conf, "Unix sockets are not supported on this system");
998  return -1;
999 #else
1001  inst, mod_conn_create, NULL, prefix, NULL, NULL);
1002  if (!inst->pool) return -1;
1003 #endif
1004  break;
1005 
1006  case LINELOG_DST_UDP:
1008  inst, mod_conn_create, NULL, prefix, NULL, NULL);
1009  if (!inst->pool) return -1;
1010  break;
1011 
1012  case LINELOG_DST_TCP:
1014  inst, mod_conn_create, NULL, prefix, NULL, NULL);
1015  if (!inst->pool) return -1;
1016  break;
1017 
1018  case LINELOG_DST_REQUEST:
1019  case LINELOG_DST_STDOUT:
1020  case LINELOG_DST_STDERR:
1021  break;
1022 
1023  case LINELOG_DST_INVALID:
1024  fr_assert(0);
1025  break;
1026  }
1027 
1028  inst->delimiter_len = talloc_array_length(inst->delimiter) - 1;
1029  inst->cs = conf;
1030 
1031  return 0;
1032 }
1033 
1034 static int mod_bootstrap(module_inst_ctx_t const *mctx)
1035 {
1036  rlm_linelog_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_linelog_t);
1037  xlat_t *xlat;
1038 
1039  static xlat_arg_parser_t const linelog_xlat_args[] = {
1040  { .required = true, .concat = true, .type = FR_TYPE_STRING },
1042  };
1043 
1045  xlat_func_mono_set(xlat, linelog_xlat_args);
1047 
1048  return 0;
1049 }
1050 
1051 /*
1052  * Externally visible module definition.
1053  */
1054 extern module_rlm_t rlm_linelog;
1056  .common = {
1057  .magic = MODULE_MAGIC_INIT,
1058  .name = "linelog",
1059  .inst_size = sizeof(rlm_linelog_t),
1060  .config = module_config,
1061  .bootstrap = mod_bootstrap,
1063  .detach = mod_detach
1064  },
1065  .method_names = (module_method_name_t[]){
1066  { .name1 = CF_IDENT_ANY, .name2 = CF_IDENT_ANY, .method = mod_do_linelog, .method_env = &linelog_method_env },
1068  }
1069 };
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:165
#define RCSID(id)
Definition: build.h:444
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define CALL_ENV_TERMINATOR
Definition: call_env.h:212
#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:216
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
Definition: call_env.h:74
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
Definition: call_env.h:83
@ CALL_ENV_FLAG_NONE
Definition: call_env.h:72
#define FR_CALL_ENV_SUBSECTION(_name, _ident2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
Definition: call_env.h:378
#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:316
#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:365
Per method call config.
Definition: call_env.h:171
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition: cf_file.c:3206
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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:385
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition: cf_parse.h:310
#define FR_CONF_OFFSET_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_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:412
@ 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
Common header for all CONF_* types.
Definition: cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition: cf_util.c:597
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:629
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:970
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:1356
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1511
fr_token_t cf_pair_value_quote(CONF_PAIR const *pair)
Return the value (rhs) quoting of a pair.
Definition: cf_util.c:1555
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define CF_IDENT_ANY
Definition: cf_util.h:78
#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:762
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:893
#define FR_DBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
Create a function local and thread local extensible dbuff.
Definition: dbuff.h:551
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
Definition: dcursor.h:434
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:287
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static int sockfd
Definition: dhcpclient.c:56
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
char const *_CONST name
Instance name.
Definition: dl_module.h:163
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
dl_module_inst_t const * inst
Definition: dl_module.h:87
int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, off_t *offset)
Open a new log file, or maybe an existing one.
Definition: exfile.c:505
int exfile_close(exfile_t *ef, int fd)
Close the log file.
Definition: exfile.c:561
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:200
IPv4/6 prefix.
Definition: merged_model.c:272
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition: interpret.c:1745
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition: interpret.c:1384
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:142
fr_table_num_sorted_t const syslog_facility_table[]
Syslog facility table.
Definition: log.c:57
#define PERROR(_fmt,...)
Definition: log.h:228
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition: log.h:335
#define RWARN(fmt,...)
Definition: log.h:297
#define RERROR(fmt,...)
Definition: log.h:298
#define RPWARN(fmt,...)
Definition: log.h:301
#define RPERROR(fmt,...)
Definition: log.h:302
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition: log.h:498
#define RINFO(fmt,...)
Definition: log.h:296
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition: log.h:705
int rad_filename_box_escape(fr_value_box_t *vb, UNUSED void *uxtc)
Definition: util.c:290
int rad_filename_box_make_safe(fr_value_box_t *vb, UNUSED void *uxtc)
Definition: util.c:165
talloc_free(reap)
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ 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
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
long long int off_t
Definition: merged_model.c:22
unsigned long int size_t
Definition: merged_model.c:25
int fr_blocking(UNUSED int fd)
Definition: misc.c:289
void * env_data
Per call environment data.
Definition: module_ctx.h:44
void * rctx
Resume ctx that a module previously set.
Definition: module_ctx.h:45
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
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
Specifies a module method identifier.
Definition: module_method.c:36
exfile_t * module_rlm_exfile_init(TALLOC_CTX *ctx, CONF_SECTION *module, uint32_t max_entries, fr_time_delta_t max_idle, bool locking, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific exfile handle.
Definition: module_rlm.c:92
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:248
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition: perm.c:345
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
Definition: pool.c:1405
void fr_pool_free(fr_pool_t *pool)
Delete a connection pool.
Definition: pool.c:1327
fr_pool_state_t const * fr_pool_state(fr_pool_t *pool)
Get the number of connections currently in the pool.
Definition: pool.c:1171
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
Definition: pool.c:1390
void * fr_pool_connection_reconnect(fr_pool_t *pool, request_t *request, void *conn)
Reconnect a suspected inviable connection.
Definition: pool.c:1498
A connection pool.
Definition: pool.c:85
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:430
static const conf_parser_t config[]
Definition: base.c:188
static bool done
Definition: radclient.c:80
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#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_RCODE(_rcode)
Definition: rcode.h:64
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
fr_dict_attr_t const * request_attr_request
Definition: request.c:41
static int mod_detach(module_detach_ctx_t const *mctx)
Definition: rlm_linelog.c:907
static int call_env_filename_parse(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED char const *section_name1, UNUSED char const *section_name2, void const *data, UNUSED call_env_parser_t const *rule)
Definition: rlm_linelog.c:878
module_rlm_t rlm_linelog
Definition: rlm_linelog.c:1055
tmpl_t * log_src
Source of log messages.
Definition: rlm_linelog.c:201
static const conf_parser_t file_config[]
Definition: rlm_linelog.c:143
static const call_env_method_t linelog_xlat_method_env
Definition: rlm_linelog.c:227
linelog_net_t tcp
TCP server.
Definition: rlm_linelog.c:132
linelog_net_t udp
UDP server.
Definition: rlm_linelog.c:133
static const conf_parser_t syslog_config[]
Definition: rlm_linelog.c:150
fr_ipaddr_t src_ipaddr
Send requests from a given src_ipaddr.
Definition: rlm_linelog.c:97
size_t delimiter_len
Length of line termination string.
Definition: rlm_linelog.c:108
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)
Definition: rlm_linelog.c:570
static int _mod_conn_free(linelog_conn_t *conn)
Definition: rlm_linelog.c:241
static unlang_action_t mod_do_linelog(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Write a linelog message.
Definition: rlm_linelog.c:678
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: rlm_linelog.c:1034
fr_value_box_list_t expanded
The result of expanding the fmt tmpl.
Definition: rlm_linelog.c:607
#define VECTOR_INCREMENT
fr_ipaddr_t dst_ipaddr
Network server.
Definition: rlm_linelog.c:96
static const conf_parser_t udp_config[]
Definition: rlm_linelog.c:161
static void linelog_hexdump(request_t *request, struct iovec *vector_p, size_t vector_len, char const *msg)
Definition: rlm_linelog.c:352
fr_pool_t * pool
Connection pool instance.
Definition: rlm_linelog.c:105
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)
Definition: rlm_linelog.c:362
fr_time_delta_t timeout
How long to wait for read/write operations.
Definition: rlm_linelog.c:99
int sockfd
File descriptor associated with socket.
Definition: rlm_linelog.c:139
linefr_log_dst_t
Definition: rlm_linelog.c:70
@ LINELOG_DST_FILE
Log to a file.
Definition: rlm_linelog.c:72
@ LINELOG_DST_STDERR
Log to stderr.
Definition: rlm_linelog.c:79
@ LINELOG_DST_UNIX
Log via Unix socket.
Definition: rlm_linelog.c:75
@ LINELOG_DST_STDOUT
Log to stdout.
Definition: rlm_linelog.c:78
@ LINELOG_DST_TCP
Log via TCP.
Definition: rlm_linelog.c:77
@ LINELOG_DST_INVALID
Definition: rlm_linelog.c:71
@ LINELOG_DST_REQUEST
Log to the request->log.
Definition: rlm_linelog.c:73
@ LINELOG_DST_UDP
Log via UDP.
Definition: rlm_linelog.c:76
@ LINELOG_DST_SYSLOG
Log to syslog.
Definition: rlm_linelog.c:74
fr_value_box_t * log_head
Header to add to each new log file.
Definition: rlm_linelog.c:206
static void * mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
Definition: rlm_linelog.c:249
static unlang_action_t mod_do_linelog_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_linelog.c:611
uint16_t port
Network port.
Definition: rlm_linelog.c:98
static fr_table_num_sorted_t const linefr_log_dst_table[]
Definition: rlm_linelog.c:82
static const call_env_method_t linelog_method_env
Definition: rlm_linelog.c:211
CONF_SECTION * cs
CONF_SECTION to use as the root for #log_ref lookups.
Definition: rlm_linelog.c:135
static const conf_parser_t module_config[]
Definition: rlm_linelog.c:175
static int linelog_escape_func(fr_value_box_t *vb, UNUSED void *uctx)
Escape unprintable characters.
Definition: rlm_linelog.c:340
fr_value_box_t * log_ref
Path to a CONF_PAIR (to use as the source of log messages).
Definition: rlm_linelog.c:203
static const conf_parser_t unix_config[]
Definition: rlm_linelog.c:156
fr_value_box_t * filename
File name, if output is to a file.
Definition: rlm_linelog.c:208
static size_t linefr_log_dst_table_len
Definition: rlm_linelog.c:93
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_linelog.c:919
char const * delimiter
Line termination string (usually ).
Definition: rlm_linelog.c:107
bool with_delim
Whether to add a delimiter.
Definition: rlm_linelog.c:608
static const conf_parser_t tcp_config[]
Definition: rlm_linelog.c:168
linefr_log_dst_t log_dst
Logging destination.
Definition: rlm_linelog.c:110
char const * log_dst_str
Logging destination string.
Definition: rlm_linelog.c:111
linelog module instance
Definition: rlm_linelog.c:104
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
#define FR_SBUFF_IN(_start, _len_or_end)
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
static fr_slen_t vpt
Definition: tmpl.h:1260
tmpl_escape_t escape
How escaping should be handled during evaluation.
Definition: tmpl.h:358
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:356
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
Definition: tmpl.h:146
@ TMPL_TYPE_DATA
Value in native boxed format.
Definition: tmpl.h:142
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.
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:341
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: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_wait_for_connect(int sockfd, fr_time_delta_t timeout)
Wait for a socket to be connected, with an optional timeout.
Definition: socket.c:803
int fr_socket_client_unix(UNUSED char const *path, UNUSED bool async)
Definition: socket.c:564
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:496
RETURN_MODULE_FAIL
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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:134
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition: table.h:253
An element in a lexicographically sorted array of name to num mappings.
Definition: table.h:45
#define talloc_get_type_abort_const
Definition: talloc.h:270
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition: talloc.h:277
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition: time.h:588
#define fr_time_delta_wrap(_time)
Definition: time.h:152
#define fr_time_delta_ispos(_a)
Definition: time.h:288
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.
Definition: tmpl_dcursor.c:419
#define tmpl_dcursor_init(_err, _ctx, _cc, _cursor, _request, _vpt)
Definition: tmpl_dcursor.h:99
Maintains state between cursor calls.
Definition: tmpl_dcursor.h:61
fr_value_box_escape_t func
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
fr_value_box_safe_for_t safe_for
Value to set on boxes which have been escaped by the fr_value_box_escape_t function.
Definition: tmpl_escape.h:83
tmpl_escape_mode_t mode
Whether to apply escape function after concatenation, i.e.
Definition: tmpl_escape.h:86
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
close(uq->fd)
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
Definition: xlat.h:365
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition: xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
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:3521
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:4001
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:3985
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition: value.h:608
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:287
static fr_slen_t data
Definition: value.h:1259
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition: value.h:580
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
Definition: value.h:155
int nonnull(2, 5))
#define fr_value_box_list_foreach(_list_head, _iter)
Definition: value.h:199
static size_t char ** out
Definition: value.h:984
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition: xlat_ctx.h:45
void * env_data
Expanded call env data.
Definition: xlat_ctx.h:46
An xlat calling ctx.
Definition: xlat_ctx.h:42
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:405
int xlat_func_mono_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the argument of an xlat.
Definition: xlat_func.c:392
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.
Definition: xlat_func.c:274