netd: add support for frr.conf backend with waitfrr service

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2026-02-24 06:59:31 +01:00
parent bcc444f0fe
commit 965906e2ff
16 changed files with 420 additions and 97 deletions
@@ -1,3 +1,2 @@
#set DEBUG=1
service <pid/mgmtd> name:netd log [S12345] netd -- Network route daemon
service [2345] <pid/confd> name:netd netd -- Network route daemon
+28
View File
@@ -0,0 +1,28 @@
# Default FRR daemons file for Infix - confd overwrites on routing changes.
# watchfrr, zebra, mgmtd, and staticd are always started by frrinit.sh.
ospfd=no
ripd=no
bfdd=no
bgpd=no
ospf6d=no
ripngd=no
isisd=no
pimd=no
pim6d=no
ldpd=no
eigrpd=no
babeld=no
vrrpd=no
pathd=no
vtysh_enable=yes
watchfrr_options="-l 4"
zebra_options=" -A 127.0.0.1 -s 90000000"
mgmtd_options=" -A 127.0.0.1"
ospfd_options=" -A 127.0.0.1"
ripd_options=" -A 127.0.0.1"
staticd_options="-A 127.0.0.1"
bfdd_options=" -A 127.0.0.1"
frr_profile="traditional"
+2
View File
@@ -0,0 +1,2 @@
# Replaces default frr.conf file
log syslog warnings
@@ -1,9 +0,0 @@
! Default settings for staticd, used for both
! confd generated routes, udhcpc and zeroconf
frr defaults traditional
hostname Router
password zebra
enable password zebra
no log unique-id
log syslog informational
log facility local2
+13 -2
View File
@@ -13,10 +13,21 @@ config BR2_PACKAGE_NETD
if BR2_PACKAGE_NETD
config BR2_PACKAGE_NETD_FRR
bool "FRR integration"
config BR2_PACKAGE_NETD_FRR_CONF
bool "FRR frr.conf backend"
default y if BR2_PACKAGE_FRR
depends on BR2_PACKAGE_FRR
help
Enable FRR integration via frr.conf file generation.
netd assembles a single /etc/frr/frr.conf from routing
config and signals FRR to reload via frrinit.sh.
Provides full routing support (static routes, RIP, OSPF).
config BR2_PACKAGE_NETD_FRR
bool "FRR gRPC backend"
depends on BR2_PACKAGE_FRR
depends on !BR2_PACKAGE_NETD_FRR_CONF
select BR2_PACKAGE_PROTOBUF
select BR2_PACKAGE_GRPC
select BR2_PACKAGE_HOST_PROTOBUF
+2 -2
View File
@@ -1,3 +1,3 @@
#set DEBUG=1
service name:netd log [S12345] netd -p /run/netd.pid -- Network route daemon
service <pid/confd> name:netd log \
[2345] netd -p /run/netd.pid -- Network route daemon
+6 -2
View File
@@ -17,12 +17,16 @@ NETD_CONF_ENV = CFLAGS="$(INFIX_CFLAGS)"
NETD_CONF_OPTS = --prefix= --disable-silent-rules
# FRR integration (gRPC backend) or standalone Linux backend
ifeq ($(BR2_PACKAGE_NETD_FRR),y)
# Backend selection: FRR frr.conf, FRR gRPC, or Linux kernel
ifeq ($(BR2_PACKAGE_NETD_FRR_CONF),y)
NETD_DEPENDENCIES += frr
NETD_CONF_OPTS += --with-frr-conf
else ifeq ($(BR2_PACKAGE_NETD_FRR),y)
NETD_DEPENDENCIES += frr grpc host-grpc protobuf
NETD_CONF_ENV += \
PROTOC="$(HOST_DIR)/bin/protoc" \
GRPC_CPP_PLUGIN="$(HOST_DIR)/bin/grpc_cpp_plugin"
NETD_CONF_OPTS += --with-frr
else
NETD_CONF_OPTS += --without-frr
endif
@@ -85,6 +85,12 @@ SKELETON_INIT_FINIT_POST_INSTALL_TARGET_HOOKS += SKELETON_INIT_FINIT_SET_DROPBEA
endif
ifeq ($(BR2_PACKAGE_FRR),y)
ifeq ($(BR2_PACKAGE_NETD_FRR_CONF),y)
define SKELETON_INIT_FINIT_SET_FRR
cp $(SKELETON_INIT_FINIT_AVAILABLE)/frr/frr.conf $(FINIT_D)/available/frr.conf
ln -sf ../available/frr.conf $(FINIT_D)/enabled/frr.conf
endef
else
define SKELETON_INIT_FINIT_SET_FRR
for svc in babeld bfdd bgpd mgmtd eigrpd isisd ldpd ospfd ospf6d pathd ripd ripng staticd vrrpd zebra; do \
cp $(SKELETON_INIT_FINIT_AVAILABLE)/frr/$$svc.conf $(FINIT_D)/available/$$svc.conf; \
@@ -93,6 +99,7 @@ define SKELETON_INIT_FINIT_SET_FRR
ln -sf ../available/staticd.conf $(FINIT_D)/enabled/staticd.conf
ln -sf ../available/mgmtd.conf $(FINIT_D)/enabled/mgmtd.conf
endef
endif
SKELETON_INIT_FINIT_POST_INSTALL_TARGET_HOOKS += SKELETON_INIT_FINIT_SET_FRR
endif # BR2_PACKAGE_FRR
@@ -0,0 +1,3 @@
sysv <!~pid/netd> name:watchfrr pid:!/run/frr/watchfrr.pid \
reload:'frrinit.sh reload' log:null \
[2345] frrinit.sh -- FRR routing suite
+112 -66
View File
@@ -18,6 +18,7 @@
#define RIPD_SIGNAL_NEXT RIPD_SIGNAL "+"
#define BFDD_SIGNAL "/run/bfd_enabled" /* Just signal that bfd should be enabled*/
#define BFDD_SIGNAL_NEXT BFDD_SIGNAL "+"
#define FRR_DAEMONS "/etc/frr/daemons"
#define FRR_STATIC_CONFIG "! Generated by Infix confd\n\
frr defaults traditional\n\
@@ -302,8 +303,10 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf)
any_debug = 1;
}
if (any_debug)
if (any_debug) {
fputs("log syslog debugging\n", fp);
fputs("!\n", fp);
}
}
areas = lydx_get_child(ospf, "areas");
@@ -337,6 +340,7 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf)
(void)touch(BFDD_SIGNAL_NEXT);
else
(void)remove(BFDD_SIGNAL_NEXT);
return 0;
}
@@ -401,11 +405,66 @@ static int parse_static_routes(sr_session_ctx_t *session, struct lyd_node *paren
return num_routes;
}
/*
* Generate the complete /etc/frr/daemons file. Written atomically as a
* single unit so the file is always consistent and easy to read.
*/
static void frr_daemons_write(int ospfd, int ripd, int bfdd)
{
const char *next = FRR_DAEMONS "+";
FILE *fp;
fp = fopen(next, "w");
if (!fp) {
ERROR("Failed to open %s", next);
return;
}
/* Daemon selection - watchfrr, zebra, mgmtd, and staticd are
* always started by frrinit.sh regardless of these settings. */
fprintf(fp,
"# Generated by Infix confd\n"
"ospfd=%s\n"
"ripd=%s\n"
"bfdd=%s\n"
"bgpd=no\n"
"ospf6d=no\n"
"ripngd=no\n"
"isisd=no\n"
"pimd=no\n"
"pim6d=no\n"
"ldpd=no\n"
"eigrpd=no\n"
"babeld=no\n"
"vrrpd=no\n"
"pathd=no\n"
"\n",
ospfd ? "yes" : "no",
ripd ? "yes" : "no",
bfdd ? "yes" : "no");
/* Global settings and per-daemon options */
fputs(
"vtysh_enable=yes\n"
"watchfrr_options=\"-l 4\"\n"
"zebra_options=\" -A 127.0.0.1 -s 90000000\"\n"
"mgmtd_options=\" -A 127.0.0.1\"\n"
"ospfd_options=\" -A 127.0.0.1\"\n"
"ripd_options=\" -A 127.0.0.1\"\n"
"staticd_options=\"-A 127.0.0.1\"\n"
"bfdd_options=\" -A 127.0.0.1\"\n"
"\n"
"frr_profile=\"traditional\"\n",
fp);
fclose(fp);
rename(next, FRR_DAEMONS);
}
int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd)
{
int netd_enabled = 0, ospfd_enabled = 0, bfdd_enabled = 0, ripd_enabled = 0;
struct lyd_node *cplane, *cplanes;
bool restart_zebra = false;
int rc = SR_ERR_OK;
FILE *fp;
@@ -413,10 +472,12 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
return SR_ERR_OK;
switch (event) {
case SR_EV_ENABLED: /* first time, on register. */
case SR_EV_CHANGE: /* regular change (copy cand running) */
break;
case SR_EV_ENABLED: /* first time, on register - no SR_EV_DONE follows */
break;
case SR_EV_ABORT: /* User abort, or other plugin failed */
(void)remove(NETD_CONF_NEXT);
return SR_ERR_OK;
@@ -427,69 +488,8 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
ospfd_enabled = fexist(OSPFD_CONF_NEXT);
bfdd_enabled = fexist(BFDD_SIGNAL_NEXT);
ripd_enabled = fexist(RIPD_SIGNAL_NEXT);
goto activate;
if (bfdd_enabled) {
(void)rename(BFDD_SIGNAL_NEXT, BFDD_SIGNAL);
systemf("initctl -bfq enable bfdd");
systemf("initctl -bfq touch bfdd");
restart_zebra = true;
} else {
(void)remove(BFDD_SIGNAL);
systemf("initctl -bfq disable bfdd");
}
if (ospfd_enabled) {
(void)remove(OSPFD_CONF_PREV);
(void)rename(OSPFD_CONF, OSPFD_CONF_PREV);
(void)rename(OSPFD_CONF_NEXT, OSPFD_CONF);
systemf("initctl enable ospfd");
systemf("initctl touch ospfd");
restart_zebra = true;
} else {
systemf("initctl -bfq disable ospfd");
(void)remove(OSPFD_CONF);
}
/* Start/stop ripd daemon based on whether RIP config is present */
if (ripd_enabled) {
systemf("initctl enable ripd");
systemf("initctl touch ripd");
restart_zebra = true;
} else {
(void)remove(RIPD_SIGNAL);
systemf("initctl -bfq disable ripd");
}
/* netd handles both static routes and RIP */
if (netd_enabled) {
restart_zebra = true;
(void)remove(NETD_CONF_PREV);
(void)rename(NETD_CONF, NETD_CONF_PREV);
(void)rename(NETD_CONF_NEXT, NETD_CONF);
if (systemf("initctl -bfq touch netd"))
ERROR("Failed to signal netd for reload");
} else {
if (!remove(NETD_CONF)) {
if (systemf("initctl -bfq touch netd"))
ERROR("Failed to signal netd for reload");
}
}
if (restart_zebra) {
/* skip in runlevel S, no routing daemons run here anyway */
if (systemf("runlevel >/dev/null 2>&1"))
return SR_ERR_OK;
if (systemf("initctl -bfq touch zebra")) {
ERROR("Failed to restart zebra routing daemon");
rc = SR_ERR_INTERNAL;
goto err_abandon;
}
}
return SR_ERR_OK;
default:
return SR_ERR_OK;
}
@@ -529,6 +529,52 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly
if (!netd_enabled)
(void)remove(NETD_CONF_NEXT);
err_abandon:
if (event == SR_EV_CHANGE)
return rc;
/* For SR_EV_ENABLED we activate immediately (no SR_EV_DONE follows) */
netd_enabled = fexist(NETD_CONF_NEXT);
ospfd_enabled = fexist(OSPFD_CONF_NEXT);
bfdd_enabled = fexist(BFDD_SIGNAL_NEXT);
ripd_enabled = fexist(RIPD_SIGNAL_NEXT);
activate:
/* Generate complete /etc/frr/daemons */
frr_daemons_write(ospfd_enabled, ripd_enabled, bfdd_enabled);
if (bfdd_enabled)
(void)rename(BFDD_SIGNAL_NEXT, BFDD_SIGNAL);
else
(void)remove(BFDD_SIGNAL);
if (ospfd_enabled) {
(void)remove(OSPFD_CONF_PREV);
(void)rename(OSPFD_CONF, OSPFD_CONF_PREV);
(void)rename(OSPFD_CONF_NEXT, OSPFD_CONF);
} else {
(void)remove(OSPFD_CONF);
}
if (ripd_enabled)
(void)rename(RIPD_SIGNAL_NEXT, RIPD_SIGNAL);
else
(void)remove(RIPD_SIGNAL);
/* netd handles both static routes and RIP, assembles frr.conf */
if (netd_enabled) {
(void)remove(NETD_CONF_PREV);
(void)rename(NETD_CONF, NETD_CONF_PREV);
(void)rename(NETD_CONF_NEXT, NETD_CONF);
} else {
(void)remove(NETD_CONF);
}
/*
* Signal netd to reload - it assembles /etc/frr/frr.conf and
* Finit propagates the restart to the frr sysv service
*/
if (systemf("initctl -bfq touch netd"))
ERROR("Failed to signal netd for reload");
return rc;
}
+6 -1
View File
@@ -8,7 +8,7 @@ netd_CFLAGS = -W -Wall -Wextra
netd_CFLAGS += $(libite_CFLAGS) $(libconfuse_CFLAGS) $(jansson_CFLAGS)
netd_LDADD = $(libite_LIBS) $(libconfuse_LIBS) $(jansson_LIBS)
# Backend selection: FRR gRPC or Linux kernel
# Backend selection: FRR gRPC, FRR frr.conf, or Linux kernel
if HAVE_FRR_GRPC
BUILT_SOURCES = grpc/frr-northbound.pb.cc grpc/frr-northbound.pb.h \
grpc/frr-northbound.grpc.pb.cc grpc/frr-northbound.grpc.pb.h
@@ -29,6 +29,11 @@ netd_LDADD += $(grpc_LIBS) $(protobuf_LIBS) -lstdc++
CLEANFILES = grpc/*.pb.cc grpc/*.pb.h
else
if HAVE_FRR_CONF
# FRR frr.conf file backend
netd_SOURCES += src/frrconf_backend.c src/frrconf_backend.h
else
# Linux kernel backend (no FRR)
netd_SOURCES += src/linux_backend.c src/linux_backend.h
endif
endif
+21 -7
View File
@@ -12,23 +12,33 @@ AC_PROG_CXX
AC_PROG_INSTALL
#
# FRR gRPC northbound API (optional, enabled by default)
# FRR backend selection
#
AC_ARG_WITH(frr,
AS_HELP_STRING([--without-frr], [Build without FRR integration (use Linux kernel backend)]),
AS_HELP_STRING([--with-frr], [Build with FRR gRPC backend]),
[with_frr=$withval],
[with_frr=yes])
[with_frr=no])
AC_ARG_WITH(frr-conf,
AS_HELP_STRING([--with-frr-conf], [Build with FRR frr.conf file backend (default when FRR available)]),
[with_frr_conf=$withval],
[with_frr_conf=no])
# Mutual exclusion check
AS_IF([test "x$with_frr" = "xyes" -a "x$with_frr_conf" = "xyes"], [
AC_MSG_ERROR([--with-frr and --with-frr-conf are mutually exclusive])
])
AS_IF([test "x$with_frr" = "xyes"], [
# Check for protoc and grpc_cpp_plugin
AC_PATH_PROG([PROTOC], [protoc], [no])
AS_IF([test "x$PROTOC" = "xno"], [
AC_MSG_ERROR([protoc not found, required for FRR support (use --without-frr to disable)])
AC_MSG_ERROR([protoc not found, required for FRR gRPC support])
])
AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin], [no])
AS_IF([test "x$GRPC_CPP_PLUGIN" = "xno"], [
AC_MSG_ERROR([grpc_cpp_plugin not found, required for FRR support (use --without-frr to disable)])
AC_MSG_ERROR([grpc_cpp_plugin not found, required for FRR gRPC support])
])
# Check for grpc++ and protobuf libraries
@@ -41,7 +51,12 @@ AS_IF([test "x$with_frr" = "xyes"], [
AC_SUBST(GRPC_CPP_PLUGIN)
])
AS_IF([test "x$with_frr_conf" = "xyes"], [
AC_DEFINE(HAVE_FRR_CONF, 1, [Built with FRR frr.conf file backend])
])
AM_CONDITIONAL(HAVE_FRR_GRPC, [test "x$with_frr" = "xyes"])
AM_CONDITIONAL(HAVE_FRR_CONF, [test "x$with_frr_conf" = "xyes"])
# Check for pkg-config first
PKG_PROG_PKG_CONFIG
@@ -74,8 +89,7 @@ cat <<EOF
Prefix................: $prefix
Exec prefix...........: $eprefix
Sysconfdir............: `eval echo $sysconfdir`
FRR integration.......: $with_frr
Backend...............: $(test "x$with_frr" = "xyes" && echo "FRR gRPC" || echo "Linux kernel")
Backend...............: $(test "x$with_frr" = "xyes" && echo "FRR gRPC" || (test "x$with_frr_conf" = "xyes" && echo "FRR frr.conf" || echo "Linux kernel"))
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
------------- Compiler version --------------
+192
View File
@@ -0,0 +1,192 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* FRR frr.conf backend for netd - assembles a single /etc/frr/frr.conf
* from static routes, RIP config, and any existing OSPF config snippet,
* then signals FRR to reload via Finit.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "netd.h"
#include "frrconf_backend.h"
#define FRR_CONF "/etc/frr/frr.conf"
#define FRR_CONF_NEXT FRR_CONF "+"
#define OSPFD_CONF "/etc/frr/ospfd.conf"
static const char *frr_header =
"! Generated by netd\n"
"frr defaults traditional\n"
"hostname Router\n"
"password zebra\n"
"enable password zebra\n"
"no log unique-id\n"
"log syslog warnings\n"
"log facility local2\n"
"!\n";
int frrconf_backend_init(void)
{
INFO("Using FRR frr.conf backend");
return 0;
}
void frrconf_backend_cleanup(void)
{
/* Nothing to clean up */
}
static void write_static_routes(FILE *fp, struct route_head *routes)
{
char prefix_str[INET6_ADDRSTRLEN];
char gw_str[INET6_ADDRSTRLEN];
struct route *r;
int count = 0;
TAILQ_FOREACH(r, routes, entries) {
const char *cmd;
if (r->family == AF_INET) {
cmd = "ip";
inet_ntop(AF_INET, &r->prefix.ip4, prefix_str, sizeof(prefix_str));
} else {
cmd = "ipv6";
inet_ntop(AF_INET6, &r->prefix.ip6, prefix_str, sizeof(prefix_str));
}
fprintf(fp, "%s route %s/%u ", cmd, prefix_str, r->prefixlen);
switch (r->nh_type) {
case NH_ADDR:
if (r->family == AF_INET)
inet_ntop(AF_INET, &r->gateway.gw4, gw_str, sizeof(gw_str));
else
inet_ntop(AF_INET6, &r->gateway.gw6, gw_str, sizeof(gw_str));
fputs(gw_str, fp);
break;
case NH_IFNAME:
fputs(r->ifname, fp);
break;
case NH_BLACKHOLE:
switch (r->bh_type) {
case BH_NULL:
fputs("Null0", fp);
break;
case BH_REJECT:
fputs("reject", fp);
break;
case BH_DROP:
fputs("blackhole", fp);
break;
}
break;
}
if (r->distance)
fprintf(fp, " %u", r->distance);
fputc('\n', fp);
count++;
}
if (count)
fputs("!\n", fp);
DEBUG("frrconf: wrote %d static routes", count);
}
static const char *redist_name(enum rip_redist_type type)
{
switch (type) {
case RIP_REDIST_CONNECTED: return "connected";
case RIP_REDIST_STATIC: return "static";
case RIP_REDIST_KERNEL: return "kernel";
case RIP_REDIST_OSPF: return "ospf";
}
return "unknown";
}
static void write_rip_config(FILE *fp, struct rip_config *rip)
{
struct rip_redistribute *redist;
struct rip_neighbor *nbr;
struct rip_network *net;
if (!rip->enabled)
return;
fputs("router rip\n", fp);
fprintf(fp, " default-metric %u\n", rip->default_metric);
fprintf(fp, " distance %u\n", rip->distance);
fprintf(fp, " timers basic %u %u %u\n",
rip->timers.update, rip->timers.invalid, rip->timers.flush);
if (rip->default_route)
fputs(" default-information originate\n", fp);
TAILQ_FOREACH(net, &rip->networks, entries) {
fprintf(fp, " network %s\n", net->ifname);
if (net->passive)
fprintf(fp, " passive-interface %s\n", net->ifname);
}
TAILQ_FOREACH(nbr, &rip->neighbors, entries) {
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &nbr->addr, addr, sizeof(addr));
fprintf(fp, " neighbor %s\n", addr);
}
TAILQ_FOREACH(redist, &rip->redistributes, entries)
fprintf(fp, " redistribute %s\n", redist_name(redist->type));
fputs("!\n", fp);
DEBUG("frrconf: wrote RIP configuration");
}
static void append_file(FILE *fp, const char *path)
{
char buf[1024];
FILE *src;
size_t n;
src = fopen(path, "r");
if (!src)
return;
while ((n = fread(buf, 1, sizeof(buf), src)) > 0)
fwrite(buf, 1, n, fp);
fclose(src);
DEBUG("frrconf: appended %s", path);
}
int frrconf_backend_apply(struct route_head *routes, struct rip_config *rip)
{
FILE *fp;
fp = fopen(FRR_CONF_NEXT, "w");
if (!fp) {
ERROR("frrconf: failed to open %s: %s", FRR_CONF_NEXT, strerror(errno));
return -1;
}
fputs(frr_header, fp);
write_static_routes(fp, routes);
write_rip_config(fp, rip);
append_file(fp, OSPFD_CONF);
fclose(fp);
if (rename(FRR_CONF_NEXT, FRR_CONF)) {
ERROR("frrconf: failed to rename %s to %s: %s",
FRR_CONF_NEXT, FRR_CONF, strerror(errno));
return -1;
}
INFO("frrconf: updated %s", FRR_CONF);
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef NETD_FRRCONF_BACKEND_H_
#define NETD_FRRCONF_BACKEND_H_
#include "netd.h"
int frrconf_backend_init(void);
void frrconf_backend_cleanup(void);
int frrconf_backend_apply(struct route_head *routes, struct rip_config *rip);
#endif /* NETD_FRRCONF_BACKEND_H_ */
+15 -6
View File
@@ -15,6 +15,13 @@ static void backend_cleanup(void) { grpc_backend_cleanup(); }
static int backend_apply(struct route_head *routes, struct rip_config *rip) {
return grpc_backend_apply(routes, rip);
}
#elif defined(HAVE_FRR_CONF)
#include "frrconf_backend.h"
static int backend_init(void) { return frrconf_backend_init(); }
static void backend_cleanup(void) { frrconf_backend_cleanup(); }
static int backend_apply(struct route_head *routes, struct rip_config *rip) {
return frrconf_backend_apply(routes, rip);
}
#else
#include "linux_backend.h"
static int backend_init(void) { return linux_backend_init(); }
@@ -35,6 +42,8 @@ static struct rip_config active_rip;
static void sighup_handler(int sig)
{
(void)sig;
INFO("Got SIGHUP, reloading ...");
do_reload = 1;
}
@@ -197,8 +206,9 @@ static void reload(void)
ERROR("Failed to launch system command: %s", cmd->command);
}
}
pidfile(NULL);
INFO("Configuration reloaded");
pidfile(NULL);
}
static int usage(int rc)
@@ -213,7 +223,7 @@ static int usage(int rc)
int main(int argc, char *argv[])
{
int log_opts = LOG_PID | LOG_NDELAY;
struct sigaction sa;
struct sigaction sa = { 0 };
int c;
while ((c = getopt(argc, argv, "dhp:")) != -1) {
@@ -230,10 +240,10 @@ int main(int argc, char *argv[])
}
openlog("netd", log_opts, LOG_DAEMON);
INFO("netd starting");
setlogmask(LOG_UPTO(LOG_INFO));
INFO("starting");
/* Set up signal handlers */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sighup_handler;
sigaction(SIGHUP, &sa, NULL);
@@ -253,7 +263,6 @@ int main(int argc, char *argv[])
/* Initial load */
do_reload = 1;
pidfile(NULL);
while (!do_shutdown) {
if (do_reload) {
do_reload = 0;
@@ -262,7 +271,7 @@ int main(int argc, char *argv[])
pause();
}
INFO("netd shutting down");
INFO("shutting down");
route_list_free(&active_routes);
rip_config_free(&active_rip);