| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef _FRR_HOOK_H |
| #define _FRR_HOOK_H |
| |
| #include <stdbool.h> |
| |
| #include "module.h" |
| #include "memory.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| struct hookent { |
| struct hookent *next; |
| void *hookfn; |
| void *hookarg; |
| bool has_arg : 1; |
| bool ent_on_heap : 1; |
| bool ent_used : 1; |
| int priority; |
| struct frrmod_runtime *module; |
| const char *fnname; |
| }; |
| |
| struct hook { |
| const char *name; |
| struct hookent *entries; |
| bool reverse; |
| }; |
| |
| #define HOOK_DEFAULT_PRIORITY 1000 |
| |
| |
| |
| |
| |
| |
| extern void _hook_register(struct hook *hook, struct hookent *stackent, |
| void *funcptr, void *arg, bool has_arg, |
| struct frrmod_runtime *module, |
| const char *funcname, int priority); |
| |
| |
| |
| |
| #define _hook_reg_svar(hook, funcptr, arg, has_arg, module, funcname, prio) \ |
| do { \ |
| static struct hookent stack_hookent = {}; \ |
| _hook_register(hook, &stack_hookent, funcptr, arg, has_arg, \ |
| module, funcname, prio); \ |
| } while (0) |
| |
| #define hook_register(hookname, func) \ |
| _hook_reg_svar(&_hook_##hookname, _hook_typecheck_##hookname(func), \ |
| NULL, false, THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY) |
| #define hook_register_arg(hookname, func, arg) \ |
| _hook_reg_svar(&_hook_##hookname, \ |
| _hook_typecheck_arg_##hookname(func), arg, true, \ |
| THIS_MODULE, #func, HOOK_DEFAULT_PRIORITY) |
| #define hook_register_prio(hookname, prio, func) \ |
| _hook_reg_svar(&_hook_##hookname, _hook_typecheck_##hookname(func), \ |
| NULL, false, THIS_MODULE, #func, prio) |
| #define hook_register_arg_prio(hookname, prio, func, arg) \ |
| _hook_reg_svar(&_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); |
| #define hook_unregister(hookname, func) \ |
| _hook_unregister(&_hook_##hookname, _hook_typecheck_##hookname(func), \ |
| NULL, false) |
| #define hook_unregister_arg(hookname, func, arg) \ |
| _hook_unregister(&_hook_##hookname, \ |
| _hook_typecheck_arg_##hookname(func), arg, true) |
| |
| |
| |
| |
| #define hook_call(hookname, ...) hook_call_##hookname(__VA_ARGS__) |
| |
| |
| #define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__) |
| #define HOOK_ADDARG(...) (hookarg , ## __VA_ARGS__) |
| |
| |
| |
| |
| |
| |
| |
| |
| #define DECLARE_HOOK(hookname, arglist, passlist) \ |
| extern struct hook _hook_##hookname; \ |
| __attribute__((unused)) static void *_hook_typecheck_##hookname( \ |
| int(*funcptr) arglist) \ |
| { \ |
| return (void *)funcptr; \ |
| } \ |
| __attribute__((unused)) static void *_hook_typecheck_arg_##hookname( \ |
| int(*funcptr) HOOK_ADDDEF arglist) \ |
| { \ |
| return (void *)funcptr; \ |
| } |
| #define DECLARE_KOOH(hookname, arglist, passlist) \ |
| DECLARE_HOOK(hookname, arglist, passlist) |
| |
| |
| |
| #define DEFINE_HOOK_INT(hookname, arglist, passlist, rev) \ |
| struct hook _hook_##hookname = { \ |
| .name = #hookname, .entries = NULL, .reverse = rev, \ |
| }; \ |
| static int hook_call_##hookname arglist \ |
| { \ |
| int hooksum = 0; \ |
| struct hookent *he = _hook_##hookname.entries; \ |
| void *hookarg; \ |
| union { \ |
| void *voidptr; \ |
| int(*fptr) arglist; \ |
| int(*farg) HOOK_ADDDEF arglist; \ |
| } hookp; \ |
| for (; he; he = he->next) { \ |
| hookarg = he->hookarg; \ |
| hookp.voidptr = he->hookfn; \ |
| if (!he->has_arg) \ |
| hooksum += hookp.fptr passlist; \ |
| else \ |
| hooksum += hookp.farg HOOK_ADDARG passlist; \ |
| } \ |
| 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) |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _FRR_HOOK_H */ |