mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
netd: add support for frr.conf backend with waitfrr service
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 --------------
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user