diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/buffer.c | 24 | ||||
| -rw-r--r-- | lib/command.c | 6 | ||||
| -rw-r--r-- | lib/compiler.h | 23 | ||||
| -rw-r--r-- | lib/csv.c | 3 | ||||
| -rw-r--r-- | lib/frrlua.c | 100 | ||||
| -rw-r--r-- | lib/frrlua.h | 21 | ||||
| -rw-r--r-- | lib/frrscript.c | 18 | ||||
| -rw-r--r-- | lib/frrscript.h | 76 | ||||
| -rw-r--r-- | lib/libfrr.c | 6 | ||||
| -rw-r--r-- | lib/link_state.c | 12 | ||||
| -rw-r--r-- | lib/network.c | 3 | ||||
| -rw-r--r-- | lib/ntop.c | 14 | ||||
| -rw-r--r-- | lib/prefix.c | 3 | ||||
| -rw-r--r-- | lib/sockopt.c | 16 | ||||
| -rw-r--r-- | lib/sockunion.c | 3 | ||||
| -rw-r--r-- | lib/sockunion.h | 1 | ||||
| -rw-r--r-- | lib/stream.c | 8 | ||||
| -rw-r--r-- | lib/systemd.c | 173 | ||||
| -rw-r--r-- | lib/systemd.h | 10 | ||||
| -rw-r--r-- | lib/zclient.c | 6 |
20 files changed, 362 insertions, 164 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 560d4a09f8..9dac60599c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -2428,14 +2428,16 @@ DEFUN(script, struct prefix p; (void)str2prefix("1.2.3.4/24", &p); - struct frrscript *fs = frrscript_load(argv[1]->arg, NULL); if (fs == NULL) { vty_out(vty, "Script '/etc/frr/scripts/%s.lua' not found\n", argv[1]->arg); } else { - int ret = frrscript_call(fs, NULL); + int ret = frrscript_call(fs, ("p", &p)); + char buf[40]; + prefix2str(&p, buf, sizeof(buf)); + vty_out(vty, "p: %s\n", buf); vty_out(vty, "Script result: %d\n", ret); } diff --git a/lib/compiler.h b/lib/compiler.h index 970ed297fc..bf443906eb 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -173,6 +173,29 @@ extern "C" { #define MACRO_REPEAT(NAME, ...) \ MACRO_VARIANT(_MACRO_REPEAT, ##__VA_ARGS__)(NAME, ##__VA_ARGS__) +/* per-arglist repeat macro, use like this: + * #define foo(...) MAP_LISTS(F, ##__VA_ARGS__) + * where F is a n-ary function where n is the number of args in each arglist. + * e.g.: MAP_LISTS(f, (a, b), (c, d)) + * expands to: f(a, b); f(c, d) + */ + +#define ESC(...) __VA_ARGS__ +#define MAP_LISTS(M, ...) \ + _CONCAT(_MAP_LISTS_, PP_NARG(__VA_ARGS__))(M, ##__VA_ARGS__) +#define _MAP_LISTS_0(M) +#define _MAP_LISTS_1(M, _1) ESC(M _1) +#define _MAP_LISTS_2(M, _1, _2) ESC(M _1; M _2) +#define _MAP_LISTS_3(M, _1, _2, _3) ESC(M _1; M _2; M _3) +#define _MAP_LISTS_4(M, _1, _2, _3, _4) ESC(M _1; M _2; M _3; M _4) +#define _MAP_LISTS_5(M, _1, _2, _3, _4, _5) ESC(M _1; M _2; M _3; M _4; M _5) +#define _MAP_LISTS_6(M, _1, _2, _3, _4, _5, _6) \ + ESC(M _1; M _2; M _3; M _4; M _5; M _6) +#define _MAP_LISTS_7(M, _1, _2, _3, _4, _5, _6, _7) \ + ESC(M _1; M _2; M _3; M _4; M _5; M _6; M _7) +#define _MAP_LISTS_8(M, _1, _2, _3, _4, _5, _6, _7, _8) \ + ESC(M _1; M _2; M _3; M _4; M _5; M _6; M _7; M _8) + /* * for warnings on macros, put in the macro content like this: * #define MACRO BLA CPP_WARN("MACRO has been deprecated") @@ -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/frrlua.c b/lib/frrlua.c index d8aaa3aa3c..e97e48121c 100644 --- a/lib/frrlua.c +++ b/lib/frrlua.c @@ -52,10 +52,9 @@ int frrlua_table_get_integer(lua_State *L, const char *key) } /* - * Encoders. - * * This section has functions that convert internal FRR datatypes into Lua - * datatypes. + * datatypes: one encoder function and two decoder functions for each type. + * */ void lua_pushprefix(lua_State *L, const struct prefix *prefix) @@ -71,14 +70,19 @@ void lua_pushprefix(lua_State *L, const struct prefix *prefix) lua_setfield(L, -2, "family"); } -void *lua_toprefix(lua_State *L, int idx) +void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix) { - struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix)); - lua_getfield(L, idx, "network"); - (void)str2prefix(lua_tostring(L, -1), p); + (void)str2prefix(lua_tostring(L, -1), prefix); lua_pop(L, 1); + /* pop the table */ + lua_pop(L, 1); +} +void *lua_toprefix(lua_State *L, int idx) +{ + struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix)); + lua_decode_prefix(L, idx, p); return p; } @@ -109,10 +113,8 @@ void lua_pushinterface(lua_State *L, const struct interface *ifp) lua_setfield(L, -2, "linklayer_type"); } -void *lua_tointerface(lua_State *L, int idx) +void lua_decode_interface(lua_State *L, int idx, struct interface *ifp) { - struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface)); - lua_getfield(L, idx, "name"); strlcpy(ifp->name, lua_tostring(L, -1), sizeof(ifp->name)); lua_pop(L, 1); @@ -146,13 +148,21 @@ void *lua_tointerface(lua_State *L, int idx) lua_getfield(L, idx, "linklayer_type"); ifp->ll_type = lua_tointeger(L, -1); lua_pop(L, 1); + /* pop the table */ + lua_pop(L, 1); +} +void *lua_tointerface(lua_State *L, int idx) +{ + struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface)); + lua_decode_interface(L, idx, ifp); return ifp; } void lua_pushinaddr(lua_State *L, const struct in_addr *addr) { char buf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, addr, buf, sizeof(buf)); lua_newtable(L); @@ -162,14 +172,19 @@ void lua_pushinaddr(lua_State *L, const struct in_addr *addr) lua_setfield(L, -2, "string"); } -void *lua_toinaddr(lua_State *L, int idx) +void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *inaddr) { - struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr)); - lua_getfield(L, idx, "value"); inaddr->s_addr = lua_tointeger(L, -1); lua_pop(L, 1); + /* pop the table */ + lua_pop(L, 1); +} +void *lua_toinaddr(lua_State *L, int idx) +{ + struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr)); + lua_decode_inaddr(L, idx, inaddr); return inaddr; } @@ -177,6 +192,7 @@ void *lua_toinaddr(lua_State *L, int idx) void lua_pushin6addr(lua_State *L, const struct in6_addr *addr) { char buf[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, addr, buf, sizeof(buf)); lua_newtable(L); @@ -186,20 +202,26 @@ void lua_pushin6addr(lua_State *L, const struct in6_addr *addr) lua_setfield(L, -2, "string"); } -void *lua_toin6addr(lua_State *L, int idx) +void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *in6addr) { - struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr)); - lua_getfield(L, idx, "string"); inet_pton(AF_INET6, lua_tostring(L, -1), in6addr); lua_pop(L, 1); + /* pop the table */ + lua_pop(L, 1); +} +void *lua_toin6addr(lua_State *L, int idx) +{ + struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr)); + lua_decode_in6addr(L, idx, in6addr); return in6addr; } void lua_pushsockunion(lua_State *L, const union sockunion *su) { char buf[SU_ADDRSTRLEN]; + sockunion2str(su, buf, sizeof(buf)); lua_newtable(L); @@ -210,13 +232,20 @@ void lua_pushsockunion(lua_State *L, const union sockunion *su) lua_setfield(L, -2, "string"); } -void *lua_tosockunion(lua_State *L, int idx) +void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su) { - union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion)); - lua_getfield(L, idx, "string"); str2sockunion(lua_tostring(L, -1), su); + lua_pop(L, 1); + /* pop the table */ + lua_pop(L, 1); +} + +void *lua_tosockunion(lua_State *L, int idx) +{ + union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion)); + lua_decode_sockunion(L, idx, su); return su; } @@ -225,12 +254,17 @@ void lua_pushtimet(lua_State *L, const time_t *time) lua_pushinteger(L, *time); } +void lua_decode_timet(lua_State *L, int idx, time_t *t) +{ + *t = lua_tointeger(L, idx); + lua_pop(L, 1); +} + void *lua_totimet(lua_State *L, int idx) { time_t *t = XCALLOC(MTYPE_TMP, sizeof(time_t)); - *t = lua_tointeger(L, idx); - + lua_decode_timet(L, idx, t); return t; } @@ -239,17 +273,28 @@ void lua_pushintegerp(lua_State *L, const long long *num) lua_pushinteger(L, *num); } -void *lua_tointegerp(lua_State *L, int idx) +void lua_decode_integerp(lua_State *L, int idx, long long *num) { int isnum; - long long *num = XCALLOC(MTYPE_TMP, sizeof(long long)); - *num = lua_tonumberx(L, idx, &isnum); + lua_pop(L, 1); assert(isnum); +} + +void *lua_tointegerp(lua_State *L, int idx) +{ + long long *num = XCALLOC(MTYPE_TMP, sizeof(long long)); + lua_decode_integerp(L, idx, num); return num; } +void lua_decode_stringp(lua_State *L, int idx, char *str) +{ + strlcpy(str, lua_tostring(L, idx), strlen(str) + 1); + lua_pop(L, 1); +} + void *lua_tostringp(lua_State *L, int idx) { char *string = XSTRDUP(MTYPE_TMP, lua_tostring(L, idx)); @@ -258,6 +303,13 @@ void *lua_tostringp(lua_State *L, int idx) } /* + * Decoder for const values, since we cannot modify them. + */ +void lua_decode_noop(lua_State *L, int idx, const void *ptr) +{ +} + +/* * Logging. * * Lua-compatible wrappers for FRR logging functions. diff --git a/lib/frrlua.h b/lib/frrlua.h index 6fb30938b0..c4de82740c 100644 --- a/lib/frrlua.h +++ b/lib/frrlua.h @@ -50,6 +50,8 @@ static inline void lua_pushstring_wrapper(lua_State *L, const char *str) */ void lua_pushprefix(lua_State *L, const struct prefix *prefix); +void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix); + /* * Converts the Lua value at idx to a prefix. * @@ -63,6 +65,8 @@ void *lua_toprefix(lua_State *L, int idx); */ void lua_pushinterface(lua_State *L, const struct interface *ifp); +void lua_decode_interface(lua_State *L, int idx, struct interface *ifp); + /* * Converts the Lua value at idx to an interface. * @@ -77,6 +81,8 @@ void *lua_tointerface(lua_State *L, int idx); */ void lua_pushinaddr(lua_State *L, const struct in_addr *addr); +void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *addr); + /* * Converts the Lua value at idx to an in_addr. * @@ -90,6 +96,8 @@ void *lua_toinaddr(lua_State *L, int idx); */ void lua_pushin6addr(lua_State *L, const struct in6_addr *addr); +void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *addr); + /* * Converts the Lua value at idx to an in6_addr. * @@ -103,6 +111,8 @@ void *lua_toin6addr(lua_State *L, int idx); */ void lua_pushtimet(lua_State *L, const time_t *time); +void lua_decode_timet(lua_State *L, int idx, time_t *time); + /* * Converts the Lua value at idx to a time_t. * @@ -116,6 +126,8 @@ void *lua_totimet(lua_State *L, int idx); */ void lua_pushsockunion(lua_State *L, const union sockunion *su); +void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su); + /* * Converts the Lua value at idx to a sockunion. * @@ -129,6 +141,8 @@ void *lua_tosockunion(lua_State *L, int idx); */ void lua_pushintegerp(lua_State *L, const long long *num); +void lua_decode_integerp(lua_State *L, int idx, long long *num); + /* * Converts the Lua value at idx to an int. * @@ -137,6 +151,8 @@ void lua_pushintegerp(lua_State *L, const long long *num); */ void *lua_tointegerp(lua_State *L, int idx); +void lua_decode_stringp(lua_State *L, int idx, char *str); + /* * Pop string. * @@ -146,6 +162,11 @@ void *lua_tointegerp(lua_State *L, int idx); void *lua_tostringp(lua_State *L, int idx); /* + * No-op decocder + */ +void lua_decode_noop(lua_State *L, int idx, const void *ptr); + +/* * Retrieve an integer from table on the top of the stack. * * key diff --git a/lib/frrscript.c b/lib/frrscript.c index 10d400886d..1a9f3639dd 100644 --- a/lib/frrscript.c +++ b/lib/frrscript.c @@ -104,24 +104,8 @@ static void codec_free(struct codec *c) /* Generic script APIs */ -int frrscript_call(struct frrscript *fs, struct frrscript_env *env) +int _frrscript_call(struct frrscript *fs) { - struct frrscript_codec c = {}; - const void *arg; - const char *bindname; - - /* Encode script arguments */ - for (int i = 0; env && env[i].val != NULL; i++) { - bindname = env[i].name; - c.typename = env[i].typename; - arg = env[i].val; - - struct frrscript_codec *codec = hash_lookup(codec_hash, &c); - assert(codec && "No encoder for type"); - codec->encoder(fs->L, arg); - - lua_setglobal(fs->L, bindname); - } int ret = lua_pcall(fs->L, 0, 0, 0); diff --git a/lib/frrscript.h b/lib/frrscript.h index f4057f531b..8612c602f3 100644 --- a/lib/frrscript.h +++ b/lib/frrscript.h @@ -25,6 +25,7 @@ #include <lua.h> #include "frrlua.h" +#include "../bgpd/bgp_script.h" #ifdef __cplusplus extern "C" { @@ -96,6 +97,56 @@ void frrscript_register_type_codecs(struct frrscript_codec *codecs); */ void frrscript_init(const char *scriptdir); +#define ENCODE_ARGS(name, value) \ + do { \ + ENCODE_ARGS_WITH_STATE(L, value); \ + lua_setglobal(L, name); \ + } while (0) + +#define DECODE_ARGS(name, value) \ + do { \ + lua_getglobal(L, name); \ + DECODE_ARGS_WITH_STATE(L, value); \ + } while (0) + +/* + * Maps the type of value to its encoder/decoder. + * Add new mappings here. + * + * L + * Lua state + * scriptdir + * Directory in which to look for scripts + */ +#define ENCODE_ARGS_WITH_STATE(L, value) \ + _Generic((value), \ +long long * : lua_pushintegerp, \ +struct prefix * : lua_pushprefix, \ +struct interface * : lua_pushinterface, \ +struct in_addr * : lua_pushinaddr, \ +struct in6_addr * : lua_pushin6addr, \ +union sockunion * : lua_pushsockunion, \ +time_t * : lua_pushtimet, \ +char * : lua_pushstring_wrapper, \ +struct attr * : lua_pushattr, \ +struct peer * : lua_pushpeer, \ +const struct prefix * : lua_pushprefix \ +)(L, value) + +#define DECODE_ARGS_WITH_STATE(L, value) \ + _Generic((value), \ +long long * : lua_decode_integerp, \ +struct prefix * : lua_decode_prefix, \ +struct interface * : lua_decode_interface, \ +struct in_addr * : lua_decode_inaddr, \ +struct in6_addr * : lua_decode_in6addr, \ +union sockunion * : lua_decode_sockunion, \ +time_t * : lua_decode_timet, \ +char * : lua_decode_stringp, \ +struct attr * : lua_decode_attr, \ +struct peer * : lua_decode_noop, \ +const struct prefix * : lua_decode_noop \ +)(L, -1, value) /* * Call script. @@ -103,14 +154,31 @@ void frrscript_init(const char *scriptdir); * fs * The script to call; this is obtained from frrscript_load(). * - * env - * The script's environment. Specify this as an array of frrscript_env. - * * Returns: * 0 if the script ran successfully, nonzero otherwise. */ -int frrscript_call(struct frrscript *fs, struct frrscript_env *env); +int _frrscript_call(struct frrscript *fs); +/* + * Wrapper for call script. Maps values passed in to their encoder + * and decoder types. + * + * fs + * The script to call; this is obtained from frrscript_load(). + * + * Returns: + * 0 if the script ran successfully, nonzero otherwise. + */ +#define frrscript_call(fs, ...) \ + ({ \ + lua_State *L = fs->L; \ + MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ + int ret = _frrscript_call(fs); \ + if (ret == 0) { \ + MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ + } \ + ret; \ + }) /* * Get result from finished script. 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/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/sockunion.c b/lib/sockunion.c index e6340a1743..c7af458e9e 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -606,8 +606,7 @@ static void __attribute__((unused)) sockunion_print(const union sockunion *su) } } -static int in6addr_cmp(const struct in6_addr *addr1, - const struct in6_addr *addr2) +int in6addr_cmp(const struct in6_addr *addr1, const struct in6_addr *addr2) { unsigned int i; const uint8_t *p1, *p2; diff --git a/lib/sockunion.h b/lib/sockunion.h index 2cc80bb70f..9e6719ccf9 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -73,6 +73,7 @@ enum connect_result { connect_error, connect_success, connect_in_progress }; /* Prototypes. */ extern int str2sockunion(const char *, union sockunion *); extern const char *sockunion2str(const union sockunion *, char *, size_t); +int in6addr_cmp(const struct in6_addr *addr1, const struct in6_addr *addr2); extern int sockunion_cmp(const union sockunion *, const union sockunion *); extern int sockunion_same(const union sockunion *, const union sockunion *); extern unsigned int sockunion_hash(const union sockunion *); 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/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; } |
