diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/hash.c | 13 | ||||
| -rw-r--r-- | lib/hook.c | 16 | ||||
| -rw-r--r-- | lib/hook.h | 51 | ||||
| -rw-r--r-- | lib/if.c | 35 | ||||
| -rw-r--r-- | lib/if.h | 17 | ||||
| -rw-r--r-- | lib/libfrr.c | 21 | ||||
| -rw-r--r-- | lib/libfrr.h | 8 | ||||
| -rw-r--r-- | lib/privs.c | 4 |
8 files changed, 114 insertions, 51 deletions
diff --git a/lib/hash.c b/lib/hash.c index 66341cf2f1..243521bef7 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -335,12 +335,13 @@ void hash_free(struct hash *hash) /* CLI commands ------------------------------------------------------------ */ -DEFUN(show_hash_stats, - show_hash_stats_cmd, - "show hashtable [statistics]", - SHOW_STR - "Statistics about hash tables\n" - "Statistics about hash tables\n") +DEFUN_NOSH(show_hash_stats, + show_hash_stats_cmd, + "show debugging hashtable [statistics]", + SHOW_STR + DEBUG_STR + "Statistics about hash tables\n" + "Statistics about hash tables\n") { struct hash *h; struct listnode *ln; diff --git a/lib/hook.c b/lib/hook.c index 2c877cbf45..1468c4d329 100644 --- a/lib/hook.c +++ b/lib/hook.c @@ -26,17 +26,25 @@ DEFINE_MTYPE_STATIC(LIB, HOOK_ENTRY, "Hook entry") void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, - struct frrmod_runtime *module, const char *funcname) + struct frrmod_runtime *module, const char *funcname, + int priority) { - struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)); + struct hookent *he = XCALLOC(MTYPE_HOOK_ENTRY, sizeof(*he)), **pos; he->hookfn = funcptr; he->hookarg = arg; he->has_arg = has_arg; he->module = module; he->fnname = funcname; + he->priority = priority; - he->next = hook->entries; - hook->entries = he; + for (pos = &hook->entries; *pos; pos = &(*pos)->next) + if (hook->reverse + ? (*pos)->priority < priority + : (*pos)->priority >= priority) + break; + + he->next = *pos; + *pos = he; } void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg) diff --git a/lib/hook.h b/lib/hook.h index 4a5cee2fd3..5f45e113e7 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -74,6 +74,29 @@ * hook_register_arg (some_update_event, event_handler, addonptr); * * (addonptr isn't typesafe, but that should be manageable.) + * + * Hooks also support a "priority" value for ordering registered calls + * relative to each other. The priority is a signed integer where lower + * values are called earlier. There is also "Koohs", which is hooks with + * reverse priority ordering (for cleanup/deinit hooks, so you can use the + * same priority value). + * + * Recommended priority value ranges are: + * + * -999 ... 0 ... 999 - main executable / daemon, or library + * -1999 ... -1000 - modules registering calls that should run before + * the daemon's bits + * 1000 ... 1999 - modules calls that should run after daemon's + * + * Note: the default value is 1000, based on the following 2 expectations: + * - most hook_register() usage will be in loadable modules + * - usage of hook_register() in the daemon itself may need relative ordering + * to itself, making an explicit value the expected case + * + * The priority value is passed as extra argument on hook_register_prio() / + * hook_register_arg_prio(). Whether a hook runs in reverse is determined + * solely by the code defining / calling the hook. (DECLARE_KOOH is actually + * the same thing as DECLARE_HOOK, it's just there to make it obvious.) */ /* TODO: @@ -94,6 +117,7 @@ struct hookent { void *hookfn; /* actually a function pointer */ void *hookarg; bool has_arg; + int priority; struct frrmod_runtime *module; const char *fnname; }; @@ -101,8 +125,11 @@ struct hookent { struct hook { const char *name; struct hookent *entries; + bool reverse; }; +#define HOOK_DEFAULT_PRIORITY 1000 + /* subscribe/add callback function to a hook * * always use hook_register(), which uses the static inline helper from @@ -110,14 +137,21 @@ struct hook { */ extern void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, struct frrmod_runtime *module, - const char *funcname); + const char *funcname, int priority); #define hook_register(hookname, func) \ _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func), \ - NULL, false, THIS_MODULE, #func) + NULL, false, THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY) #define hook_register_arg(hookname, func, arg) \ _hook_register(&_hook_##hookname, \ _hook_typecheck_arg_##hookname(func), arg, true, \ - THIS_MODULE, #func) + THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY) +#define hook_register_prio(hookname, prio, func) \ + _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func), \ + NULL, false, THIS_MODULE, #func, prio) +#define hook_register_arg_prio(hookname, prio, func, arg) \ + _hook_register(&_hook_##hookname, \ + _hook_typecheck_arg_##hookname(func), \ + arg, true, THIS_MODULE, #func, prio) extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg); @@ -156,12 +190,14 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, { \ return (void *)funcptr; \ } +#define DECLARE_KOOH(hookname, arglist, passlist) \ + DECLARE_HOOK(hookname, arglist, passlist) /* use in source file - contains hook-related definitions. */ -#define DEFINE_HOOK(hookname, arglist, passlist) \ +#define DEFINE_HOOK_INT(hookname, arglist, passlist, rev) \ struct hook _hook_##hookname = { \ - .name = #hookname, .entries = NULL, \ + .name = #hookname, .entries = NULL, .reverse = rev, \ }; \ static int hook_call_##hookname arglist \ { \ @@ -184,4 +220,9 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, return hooksum; \ } +#define DEFINE_HOOK(hookname, arglist, passlist) \ + DEFINE_HOOK_INT(hookname, arglist, passlist, false) +#define DEFINE_KOOH(hookname, arglist, passlist) \ + DEFINE_HOOK_INT(hookname, arglist, passlist, true) + #endif /* _FRR_HOOK_H */ @@ -42,17 +42,12 @@ DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") DEFINE_QOBJ_TYPE(interface) +DEFINE_HOOK(if_add, (struct interface *ifp), (ifp)) +DEFINE_KOOH(if_del, (struct interface *ifp), (ifp)) + /* List of interfaces in only the default VRF */ int ptm_enable = 0; -/* One for each program. This structure is needed to store hooks. */ -struct if_master { - int (*if_new_hook)(struct interface *); - int (*if_delete_hook)(struct interface *); -} if_master = { - 0, -}; - /* Compare interface names, returning an integer greater than, equal to, or * less than 0, (following the strcmp convention), according to the * relationship between ifp1 and ifp2. Interface names consist of an @@ -150,10 +145,7 @@ struct interface *if_create(const char *name, int namelen, vrf_id_t vrf_id) SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); QOBJ_REG(ifp, interface); - - if (if_master.if_new_hook) - (*if_master.if_new_hook)(ifp); - + hook_call(if_add, ifp); return ifp; } @@ -182,9 +174,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) /* Delete interface structure. */ void if_delete_retain(struct interface *ifp) { - if (if_master.if_delete_hook) - (*if_master.if_delete_hook)(ifp); - + hook_call(if_del, ifp); QOBJ_UNREG(ifp); /* Free connected address list */ @@ -209,21 +199,6 @@ void if_delete(struct interface *ifp) XFREE(MTYPE_IF, ifp); } -/* Add hook to interface master. */ -void if_add_hook(int type, int (*func)(struct interface *ifp)) -{ - switch (type) { - case IF_NEW_HOOK: - if_master.if_new_hook = func; - break; - case IF_DELETE_HOOK: - if_master.if_delete_hook = func; - break; - default: - break; - } -} - /* Interface existance check by index. */ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { @@ -25,6 +25,7 @@ #include "linklist.h" #include "memory.h" #include "qobj.h" +#include "hook.h" DECLARE_MTYPE(IF) DECLARE_MTYPE(CONNECTED_LABEL) @@ -283,6 +284,17 @@ struct interface { }; DECLARE_QOBJ_TYPE(interface) +/* called from the library code whenever interfaces are created/deleted + * note: interfaces may not be fully realized at that point; also they + * may not exist in the system (ifindex = IFINDEX_INTERNAL) + * + * priority values are important here, daemons should be at 0 while modules + * can use 1000+ so they run after the daemon has initialised daemon-specific + * interface data + */ +DECLARE_HOOK(if_add, (struct interface *ifp), (ifp)) +DECLARE_KOOH(if_del, (struct interface *ifp), (ifp)) + /* Connected address structure. */ struct connected { /* Attached interface. */ @@ -355,10 +367,6 @@ struct nbr_connected { ? (C)->destination \ : (C)->address) -/* Interface hook sort. */ -#define IF_NEW_HOOK 0 -#define IF_DELETE_HOOK 1 - /* There are some interface flags which are only supported by some operating system. */ @@ -442,7 +450,6 @@ extern int if_is_loopback(struct interface *); extern int if_is_broadcast(struct interface *); extern int if_is_pointopoint(struct interface *); extern int if_is_multicast(struct interface *); -extern void if_add_hook(int, int (*)(struct interface *)); extern void if_init(struct list **); extern void if_cmd_init(void); extern void if_terminate(struct list **); diff --git a/lib/libfrr.c b/lib/libfrr.c index a5c87e6edc..255f91ec71 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -37,6 +37,8 @@ #include "network.h" DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) +DEFINE_KOOH(frr_early_fini, (), ()) +DEFINE_KOOH(frr_fini, (), ()) const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; @@ -831,3 +833,22 @@ void frr_run(struct thread_master *master) while (thread_fetch(master, &thread)) thread_call(&thread); } + +void frr_early_fini(void) +{ + hook_call(frr_early_fini); +} + +void frr_fini(void) +{ + hook_call(frr_fini); + + /* memory_init -> nothing needed */ + vty_terminate(); + cmd_terminate(); + zprivs_terminate(di->privs); + /* signal_init -> nothing needed */ + thread_master_free(master); + closezlog(); + /* frrmod_init -> nothing needed / hooks */ +} diff --git a/lib/libfrr.h b/lib/libfrr.h index 1710fc9a84..8a15d168a1 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -104,6 +104,14 @@ extern void frr_run(struct thread_master *master); extern bool frr_zclient_addr(struct sockaddr_storage *sa, socklen_t *sa_len, const char *path); +/* these two are before the protocol daemon does its own shutdown + * it's named this way being the counterpart to frr_late_init */ +DECLARE_KOOH(frr_early_fini, (), ()) +extern void frr_early_fini(void); +/* and these two are after the daemon did its own cleanup */ +DECLARE_KOOH(frr_fini, (), ()) +extern void frr_fini(void); + extern char config_default[256]; extern char frr_zclientpath[256]; extern const char frr_sysconfdir[]; diff --git a/lib/privs.c b/lib/privs.c index eda3fb02d4..cfe7d6d6f8 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -856,7 +856,9 @@ void zprivs_terminate(struct zebra_privs_t *zprivs) } #ifdef HAVE_CAPABILITIES - zprivs_caps_terminate(); + if (zprivs->user || zprivs->group || zprivs->cap_num_p + || zprivs->cap_num_i) + zprivs_caps_terminate(); #else /* !HAVE_CAPABILITIES */ /* only change uid if we don't have the correct one */ if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { |
