back to topotato report
topotato coverage report
Current view: top level - lib - zlog.h (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 6 12 50.0 %
Date: 2023-11-16 17:19:14 Functions: 1 4 25.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: ISC
       2             : /*
       3             :  * Copyright (c) 2015-19  David Lamparter, for NetDEF, Inc.
       4             :  */
       5             : 
       6             : #ifndef _FRR_ZLOG_H
       7             : #define _FRR_ZLOG_H
       8             : 
       9             : #include <stdarg.h>
      10             : #include <stdbool.h>
      11             : #include <stdint.h>
      12             : #include <string.h>
      13             : #include <syslog.h>
      14             : #include <unistd.h>
      15             : #include <sys/uio.h>
      16             : 
      17             : #include <assert.h>
      18             : 
      19             : #include "atomlist.h"
      20             : #include "frrcu.h"
      21             : #include "memory.h"
      22             : #include "hook.h"
      23             : #include "printfrr.h"
      24             : 
      25             : #ifdef __cplusplus
      26             : extern "C" {
      27             : #endif
      28             : 
      29             : DECLARE_MGROUP(LOG);
      30             : 
      31             : extern char zlog_prefix[];
      32             : extern size_t zlog_prefixsz;
      33             : extern int zlog_tmpdirfd;
      34             : extern int zlog_instance;
      35             : extern const char *zlog_progname;
      36             : 
      37             : struct xref_logmsg {
      38             :         struct xref xref;
      39             : 
      40             :         const char *fmtstring;
      41             :         uint32_t priority;
      42             :         uint32_t ec;
      43             :         const char *args;
      44             : };
      45             : 
      46             : /* whether flag was added in config mode or enable mode */
      47             : #define LOGMSG_FLAG_EPHEMERAL   (1 << 0)
      48             : #define LOGMSG_FLAG_PERSISTENT  (1 << 1)
      49             : 
      50             : struct xrefdata_logmsg {
      51             :         struct xrefdata xrefdata;
      52             : 
      53             :         uint8_t fl_print_bt;
      54             : };
      55             : 
      56             : /* These functions are set up to write to stdout/stderr without explicit
      57             :  * initialization and/or before config load.  There is no need to call e.g.
      58             :  * fprintf(stderr, ...) just because it's "too early" at startup.  Depending
      59             :  * on context, it may still be the right thing to use fprintf though -- try to
      60             :  * determine whether something is a log message or something else.
      61             :  */
      62             : 
      63             : extern void vzlogx(const struct xref_logmsg *xref, int prio, const char *fmt,
      64             :                    va_list ap) PRINTFRR(3, 0);
      65             : #define vzlog(prio, ...) vzlogx(NULL, prio, __VA_ARGS__)
      66             : 
      67             : PRINTFRR(2, 3)
      68           0 : static inline void zlog(int prio, const char *fmt, ...)
      69             : {
      70           0 :         va_list ap;
      71             : 
      72           0 :         va_start(ap, fmt);
      73           0 :         vzlog(prio, fmt, ap);
      74           0 :         va_end(ap);
      75           0 : }
      76             : 
      77             : PRINTFRR(2, 3)
      78         690 : static inline void zlog_ref(const struct xref_logmsg *xref,
      79             :                             const char *fmt, ...)
      80             : {
      81         690 :         va_list ap;
      82             : 
      83         690 :         va_start(ap, fmt);
      84         690 :         vzlogx(xref, xref->priority, fmt, ap);
      85         690 :         va_end(ap);
      86         690 : }
      87             : 
      88             : #define _zlog_ecref(ec_, prio, msg, ...)                                       \
      89             :         do {                                                                   \
      90             :                 static struct xrefdata_logmsg _xrefdata = {                    \
      91             :                         .xrefdata =                                            \
      92             :                                 {                                              \
      93             :                                         .xref = NULL,                          \
      94             :                                         .uid = {},                             \
      95             :                                         .hashstr = (msg),                      \
      96             :                                         .hashu32 = {(prio), (ec_)},            \
      97             :                                 },                                             \
      98             :                 };                                                             \
      99             :                 static const struct xref_logmsg _xref __attribute__(           \
     100             :                         (used)) = {                                            \
     101             :                         .xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata.xrefdata,   \
     102             :                                           __func__),                           \
     103             :                         .fmtstring = (msg),                                    \
     104             :                         .priority = (prio),                                    \
     105             :                         .ec = (ec_),                                           \
     106             :                         .args = (#__VA_ARGS__),                                \
     107             :                 };                                                             \
     108             :                 XREF_LINK(_xref.xref);                                         \
     109             :                 zlog_ref(&_xref, (msg), ##__VA_ARGS__);                        \
     110             :         } while (0)
     111             : 
     112             : #define zlog_err(...)    _zlog_ecref(0, LOG_ERR, __VA_ARGS__)
     113             : #define zlog_warn(...)   _zlog_ecref(0, LOG_WARNING, __VA_ARGS__)
     114             : #define zlog_info(...)   _zlog_ecref(0, LOG_INFO, __VA_ARGS__)
     115             : #define zlog_notice(...) _zlog_ecref(0, LOG_NOTICE, __VA_ARGS__)
     116             : #define zlog_debug(...)  _zlog_ecref(0, LOG_DEBUG, __VA_ARGS__)
     117             : 
     118             : #define flog_err(ferr_id, format, ...)                                         \
     119             :         _zlog_ecref(ferr_id, LOG_ERR, format, ## __VA_ARGS__)
     120             : #define flog_warn(ferr_id, format, ...)                                        \
     121             :         _zlog_ecref(ferr_id, LOG_WARNING, format, ## __VA_ARGS__)
     122             : 
     123             : #define flog_err_sys(ferr_id, format, ...)                                     \
     124             :         _zlog_ecref(ferr_id, LOG_ERR, format, ## __VA_ARGS__)
     125             : 
     126             : extern void zlog_sigsafe(const char *text, size_t len);
     127             : 
     128             : /* extra priority value to disable a target without deleting it */
     129             : #define ZLOG_DISABLED   (LOG_EMERG-1)
     130             : 
     131             : /* zlog_msg encapsulates a particular logging call from somewhere in the code.
     132             :  * The same struct is passed around to all zlog_targets.
     133             :  *
     134             :  * This is used to defer formatting the log message until it is actually
     135             :  * requested by one of the targets.  If none of the targets needs the message
     136             :  * formatted, the formatting call is avoided entirely.
     137             :  *
     138             :  * This struct is opaque / private to the core zlog code.  Logging targets
     139             :  * should use zlog_msg_* functions to get text / timestamps / ... for a
     140             :  * message.
     141             :  */
     142             : 
     143             : struct zlog_msg;
     144             : 
     145             : extern int zlog_msg_prio(struct zlog_msg *msg);
     146             : extern const struct xref_logmsg *zlog_msg_xref(struct zlog_msg *msg);
     147             : 
     148             : /* text is NOT \0 terminated; instead there is a \n after textlen since the
     149             :  * logging targets would jump extra hoops otherwise for a single byte.  (the
     150             :  * \n is not included in textlen)
     151             :  *
     152             :  * calling this with NULL textlen is likely wrong.
     153             :  * use  "%.*s", (int)textlen, text  when passing to printf-like functions
     154             :  */
     155             : extern const char *zlog_msg_text(struct zlog_msg *msg, size_t *textlen);
     156             : 
     157             : extern void zlog_msg_args(struct zlog_msg *msg, size_t *hdrlen,
     158             :                           size_t *n_argpos, const struct fmt_outpos **argpos);
     159             : 
     160             : /* timestamp formatting control flags */
     161             : 
     162             : /* sub-second digit count */
     163             : #define ZLOG_TS_PREC            0xfU
     164             : 
     165             : /* 8601:   0000-00-00T00:00:00Z      (if used with ZLOG_TS_UTC)
     166             :  *         0000-00-00T00:00:00+00:00 (otherwise)
     167             :  * Legacy: 0000/00/00 00:00:00       (no TZ indicated!)
     168             :  */
     169             : #define ZLOG_TS_ISO8601         (1 << 8)
     170             : #define ZLOG_TS_LEGACY          (1 << 9)
     171             : 
     172             : /* default is local time zone */
     173             : #define ZLOG_TS_UTC             (1 << 10)
     174             : 
     175             : struct timespec;
     176             : 
     177             : extern size_t zlog_msg_ts(struct zlog_msg *msg, struct fbuf *out,
     178             :                           uint32_t flags);
     179             : extern void zlog_msg_tsraw(struct zlog_msg *msg, struct timespec *ts);
     180             : 
     181             : /* "mmm dd hh:mm:ss" for RFC3164 syslog.  Only ZLOG_TS_UTC for flags. */
     182             : extern size_t zlog_msg_ts_3164(struct zlog_msg *msg, struct fbuf *out,
     183             :                                uint32_t flags);
     184             : 
     185             : /* currently just returns the current PID/TID since we never write another
     186             :  * thread's messages
     187             :  */
     188             : extern void zlog_msg_pid(struct zlog_msg *msg, intmax_t *pid, intmax_t *tid);
     189             : 
     190             : /* This list & struct implements the actual logging targets.  It is accessed
     191             :  * lock-free from all threads, and thus MUST only be changed atomically, i.e.
     192             :  * RCU.
     193             :  *
     194             :  * Since there's no atomic replace, the replacement action is an add followed
     195             :  * by a delete.  This means that during logging config changes, log messages
     196             :  * may be duplicated in the log target that is being changed.  The old entry
     197             :  * being changed MUST also at the very least not crash or do other stupid
     198             :  * things.
     199             :  *
     200             :  * This list and struct are NOT related to config.  Logging config is kept
     201             :  * separately, and results in creating appropriate zlog_target(s) to realize
     202             :  * the config.  Log targets may also be created from varying sources, e.g.
     203             :  * command line options, or VTY commands ("log monitor").
     204             :  *
     205             :  * struct zlog_target is intended to be embedded into a larger structure that
     206             :  * contains additional field for the specific logging target, e.g. an fd or
     207             :  * additional options.  It MUST be the first field in that larger struct.
     208             :  */
     209             : 
     210             : PREDECL_ATOMLIST(zlog_targets);
     211             : struct zlog_target {
     212             :         struct zlog_targets_item head;
     213             : 
     214             :         int prio_min;
     215             : 
     216             :         void (*logfn)(struct zlog_target *zt, struct zlog_msg *msg[],
     217             :                       size_t nmsgs);
     218             : 
     219             :         /* for crash handlers, set to NULL if log target can't write crash logs
     220             :          * without possibly deadlocking (AS-Safe)
     221             :          *
     222             :          * text is not \0 terminated & split up into lines (e.g. no \n)
     223             :          */
     224             :         void (*logfn_sigsafe)(struct zlog_target *zt, const char *text,
     225             :                               size_t len);
     226             : 
     227             :         struct rcu_head rcu_head;
     228             : };
     229             : 
     230             : /* make a copy for RCUpdating.  oldzt may be NULL to allocate a fresh one. */
     231             : extern struct zlog_target *zlog_target_clone(struct memtype *mt,
     232             :                                              struct zlog_target *oldzt,
     233             :                                              size_t size);
     234             : 
     235             : /* update the zlog_targets list;  both oldzt and newzt may be NULL.  You
     236             :  * still need to zlog_target_free() the old target afterwards if it wasn't
     237             :  * NULL.
     238             :  *
     239             :  * Returns oldzt so you can zlog_target_free(zlog_target_replace(old, new));
     240             :  * (Some log targets may need extra cleanup inbetween, but remember the old
     241             :  * target MUST remain functional until the end of the current RCU cycle.)
     242             :  */
     243             : extern struct zlog_target *zlog_target_replace(struct zlog_target *oldzt,
     244             :                                                struct zlog_target *newzt);
     245             : 
     246             : /* Mostly for symmetry for zlog_target_clone(), just rcu_free() internally. */
     247             : #define zlog_target_free(mt, zt) \
     248             :         rcu_free(mt, zt, rcu_head)
     249             : 
     250             : extern void zlog_init(const char *progname, const char *protoname,
     251             :                       unsigned short instance, uid_t uid, gid_t gid);
     252             : DECLARE_HOOK(zlog_init, (const char *progname, const char *protoname,
     253             :                          unsigned short instance, uid_t uid, gid_t gid),
     254             :                         (progname, protoname, instance, uid, gid));
     255             : 
     256             : extern void zlog_fini(void);
     257             : DECLARE_KOOH(zlog_fini, (), ());
     258             : 
     259             : extern void zlog_set_prefix_ec(bool enable);
     260             : extern bool zlog_get_prefix_ec(void);
     261             : extern void zlog_set_prefix_xid(bool enable);
     262             : extern bool zlog_get_prefix_xid(void);
     263             : 
     264             : /* for tools & test programs, i.e. anything not a daemon.
     265             :  * (no cleanup needed at exit)
     266             :  */
     267             : extern void zlog_aux_init(const char *prefix, int prio_min);
     268             : DECLARE_HOOK(zlog_aux_init, (const char *prefix, int prio_min),
     269             :                             (prefix, prio_min));
     270             : 
     271             : extern void zlog_startup_end(void);
     272             : 
     273             : extern void zlog_tls_buffer_init(void);
     274             : extern void zlog_tls_buffer_flush(void);
     275             : extern void zlog_tls_buffer_fini(void);
     276             : 
     277             : /* Enable or disable 'immediate' output - default is to buffer messages. */
     278             : extern void zlog_set_immediate(bool set_p);
     279             : 
     280             : extern const char *zlog_priority_str(int priority);
     281             : 
     282             : #ifdef __cplusplus
     283             : }
     284             : #endif
     285             : 
     286             : #endif /* _FRR_ZLOG_H */

Generated by: LCOV version v1.16-topotato