frr/nhrpd/nhrp_main.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

169 lines
3.1 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-or-later
/* NHRP daemon main functions
* Copyright (c) 2014-2015 Timo Teräs
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include "zebra.h"
#include "privs.h"
#include "getopt.h"
#include "frrevent.h"
#include "sigevent.h"
#include "lib/version.h"
#include "log.h"
#include "memory.h"
#include "command.h"
#include "libfrr.h"
#include "filter.h"
#include "nhrpd.h"
#include "nhrp_errors.h"
DEFINE_MGROUP(NHRPD, "NHRP");
unsigned int debug_flags = 0;
struct event_loop *master;
struct timeval current_time;
/* nhrpd options. */
struct option longopts[] = {{0}};
/* nhrpd privileges */
static zebra_capabilities_t _caps_p[] = {
ZCAP_NET_RAW, ZCAP_NET_ADMIN,
ZCAP_DAC_OVERRIDE, /* for now needed to write to
/proc/sys/net/ipv4/<if>/send_redirect */
};
struct zebra_privs_t nhrpd_privs = {
#if defined(FRR_USER) && defined(FRR_GROUP)
.user = FRR_USER,
.group = FRR_GROUP,
#endif
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
.cap_num_p = array_size(_caps_p),
.cap_num_i = 0
};
static void parse_arguments(int argc, char **argv)
{
int opt;
while (1) {
opt = frr_getopt(argc, argv, 0);
if (opt < 0)
break;
switch (opt) {
case 0:
break;
default:
frr_help_exit(1);
}
}
}
static void nhrp_sigusr1(void)
{
zlog_rotate();
}
static void nhrp_request_stop(void)
{
debugf(NHRP_DEBUG_COMMON, "Exiting...");
frr_early_fini();
nhrp_shortcut_terminate();
nhrp_nhs_terminate();
nhrp_zebra_terminate();
vici_terminate();
evmgr_terminate();
vrf_terminate();
nhrpd: Fix nhrp_peer leak - Addressed memory leak by removing `&c->peer_notifier` from the notifier list on termination. Retaining it caused the notifier list to stay active, preventing the deletion of `c->cur.peer` thereby causing a memory leak. - Reordered termination steps to call `vrf_terminate` before `nhrp_vc_terminate`, preventing a heap-use-after-free issue when `nhrp_vc_notify_del` is invoked in `nhrp_peer_check_delete`. - Added an if statement to avoid passing NULL as hash to `hash_release`, which leads to a SIGSEGV. The ASan leak log for reference: ``` *********************************************************************************** Address Sanitizer Error detected in nhrp_topo.test_nhrp_topo/r1.asan.nhrpd.20265 ================================================================= ==20265==ERROR: LeakSanitizer: detected memory leaks Direct leak of 112 byte(s) in 1 object(s) allocated from: #0 0x7f80270c9b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40) #1 0x7f8026ac1eb8 in qmalloc lib/memory.c:100 #2 0x560fd648f0a6 in nhrp_peer_create nhrpd/nhrp_peer.c:175 #3 0x7f8026a88d3f in hash_get lib/hash.c:147 #4 0x560fd6490a5d in nhrp_peer_get nhrpd/nhrp_peer.c:228 #5 0x560fd648a51a in nhrp_nhs_resolve_cb nhrpd/nhrp_nhs.c:297 #6 0x7f80266b000f in resolver_cb_literal lib/resolver.c:234 #7 0x7f8026b62e0e in event_call lib/event.c:1969 #8 0x7f8026aa5437 in frr_run lib/libfrr.c:1213 #9 0x560fd6488b4f in main nhrpd/nhrp_main.c:166 #10 0x7f8025eb2c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) SUMMARY: AddressSanitizer: 112 byte(s) leaked in 1 allocation(s). *********************************************************************************** *********************************************************************************** Address Sanitizer Error detected in nhrp_topo.test_nhrp_topo/r2.asan.nhrpd.20400 ================================================================= ==20400==ERROR: LeakSanitizer: detected memory leaks Direct leak of 112 byte(s) in 1 object(s) allocated from: #0 0x7fb6e3ca5b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40) #1 0x7fb6e369deb8 in qmalloc lib/memory.c:100 #2 0x562652de40a6 in nhrp_peer_create nhrpd/nhrp_peer.c:175 #3 0x7fb6e3664d3f in hash_get lib/hash.c:147 #4 0x562652de5a5d in nhrp_peer_get nhrpd/nhrp_peer.c:228 #5 0x562652de1e8e in nhrp_packet_recvraw nhrpd/nhrp_packet.c:325 #6 0x7fb6e373ee0e in event_call lib/event.c:1969 #7 0x7fb6e3681437 in frr_run lib/libfrr.c:1213 #8 0x562652dddb4f in main nhrpd/nhrp_main.c:166 #9 0x7fb6e2a8ec86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86) SUMMARY: AddressSanitizer: 112 byte(s) leaked in 1 allocation(s). *********************************************************************************** ``` Signed-off-by: Keelan Cannoo <keelan.cannoo@icloud.com>
2023-10-12 16:04:52 +02:00
nhrp_vc_terminate();
debugf(NHRP_DEBUG_COMMON, "Done.");
frr_fini();
exit(0);
}
static struct frr_signal_t sighandlers[] = {
{
.signal = SIGUSR1,
.handler = &nhrp_sigusr1,
},
{
.signal = SIGINT,
.handler = &nhrp_request_stop,
},
{
.signal = SIGTERM,
.handler = &nhrp_request_stop,
},
};
static const struct frr_yang_module_info *const nhrpd_yang_modules[] = {
&frr_filter_info,
&frr_interface_info,
&frr_vrf_info,
};
FRR_DAEMON_INFO(nhrpd, NHRP, .vty_port = NHRP_VTY_PORT,
.proghelp = "Implementation of the NHRP routing protocol.",
.signals = sighandlers, .n_signals = array_size(sighandlers),
.privs = &nhrpd_privs, .yang_modules = nhrpd_yang_modules,
.n_yang_modules = array_size(nhrpd_yang_modules),
);
int main(int argc, char **argv)
{
frr_preinit(&nhrpd_di, argc, argv);
frr_opt_add("", longopts, "");
parse_arguments(argc, argv);
/* Library inits. */
master = frr_init();
nhrp_error_init();
*: rework renaming the default VRF Currently, it is possible to rename the default VRF either by passing `-o` option to zebra or by creating a file in `/var/run/netns` and binding it to `/proc/self/ns/net`. In both cases, only zebra knows about the rename and other daemons learn about it only after they connect to zebra. This is a problem, because daemons may read their config before they connect to zebra. To handle this rename after the config is read, we have some special code in every single daemon, which is not very bad but not desirable in my opinion. But things are getting worse when we need to handle this in northbound layer as we have to manually rewrite the config nodes. This approach is already hacky, but still works as every daemon handles its own NB structures. But it is completely incompatible with the central management daemon architecture we are aiming for, as mgmtd doesn't even have a connection with zebra to learn from it. And it shouldn't have it, because operational state changes should never affect configuration. To solve the problem and simplify the code, I propose to expand the `-o` option to all daemons. By using the startup option, we let daemons know about the rename before they read their configs so we don't need any special code to deal with it. There's an easy way to pass the option to all daemons by using `frr_global_options` variable. Unfortunately, the second way of renaming by creating a file in `/var/run/netns` is incompatible with the new mgmtd architecture. Theoretically, we could force daemons to read their configs only after they connect to zebra, but it means adding even more code to handle a very specific use-case. And anyway this won't work for mgmtd as it doesn't have a connection with zebra. So I had to remove this option. Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-12-03 23:22:55 +01:00
vrf_init(NULL, NULL, NULL, NULL);
nhrp_interface_init();
resolver_init(master);
/*
* Run with elevated capabilities, as for all netlink activity
* we need privileges anyway.
* The assert is for clang SA code where it does
* not see the change function being set in lib
*/
assert(nhrpd_privs.change);
nhrpd_privs.change(ZPRIVS_RAISE);
evmgr_init();
nhrp_vc_init();
nhrp_packet_init();
vici_init();
if_zapi_callbacks(nhrp_ifp_create, nhrp_ifp_up,
nhrp_ifp_down, nhrp_ifp_destroy);
nhrp_zebra_init();
nhrp_shortcut_init();
nhrp_config_init();
frr_config_fork();
frr_run(master);
return 0;
}