summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/buffer.c24
-rw-r--r--lib/command.c3
-rw-r--r--lib/command.h2
-rw-r--r--lib/csv.c3
-rw-r--r--lib/libfrr.c6
-rw-r--r--lib/link_state.c12
-rw-r--r--lib/network.c3
-rw-r--r--lib/ntop.c14
-rw-r--r--lib/prefix.c3
-rw-r--r--lib/prefix.h32
-rw-r--r--lib/route_types.txt4
-rw-r--r--lib/routemap.h1
-rw-r--r--lib/routemap_cli.c5
-rw-r--r--lib/sockopt.c16
-rw-r--r--lib/stream.c8
-rw-r--r--lib/subdir.am17
-rw-r--r--lib/systemd.c173
-rw-r--r--lib/systemd.h10
-rw-r--r--lib/zclient.c6
19 files changed, 207 insertions, 135 deletions
diff --git a/lib/buffer.c b/lib/buffer.c
index 7929b3709d..41b1adc9fc 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -357,7 +357,8 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
iov_size =
((iov_index > IOV_MAX) ? IOV_MAX : iov_index);
- if ((nbytes = writev(fd, c_iov, iov_size)) < 0) {
+ nbytes = writev(fd, c_iov, iov_size);
+ if (nbytes < 0) {
flog_err(EC_LIB_SOCKET,
"%s: writev to fd %d failed: %s",
__func__, fd, safe_strerror(errno));
@@ -370,7 +371,8 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
}
}
#else /* IOV_MAX */
- if ((nbytes = writev(fd, iov, iov_index)) < 0)
+ nbytes = writev(fd, iov, iov_index);
+ if (nbytes < 0)
flog_err(EC_LIB_SOCKET, "%s: writev to fd %d failed: %s",
__func__, fd, safe_strerror(errno));
#endif /* IOV_MAX */
@@ -472,13 +474,17 @@ buffer_status_t buffer_write(struct buffer *b, int fd, const void *p,
/* Buffer is not empty, so do not attempt to write the new data.
*/
nbytes = 0;
- else if ((nbytes = write(fd, p, size)) < 0) {
- if (ERRNO_IO_RETRY(errno))
- nbytes = 0;
- else {
- flog_err(EC_LIB_SOCKET, "%s: write error on fd %d: %s",
- __func__, fd, safe_strerror(errno));
- return BUFFER_ERROR;
+ else {
+ nbytes = write(fd, p, size);
+ if (nbytes < 0) {
+ if (ERRNO_IO_RETRY(errno))
+ nbytes = 0;
+ else {
+ flog_err(EC_LIB_SOCKET,
+ "%s: write error on fd %d: %s",
+ __func__, fd, safe_strerror(errno));
+ return BUFFER_ERROR;
+ }
}
}
/* Add any remaining data to the buffer. */
diff --git a/lib/command.c b/lib/command.c
index 9dac60599c..fe17c68a8b 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -160,6 +160,9 @@ static bool vty_check_node_for_xpath_decrement(enum node_type target_node,
|| node == BGP_FLOWSPECV6_NODE))
return false;
+ if (target_node == INTERFACE_NODE && node == LINK_PARAMS_NODE)
+ return false;
+
return true;
}
diff --git a/lib/command.h b/lib/command.h
index 13bd61e9fd..2b50bc2374 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -438,6 +438,8 @@ struct cmd_node {
#define BFD_PROFILE_STR "BFD profile.\n"
#define BFD_PROFILE_NAME_STR "BFD profile name.\n"
#define SHARP_STR "Sharp Routing Protocol\n"
+#define OSPF_GR_STR \
+ "OSPF non-stop forwarding (NSF) also known as OSPF Graceful Restart\n"
#define CMD_VNI_RANGE "(1-16777215)"
#define CONF_BACKUP_EXT ".sav"
diff --git a/lib/csv.c b/lib/csv.c
index b48b79792e..05b9dbe39e 100644
--- a/lib/csv.c
+++ b/lib/csv.c
@@ -641,7 +641,8 @@ static int get_memory_usage(pid_t pid)
char *vm;
snprintf(status_child, sizeof(status_child), "/proc/%d/status", pid);
- if ((fd = open(status_child, O_RDONLY)) < 0)
+ fd = open(status_child, O_RDONLY);
+ if (fd < 0)
return -1;
read(fd, buf, 4095);
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 0817182f7a..97dab74d9b 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -44,6 +44,7 @@
#include "frr_pthread.h"
#include "defaults.h"
#include "frrscript.h"
+#include "systemd.h"
DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm));
DEFINE_HOOK(frr_config_pre, (struct thread_master * tm), (tm));
@@ -363,6 +364,11 @@ void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv)
startup_fds |= UINT64_C(0x1) << (uint64_t)i;
}
+
+ /* note this doesn't do anything, it just grabs state, so doing it
+ * early in _preinit is perfect.
+ */
+ systemd_init_env();
}
bool frr_is_startup_fd(int fd)
diff --git a/lib/link_state.c b/lib/link_state.c
index e8a6b89f89..062384aac7 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -538,8 +538,6 @@ struct ls_edge *ls_edge_add(struct ls_ted *ted,
/* Create Edge and add it to the TED */
new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_edge));
- if (!new)
- return NULL;
new->attributes = attributes;
new->key = key;
@@ -804,8 +802,6 @@ struct ls_ted *ls_ted_new(const uint32_t key, const char *name,
struct ls_ted *new;
new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_ted));
- if (new == NULL)
- return new;
/* Set basic information for this ted */
new->key = key;
@@ -1005,8 +1001,6 @@ static struct ls_node *ls_parse_node(struct stream *s)
size_t len;
node = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
- if (node == NULL)
- return NULL;
STREAM_GET(&node->adv, s, sizeof(struct ls_node_id));
STREAM_GETW(s, node->flags);
@@ -1051,8 +1045,6 @@ static struct ls_attributes *ls_parse_attributes(struct stream *s)
size_t len;
attr = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
- if (attr == NULL)
- return NULL;
attr->srlgs = NULL;
STREAM_GET(&attr->adv, s, sizeof(struct ls_node_id));
@@ -1157,8 +1149,6 @@ static struct ls_prefix *ls_parse_prefix(struct stream *s)
size_t len;
ls_pref = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
- if (ls_pref == NULL)
- return NULL;
STREAM_GET(&ls_pref->adv, s, sizeof(struct ls_node_id));
STREAM_GETW(s, ls_pref->flags);
@@ -1193,8 +1183,6 @@ struct ls_message *ls_parse_msg(struct stream *s)
struct ls_message *msg;
msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
- if (msg == NULL)
- return NULL;
/* Read LS Message header */
STREAM_GETC(s, msg->event);
diff --git a/lib/network.c b/lib/network.c
index 411661a5e1..b60ad9a57c 100644
--- a/lib/network.c
+++ b/lib/network.c
@@ -78,7 +78,8 @@ int set_nonblocking(int fd)
/* According to the Single UNIX Spec, the return value for F_GETFL
should
never be negative. */
- if ((flags = fcntl(fd, F_GETFL)) < 0) {
+ flags = fcntl(fd, F_GETFL);
+ if (flags < 0) {
flog_err(EC_LIB_SYSTEM_CALL,
"fcntl(F_GETFL) failed for fd %d: %s", fd,
safe_strerror(errno));
diff --git a/lib/ntop.c b/lib/ntop.c
index ccbf8793d3..1b2dd7a6d1 100644
--- a/lib/ntop.c
+++ b/lib/ntop.c
@@ -40,14 +40,18 @@ static inline void putbyte(uint8_t bytex, char **posx)
bool zero = false;
int byte = bytex, tmp, a, b;
- if ((tmp = byte - 200) >= 0) {
+ tmp = byte - 200;
+ if (tmp >= 0) {
*pos++ = '2';
zero = true;
byte = tmp;
- } else if ((tmp = byte - 100) >= 0) {
- *pos++ = '1';
- zero = true;
- byte = tmp;
+ } else {
+ tmp = byte - 100;
+ if (tmp >= 0) {
+ *pos++ = '1';
+ zero = true;
+ byte = tmp;
+ }
}
/* make sure the compiler knows the value range of "byte" */
diff --git a/lib/prefix.c b/lib/prefix.c
index 1c57715e8f..ef7d2e59da 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1034,7 +1034,8 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
l = strlen(buf);
buf[l++] = '/';
byte = p->prefixlen;
- if ((tmp = p->prefixlen - 100) >= 0) {
+ tmp = p->prefixlen - 100;
+ if (tmp >= 0) {
buf[l++] = '1';
z = true;
byte = tmp;
diff --git a/lib/prefix.h b/lib/prefix.h
index bc4cb7f441..944c94f57f 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -537,20 +537,32 @@ static inline int ipv4_martian(struct in_addr *addr)
return 0;
}
-static inline int is_default_prefix(const struct prefix *p)
+static inline bool is_default_prefix4(const struct prefix_ipv4 *p)
{
- if (!p)
- return 0;
+ return p && p->family == AF_INET && p->prefixlen == 0
+ && p->prefix.s_addr == INADDR_ANY;
+}
- if ((p->family == AF_INET) && (p->u.prefix4.s_addr == INADDR_ANY)
- && (p->prefixlen == 0))
- return 1;
+static inline bool is_default_prefix6(const struct prefix_ipv6 *p)
+{
+ return p && p->family == AF_INET6 && p->prefixlen == 0
+ && memcmp(&p->prefix, &in6addr_any, sizeof(struct in6_addr))
+ == 0;
+}
- if ((p->family == AF_INET6) && (p->prefixlen == 0)
- && (!memcmp(&p->u.prefix6, &in6addr_any, sizeof(struct in6_addr))))
- return 1;
+static inline bool is_default_prefix(const struct prefix *p)
+{
+ if (p == NULL)
+ return false;
+
+ switch (p->family) {
+ case AF_INET:
+ return is_default_prefix4((const struct prefix_ipv4 *)p);
+ case AF_INET6:
+ return is_default_prefix6((const struct prefix_ipv6 *)p);
+ }
- return 0;
+ return false;
}
static inline int is_host_route(const struct prefix *p)
diff --git a/lib/route_types.txt b/lib/route_types.txt
index c48391545d..77639070c9 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -1,4 +1,4 @@
-# Canonical Zserv route types information registry for Quagga.
+# Canonical Zserv route types information registry for FRR.
#
# Used to construct route_types.c and route_types.h
#
@@ -60,7 +60,7 @@ ZEBRA_ROUTE_PIM, pim, pimd, 'P', 0, 0, 0, "PIM", pimd
ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, 1, "EIGRP", eigrpd
ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, 1, "NHRP", nhrpd
# HSLS and OLSR both are AFI independent (so: 1, 1), however
-# we want to disable for them for general Quagga distribution.
+# we want to disable for them for general FRR distribution.
# This at least makes it trivial for users of these protocols
# to 'switch on' redist support (direct numeric entry remaining
# possible).
diff --git a/lib/routemap.h b/lib/routemap.h
index 4a40ec08b9..8af3b2c3c0 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -270,6 +270,7 @@ DECLARE_QOBJ_TYPE(route_map);
/* BGP route-map match conditions */
#define IS_MATCH_LOCAL_PREF(C) \
(strmatch(C, "frr-bgp-route-map:match-local-preference"))
+#define IS_MATCH_ALIAS(C) (strmatch(C, "frr-bgp-route-map:match-alias"))
#define IS_MATCH_ORIGIN(C) \
(strmatch(C, "frr-bgp-route-map:match-origin"))
#define IS_MATCH_RPKI(C) (strmatch(C, "frr-bgp-route-map:rpki"))
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index bf982cfa2b..ec9033b3aa 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -634,6 +634,11 @@ void route_map_condition_show(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:local-preference"));
+ } else if (IS_MATCH_ALIAS(condition)) {
+ vty_out(vty, " match alias %s\n",
+ yang_dnode_get_string(
+ dnode,
+ "./rmap-match-condition/frr-bgp-route-map:alias"));
} else if (IS_MATCH_ORIGIN(condition)) {
vty_out(vty, " match origin %s\n",
yang_dnode_get_string(
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 98bfda5079..150736e00c 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -379,14 +379,14 @@ static int setsockopt_ipv4_ifindex(int sock, ifindex_t val)
int ret;
#if defined(IP_PKTINFO)
- if ((ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)))
- < 0)
+ ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
+ if (ret < 0)
flog_err(EC_LIB_SOCKET,
"Can't set IP_PKTINFO option for fd %d to %d: %s",
sock, val, safe_strerror(errno));
#elif defined(IP_RECVIF)
- if ((ret = setsockopt(sock, IPPROTO_IP, IP_RECVIF, &val, sizeof(val)))
- < 0)
+ ret = setsockopt(sock, IPPROTO_IP, IP_RECVIF, &val, sizeof(val));
+ if (ret < 0)
flog_err(EC_LIB_SOCKET,
"Can't set IP_RECVIF option for fd %d to %d: %s", sock,
val, safe_strerror(errno));
@@ -639,12 +639,8 @@ int sockopt_tcp_signature_ext(int sock, union sockunion *su, uint16_t prefixlen,
#endif /* GNU_LINUX */
- if ((ret = setsockopt(sock, IPPROTO_TCP, optname, &md5sig,
- sizeof(md5sig)))
- < 0) {
- /* ENOENT is harmless. It is returned when we clear a password
- for which
- one was not previously set. */
+ ret = setsockopt(sock, IPPROTO_TCP, optname, &md5sig, sizeof(md5sig));
+ if (ret < 0) {
if (ENOENT == errno)
ret = 0;
else
diff --git a/lib/stream.c b/lib/stream.c
index 904ee73b10..1557500c60 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -1097,7 +1097,8 @@ ssize_t stream_read_try(struct stream *s, int fd, size_t size)
return -1;
}
- if ((nbytes = read(fd, s->data + s->endp, size)) >= 0) {
+ nbytes = read(fd, s->data + s->endp, size);
+ if (nbytes >= 0) {
s->endp += nbytes;
return nbytes;
}
@@ -1126,9 +1127,8 @@ ssize_t stream_recvfrom(struct stream *s, int fd, size_t size, int flags,
return -1;
}
- if ((nbytes = recvfrom(fd, s->data + s->endp, size, flags, from,
- fromlen))
- >= 0) {
+ nbytes = recvfrom(fd, s->data + s->endp, size, flags, from, fromlen);
+ if (nbytes >= 0) {
s->endp += nbytes;
return nbytes;
}
diff --git a/lib/subdir.am b/lib/subdir.am
index 90301d800a..714af43238 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -2,7 +2,7 @@
# libfrr
#
lib_LTLIBRARIES += lib/libfrr.la
-lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version
+lib_libfrr_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0 -Xlinker -e_libfrr_version
lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS) $(LUA_LIB) $(UST_LIBS) $(LIBM)
lib_libfrr_la_SOURCES = \
@@ -322,7 +322,7 @@ lib_LTLIBRARIES += lib/libfrrsnmp.la
endif
lib_libfrrsnmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
-lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
+lib_libfrrsnmp_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0
lib_libfrrsnmp_la_LIBADD = $(SNMP_LIBS)
lib_libfrrsnmp_la_SOURCES = \
lib/agentx.c \
@@ -338,7 +338,7 @@ pkginclude_HEADERS += lib/resolver.h
endif
lib_libfrrcares_la_CFLAGS = $(AM_CFLAGS) $(CARES_CFLAGS)
-lib_libfrrcares_la_LDFLAGS = -version-info 0:0:0
+lib_libfrrcares_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0
lib_libfrrcares_la_LIBADD = $(CARES_LIBS)
lib_libfrrcares_la_SOURCES = \
lib/resolver.c \
@@ -353,7 +353,7 @@ pkginclude_HEADERS += lib/frr_zmq.h
endif
lib_libfrrzmq_la_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
-lib_libfrrzmq_la_LDFLAGS = -version-info 0:0:0
+lib_libfrrzmq_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0
lib_libfrrzmq_la_LIBADD = $(ZEROMQ_LIBS)
lib_libfrrzmq_la_SOURCES = \
lib/frr_zmq.c \
@@ -367,7 +367,7 @@ module_LTLIBRARIES += lib/confd.la
endif
lib_confd_la_CFLAGS = $(AM_CFLAGS) $(CONFD_CFLAGS)
-lib_confd_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+lib_confd_la_LDFLAGS = $(MODULE_LDFLAGS)
lib_confd_la_LIBADD = lib/libfrr.la $(CONFD_LIBS)
lib_confd_la_SOURCES = lib/northbound_confd.c
@@ -379,7 +379,7 @@ module_LTLIBRARIES += lib/sysrepo.la
endif
lib_sysrepo_la_CFLAGS = $(AM_CFLAGS) $(SYSREPO_CFLAGS)
-lib_sysrepo_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+lib_sysrepo_la_LDFLAGS = $(MODULE_LDFLAGS)
lib_sysrepo_la_LIBADD = lib/libfrr.la $(SYSREPO_LIBS)
lib_sysrepo_la_SOURCES = lib/northbound_sysrepo.c
@@ -391,7 +391,7 @@ module_LTLIBRARIES += lib/grpc.la
endif
lib_grpc_la_CXXFLAGS = $(WERROR) $(GRPC_CFLAGS)
-lib_grpc_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+lib_grpc_la_LDFLAGS = $(MODULE_LDFLAGS)
lib_grpc_la_LIBADD = lib/libfrr.la grpc/libfrrgrpc_pb.la $(GRPC_LIBS)
lib_grpc_la_SOURCES = lib/northbound_grpc.cpp
@@ -419,7 +419,8 @@ lib_grammar_sandbox_LDADD = \
lib_clippy_CPPFLAGS = $(CPPFLAGS_BASE) -D_GNU_SOURCE -DBUILDING_CLIPPY
lib_clippy_CFLAGS = $(AC_CFLAGS) $(PYTHON_CFLAGS)
lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS) -lelf
-lib_clippy_LDFLAGS = -export-dynamic
+# no $(SAN_FLAGS) here
+lib_clippy_LDFLAGS = -export-dynamic $(AC_LDFLAGS) $(AC_LDFLAGS_EXEC)
lib_clippy_SOURCES = \
lib/jhash.c \
lib/clippy.c \
diff --git a/lib/systemd.c b/lib/systemd.c
index c5cc3aa447..2238dc9f3d 100644
--- a/lib/systemd.c
+++ b/lib/systemd.c
@@ -20,68 +20,56 @@
*/
#include <zebra.h>
+#include <sys/un.h>
#include "thread.h"
#include "systemd.h"
+#include "lib_errors.h"
-#if defined HAVE_SYSTEMD
-#include <systemd/sd-daemon.h>
-#endif
+/* these are cleared from env so they don't "leak" into things we fork(),
+ * particularly for watchfrr starting individual daemons
+ *
+ * watchdog_pid is currently not used since watchfrr starts forking.
+ * (TODO: handle that better, somehow?)
+ */
+static pid_t watchdog_pid = -1;
+static intmax_t watchdog_msec;
+
+/* not used yet, but can trigger auto-switch to journald logging */
+bool sd_stdout_is_journal;
+bool sd_stderr_is_journal;
+
+static char *notify_socket;
-/*
- * Wrapper this silliness if we
- * don't have systemd
+/* talk to whatever entity claims to be systemd ;)
+ *
+ * refer to sd_notify docs for messages systemd accepts over this socket.
+ * This function should be functionally equivalent to sd_notify().
*/
static void systemd_send_information(const char *info)
{
-#if defined HAVE_SYSTEMD
- sd_notify(0, info);
-#else
- return;
-#endif
-}
+ int sock;
+ struct sockaddr_un sun;
-/*
- * A return of 0 means that we are not watchdoged
- */
-static int systemd_get_watchdog_time(int the_process)
-{
-#if defined HAVE_SYSTEMD
- uint64_t usec;
- char *watchdog = NULL;
- int ret;
-
- ret = sd_watchdog_enabled(0, &usec);
-
- /*
- * If return is 0 -> we don't want watchdog
- * if return is < 0, some sort of failure occurred
- */
- if (ret < 0)
- return 0;
-
- /*
- * systemd can return that this process
- * is not the expected sender of the watchdog timer
- * If we set the_process = 0 then we expect to
- * be able to send the watchdog to systemd
- * irrelevant of the pid of this process.
- */
- if (ret == 0 && the_process)
- return 0;
-
- if (ret == 0 && !the_process) {
- watchdog = getenv("WATCHDOG_USEC");
- if (!watchdog)
- return 0;
-
- usec = atol(watchdog);
- }
+ if (!notify_socket)
+ return;
+
+ sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0)
+ return;
+
+ sun.sun_family = AF_UNIX;
+ strlcpy(sun.sun_path, notify_socket, sizeof(sun.sun_path));
- return (usec / 1000000) / 3;
-#else
- return 0;
-#endif
+ /* linux abstract unix socket namespace */
+ if (sun.sun_path[0] == '@')
+ sun.sun_path[0] = '\0';
+
+ /* nothing we can do if this errors out... */
+ (void)sendto(sock, info, strlen(info), 0, (struct sockaddr *)&sun,
+ sizeof(sun));
+
+ close(sock);
}
void systemd_send_stopping(void)
@@ -90,34 +78,27 @@ void systemd_send_stopping(void)
systemd_send_information("STOPPING=1");
}
-/*
- * How many seconds should we wait between watchdog sends
- */
-static int wsecs = 0;
static struct thread_master *systemd_master = NULL;
static int systemd_send_watchdog(struct thread *t)
{
systemd_send_information("WATCHDOG=1");
- thread_add_timer(systemd_master, systemd_send_watchdog, NULL, wsecs,
- NULL);
-
+ assert(watchdog_msec > 0);
+ thread_add_timer_msec(systemd_master, systemd_send_watchdog, NULL,
+ watchdog_msec, NULL);
return 1;
}
-void systemd_send_started(struct thread_master *m, int the_process)
+void systemd_send_started(struct thread_master *m)
{
assert(m != NULL);
- wsecs = systemd_get_watchdog_time(the_process);
systemd_master = m;
systemd_send_information("READY=1");
- if (wsecs != 0) {
- systemd_send_information("WATCHDOG=1");
- thread_add_timer(m, systemd_send_watchdog, m, wsecs, NULL);
- }
+ if (watchdog_msec > 0)
+ systemd_send_watchdog(NULL);
}
void systemd_send_status(const char *status)
@@ -127,3 +108,65 @@ void systemd_send_status(const char *status)
snprintf(buffer, sizeof(buffer), "STATUS=%s", status);
systemd_send_information(buffer);
}
+
+static intmax_t getenv_int(const char *varname, intmax_t dflt)
+{
+ char *val, *err;
+ intmax_t intval;
+
+ val = getenv(varname);
+ if (!val)
+ return dflt;
+
+ intval = strtoimax(val, &err, 0);
+ if (*err || !*val)
+ return dflt;
+ return intval;
+}
+
+void systemd_init_env(void)
+{
+ char *tmp;
+ uintmax_t dev, ino;
+ int len;
+ struct stat st;
+
+ notify_socket = getenv("NOTIFY_SOCKET");
+
+ /* no point in setting up watchdog w/o notify socket */
+ if (notify_socket) {
+ intmax_t watchdog_usec;
+
+ watchdog_pid = getenv_int("WATCHDOG_PID", -1);
+ if (watchdog_pid <= 0)
+ watchdog_pid = -1;
+
+ /* note this is the deadline, hence the divide by 3 */
+ watchdog_usec = getenv_int("WATCHDOG_USEC", 0);
+ if (watchdog_usec >= 3000)
+ watchdog_msec = watchdog_usec / 3000;
+ else {
+ if (watchdog_usec != 0)
+ flog_err(
+ EC_LIB_UNAVAILABLE,
+ "systemd expects a %jd microsecond watchdog timer, but FRR only supports millisecond resolution!",
+ watchdog_usec);
+ watchdog_msec = 0;
+ }
+ }
+
+ tmp = getenv("JOURNAL_STREAM");
+ if (tmp && sscanf(tmp, "%ju:%ju%n", &dev, &ino, &len) == 2
+ && (size_t)len == strlen(tmp)) {
+ if (fstat(1, &st) == 0 && st.st_dev == (dev_t)dev
+ && st.st_ino == (ino_t)ino)
+ sd_stdout_is_journal = true;
+ if (fstat(2, &st) == 0 && st.st_dev == (dev_t)dev
+ && st.st_ino == (ino_t)ino)
+ sd_stderr_is_journal = true;
+ }
+
+ /* these should *not* be passed to any other process we start */
+ unsetenv("WATCHDOG_PID");
+ unsetenv("WATCHDOG_USEC");
+}
diff --git a/lib/systemd.h b/lib/systemd.h
index d9885c5d9c..1933f4f688 100644
--- a/lib/systemd.h
+++ b/lib/systemd.h
@@ -28,9 +28,6 @@ extern "C" {
*
* Design point is that if systemd is not being used on this system
* then these functions becomes a no-op.
- *
- * To turn on systemd compilation, use --enable-systemd on
- * configure run.
*/
void systemd_send_stopping(void);
@@ -39,13 +36,18 @@ void systemd_send_stopping(void);
* the_process - Should we send watchdog if we are not the requested
* process?
*/
-void systemd_send_started(struct thread_master *master, int the_process);
+void systemd_send_started(struct thread_master *master);
/*
* status - A status string to send to systemd
*/
void systemd_send_status(const char *status);
+/*
+ * grab startup state from env vars
+ */
+void systemd_init_env(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/zclient.c b/lib/zclient.c
index 1b4ac080cd..0815e77d4e 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1537,7 +1537,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_OPAQUE)) {
STREAM_GETW(s, api->opaque.length);
- assert(api->opaque.length < ZAPI_MESSAGE_OPAQUE_LENGTH);
+ assert(api->opaque.length <= ZAPI_MESSAGE_OPAQUE_LENGTH);
STREAM_GET(api->opaque.data, s, api->opaque.length);
}
@@ -3812,7 +3812,8 @@ static int zclient_read(struct thread *thread)
zclient->t_read = NULL;
/* Read zebra header (if we don't have it already). */
- if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE) {
+ already = stream_get_endp(zclient->ibuf);
+ if (already < ZEBRA_HEADER_SIZE) {
ssize_t nbyte;
if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
ZEBRA_HEADER_SIZE - already))
@@ -3825,7 +3826,6 @@ static int zclient_read(struct thread *thread)
return zclient_failed(zclient);
}
if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) {
- /* Try again later. */
zclient_event(ZCLIENT_READ, zclient);
return 0;
}