2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: ISC
|
2016-03-01 19:27:36 +01:00
|
|
|
/* $OpenBSD$ */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
|
|
|
|
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
|
|
|
|
* Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org>
|
|
|
|
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
|
|
|
*/
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
#include <zebra.h>
|
2016-03-01 19:27:36 +01:00
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
#include "ldpd.h"
|
|
|
|
#include "ldpe.h"
|
|
|
|
#include "lde.h"
|
|
|
|
#include "log.h"
|
2016-03-01 19:31:28 +01:00
|
|
|
#include "ldp_vty.h"
|
|
|
|
#include "ldp_debug.h"
|
|
|
|
|
|
|
|
#include <lib/version.h>
|
|
|
|
#include <lib/log.h>
|
|
|
|
#include "getopt.h"
|
|
|
|
#include "vty.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "privs.h"
|
|
|
|
#include "sigevent.h"
|
|
|
|
#include "zclient.h"
|
|
|
|
#include "vrf.h"
|
2017-01-27 17:22:47 +01:00
|
|
|
#include "filter.h"
|
2016-06-22 14:59:28 +02:00
|
|
|
#include "qobj.h"
|
2016-11-13 08:02:23 +01:00
|
|
|
#include "libfrr.h"
|
2018-06-18 16:59:27 +02:00
|
|
|
#include "lib_errors.h"
|
2016-03-01 19:31:28 +01:00
|
|
|
|
|
|
|
static void ldpd_shutdown(void);
|
2017-04-19 03:03:35 +02:00
|
|
|
static pid_t start_child(enum ldpd_process, char *, int, int);
|
2022-03-01 22:18:12 +01:00
|
|
|
static void main_dispatch_ldpe(struct event *thread);
|
|
|
|
static void main_dispatch_lde(struct event *thread);
|
2016-03-01 19:27:36 +01:00
|
|
|
static int main_imsg_send_ipc_sockets(struct imsgbuf *,
|
|
|
|
struct imsgbuf *);
|
|
|
|
static void main_imsg_send_net_sockets(int);
|
|
|
|
static void main_imsg_send_net_socket(int, enum socket_type);
|
|
|
|
static int main_imsg_send_config(struct ldpd_conf *);
|
2017-03-23 18:49:28 +01:00
|
|
|
static void ldp_config_normalize(struct ldpd_conf *);
|
2017-06-03 00:08:14 +02:00
|
|
|
static void ldp_config_reset(struct ldpd_conf *);
|
2017-03-23 18:49:28 +01:00
|
|
|
static void ldp_config_reset_main(struct ldpd_conf *);
|
|
|
|
static void ldp_config_reset_af(struct ldpd_conf *, int);
|
2017-03-30 16:33:08 +02:00
|
|
|
static void ldp_config_reset_l2vpns(struct ldpd_conf *);
|
2016-03-01 19:27:36 +01:00
|
|
|
static void merge_global(struct ldpd_conf *, struct ldpd_conf *);
|
|
|
|
static void merge_af(int, struct ldpd_af_conf *,
|
|
|
|
struct ldpd_af_conf *);
|
2017-03-23 18:49:28 +01:00
|
|
|
static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *);
|
2016-03-01 19:27:36 +01:00
|
|
|
static void merge_iface_af(struct iface_af *, struct iface_af *);
|
2017-03-23 18:49:28 +01:00
|
|
|
static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *);
|
|
|
|
static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *);
|
|
|
|
static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *);
|
2016-03-01 19:27:36 +01:00
|
|
|
static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *,
|
2017-03-23 18:49:28 +01:00
|
|
|
struct l2vpn *);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-06-22 14:59:28 +02:00
|
|
|
DEFINE_QOBJ_TYPE(iface);
|
|
|
|
DEFINE_QOBJ_TYPE(tnbr);
|
|
|
|
DEFINE_QOBJ_TYPE(nbr_params);
|
|
|
|
DEFINE_QOBJ_TYPE(l2vpn_if);
|
|
|
|
DEFINE_QOBJ_TYPE(l2vpn_pw);
|
|
|
|
DEFINE_QOBJ_TYPE(l2vpn);
|
|
|
|
DEFINE_QOBJ_TYPE(ldpd_conf);
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
struct ldpd_global global;
|
2017-04-19 03:03:35 +02:00
|
|
|
struct ldpd_init init;
|
2017-03-23 18:49:28 +01:00
|
|
|
struct ldpd_conf *ldpd_conf, *vty_conf;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-02-01 12:51:54 +01:00
|
|
|
static struct imsgev *iev_ldpe, *iev_ldpe_sync;
|
|
|
|
static struct imsgev *iev_lde, *iev_lde_sync;
|
2016-03-01 19:27:36 +01:00
|
|
|
static pid_t ldpe_pid;
|
|
|
|
static pid_t lde_pid;
|
|
|
|
|
2021-02-24 23:24:35 +01:00
|
|
|
static struct frr_daemon_info ldpd_di;
|
|
|
|
|
2023-03-07 20:14:41 +01:00
|
|
|
DEFINE_HOOK(ldp_register_mib, (struct event_loop * tm), (tm));
|
2021-02-24 23:24:35 +01:00
|
|
|
|
|
|
|
static void ldp_load_module(const char *name)
|
|
|
|
{
|
|
|
|
const char *dir;
|
|
|
|
dir = ldpd_di.module_path ? ldpd_di.module_path : frr_moduledir;
|
|
|
|
struct frrmod_runtime *module;
|
|
|
|
|
2021-09-03 18:49:05 +02:00
|
|
|
module = frrmod_load(name, dir, NULL,NULL);
|
2021-02-24 23:24:35 +01:00
|
|
|
if (!module) {
|
|
|
|
fprintf(stderr, "%s: failed to load %s", __func__, name);
|
|
|
|
log_warnx("%s: failed to load %s", __func__, name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ldp_agentx_enabled(void)
|
|
|
|
{
|
|
|
|
ldp_load_module("snmp");
|
|
|
|
hook_call(ldp_register_mib, master);
|
|
|
|
}
|
|
|
|
|
2020-03-08 20:17:42 +01:00
|
|
|
enum ldpd_process ldpd_process;
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
#define LDP_DEFAULT_CONFIG "ldpd.conf"
|
|
|
|
#define LDP_VTY_PORT 2612
|
|
|
|
|
|
|
|
/* Master of threads. */
|
2023-03-07 20:14:41 +01:00
|
|
|
struct event_loop *master;
|
2016-03-01 19:31:28 +01:00
|
|
|
|
|
|
|
/* ldpd privileges */
|
|
|
|
static zebra_capabilities_t _caps_p [] =
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
2016-03-01 19:31:28 +01:00
|
|
|
ZCAP_BIND,
|
|
|
|
ZCAP_NET_ADMIN
|
|
|
|
};
|
|
|
|
|
|
|
|
struct zebra_privs_t ldpd_privs =
|
|
|
|
{
|
2016-12-14 19:30:44 +01:00
|
|
|
#if defined(FRR_USER) && defined(FRR_GROUP)
|
|
|
|
.user = FRR_USER,
|
|
|
|
.group = FRR_GROUP,
|
2016-03-01 19:31:28 +01:00
|
|
|
#endif
|
|
|
|
#if defined(VTY_GROUP)
|
|
|
|
.vty_group = VTY_GROUP,
|
|
|
|
#endif
|
|
|
|
.caps_p = _caps_p,
|
|
|
|
.cap_num_p = array_size(_caps_p),
|
|
|
|
.cap_num_i = 0
|
|
|
|
};
|
|
|
|
|
2017-01-24 18:31:40 +01:00
|
|
|
/* CTL Socket path */
|
2019-05-31 01:23:15 +02:00
|
|
|
char ctl_sock_path[MAXPATHLEN];
|
2017-01-24 18:31:40 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
/* LDPd options. */
|
2017-01-24 18:31:40 +01:00
|
|
|
#define OPTION_CTLSOCK 1001
|
2019-11-20 17:26:59 +01:00
|
|
|
static const struct option longopts[] =
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
2017-01-24 18:31:40 +01:00
|
|
|
{ "ctl_socket", required_argument, NULL, OPTION_CTLSOCK},
|
2017-03-20 15:34:49 +01:00
|
|
|
{ "instance", required_argument, NULL, 'n'},
|
2016-03-01 19:31:28 +01:00
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* SIGHUP handler. */
|
|
|
|
static void
|
|
|
|
sighup(void)
|
|
|
|
{
|
|
|
|
log_info("SIGHUP received");
|
2017-03-22 16:53:36 +01:00
|
|
|
|
|
|
|
/*
|
2017-06-03 00:08:14 +02:00
|
|
|
* Do a full configuration reload. In other words, reset vty_conf
|
|
|
|
* and build a new configuartion from scratch.
|
2017-03-22 16:53:36 +01:00
|
|
|
*/
|
2017-06-03 00:08:14 +02:00
|
|
|
ldp_config_reset(vty_conf);
|
2017-12-07 20:31:48 +01:00
|
|
|
vty_read_config(NULL, ldpd_di.config_file, config_default);
|
2017-06-03 00:08:14 +02:00
|
|
|
ldp_config_apply(NULL, vty_conf);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* SIGINT / SIGTERM handler. */
|
|
|
|
static void
|
|
|
|
sigint(void)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
2016-03-01 19:31:28 +01:00
|
|
|
log_info("SIGINT received");
|
|
|
|
ldpd_shutdown();
|
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
/* SIGUSR1 handler. */
|
|
|
|
static void
|
|
|
|
sigusr1(void)
|
|
|
|
{
|
2016-02-23 12:49:45 +01:00
|
|
|
zlog_rotate();
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
2021-11-11 20:28:54 +01:00
|
|
|
static struct frr_signal_t ldp_signals[] =
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
|
|
|
{
|
|
|
|
.signal = SIGHUP,
|
|
|
|
.handler = &sighup,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.signal = SIGINT,
|
|
|
|
.handler = &sigint,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.signal = SIGTERM,
|
|
|
|
.handler = &sigint,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.signal = SIGUSR1,
|
|
|
|
.handler = &sigusr1,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-11-20 17:23:04 +01:00
|
|
|
static const struct frr_yang_module_info *const ldpd_yang_modules[] = {
|
2020-05-04 23:56:56 +02:00
|
|
|
&frr_filter_info,
|
2020-03-11 21:14:08 +01:00
|
|
|
&frr_vrf_info,
|
2018-05-24 01:29:50 +02:00
|
|
|
};
|
|
|
|
|
2016-11-13 08:02:23 +01:00
|
|
|
FRR_DAEMON_INFO(ldpd, LDP,
|
|
|
|
.vty_port = LDP_VTY_PORT,
|
|
|
|
|
|
|
|
.proghelp = "Implementation of the LDP protocol.",
|
|
|
|
|
|
|
|
.signals = ldp_signals,
|
|
|
|
.n_signals = array_size(ldp_signals),
|
|
|
|
|
|
|
|
.privs = &ldpd_privs,
|
2018-05-24 01:29:50 +02:00
|
|
|
|
|
|
|
.yang_modules = ldpd_yang_modules,
|
|
|
|
.n_yang_modules = array_size(ldpd_yang_modules),
|
2016-11-13 08:02:23 +01:00
|
|
|
);
|
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
static void ldp_config_fork_apply(struct event *t)
|
2018-06-15 04:33:59 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* So the frr_config_fork() function schedules
|
|
|
|
* the read of the vty config( if there is a
|
|
|
|
* non-integrated config ) to be after the
|
|
|
|
* end of startup and we are starting the
|
|
|
|
* main process loop. We need to schedule
|
|
|
|
* the application of this if necessary
|
|
|
|
* after the read in of the config.
|
|
|
|
*/
|
|
|
|
ldp_config_apply(NULL, vty_conf);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
char *saved_argv0;
|
2016-03-01 19:31:28 +01:00
|
|
|
int lflag = 0, eflag = 0;
|
2017-02-01 12:51:54 +01:00
|
|
|
int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
|
|
|
|
int pipe_parent2lde[2], pipe_parent2lde_sync[2];
|
2017-01-24 18:31:40 +01:00
|
|
|
char *ctl_sock_name;
|
2019-05-31 01:23:15 +02:00
|
|
|
bool ctl_sock_used = false;
|
|
|
|
|
|
|
|
snprintf(ctl_sock_path, sizeof(ctl_sock_path), LDPD_SOCKET,
|
|
|
|
"", "");
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
ldpd_process = PROC_MAIN;
|
2017-04-18 17:04:44 +02:00
|
|
|
log_procname = log_procnames[ldpd_process];
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
saved_argv0 = argv[0];
|
|
|
|
if (saved_argv0 == NULL)
|
2016-03-01 19:31:28 +01:00
|
|
|
saved_argv0 = (char *)"ldpd";
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-11-13 08:02:23 +01:00
|
|
|
frr_preinit(&ldpd_di, argc, argv);
|
2017-03-20 15:34:49 +01:00
|
|
|
frr_opt_add("LEn:", longopts,
|
|
|
|
" --ctl_socket Override ctl socket path\n"
|
2017-10-03 15:24:45 +02:00
|
|
|
" -n, --instance Instance id\n");
|
2016-11-13 08:02:23 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
while (1) {
|
|
|
|
int opt;
|
|
|
|
|
2016-11-13 08:02:23 +01:00
|
|
|
opt = frr_getopt(argc, argv, NULL);
|
2016-03-01 19:31:28 +01:00
|
|
|
|
|
|
|
if (opt == EOF)
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
2016-03-01 19:31:28 +01:00
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
case 0:
|
|
|
|
break;
|
2017-01-24 18:31:40 +01:00
|
|
|
case OPTION_CTLSOCK:
|
2019-05-31 01:23:15 +02:00
|
|
|
ctl_sock_used = true;
|
2017-01-24 18:31:40 +01:00
|
|
|
ctl_sock_name = strrchr(LDPD_SOCKET, '/');
|
|
|
|
if (ctl_sock_name)
|
|
|
|
/* skip '/' */
|
|
|
|
ctl_sock_name++;
|
|
|
|
else
|
|
|
|
/*
|
|
|
|
* LDPD_SOCKET configured as relative path
|
|
|
|
* during config? Should really never happen for
|
|
|
|
* sensible config
|
|
|
|
*/
|
|
|
|
ctl_sock_name = (char *)LDPD_SOCKET;
|
2017-04-19 03:03:35 +02:00
|
|
|
strlcpy(ctl_sock_path, optarg, sizeof(ctl_sock_path));
|
2017-01-24 18:31:40 +01:00
|
|
|
strlcat(ctl_sock_path, "/", sizeof(ctl_sock_path));
|
|
|
|
strlcat(ctl_sock_path, ctl_sock_name,
|
|
|
|
sizeof(ctl_sock_path));
|
|
|
|
break;
|
2017-03-20 15:34:49 +01:00
|
|
|
case 'n':
|
2017-04-19 03:03:35 +02:00
|
|
|
init.instance = atoi(optarg);
|
|
|
|
if (init.instance < 1)
|
2017-03-20 15:34:49 +01:00
|
|
|
exit(0);
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
case 'L':
|
|
|
|
lflag = 1;
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
eflag = 1;
|
|
|
|
break;
|
|
|
|
default:
|
2016-11-13 08:02:23 +01:00
|
|
|
frr_help_exit(1);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-31 01:23:15 +02:00
|
|
|
if (ldpd_di.pathspace && !ctl_sock_used)
|
|
|
|
snprintf(ctl_sock_path, sizeof(ctl_sock_path), LDPD_SOCKET,
|
|
|
|
"/", ldpd_di.pathspace);
|
|
|
|
|
2017-04-19 03:03:35 +02:00
|
|
|
strlcpy(init.user, ldpd_privs.user, sizeof(init.user));
|
|
|
|
strlcpy(init.group, ldpd_privs.group, sizeof(init.group));
|
|
|
|
strlcpy(init.ctl_sock_path, ctl_sock_path, sizeof(init.ctl_sock_path));
|
2017-08-06 07:35:50 +02:00
|
|
|
strlcpy(init.zclient_serv_path, frr_zclientpath,
|
2017-04-19 03:03:35 +02:00
|
|
|
sizeof(init.zclient_serv_path));
|
2016-11-13 08:02:23 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
argc -= optind;
|
|
|
|
if (argc > 0 || (lflag && eflag))
|
2016-11-13 08:02:23 +01:00
|
|
|
frr_help_exit(1);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
/* check for root privileges */
|
|
|
|
if (geteuid() != 0) {
|
|
|
|
errno = EPERM;
|
2016-11-13 08:02:23 +01:00
|
|
|
perror(ldpd_di.progname);
|
2016-03-01 19:27:36 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2017-05-06 06:40:17 +02:00
|
|
|
if (lflag || eflag) {
|
|
|
|
struct zprivs_ids_t ids;
|
|
|
|
|
|
|
|
zprivs_preinit(&ldpd_privs);
|
|
|
|
zprivs_get_ids(&ids);
|
|
|
|
|
|
|
|
zlog_init(ldpd_di.progname, "LDP", 0,
|
|
|
|
ids.uid_normal, ids.gid_normal);
|
|
|
|
}
|
2016-03-01 19:31:28 +01:00
|
|
|
if (lflag)
|
2017-04-19 03:03:35 +02:00
|
|
|
lde();
|
2016-03-01 19:31:28 +01:00
|
|
|
else if (eflag)
|
2017-04-19 03:03:35 +02:00
|
|
|
ldpe();
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1)
|
2016-03-01 19:27:36 +01:00
|
|
|
fatal("socketpair");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-02-01 12:51:54 +01:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
|
|
|
|
pipe_parent2ldpe_sync) == -1)
|
|
|
|
fatal("socketpair");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
|
2016-03-01 19:27:36 +01:00
|
|
|
fatal("socketpair");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-02-01 12:51:54 +01:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
|
|
|
|
pipe_parent2lde_sync) == -1)
|
|
|
|
fatal("socketpair");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
sock_set_nonblock(pipe_parent2ldpe[0]);
|
|
|
|
sock_set_cloexec(pipe_parent2ldpe[0]);
|
|
|
|
sock_set_nonblock(pipe_parent2ldpe[1]);
|
|
|
|
sock_set_cloexec(pipe_parent2ldpe[1]);
|
2017-02-01 12:51:54 +01:00
|
|
|
sock_set_nonblock(pipe_parent2ldpe_sync[0]);
|
|
|
|
sock_set_cloexec(pipe_parent2ldpe_sync[0]);
|
|
|
|
sock_set_cloexec(pipe_parent2ldpe_sync[1]);
|
2016-03-01 19:31:28 +01:00
|
|
|
sock_set_nonblock(pipe_parent2lde[0]);
|
|
|
|
sock_set_cloexec(pipe_parent2lde[0]);
|
|
|
|
sock_set_nonblock(pipe_parent2lde[1]);
|
|
|
|
sock_set_cloexec(pipe_parent2lde[1]);
|
2017-02-01 12:51:54 +01:00
|
|
|
sock_set_nonblock(pipe_parent2lde_sync[0]);
|
|
|
|
sock_set_cloexec(pipe_parent2lde_sync[0]);
|
|
|
|
sock_set_cloexec(pipe_parent2lde_sync[1]);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
/* start children */
|
|
|
|
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
|
2017-04-19 03:03:35 +02:00
|
|
|
pipe_parent2lde[1], pipe_parent2lde_sync[1]);
|
2016-03-01 19:27:36 +01:00
|
|
|
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
|
2017-04-19 03:03:35 +02:00
|
|
|
pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1]);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-05-17 21:34:01 +02:00
|
|
|
master = frr_init();
|
2017-03-22 20:23:46 +01:00
|
|
|
|
*: 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);
|
2017-03-22 20:23:46 +01:00
|
|
|
access_list_init();
|
|
|
|
ldp_vty_init();
|
2016-03-01 19:31:28 +01:00
|
|
|
ldp_zebra_init(master);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-03-23 18:49:28 +01:00
|
|
|
/*
|
2017-06-03 00:08:14 +02:00
|
|
|
* Create base configuration with sane defaults. All configuration
|
|
|
|
* requests (e.g. CLI) act on vty_conf and then call ldp_config_apply()
|
|
|
|
* to merge the changes into ldpd_conf, which contains the actual
|
|
|
|
* running configuration.
|
2017-03-23 18:49:28 +01:00
|
|
|
*/
|
2017-06-03 00:08:14 +02:00
|
|
|
ldpd_conf = config_new_empty();
|
2017-03-30 16:33:08 +02:00
|
|
|
vty_conf = config_new_empty();
|
|
|
|
QOBJ_REG(vty_conf, ldpd_conf);
|
2017-03-23 18:49:28 +01:00
|
|
|
|
|
|
|
/* read configuration file and daemonize */
|
2017-03-22 20:23:46 +01:00
|
|
|
frr_config_fork();
|
|
|
|
|
2017-06-03 00:08:14 +02:00
|
|
|
/* apply configuration */
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_event(master, ldp_config_fork_apply, NULL, 0, NULL);
|
2017-06-03 00:08:14 +02:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
/* setup pipes to children */
|
2017-02-01 12:51:54 +01:00
|
|
|
if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL ||
|
|
|
|
(iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL ||
|
|
|
|
(iev_lde = calloc(1, sizeof(struct imsgev))) == NULL ||
|
|
|
|
(iev_lde_sync = calloc(1, sizeof(struct imsgev))) == NULL)
|
2016-03-01 19:27:36 +01:00
|
|
|
fatal(NULL);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]);
|
2016-03-01 19:31:28 +01:00
|
|
|
iev_ldpe->handler_read = main_dispatch_ldpe;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, iev_ldpe->handler_read, iev_ldpe,
|
|
|
|
iev_ldpe->ibuf.fd, &iev_ldpe->ev_read);
|
2016-03-01 19:31:28 +01:00
|
|
|
iev_ldpe->handler_write = ldp_write_handler;
|
2017-02-01 12:51:54 +01:00
|
|
|
|
|
|
|
imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]);
|
|
|
|
iev_ldpe_sync->handler_read = main_dispatch_ldpe;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, iev_ldpe_sync->handler_read, iev_ldpe_sync,
|
|
|
|
iev_ldpe_sync->ibuf.fd, &iev_ldpe_sync->ev_read);
|
2017-02-01 12:51:54 +01:00
|
|
|
iev_ldpe_sync->handler_write = ldp_write_handler;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]);
|
|
|
|
iev_lde->handler_read = main_dispatch_lde;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd,
|
|
|
|
&iev_lde->ev_read);
|
2016-03-01 19:31:28 +01:00
|
|
|
iev_lde->handler_write = ldp_write_handler;
|
2017-02-01 12:51:54 +01:00
|
|
|
|
|
|
|
imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]);
|
|
|
|
iev_lde_sync->handler_read = main_dispatch_lde;
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, iev_lde_sync->handler_read, iev_lde_sync,
|
|
|
|
iev_lde_sync->ibuf.fd, &iev_lde_sync->ev_read);
|
2017-02-01 12:51:54 +01:00
|
|
|
iev_lde_sync->handler_write = ldp_write_handler;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
|
|
|
|
fatal("could not establish imsg links");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
|
|
|
main_imsg_compose_both(IMSG_DEBUG_UPDATE, &ldp_debug, sizeof(ldp_debug));
|
2017-09-12 14:52:20 +02:00
|
|
|
main_imsg_compose_both(IMSG_INIT, &init, sizeof(init));
|
2016-03-01 19:27:36 +01:00
|
|
|
main_imsg_send_config(ldpd_conf);
|
|
|
|
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(ldpd_conf->ipv4.flags, F_LDPD_AF_ENABLED))
|
2016-03-01 19:27:36 +01:00
|
|
|
main_imsg_send_net_sockets(AF_INET);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
|
|
|
if (CHECK_FLAG(ldpd_conf->ipv6.flags, F_LDPD_AF_ENABLED))
|
2016-03-01 19:27:36 +01:00
|
|
|
main_imsg_send_net_sockets(AF_INET6);
|
|
|
|
|
2016-11-14 01:56:02 +01:00
|
|
|
frr_run(master);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
/* NOTREACHED */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
static void
|
2016-03-01 19:27:36 +01:00
|
|
|
ldpd_shutdown(void)
|
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
int status;
|
|
|
|
|
2017-08-06 08:28:16 +02:00
|
|
|
frr_early_fini();
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
/* close pipes */
|
|
|
|
msgbuf_clear(&iev_ldpe->ibuf.w);
|
|
|
|
close(iev_ldpe->ibuf.fd);
|
|
|
|
msgbuf_clear(&iev_lde->ibuf.w);
|
|
|
|
close(iev_lde->ibuf.fd);
|
|
|
|
|
|
|
|
config_clear(ldpd_conf);
|
2017-03-30 16:33:08 +02:00
|
|
|
|
2017-06-03 00:08:14 +02:00
|
|
|
ldp_config_reset(vty_conf);
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(vty_conf);
|
|
|
|
free(vty_conf);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
log_debug("waiting for children to terminate");
|
2018-06-18 17:25:20 +02:00
|
|
|
|
|
|
|
while (true) {
|
|
|
|
/* Wait for child process. */
|
2016-03-01 19:27:36 +01:00
|
|
|
pid = wait(&status);
|
|
|
|
if (pid == -1) {
|
2018-06-18 17:25:20 +02:00
|
|
|
/* We got interrupted, try again. */
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
/* No more processes were found. */
|
2019-06-11 13:55:10 +02:00
|
|
|
if (errno == ECHILD)
|
2018-06-18 17:25:20 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* Unhandled errno condition. */
|
|
|
|
fatal("wait");
|
|
|
|
/* UNREACHABLE */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We found something, lets announce it. */
|
|
|
|
if (WIFSIGNALED(status))
|
2016-03-01 19:27:36 +01:00
|
|
|
log_warnx("%s terminated; signal %d",
|
2018-06-18 17:25:20 +02:00
|
|
|
(pid == lde_pid ? "label decision engine"
|
|
|
|
: "ldp engine"),
|
|
|
|
WTERMSIG(status));
|
|
|
|
|
|
|
|
/* Repeat until there are no more child processes. */
|
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
free(iev_ldpe);
|
|
|
|
free(iev_lde);
|
|
|
|
|
|
|
|
log_info("terminating");
|
2017-01-27 23:01:35 +01:00
|
|
|
|
|
|
|
vrf_terminate();
|
2017-01-27 17:22:47 +01:00
|
|
|
access_list_reset();
|
2017-01-27 23:01:35 +01:00
|
|
|
ldp_zebra_destroy();
|
|
|
|
|
2017-08-06 08:28:16 +02:00
|
|
|
frr_fini();
|
2016-03-01 19:27:36 +01:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static pid_t
|
2017-04-19 03:03:35 +02:00
|
|
|
start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
2017-05-06 06:40:17 +02:00
|
|
|
char *argv[7];
|
2017-10-03 21:11:07 +02:00
|
|
|
int argc = 0, nullfd;
|
2016-03-01 19:27:36 +01:00
|
|
|
pid_t pid;
|
|
|
|
|
2020-06-17 16:00:03 +02:00
|
|
|
pid = fork();
|
|
|
|
switch (pid) {
|
2016-03-01 19:27:36 +01:00
|
|
|
case -1:
|
|
|
|
fatal("cannot fork");
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
default:
|
2017-02-01 12:51:54 +01:00
|
|
|
close(fd_async);
|
|
|
|
close(fd_sync);
|
2016-03-01 19:27:36 +01:00
|
|
|
return (pid);
|
|
|
|
}
|
|
|
|
|
2017-10-03 21:11:07 +02:00
|
|
|
nullfd = open("/dev/null", O_RDONLY | O_NOCTTY);
|
2017-10-06 02:47:11 +02:00
|
|
|
if (nullfd == -1) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SYSTEM_CALL,
|
2018-08-06 18:36:50 +02:00
|
|
|
"%s: failed to open /dev/null: %s", __func__,
|
|
|
|
safe_strerror(errno));
|
2017-10-06 02:47:11 +02:00
|
|
|
} else {
|
|
|
|
dup2(nullfd, 0);
|
|
|
|
dup2(nullfd, 1);
|
|
|
|
dup2(nullfd, 2);
|
|
|
|
close(nullfd);
|
|
|
|
}
|
2017-10-03 21:11:07 +02:00
|
|
|
|
2017-02-01 12:51:54 +01:00
|
|
|
if (dup2(fd_async, LDPD_FD_ASYNC) == -1)
|
|
|
|
fatal("cannot setup imsg async fd");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-02-01 12:51:54 +01:00
|
|
|
if (dup2(fd_sync, LDPD_FD_SYNC) == -1)
|
|
|
|
fatal("cannot setup imsg sync fd");
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
argv[argc++] = argv0;
|
|
|
|
switch (p) {
|
|
|
|
case PROC_MAIN:
|
|
|
|
fatalx("Can not start main process");
|
|
|
|
case PROC_LDE_ENGINE:
|
2016-03-01 19:31:28 +01:00
|
|
|
argv[argc++] = (char *)"-L";
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
case PROC_LDP_ENGINE:
|
2016-03-01 19:31:28 +01:00
|
|
|
argv[argc++] = (char *)"-E";
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2017-05-06 06:40:17 +02:00
|
|
|
|
|
|
|
argv[argc++] = (char *)"-u";
|
|
|
|
argv[argc++] = (char *)ldpd_privs.user;
|
|
|
|
argv[argc++] = (char *)"-g";
|
|
|
|
argv[argc++] = (char *)ldpd_privs.group;
|
2016-03-01 19:27:36 +01:00
|
|
|
argv[argc++] = NULL;
|
|
|
|
|
|
|
|
execvp(argv0, argv);
|
|
|
|
fatal("execvp");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* imsg handling */
|
|
|
|
/* ARGSUSED */
|
2022-03-01 22:18:12 +01:00
|
|
|
static void main_dispatch_ldpe(struct event *thread)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
2022-12-25 16:26:52 +01:00
|
|
|
struct imsgev *iev = EVENT_ARG(thread);
|
2016-03-01 19:27:36 +01:00
|
|
|
struct imsgbuf *ibuf = &iev->ibuf;
|
|
|
|
struct imsg imsg;
|
|
|
|
int af;
|
|
|
|
ssize_t n;
|
2016-03-01 19:31:28 +01:00
|
|
|
int shut = 0;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
iev->ev_read = NULL;
|
|
|
|
|
|
|
|
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
|
|
|
|
fatal("imsg_read error");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
if (n == 0) /* connection closed */
|
|
|
|
shut = 1;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if ((n = imsg_get(ibuf, &imsg)) == -1)
|
|
|
|
fatal("imsg_get");
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (imsg.hdr.type) {
|
2016-03-01 19:31:28 +01:00
|
|
|
case IMSG_LOG:
|
|
|
|
logit(imsg.hdr.pid, "%s", (const char *)imsg.data);
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
case IMSG_REQUEST_SOCKETS:
|
|
|
|
af = imsg.hdr.pid;
|
|
|
|
main_imsg_send_net_sockets(af);
|
|
|
|
break;
|
2017-01-27 17:22:47 +01:00
|
|
|
case IMSG_ACL_CHECK:
|
|
|
|
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
|
|
|
sizeof(struct acl_check))
|
|
|
|
fatalx("IMSG_ACL_CHECK imsg with wrong len");
|
|
|
|
ldp_acl_reply(iev, (struct acl_check *)imsg.data);
|
|
|
|
break;
|
2020-07-22 18:10:59 +02:00
|
|
|
case IMSG_LDP_SYNC_IF_STATE_UPDATE:
|
|
|
|
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
|
|
|
sizeof(struct ldp_igp_sync_if_state))
|
|
|
|
fatalx("IMSG_LDP_SYNC_IF_STATE_UPDATE imsg with wrong len");
|
|
|
|
|
|
|
|
ldp_sync_zebra_send_state_update((struct ldp_igp_sync_if_state *)imsg.data);
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
default:
|
|
|
|
log_debug("%s: error handling imsg %d", __func__,
|
|
|
|
imsg.hdr.type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
imsg_free(&imsg);
|
|
|
|
}
|
|
|
|
if (!shut)
|
|
|
|
imsg_event_add(iev);
|
|
|
|
else {
|
2016-03-01 19:31:28 +01:00
|
|
|
/* this pipe is dead, so remove the event handlers and exit */
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(iev->ev_read);
|
|
|
|
EVENT_OFF(iev->ev_write);
|
2016-03-01 19:31:28 +01:00
|
|
|
ldpe_pid = 0;
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
if (lde_pid == 0)
|
|
|
|
ldpd_shutdown();
|
|
|
|
else
|
|
|
|
kill(lde_pid, SIGTERM);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
2022-03-01 22:18:12 +01:00
|
|
|
static void main_dispatch_lde(struct event *thread)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
2022-12-25 16:26:52 +01:00
|
|
|
struct imsgev *iev = EVENT_ARG(thread);
|
2016-03-01 19:27:36 +01:00
|
|
|
struct imsgbuf *ibuf = &iev->ibuf;
|
|
|
|
struct imsg imsg;
|
|
|
|
ssize_t n;
|
|
|
|
int shut = 0;
|
2020-12-06 01:45:52 +01:00
|
|
|
struct zapi_rlfa_response *rlfa_labels;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
iev->ev_read = NULL;
|
|
|
|
|
|
|
|
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
|
|
|
|
fatal("imsg_read error");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
if (n == 0) /* connection closed */
|
|
|
|
shut = 1;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if ((n = imsg_get(ibuf, &imsg)) == -1)
|
|
|
|
fatal("imsg_get");
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (imsg.hdr.type) {
|
2016-03-01 19:31:28 +01:00
|
|
|
case IMSG_LOG:
|
|
|
|
logit(imsg.hdr.pid, "%s", (const char *)imsg.data);
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
case IMSG_KLABEL_CHANGE:
|
|
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
|
|
|
|
sizeof(struct kroute))
|
|
|
|
fatalx("invalid size of IMSG_KLABEL_CHANGE");
|
|
|
|
if (kr_change(imsg.data))
|
|
|
|
log_warnx("%s: error changing route", __func__);
|
|
|
|
break;
|
|
|
|
case IMSG_KLABEL_DELETE:
|
|
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
|
|
|
|
sizeof(struct kroute))
|
|
|
|
fatalx("invalid size of IMSG_KLABEL_DELETE");
|
|
|
|
if (kr_delete(imsg.data))
|
|
|
|
log_warnx("%s: error deleting route", __func__);
|
|
|
|
break;
|
2017-06-30 17:19:39 +02:00
|
|
|
case IMSG_KPW_ADD:
|
|
|
|
case IMSG_KPW_DELETE:
|
|
|
|
case IMSG_KPW_SET:
|
|
|
|
case IMSG_KPW_UNSET:
|
2016-03-01 19:27:36 +01:00
|
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
|
2017-06-30 17:19:39 +02:00
|
|
|
sizeof(struct zapi_pw))
|
2016-03-01 19:27:36 +01:00
|
|
|
fatalx("invalid size of IMSG_KPWLABEL_CHANGE");
|
2017-06-30 17:19:39 +02:00
|
|
|
|
|
|
|
switch (imsg.hdr.type) {
|
|
|
|
case IMSG_KPW_ADD:
|
|
|
|
if (kmpw_add(imsg.data))
|
2020-03-27 12:35:23 +01:00
|
|
|
log_warnx("%s: error adding pseudowire", __func__);
|
2017-06-30 17:19:39 +02:00
|
|
|
break;
|
|
|
|
case IMSG_KPW_DELETE:
|
|
|
|
if (kmpw_del(imsg.data))
|
2020-03-27 12:35:23 +01:00
|
|
|
log_warnx("%s: error deleting pseudowire", __func__);
|
2017-06-30 17:19:39 +02:00
|
|
|
break;
|
|
|
|
case IMSG_KPW_SET:
|
|
|
|
if (kmpw_set(imsg.data))
|
2020-03-27 12:35:23 +01:00
|
|
|
log_warnx("%s: error setting pseudowire", __func__);
|
2017-06-30 17:19:39 +02:00
|
|
|
break;
|
|
|
|
case IMSG_KPW_UNSET:
|
|
|
|
if (kmpw_unset(imsg.data))
|
2020-03-27 12:35:23 +01:00
|
|
|
log_warnx("%s: error unsetting pseudowire", __func__);
|
2017-06-30 17:19:39 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
2017-01-27 17:22:47 +01:00
|
|
|
case IMSG_ACL_CHECK:
|
|
|
|
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
|
|
|
sizeof(struct acl_check))
|
|
|
|
fatalx("IMSG_ACL_CHECK imsg with wrong len");
|
|
|
|
ldp_acl_reply(iev, (struct acl_check *)imsg.data);
|
|
|
|
break;
|
2020-12-06 01:45:52 +01:00
|
|
|
case IMSG_RLFA_LABELS:
|
|
|
|
if (imsg.hdr.len != IMSG_HEADER_SIZE +
|
|
|
|
sizeof(struct zapi_rlfa_response)) {
|
|
|
|
log_warnx("%s: wrong imsg len", __func__);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rlfa_labels = imsg.data;
|
|
|
|
ldp_zebra_send_rlfa_labels(rlfa_labels);
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
default:
|
|
|
|
log_debug("%s: error handling imsg %d", __func__,
|
|
|
|
imsg.hdr.type);
|
|
|
|
break;
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
imsg_free(&imsg);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
if (!shut)
|
|
|
|
imsg_event_add(iev);
|
|
|
|
else {
|
2016-03-01 19:31:28 +01:00
|
|
|
/* this pipe is dead, so remove the event handlers and exit */
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(iev->ev_read);
|
|
|
|
EVENT_OFF(iev->ev_write);
|
2016-03-01 19:31:28 +01:00
|
|
|
lde_pid = 0;
|
|
|
|
if (ldpe_pid == 0)
|
|
|
|
ldpd_shutdown();
|
|
|
|
else
|
|
|
|
kill(ldpe_pid, SIGTERM);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
2022-03-01 22:18:12 +01:00
|
|
|
void ldp_write_handler(struct event *thread)
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
2022-12-25 16:26:52 +01:00
|
|
|
struct imsgev *iev = EVENT_ARG(thread);
|
2016-03-01 19:31:28 +01:00
|
|
|
struct imsgbuf *ibuf = &iev->ibuf;
|
|
|
|
ssize_t n;
|
|
|
|
|
|
|
|
iev->ev_write = NULL;
|
|
|
|
|
|
|
|
if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
|
|
|
|
fatal("msgbuf_write");
|
|
|
|
if (n == 0) {
|
|
|
|
/* this pipe is dead, so remove the event handlers */
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(iev->ev_read);
|
|
|
|
EVENT_OFF(iev->ev_write);
|
2022-02-23 01:04:25 +01:00
|
|
|
return;
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
imsg_event_add(iev);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main_imsg_compose_ldpe(int type, pid_t pid, void *data, uint16_t datalen)
|
|
|
|
{
|
|
|
|
if (iev_ldpe == NULL)
|
|
|
|
return;
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
imsg_compose_event(iev_ldpe, type, 0, pid, -1, data, datalen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main_imsg_compose_lde(int type, pid_t pid, void *data, uint16_t datalen)
|
|
|
|
{
|
|
|
|
imsg_compose_event(iev_lde, type, 0, pid, -1, data, datalen);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
int
|
2016-03-01 19:27:36 +01:00
|
|
|
main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len)
|
|
|
|
{
|
2016-03-01 19:31:28 +01:00
|
|
|
if (iev_ldpe == NULL || iev_lde == NULL)
|
|
|
|
return (0);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
if (imsg_compose_event(iev_ldpe, type, 0, 0, -1, buf, len) == -1)
|
|
|
|
return (-1);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
if (imsg_compose_event(iev_lde, type, 0, 0, -1, buf, len) == -1)
|
|
|
|
return (-1);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
imsg_event_add(struct imsgev *iev)
|
|
|
|
{
|
2017-02-01 12:51:54 +01:00
|
|
|
if (iev->handler_read)
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_read(master, iev->handler_read, iev, iev->ibuf.fd,
|
|
|
|
&iev->ev_read);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-02-01 12:51:54 +01:00
|
|
|
if (iev->handler_write && iev->ibuf.w.queued)
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_write(master, iev->handler_write, iev, iev->ibuf.fd,
|
|
|
|
&iev->ev_write);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
|
|
|
|
pid_t pid, int fd, void *data, uint16_t datalen)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if ((ret = imsg_compose(&iev->ibuf, type, peerid,
|
|
|
|
pid, fd, data, datalen)) != -1)
|
|
|
|
imsg_event_add(iev);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evbuf_enqueue(struct evbuf *eb, struct ibuf *buf)
|
|
|
|
{
|
|
|
|
ibuf_close(&eb->wbuf, buf);
|
|
|
|
evbuf_event_add(eb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evbuf_event_add(struct evbuf *eb)
|
|
|
|
{
|
|
|
|
if (eb->wbuf.queued)
|
2022-05-20 20:19:08 +02:00
|
|
|
event_add_write(master, eb->handler, eb->arg, eb->wbuf.fd,
|
|
|
|
&eb->ev);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
2022-03-01 22:18:12 +01:00
|
|
|
void evbuf_init(struct evbuf *eb, int fd, void (*handler)(struct event *),
|
2022-02-23 01:04:25 +01:00
|
|
|
void *arg)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
msgbuf_init(&eb->wbuf);
|
|
|
|
eb->wbuf.fd = fd;
|
2016-03-01 19:31:28 +01:00
|
|
|
eb->handler = handler;
|
|
|
|
eb->arg = arg;
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evbuf_clear(struct evbuf *eb)
|
|
|
|
{
|
2022-12-25 16:26:52 +01:00
|
|
|
EVENT_OFF(eb->ev);
|
2016-03-01 19:27:36 +01:00
|
|
|
msgbuf_clear(&eb->wbuf);
|
|
|
|
eb->wbuf.fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
main_imsg_send_ipc_sockets(struct imsgbuf *ldpe_buf, struct imsgbuf *lde_buf)
|
|
|
|
{
|
|
|
|
int pipe_ldpe2lde[2];
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_ldpe2lde) == -1)
|
2016-03-01 19:27:36 +01:00
|
|
|
return (-1);
|
2016-03-01 19:31:28 +01:00
|
|
|
sock_set_nonblock(pipe_ldpe2lde[0]);
|
|
|
|
sock_set_nonblock(pipe_ldpe2lde[1]);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
if (imsg_compose(ldpe_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[0],
|
|
|
|
NULL, 0) == -1)
|
|
|
|
return (-1);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
if (imsg_compose(lde_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[1],
|
|
|
|
NULL, 0) == -1)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
main_imsg_send_net_sockets(int af)
|
|
|
|
{
|
2016-03-01 19:31:28 +01:00
|
|
|
if (!ldp_addrisset(af, &(ldp_af_conf_get(ldpd_conf, af))->trans_addr))
|
|
|
|
return;
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
main_imsg_send_net_socket(af, LDP_SOCKET_DISC);
|
|
|
|
main_imsg_send_net_socket(af, LDP_SOCKET_EDISC);
|
|
|
|
main_imsg_send_net_socket(af, LDP_SOCKET_SESSION);
|
|
|
|
imsg_compose_event(iev_ldpe, IMSG_SETUP_SOCKETS, af, 0, -1, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
main_imsg_send_net_socket(int af, enum socket_type type)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = ldp_create_socket(af, type);
|
|
|
|
if (fd == -1) {
|
2020-03-27 12:35:23 +01:00
|
|
|
log_warnx("%s: failed to create %s socket for address-family %s", __func__, socket_name(type), af_name(af));
|
2016-03-01 19:27:36 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
imsg_compose_event(iev_ldpe, IMSG_SOCKET_NET, af, 0, fd, &type,
|
|
|
|
sizeof(type));
|
|
|
|
}
|
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
int
|
|
|
|
ldp_acl_request(struct imsgev *iev, char *acl_name, int af,
|
|
|
|
union ldpd_addr *addr, uint8_t prefixlen)
|
|
|
|
{
|
|
|
|
struct imsg imsg;
|
|
|
|
struct acl_check acl_check;
|
|
|
|
|
|
|
|
if (acl_name[0] == '\0')
|
|
|
|
return FILTER_PERMIT;
|
|
|
|
|
|
|
|
/* build request */
|
|
|
|
strlcpy(acl_check.acl, acl_name, sizeof(acl_check.acl));
|
|
|
|
acl_check.af = af;
|
|
|
|
acl_check.addr = *addr;
|
|
|
|
acl_check.prefixlen = prefixlen;
|
|
|
|
|
|
|
|
/* send (blocking) */
|
|
|
|
imsg_compose_event(iev, IMSG_ACL_CHECK, 0, 0, -1, &acl_check,
|
|
|
|
sizeof(acl_check));
|
|
|
|
imsg_flush(&iev->ibuf);
|
|
|
|
|
|
|
|
/* receive (blocking) and parse result */
|
2020-02-24 14:34:53 +01:00
|
|
|
if (imsg_read(&iev->ibuf) == -1)
|
2017-01-27 17:22:47 +01:00
|
|
|
fatal("imsg_read error");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2020-02-24 14:34:53 +01:00
|
|
|
if (imsg_get(&iev->ibuf, &imsg) == -1)
|
2017-01-27 17:22:47 +01:00
|
|
|
fatal("imsg_get");
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
if (imsg.hdr.type != IMSG_ACL_CHECK ||
|
|
|
|
imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(int))
|
|
|
|
fatalx("ldp_acl_request: invalid response");
|
|
|
|
|
|
|
|
return (*((int *)imsg.data));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ldp_acl_reply(struct imsgev *iev, struct acl_check *acl_check)
|
|
|
|
{
|
|
|
|
struct access_list *alist;
|
|
|
|
struct prefix prefix;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
alist = access_list_lookup(family2afi(acl_check->af), acl_check->acl);
|
|
|
|
if (alist == NULL)
|
|
|
|
result = FILTER_DENY;
|
|
|
|
else {
|
|
|
|
prefix.family = acl_check->af;
|
|
|
|
switch (prefix.family) {
|
|
|
|
case AF_INET:
|
|
|
|
prefix.u.prefix4 = acl_check->addr.v4;
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
prefix.u.prefix6 = acl_check->addr.v6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fatalx("ldp_acl_reply: unknown af");
|
|
|
|
}
|
|
|
|
prefix.prefixlen = acl_check->prefixlen;
|
|
|
|
result = access_list_apply(alist, &prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
imsg_compose_event(iev, IMSG_ACL_CHECK, 0, 0, -1, &result,
|
|
|
|
sizeof(result));
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
struct ldpd_af_conf *
|
|
|
|
ldp_af_conf_get(struct ldpd_conf *xconf, int af)
|
|
|
|
{
|
|
|
|
switch (af) {
|
|
|
|
case AF_INET:
|
|
|
|
return (&xconf->ipv4);
|
|
|
|
case AF_INET6:
|
|
|
|
return (&xconf->ipv6);
|
|
|
|
default:
|
|
|
|
fatalx("ldp_af_conf_get: unknown af");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ldpd_af_global *
|
|
|
|
ldp_af_global_get(struct ldpd_global *xglobal, int af)
|
|
|
|
{
|
|
|
|
switch (af) {
|
|
|
|
case AF_INET:
|
|
|
|
return (&xglobal->ipv4);
|
|
|
|
case AF_INET6:
|
|
|
|
return (&xglobal->ipv6);
|
|
|
|
default:
|
|
|
|
fatalx("ldp_af_global_get: unknown af");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ldp_is_dual_stack(struct ldpd_conf *xconf)
|
|
|
|
{
|
2023-02-20 17:42:24 +01:00
|
|
|
return (CHECK_FLAG(xconf->ipv4.flags, F_LDPD_AF_ENABLED)
|
|
|
|
&& CHECK_FLAG(xconf->ipv6.flags, F_LDPD_AF_ENABLED));
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
in_addr_t
|
|
|
|
ldp_rtr_id_get(struct ldpd_conf *xconf)
|
|
|
|
{
|
|
|
|
if (xconf->rtr_id.s_addr != INADDR_ANY)
|
|
|
|
return (xconf->rtr_id.s_addr);
|
|
|
|
else
|
|
|
|
return (global.rtr_id.s_addr);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
static int
|
|
|
|
main_imsg_send_config(struct ldpd_conf *xconf)
|
|
|
|
{
|
|
|
|
struct iface *iface;
|
|
|
|
struct tnbr *tnbr;
|
|
|
|
struct nbr_params *nbrp;
|
|
|
|
struct l2vpn *l2vpn;
|
|
|
|
struct l2vpn_if *lif;
|
|
|
|
struct l2vpn_pw *pw;
|
|
|
|
|
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_CONF, xconf,
|
|
|
|
sizeof(*xconf)) == -1)
|
|
|
|
return (-1);
|
|
|
|
|
2016-12-13 18:29:35 +01:00
|
|
|
RB_FOREACH(iface, iface_head, &xconf->iface_tree) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface,
|
|
|
|
sizeof(*iface)) == -1)
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_FOREACH(tnbr, tnbr_head, &xconf->tnbr_tree) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr,
|
|
|
|
sizeof(*tnbr)) == -1)
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2016-12-14 12:14:52 +01:00
|
|
|
RB_FOREACH(nbrp, nbrp_head, &xconf->nbrp_tree) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp,
|
|
|
|
sizeof(*nbrp)) == -1)
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
|
2016-12-14 13:42:45 +01:00
|
|
|
RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn,
|
|
|
|
sizeof(*l2vpn)) == -1)
|
|
|
|
return (-1);
|
|
|
|
|
2016-12-14 15:34:57 +01:00
|
|
|
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif,
|
|
|
|
sizeof(*lif)) == -1)
|
|
|
|
return (-1);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw,
|
|
|
|
sizeof(*pw)) == -1)
|
|
|
|
return (-1);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
|
2016-03-01 19:31:28 +01:00
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IPW, pw,
|
|
|
|
sizeof(*pw)) == -1)
|
|
|
|
return (-1);
|
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (main_imsg_compose_both(IMSG_RECONF_END, NULL, 0) == -1)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
int
|
2017-06-03 00:08:14 +02:00
|
|
|
ldp_config_apply(struct vty *vty, struct ldpd_conf *xconf)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
2017-06-03 00:08:14 +02:00
|
|
|
/*
|
|
|
|
* When reading from a configuration file (startup and sighup), we
|
|
|
|
* call merge_config() only once after the whole config has been read.
|
|
|
|
* This is the optimal and least disruptive way to update the running
|
|
|
|
* configuration.
|
|
|
|
*/
|
|
|
|
if (vty && vty->type == VTY_FILE)
|
2017-03-22 16:53:36 +01:00
|
|
|
return (0);
|
|
|
|
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_normalize(xconf);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
if (main_imsg_send_config(xconf) == -1)
|
|
|
|
return (-1);
|
|
|
|
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_config(ldpd_conf, xconf);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-03-23 18:49:28 +01:00
|
|
|
return (0);
|
2016-06-22 14:59:28 +02:00
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_normalize(struct ldpd_conf *xconf)
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
2017-03-31 03:15:33 +02:00
|
|
|
struct iface *iface, *itmp;
|
|
|
|
struct nbr_params *nbrp, *ntmp;
|
2016-03-01 19:31:28 +01:00
|
|
|
struct l2vpn *l2vpn;
|
2017-03-31 03:15:33 +02:00
|
|
|
struct l2vpn_pw *pw, *ptmp;
|
2016-03-01 19:31:28 +01:00
|
|
|
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(xconf->flags, F_LDPD_ENABLED))
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_reset_main(xconf);
|
2016-03-01 19:31:28 +01:00
|
|
|
else {
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(xconf->ipv4.flags, F_LDPD_AF_ENABLED))
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_reset_af(xconf, AF_INET);
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(xconf->ipv6.flags, F_LDPD_AF_ENABLED))
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_reset_af(xconf, AF_INET6);
|
2016-03-01 19:31:28 +01:00
|
|
|
|
2017-03-31 03:15:33 +02:00
|
|
|
RB_FOREACH_SAFE(iface, iface_head, &xconf->iface_tree, itmp) {
|
|
|
|
if (iface->ipv4.enabled || iface->ipv6.enabled)
|
2016-03-01 19:31:28 +01:00
|
|
|
continue;
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(iface);
|
2017-03-31 03:15:33 +02:00
|
|
|
RB_REMOVE(iface_head, &vty_conf->iface_tree, iface);
|
|
|
|
free(iface);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
2017-03-31 03:15:33 +02:00
|
|
|
|
|
|
|
RB_FOREACH_SAFE(nbrp, nbrp_head, &xconf->nbrp_tree, ntmp) {
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(nbrp->flags, (F_NBRP_KEEPALIVE|F_NBRP_GTSM)))
|
2017-03-31 03:15:33 +02:00
|
|
|
continue;
|
|
|
|
if (nbrp->auth.method != AUTH_NONE)
|
|
|
|
continue;
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(nbrp);
|
2017-03-31 03:15:33 +02:00
|
|
|
RB_REMOVE(nbrp_head, &vty_conf->nbrp_tree, nbrp);
|
|
|
|
free(nbrp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
|
|
|
|
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(pw->flags, F_PW_STATIC_NBR_ADDR)) {
|
2017-03-31 03:15:33 +02:00
|
|
|
pw->af = AF_INET;
|
|
|
|
pw->addr.v4 = pw->lsr_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0)
|
2016-03-01 19:31:28 +01:00
|
|
|
continue;
|
2017-03-31 03:15:33 +02:00
|
|
|
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
|
|
|
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-03-31 03:15:33 +02:00
|
|
|
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree,
|
|
|
|
ptmp) {
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(pw->flags, F_PW_STATIC_NBR_ADDR)) {
|
2017-03-31 03:15:33 +02:00
|
|
|
pw->af = AF_INET;
|
|
|
|
pw->addr.v4 = pw->lsr_id;
|
|
|
|
}
|
2016-03-01 19:31:28 +01:00
|
|
|
|
2017-03-31 03:15:33 +02:00
|
|
|
if (pw->lsr_id.s_addr == INADDR_ANY || pw->pwid == 0)
|
|
|
|
continue;
|
|
|
|
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
|
|
|
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-03 00:08:14 +02:00
|
|
|
static void
|
|
|
|
ldp_config_reset(struct ldpd_conf *conf)
|
|
|
|
{
|
|
|
|
ldp_config_reset_main(conf);
|
|
|
|
ldp_config_reset_l2vpns(conf);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_reset_main(struct ldpd_conf *conf)
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
|
|
|
struct iface *iface;
|
|
|
|
struct nbr_params *nbrp;
|
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(iface_head, &conf->iface_tree)) {
|
|
|
|
iface = RB_ROOT(iface_head, &conf->iface_tree);
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(iface);
|
2016-12-13 18:29:35 +01:00
|
|
|
RB_REMOVE(iface_head, &conf->iface_tree, iface);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(iface);
|
|
|
|
}
|
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(nbrp_head, &conf->nbrp_tree)) {
|
|
|
|
nbrp = RB_ROOT(nbrp_head, &conf->nbrp_tree);
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(nbrp);
|
2016-12-14 12:14:52 +01:00
|
|
|
RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(nbrp);
|
|
|
|
}
|
|
|
|
|
|
|
|
conf->rtr_id.s_addr = INADDR_ANY;
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_reset_af(conf, AF_INET);
|
|
|
|
ldp_config_reset_af(conf, AF_INET6);
|
2016-03-01 19:31:28 +01:00
|
|
|
conf->lhello_holdtime = LINK_DFLT_HOLDTIME;
|
|
|
|
conf->lhello_interval = DEFAULT_HELLO_INTERVAL;
|
|
|
|
conf->thello_holdtime = TARGETED_DFLT_HOLDTIME;
|
|
|
|
conf->thello_interval = DEFAULT_HELLO_INTERVAL;
|
2020-07-22 18:10:59 +02:00
|
|
|
conf->wait_for_sync_interval = DFLT_WAIT_FOR_SYNC;
|
2016-03-01 19:31:28 +01:00
|
|
|
conf->trans_pref = DUAL_STACK_LDPOV6;
|
|
|
|
conf->flags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
ldp_config_reset_af(struct ldpd_conf *conf, int af)
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
|
|
|
struct ldpd_af_conf *af_conf;
|
|
|
|
struct iface *iface;
|
|
|
|
struct iface_af *ia;
|
|
|
|
struct tnbr *tnbr, *ttmp;
|
|
|
|
|
2016-12-13 18:29:35 +01:00
|
|
|
RB_FOREACH(iface, iface_head, &conf->iface_tree) {
|
2016-03-01 19:31:28 +01:00
|
|
|
ia = iface_af_get(iface, af);
|
|
|
|
ia->enabled = 0;
|
|
|
|
}
|
|
|
|
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) {
|
2016-03-01 19:31:28 +01:00
|
|
|
if (tnbr->af != af)
|
|
|
|
continue;
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(tnbr);
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(tnbr);
|
|
|
|
}
|
|
|
|
|
|
|
|
af_conf = ldp_af_conf_get(conf, af);
|
|
|
|
af_conf->keepalive = 180;
|
|
|
|
af_conf->lhello_holdtime = 0;
|
|
|
|
af_conf->lhello_interval = 0;
|
|
|
|
af_conf->thello_holdtime = 0;
|
|
|
|
af_conf->thello_interval = 0;
|
|
|
|
memset(&af_conf->trans_addr, 0, sizeof(af_conf->trans_addr));
|
|
|
|
af_conf->flags = 0;
|
|
|
|
}
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
static void
|
|
|
|
ldp_config_reset_l2vpns(struct ldpd_conf *conf)
|
2016-03-01 19:31:28 +01:00
|
|
|
{
|
2017-03-30 16:33:08 +02:00
|
|
|
struct l2vpn *l2vpn;
|
|
|
|
struct l2vpn_if *lif;
|
|
|
|
struct l2vpn_pw *pw;
|
2016-03-01 19:31:28 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(l2vpn_head, &conf->l2vpn_tree)) {
|
|
|
|
l2vpn = RB_ROOT(l2vpn_head, &conf->l2vpn_tree);
|
|
|
|
while (!RB_EMPTY(l2vpn_if_head, &l2vpn->if_tree)) {
|
|
|
|
lif = RB_ROOT(l2vpn_if_head, &l2vpn->if_tree);
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(lif);
|
|
|
|
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
|
|
|
|
free(lif);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_tree)) {
|
|
|
|
pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_tree);
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(pw);
|
|
|
|
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
|
|
|
free(pw);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(l2vpn_pw_head, &l2vpn->pw_inactive_tree)) {
|
|
|
|
pw = RB_ROOT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(pw);
|
|
|
|
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
|
|
|
free(pw);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
QOBJ_UNREG(l2vpn);
|
|
|
|
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
|
|
|
|
free(l2vpn);
|
2016-03-01 19:31:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ldp_clear_config(struct ldpd_conf *xconf)
|
|
|
|
{
|
|
|
|
struct iface *iface;
|
|
|
|
struct tnbr *tnbr;
|
|
|
|
struct nbr_params *nbrp;
|
|
|
|
struct l2vpn *l2vpn;
|
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(iface_head, &xconf->iface_tree)) {
|
|
|
|
iface = RB_ROOT(iface_head, &xconf->iface_tree);
|
|
|
|
|
2016-12-13 18:29:35 +01:00
|
|
|
RB_REMOVE(iface_head, &xconf->iface_tree, iface);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(iface);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(tnbr_head, &xconf->tnbr_tree)) {
|
|
|
|
tnbr = RB_ROOT(tnbr_head, &xconf->tnbr_tree);
|
|
|
|
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(tnbr);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(nbrp_head, &xconf->nbrp_tree)) {
|
|
|
|
nbrp = RB_ROOT(nbrp_head, &xconf->nbrp_tree);
|
|
|
|
|
2016-12-14 12:14:52 +01:00
|
|
|
RB_REMOVE(nbrp_head, &xconf->nbrp_tree, nbrp);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(nbrp);
|
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(l2vpn_head, &xconf->l2vpn_tree)) {
|
|
|
|
l2vpn = RB_ROOT(l2vpn_head, &xconf->l2vpn_tree);
|
|
|
|
|
2016-12-14 13:42:45 +01:00
|
|
|
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, l2vpn);
|
2016-03-01 19:31:28 +01:00
|
|
|
l2vpn_del(l2vpn);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(xconf);
|
|
|
|
}
|
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
#define COPY(a, b) do { \
|
|
|
|
a = malloc(sizeof(*a)); \
|
|
|
|
if (a == NULL) \
|
|
|
|
fatal(__func__); \
|
|
|
|
*a = *b; \
|
|
|
|
} while (0)
|
|
|
|
|
2017-03-23 18:49:28 +01:00
|
|
|
void
|
|
|
|
merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
merge_global(conf, xconf);
|
|
|
|
merge_af(AF_INET, &conf->ipv4, &xconf->ipv4);
|
|
|
|
merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6);
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_ifaces(conf, xconf);
|
|
|
|
merge_tnbrs(conf, xconf);
|
|
|
|
merge_nbrps(conf, xconf);
|
|
|
|
merge_l2vpns(conf, xconf);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
|
|
|
{
|
2020-07-22 18:10:59 +02:00
|
|
|
/* Removing global LDP config requires resetting LDP IGP Sync FSM */
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(conf->flags, F_LDPD_ENABLED)
|
|
|
|
&& (!CHECK_FLAG(xconf->flags, F_LDPD_ENABLED)))
|
2020-07-22 18:10:59 +02:00
|
|
|
{
|
|
|
|
if (ldpd_process == PROC_LDP_ENGINE)
|
|
|
|
ldp_sync_fsm_reset_all();
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
/* change of router-id requires resetting all neighborships */
|
|
|
|
if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
|
|
|
|
if (ldpd_process == PROC_LDP_ENGINE) {
|
2017-01-27 17:22:47 +01:00
|
|
|
ldpe_reset_nbrs(AF_UNSPEC);
|
2016-03-01 19:27:36 +01:00
|
|
|
if (conf->rtr_id.s_addr == INADDR_ANY ||
|
|
|
|
xconf->rtr_id.s_addr == INADDR_ANY) {
|
|
|
|
if_update_all(AF_UNSPEC);
|
|
|
|
tnbr_update_all(AF_UNSPEC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
conf->rtr_id = xconf->rtr_id;
|
|
|
|
}
|
|
|
|
|
2020-02-20 20:27:49 +01:00
|
|
|
/*
|
|
|
|
* Configuration of ordered-control or independent-control
|
|
|
|
* requires resetting all neighborships.
|
|
|
|
*/
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(conf->flags, F_LDPD_ORDERED_CONTROL) !=
|
|
|
|
CHECK_FLAG(xconf->flags, F_LDPD_ORDERED_CONTROL))
|
2020-02-20 20:27:49 +01:00
|
|
|
ldpe_reset_nbrs(AF_UNSPEC);
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
conf->lhello_holdtime = xconf->lhello_holdtime;
|
|
|
|
conf->lhello_interval = xconf->lhello_interval;
|
|
|
|
conf->thello_holdtime = xconf->thello_holdtime;
|
|
|
|
conf->thello_interval = xconf->thello_interval;
|
2020-07-22 18:10:59 +02:00
|
|
|
conf->wait_for_sync_interval = xconf->wait_for_sync_interval;
|
2016-03-01 19:31:28 +01:00
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
if (conf->trans_pref != xconf->trans_pref) {
|
|
|
|
if (ldpd_process == PROC_LDP_ENGINE)
|
|
|
|
ldpe_reset_ds_nbrs();
|
|
|
|
conf->trans_pref = xconf->trans_pref;
|
|
|
|
}
|
|
|
|
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(conf->flags, F_LDPD_DS_CISCO_INTEROP) !=
|
|
|
|
CHECK_FLAG(xconf->flags, F_LDPD_DS_CISCO_INTEROP)) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (ldpd_process == PROC_LDP_ENGINE)
|
|
|
|
ldpe_reset_ds_nbrs();
|
|
|
|
}
|
|
|
|
|
2021-04-27 18:21:54 +02:00
|
|
|
/*
|
|
|
|
* Configuration of allow-broken-lsp requires reprograming all
|
|
|
|
* labeled routes
|
|
|
|
*/
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(conf->flags, F_LDPD_ALLOW_BROKEN_LSP) !=
|
|
|
|
CHECK_FLAG(xconf->flags, F_LDPD_ALLOW_BROKEN_LSP)) {
|
2021-04-27 18:21:54 +02:00
|
|
|
if (ldpd_process == PROC_LDE_ENGINE)
|
|
|
|
lde_allow_broken_lsp_update(xconf->flags);
|
|
|
|
}
|
|
|
|
|
2021-02-24 23:24:35 +01:00
|
|
|
if (ldpd_process == PROC_LDP_ENGINE)
|
|
|
|
ldpe_set_config_change_time();
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
conf->flags = xconf->flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
|
|
|
|
{
|
2017-01-27 17:22:47 +01:00
|
|
|
int stop_init_backoff = 0;
|
|
|
|
int remove_dynamic_tnbrs = 0;
|
|
|
|
int change_egress_label = 0;
|
2020-03-29 19:47:36 +02:00
|
|
|
int change_host_label = 0;
|
2017-01-27 17:22:47 +01:00
|
|
|
int reset_nbrs_ipv4 = 0;
|
|
|
|
int reset_nbrs = 0;
|
|
|
|
int update_sockets = 0;
|
2020-08-13 01:15:24 +02:00
|
|
|
int change_ldp_disabled = 0;
|
2017-01-27 17:22:47 +01:00
|
|
|
|
|
|
|
/* update timers */
|
2016-03-01 19:27:36 +01:00
|
|
|
if (af_conf->keepalive != xa->keepalive) {
|
|
|
|
af_conf->keepalive = xa->keepalive;
|
2017-01-27 17:22:47 +01:00
|
|
|
stop_init_backoff = 1;
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
af_conf->lhello_holdtime = xa->lhello_holdtime;
|
|
|
|
af_conf->lhello_interval = xa->lhello_interval;
|
2016-03-01 19:27:36 +01:00
|
|
|
af_conf->thello_holdtime = xa->thello_holdtime;
|
|
|
|
af_conf->thello_interval = xa->thello_interval;
|
|
|
|
|
|
|
|
/* update flags */
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(af_conf->flags, F_LDPD_AF_THELLO_ACCEPT) &&
|
|
|
|
!CHECK_FLAG(xa->flags, F_LDPD_AF_THELLO_ACCEPT))
|
2017-01-27 17:22:47 +01:00
|
|
|
remove_dynamic_tnbrs = 1;
|
2023-02-20 17:42:24 +01:00
|
|
|
|
|
|
|
if (CHECK_FLAG(af_conf->flags, F_LDPD_AF_NO_GTSM) !=
|
|
|
|
CHECK_FLAG(xa->flags, F_LDPD_AF_NO_GTSM)) {
|
2016-03-01 19:27:36 +01:00
|
|
|
if (af == AF_INET6)
|
|
|
|
/* need to set/unset IPV6_MINHOPCOUNT */
|
|
|
|
update_sockets = 1;
|
2017-01-27 17:22:47 +01:00
|
|
|
else
|
2016-03-01 19:27:36 +01:00
|
|
|
/* for LDPv4 just resetting the neighbors is enough */
|
2017-01-27 17:22:47 +01:00
|
|
|
reset_nbrs_ipv4 = 1;
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(af_conf->flags, F_LDPD_AF_EXPNULL) !=
|
|
|
|
CHECK_FLAG(xa->flags, F_LDPD_AF_EXPNULL))
|
2017-01-27 17:22:47 +01:00
|
|
|
change_egress_label = 1;
|
2020-03-29 19:47:36 +02:00
|
|
|
|
|
|
|
/* changing config of host only fec filtering */
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(af_conf->flags, F_LDPD_AF_ALLOCHOSTONLY)
|
|
|
|
!= CHECK_FLAG(xa->flags, F_LDPD_AF_ALLOCHOSTONLY))
|
2020-03-29 19:47:36 +02:00
|
|
|
change_host_label = 1;
|
|
|
|
|
2020-08-13 01:15:24 +02:00
|
|
|
/* disabling LDP for address family */
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(af_conf->flags, F_LDPD_AF_ENABLED) &&
|
|
|
|
!CHECK_FLAG(xa->flags, F_LDPD_AF_ENABLED))
|
2020-08-13 01:15:24 +02:00
|
|
|
change_ldp_disabled = 1;
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
af_conf->flags = xa->flags;
|
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
/* update the transport address */
|
2016-03-01 19:27:36 +01:00
|
|
|
if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) {
|
|
|
|
af_conf->trans_addr = xa->trans_addr;
|
|
|
|
update_sockets = 1;
|
|
|
|
}
|
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
/* update ACLs */
|
2020-04-15 19:49:41 +02:00
|
|
|
if (strcmp(af_conf->acl_label_allocate_for, xa->acl_label_allocate_for))
|
2020-03-29 19:47:36 +02:00
|
|
|
change_host_label = 1;
|
|
|
|
|
2023-02-20 17:42:24 +01:00
|
|
|
if (strcmp(af_conf->acl_label_advertise_to, xa->acl_label_advertise_to) ||
|
|
|
|
strcmp(af_conf->acl_label_advertise_for, xa->acl_label_advertise_for) ||
|
|
|
|
strcmp(af_conf->acl_label_accept_from, xa->acl_label_accept_from) ||
|
|
|
|
strcmp(af_conf->acl_label_accept_for, xa->acl_label_accept_for))
|
2017-01-27 17:22:47 +01:00
|
|
|
reset_nbrs = 1;
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
if (strcmp(af_conf->acl_thello_accept_from, xa->acl_thello_accept_from))
|
|
|
|
remove_dynamic_tnbrs = 1;
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
if (strcmp(af_conf->acl_label_expnull_for, xa->acl_label_expnull_for))
|
|
|
|
change_egress_label = 1;
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_thello_accept_from, xa->acl_thello_accept_from,
|
|
|
|
sizeof(af_conf->acl_thello_accept_from));
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_label_allocate_for, xa->acl_label_allocate_for,
|
|
|
|
sizeof(af_conf->acl_label_allocate_for));
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_label_advertise_to, xa->acl_label_advertise_to,
|
|
|
|
sizeof(af_conf->acl_label_advertise_to));
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_label_advertise_for, xa->acl_label_advertise_for,
|
|
|
|
sizeof(af_conf->acl_label_advertise_for));
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_label_accept_from, xa->acl_label_accept_from,
|
|
|
|
sizeof(af_conf->acl_label_accept_from));
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_label_accept_for, xa->acl_label_accept_for,
|
|
|
|
sizeof(af_conf->acl_label_accept_for));
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
strlcpy(af_conf->acl_label_expnull_for, xa->acl_label_expnull_for,
|
|
|
|
sizeof(af_conf->acl_label_expnull_for));
|
|
|
|
|
|
|
|
/* apply the new configuration */
|
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
if (change_egress_label)
|
|
|
|
lde_change_egress_label(af);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2020-03-29 19:47:36 +02:00
|
|
|
if (change_host_label)
|
2020-04-15 19:49:41 +02:00
|
|
|
lde_change_allocate_filter(af);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2020-08-13 01:15:24 +02:00
|
|
|
if (change_ldp_disabled)
|
|
|
|
lde_route_update_release_all(af);
|
|
|
|
|
2017-01-27 17:22:47 +01:00
|
|
|
break;
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
if (stop_init_backoff)
|
|
|
|
ldpe_stop_init_backoff(af);
|
|
|
|
if (remove_dynamic_tnbrs)
|
|
|
|
ldpe_remove_dynamic_tnbrs(af);
|
|
|
|
if (reset_nbrs)
|
|
|
|
ldpe_reset_nbrs(AF_UNSPEC);
|
|
|
|
else if (reset_nbrs_ipv4)
|
|
|
|
ldpe_reset_nbrs(AF_INET);
|
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
|
|
|
if (update_sockets && iev_ldpe)
|
|
|
|
imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af,
|
|
|
|
0, -1, NULL, 0);
|
|
|
|
break;
|
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
struct iface *iface, *itmp, *xi;
|
|
|
|
|
2016-12-13 18:29:35 +01:00
|
|
|
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
|
2020-08-13 01:15:24 +02:00
|
|
|
/* find deleted interfaces, which occurs when LDP is removed
|
|
|
|
* for all address families
|
|
|
|
*/
|
2020-02-24 14:34:53 +01:00
|
|
|
if (if_lookup_name(xconf, iface->name) == NULL) {
|
2016-06-22 14:59:28 +02:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
ldpe_if_exit(iface);
|
2016-06-22 14:59:28 +02:00
|
|
|
break;
|
2017-03-30 16:33:08 +02:00
|
|
|
case PROC_LDE_ENGINE:
|
2020-08-13 01:15:24 +02:00
|
|
|
if (iface->ipv4.enabled)
|
|
|
|
lde_route_update_release(iface,
|
|
|
|
AF_INET);
|
|
|
|
if (iface->ipv6.enabled)
|
|
|
|
lde_route_update_release(iface,
|
|
|
|
AF_INET6);
|
|
|
|
break;
|
2016-06-22 14:59:28 +02:00
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
|
|
|
}
|
2017-03-30 16:33:08 +02:00
|
|
|
RB_REMOVE(iface_head, &conf->iface_tree, iface);
|
2016-03-01 19:27:36 +01:00
|
|
|
free(iface);
|
|
|
|
}
|
|
|
|
}
|
2016-12-13 18:29:35 +01:00
|
|
|
RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find new interfaces */
|
2016-03-01 19:31:28 +01:00
|
|
|
if ((iface = if_lookup_name(conf, xi->name)) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(iface, xi);
|
|
|
|
RB_INSERT(iface_head, &conf->iface_tree, iface);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-03-30 16:33:08 +02:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
ldpe_if_init(iface);
|
|
|
|
break;
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
2016-06-22 14:59:28 +02:00
|
|
|
/* resend addresses to activate new interfaces */
|
2017-03-30 16:33:08 +02:00
|
|
|
kif_redistribute(iface->name);
|
|
|
|
break;
|
2016-06-22 14:59:28 +02:00
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-08-13 01:15:24 +02:00
|
|
|
/* update labels when adding or removing ldp on an
|
|
|
|
* interface
|
|
|
|
*/
|
|
|
|
if (ldpd_process == PROC_LDE_ENGINE) {
|
|
|
|
/* if we are removing lpd config for an address
|
|
|
|
* family on an interface then advertise routes
|
|
|
|
* learned over this interface as if they were
|
|
|
|
* connected routes
|
|
|
|
*/
|
|
|
|
if (iface->ipv4.enabled && !xi->ipv4.enabled)
|
|
|
|
lde_route_update_release(iface, AF_INET);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2020-08-13 01:15:24 +02:00
|
|
|
if (iface->ipv6.enabled && !xi->ipv6.enabled)
|
|
|
|
lde_route_update_release(iface, AF_INET6);
|
|
|
|
|
|
|
|
/* if we are adding lpd config for an address
|
|
|
|
* family on an interface then add proper labels
|
|
|
|
*/
|
|
|
|
if (!iface->ipv4.enabled && xi->ipv4.enabled)
|
|
|
|
lde_route_update(iface, AF_INET);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2020-08-13 01:15:24 +02:00
|
|
|
if (!iface->ipv6.enabled && xi->ipv6.enabled)
|
|
|
|
lde_route_update(iface, AF_INET6);
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
/* update existing interfaces */
|
|
|
|
merge_iface_af(&iface->ipv4, &xi->ipv4);
|
|
|
|
merge_iface_af(&iface->ipv6, &xi->ipv6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
merge_iface_af(struct iface_af *ia, struct iface_af *xi)
|
|
|
|
{
|
|
|
|
if (ia->enabled != xi->enabled) {
|
|
|
|
ia->enabled = xi->enabled;
|
|
|
|
if (ldpd_process == PROC_LDP_ENGINE)
|
2017-03-15 15:49:21 +01:00
|
|
|
ldp_if_update(ia->iface, ia->af);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
ia->hello_holdtime = xi->hello_holdtime;
|
|
|
|
ia->hello_interval = xi->hello_interval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
struct tnbr *tnbr, *ttmp, *xt;
|
|
|
|
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) {
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(tnbr->flags, F_TNBR_CONFIGURED))
|
2016-03-01 19:27:36 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* find deleted tnbrs */
|
2020-02-24 14:34:53 +01:00
|
|
|
if (tnbr_find(xconf, tnbr->af, &tnbr->addr) == NULL) {
|
2016-06-22 14:59:28 +02:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
2023-02-20 17:42:24 +01:00
|
|
|
UNSET_FLAG(tnbr->flags, F_TNBR_CONFIGURED);
|
2016-12-13 19:19:15 +01:00
|
|
|
tnbr_check(conf, tnbr);
|
2016-06-22 14:59:28 +02:00
|
|
|
break;
|
2017-03-30 16:33:08 +02:00
|
|
|
case PROC_LDE_ENGINE:
|
2016-06-22 14:59:28 +02:00
|
|
|
case PROC_MAIN:
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
|
2016-03-01 19:27:36 +01:00
|
|
|
free(tnbr);
|
2016-06-22 14:59:28 +02:00
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-13 19:19:15 +01:00
|
|
|
RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find new tnbrs */
|
|
|
|
if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(tnbr, xt);
|
|
|
|
RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-06-22 14:59:28 +02:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
tnbr_update(tnbr);
|
2016-06-22 14:59:28 +02:00
|
|
|
break;
|
2017-03-30 16:33:08 +02:00
|
|
|
case PROC_LDE_ENGINE:
|
2016-06-22 14:59:28 +02:00
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update existing tnbrs */
|
2023-02-20 17:42:24 +01:00
|
|
|
if (!CHECK_FLAG(tnbr->flags, F_TNBR_CONFIGURED))
|
|
|
|
SET_FLAG(tnbr->flags, F_TNBR_CONFIGURED);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
struct nbr_params *nbrp, *ntmp, *xn;
|
|
|
|
struct nbr *nbr;
|
|
|
|
int nbrp_changed;
|
|
|
|
|
2016-12-14 12:14:52 +01:00
|
|
|
RB_FOREACH_SAFE(nbrp, nbrp_head, &conf->nbrp_tree, ntmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find deleted nbrps */
|
2020-02-24 15:12:17 +01:00
|
|
|
if (nbr_params_find(xconf, nbrp->lsr_id) != NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
|
|
|
|
if (nbr) {
|
|
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
|
2016-03-01 19:31:28 +01:00
|
|
|
#ifdef __OpenBSD__
|
2020-02-24 15:12:17 +01:00
|
|
|
pfkey_remove(nbr);
|
2016-03-01 19:31:28 +01:00
|
|
|
#else
|
2020-02-24 15:12:17 +01:00
|
|
|
sock_set_md5sig(
|
|
|
|
(ldp_af_global_get(&global, nbr->af))
|
|
|
|
->ldp_session_socket,
|
|
|
|
nbr->af, &nbr->raddr, NULL);
|
2016-03-01 19:31:28 +01:00
|
|
|
#endif
|
2020-02-24 15:12:17 +01:00
|
|
|
nbr->auth.method = AUTH_NONE;
|
|
|
|
if (nbr_session_active_role(nbr))
|
|
|
|
nbr_establish_connection(nbr);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
2020-02-24 15:12:17 +01:00
|
|
|
break;
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
2020-02-24 15:12:17 +01:00
|
|
|
RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
|
|
|
|
free(nbrp);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
2020-02-24 15:12:17 +01:00
|
|
|
|
2016-12-14 12:14:52 +01:00
|
|
|
RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find new nbrps */
|
|
|
|
if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(nbrp, xn);
|
|
|
|
RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2016-06-22 14:59:28 +02:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
|
2016-03-01 19:27:36 +01:00
|
|
|
if (nbr) {
|
|
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
|
2017-03-30 16:33:08 +02:00
|
|
|
nbr->auth.method = nbrp->auth.method;
|
2016-03-01 19:31:28 +01:00
|
|
|
#ifdef __OpenBSD__
|
2017-03-30 16:33:08 +02:00
|
|
|
if (pfkey_establish(nbr, nbrp) == -1)
|
2016-03-01 19:27:36 +01:00
|
|
|
fatalx("pfkey setup failed");
|
2016-03-01 19:31:28 +01:00
|
|
|
#else
|
|
|
|
sock_set_md5sig(
|
|
|
|
(ldp_af_global_get(&global,
|
|
|
|
nbr->af))->ldp_session_socket,
|
|
|
|
nbr->af, &nbr->raddr,
|
2017-03-30 16:33:08 +02:00
|
|
|
nbrp->auth.md5key);
|
2016-03-01 19:31:28 +01:00
|
|
|
#endif
|
2016-03-01 19:27:36 +01:00
|
|
|
if (nbr_session_active_role(nbr))
|
|
|
|
nbr_establish_connection(nbr);
|
|
|
|
}
|
2016-06-22 14:59:28 +02:00
|
|
|
break;
|
2017-03-30 16:33:08 +02:00
|
|
|
case PROC_LDE_ENGINE:
|
2016-06-22 14:59:28 +02:00
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update existing nbrps */
|
|
|
|
if (nbrp->flags != xn->flags ||
|
|
|
|
nbrp->keepalive != xn->keepalive ||
|
|
|
|
nbrp->gtsm_enabled != xn->gtsm_enabled ||
|
|
|
|
nbrp->gtsm_hops != xn->gtsm_hops ||
|
|
|
|
nbrp->auth.method != xn->auth.method ||
|
|
|
|
strcmp(nbrp->auth.md5key, xn->auth.md5key) != 0)
|
|
|
|
nbrp_changed = 1;
|
|
|
|
else
|
|
|
|
nbrp_changed = 0;
|
|
|
|
|
|
|
|
nbrp->keepalive = xn->keepalive;
|
|
|
|
nbrp->gtsm_enabled = xn->gtsm_enabled;
|
|
|
|
nbrp->gtsm_hops = xn->gtsm_hops;
|
|
|
|
nbrp->auth.method = xn->auth.method;
|
|
|
|
strlcpy(nbrp->auth.md5key, xn->auth.md5key,
|
|
|
|
sizeof(nbrp->auth.md5key));
|
|
|
|
nbrp->auth.md5key_len = xn->auth.md5key_len;
|
|
|
|
nbrp->flags = xn->flags;
|
|
|
|
|
|
|
|
if (ldpd_process == PROC_LDP_ENGINE) {
|
|
|
|
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
|
|
|
|
if (nbr && nbrp_changed) {
|
|
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
|
2016-03-01 19:31:28 +01:00
|
|
|
#ifdef __OpenBSD__
|
2016-03-01 19:27:36 +01:00
|
|
|
pfkey_remove(nbr);
|
2017-03-19 01:58:51 +01:00
|
|
|
nbr->auth.method = nbrp->auth.method;
|
2016-03-01 19:27:36 +01:00
|
|
|
if (pfkey_establish(nbr, nbrp) == -1)
|
|
|
|
fatalx("pfkey setup failed");
|
2016-03-01 19:31:28 +01:00
|
|
|
#else
|
2017-03-19 01:58:51 +01:00
|
|
|
nbr->auth.method = nbrp->auth.method;
|
2016-03-01 19:31:28 +01:00
|
|
|
sock_set_md5sig((ldp_af_global_get(&global,
|
|
|
|
nbr->af))->ldp_session_socket, nbr->af,
|
|
|
|
&nbr->raddr, nbrp->auth.md5key);
|
|
|
|
#endif
|
2016-03-01 19:27:36 +01:00
|
|
|
if (nbr_session_active_role(nbr))
|
|
|
|
nbr_establish_connection(nbr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
struct l2vpn *l2vpn, *ltmp, *xl;
|
|
|
|
|
2016-12-14 13:42:45 +01:00
|
|
|
RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find deleted l2vpns */
|
2020-02-24 14:34:53 +01:00
|
|
|
if (l2vpn_find(xconf, l2vpn->name) == NULL) {
|
2016-03-01 19:27:36 +01:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
l2vpn_exit(l2vpn);
|
|
|
|
break;
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
ldpe_l2vpn_exit(l2vpn);
|
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
|
|
|
}
|
2017-03-30 16:33:08 +02:00
|
|
|
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
|
2016-03-01 19:27:36 +01:00
|
|
|
l2vpn_del(l2vpn);
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 13:42:45 +01:00
|
|
|
RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find new l2vpns */
|
|
|
|
if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(l2vpn, xl);
|
|
|
|
RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
|
2017-06-16 15:44:31 +02:00
|
|
|
RB_INIT(l2vpn_if_head, &l2vpn->if_tree);
|
|
|
|
RB_INIT(l2vpn_pw_head, &l2vpn->pw_tree);
|
|
|
|
RB_INIT(l2vpn_pw_head, &l2vpn->pw_inactive_tree);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDE_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
l2vpn_init(l2vpn);
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
case PROC_LDP_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
ldpe_l2vpn_init(l2vpn);
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update existing l2vpns */
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_l2vpn(conf, l2vpn, xl);
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-03-23 18:49:28 +01:00
|
|
|
merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
2016-03-01 19:27:36 +01:00
|
|
|
{
|
|
|
|
struct l2vpn_if *lif, *ftmp, *xf;
|
|
|
|
struct l2vpn_pw *pw, *ptmp, *xp;
|
|
|
|
struct nbr *nbr;
|
|
|
|
int reset_nbr, reinstall_pwfec, reinstall_tnbr;
|
|
|
|
int previous_pw_type, previous_mtu;
|
|
|
|
|
|
|
|
previous_pw_type = l2vpn->pw_type;
|
|
|
|
previous_mtu = l2vpn->mtu;
|
|
|
|
|
2022-04-19 14:21:31 +02:00
|
|
|
/* merge interfaces */
|
2016-12-14 15:34:57 +01:00
|
|
|
RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find deleted interfaces */
|
2020-02-24 14:34:53 +01:00
|
|
|
if (l2vpn_if_find(xl, lif->ifname) == NULL) {
|
2016-12-14 15:34:57 +01:00
|
|
|
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
|
2016-03-01 19:27:36 +01:00
|
|
|
free(lif);
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 15:34:57 +01:00
|
|
|
RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) {
|
2016-03-01 19:27:36 +01:00
|
|
|
/* find new interfaces */
|
2020-03-03 02:29:01 +01:00
|
|
|
if (l2vpn_if_find(l2vpn, xf->ifname) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(lif, xf);
|
|
|
|
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
|
|
|
|
lif->l2vpn = l2vpn;
|
|
|
|
|
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
|
|
|
kif_redistribute(lif->ifname);
|
|
|
|
break;
|
2017-03-31 02:58:47 +02:00
|
|
|
}
|
2016-03-01 19:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
/* merge active pseudowires */
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
|
2016-03-01 19:31:28 +01:00
|
|
|
/* find deleted active pseudowires */
|
2020-02-24 14:34:53 +01:00
|
|
|
if (l2vpn_pw_find_active(xl, pw->ifname) == NULL) {
|
2016-03-01 19:27:36 +01:00
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
l2vpn_pw_exit(pw);
|
|
|
|
break;
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
ldpe_l2vpn_pw_exit(pw);
|
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
2016-03-01 19:27:36 +01:00
|
|
|
free(pw);
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
|
2016-03-01 19:31:28 +01:00
|
|
|
/* find new active pseudowires */
|
2017-03-26 00:57:03 +01:00
|
|
|
if ((pw = l2vpn_pw_find_active(l2vpn, xp->ifname)) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(pw, xp);
|
|
|
|
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
|
|
|
pw->l2vpn = l2vpn;
|
2016-03-01 19:27:36 +01:00
|
|
|
|
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDE_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
l2vpn_pw_init(pw);
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
case PROC_LDP_ENGINE:
|
2017-03-30 16:33:08 +02:00
|
|
|
ldpe_l2vpn_pw_init(pw);
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
2017-03-30 16:33:08 +02:00
|
|
|
kif_redistribute(pw->ifname);
|
2016-03-01 19:27:36 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
/* update existing active pseudowire */
|
2016-03-01 19:27:36 +01:00
|
|
|
if (pw->af != xp->af ||
|
|
|
|
ldp_addrcmp(pw->af, &pw->addr, &xp->addr))
|
|
|
|
reinstall_tnbr = 1;
|
|
|
|
else
|
|
|
|
reinstall_tnbr = 0;
|
|
|
|
|
|
|
|
/* changes that require a session restart */
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(pw->flags, (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)) !=
|
|
|
|
CHECK_FLAG(xp->flags, (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)))
|
2016-03-01 19:27:36 +01:00
|
|
|
reset_nbr = 1;
|
|
|
|
else
|
|
|
|
reset_nbr = 0;
|
|
|
|
|
|
|
|
if (l2vpn->pw_type != xl->pw_type || l2vpn->mtu != xl->mtu ||
|
|
|
|
pw->pwid != xp->pwid || reinstall_tnbr || reset_nbr ||
|
|
|
|
pw->lsr_id.s_addr != xp->lsr_id.s_addr)
|
|
|
|
reinstall_pwfec = 1;
|
|
|
|
else
|
|
|
|
reinstall_pwfec = 0;
|
|
|
|
|
|
|
|
if (ldpd_process == PROC_LDP_ENGINE) {
|
|
|
|
if (reinstall_tnbr)
|
|
|
|
ldpe_l2vpn_pw_exit(pw);
|
|
|
|
if (reset_nbr) {
|
|
|
|
nbr = nbr_find_ldpid(pw->lsr_id.s_addr);
|
|
|
|
if (nbr && nbr->state == NBR_STA_OPER)
|
|
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
2017-06-02 16:14:54 +02:00
|
|
|
if (ldpd_process == PROC_LDE_ENGINE && reinstall_pwfec)
|
2016-03-01 19:27:36 +01:00
|
|
|
l2vpn_pw_exit(pw);
|
|
|
|
pw->lsr_id = xp->lsr_id;
|
|
|
|
pw->af = xp->af;
|
|
|
|
pw->addr = xp->addr;
|
|
|
|
pw->pwid = xp->pwid;
|
|
|
|
strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname));
|
|
|
|
pw->ifindex = xp->ifindex;
|
2023-02-20 17:42:24 +01:00
|
|
|
if (CHECK_FLAG(xp->flags, F_PW_CWORD_CONF))
|
|
|
|
SET_FLAG(pw->flags, F_PW_CWORD_CONF);
|
2016-03-01 19:27:36 +01:00
|
|
|
else
|
2023-02-20 17:42:24 +01:00
|
|
|
UNSET_FLAG(pw->flags, F_PW_CWORD_CONF);
|
|
|
|
|
|
|
|
if (CHECK_FLAG(xp->flags, F_PW_STATUSTLV_CONF))
|
|
|
|
SET_FLAG(pw->flags, F_PW_STATUSTLV_CONF);
|
2016-03-01 19:27:36 +01:00
|
|
|
else
|
2023-02-20 17:42:24 +01:00
|
|
|
UNSET_FLAG(pw->flags, F_PW_STATUSTLV_CONF);
|
|
|
|
|
|
|
|
if (CHECK_FLAG(xp->flags, F_PW_STATIC_NBR_ADDR))
|
|
|
|
SET_FLAG(pw->flags, F_PW_STATIC_NBR_ADDR);
|
2016-03-01 19:31:28 +01:00
|
|
|
else
|
2023-02-20 17:42:24 +01:00
|
|
|
UNSET_FLAG(pw->flags, F_PW_STATIC_NBR_ADDR);
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
if (ldpd_process == PROC_LDP_ENGINE && reinstall_tnbr)
|
|
|
|
ldpe_l2vpn_pw_init(pw);
|
2023-02-20 17:42:24 +01:00
|
|
|
|
2017-06-02 16:14:54 +02:00
|
|
|
if (ldpd_process == PROC_LDE_ENGINE && reinstall_pwfec) {
|
2016-03-01 19:27:36 +01:00
|
|
|
l2vpn->pw_type = xl->pw_type;
|
|
|
|
l2vpn->mtu = xl->mtu;
|
|
|
|
l2vpn_pw_init(pw);
|
|
|
|
l2vpn->pw_type = previous_pw_type;
|
|
|
|
l2vpn->mtu = previous_mtu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:31:28 +01:00
|
|
|
/* merge inactive pseudowires */
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) {
|
2016-03-01 19:31:28 +01:00
|
|
|
/* find deleted inactive pseudowires */
|
2020-02-24 14:34:53 +01:00
|
|
|
if (l2vpn_pw_find_inactive(xl, pw->ifname) == NULL) {
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
2016-03-01 19:31:28 +01:00
|
|
|
free(pw);
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 16:53:07 +01:00
|
|
|
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
|
2016-03-01 19:31:28 +01:00
|
|
|
/* find new inactive pseudowires */
|
2017-03-26 00:57:03 +01:00
|
|
|
if ((pw = l2vpn_pw_find_inactive(l2vpn, xp->ifname)) == NULL) {
|
2017-03-30 16:33:08 +02:00
|
|
|
COPY(pw, xp);
|
|
|
|
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
|
|
|
pw->l2vpn = l2vpn;
|
|
|
|
|
|
|
|
switch (ldpd_process) {
|
|
|
|
case PROC_LDE_ENGINE:
|
|
|
|
case PROC_LDP_ENGINE:
|
|
|
|
break;
|
|
|
|
case PROC_MAIN:
|
|
|
|
kif_redistribute(pw->ifname);
|
|
|
|
break;
|
2017-03-31 02:58:47 +02:00
|
|
|
}
|
2016-03-01 19:31:28 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update existing inactive pseudowire */
|
|
|
|
pw->lsr_id.s_addr = xp->lsr_id.s_addr;
|
|
|
|
pw->af = xp->af;
|
|
|
|
pw->addr = xp->addr;
|
|
|
|
pw->pwid = xp->pwid;
|
|
|
|
strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname));
|
|
|
|
pw->ifindex = xp->ifindex;
|
|
|
|
pw->flags = xp->flags;
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
l2vpn->pw_type = xl->pw_type;
|
|
|
|
l2vpn->mtu = xl->mtu;
|
|
|
|
strlcpy(l2vpn->br_ifname, xl->br_ifname, sizeof(l2vpn->br_ifname));
|
|
|
|
l2vpn->br_ifindex = xl->br_ifindex;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ldpd_conf *
|
|
|
|
config_new_empty(void)
|
|
|
|
{
|
|
|
|
struct ldpd_conf *xconf;
|
|
|
|
|
|
|
|
xconf = calloc(1, sizeof(*xconf));
|
|
|
|
if (xconf == NULL)
|
|
|
|
fatal(NULL);
|
|
|
|
|
2017-06-16 15:44:31 +02:00
|
|
|
RB_INIT(iface_head, &xconf->iface_tree);
|
|
|
|
RB_INIT(tnbr_head, &xconf->tnbr_tree);
|
|
|
|
RB_INIT(nbrp_head, &xconf->nbrp_tree);
|
|
|
|
RB_INIT(l2vpn_head, &xconf->l2vpn_tree);
|
2016-03-01 19:27:36 +01:00
|
|
|
|
2017-06-03 00:08:14 +02:00
|
|
|
/* set default values */
|
|
|
|
ldp_config_reset(xconf);
|
|
|
|
|
2016-03-01 19:27:36 +01:00
|
|
|
return (xconf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
config_clear(struct ldpd_conf *conf)
|
|
|
|
{
|
|
|
|
struct ldpd_conf *xconf;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Merge current config with an empty config, this will deactivate
|
|
|
|
* and deallocate all the interfaces, pseudowires and so on. Before
|
|
|
|
* merging, copy the router-id and other variables to avoid some
|
|
|
|
* unnecessary operations, like trying to reset the neighborships.
|
|
|
|
*/
|
|
|
|
xconf = config_new_empty();
|
|
|
|
xconf->ipv4 = conf->ipv4;
|
|
|
|
xconf->ipv6 = conf->ipv6;
|
|
|
|
xconf->rtr_id = conf->rtr_id;
|
|
|
|
xconf->trans_pref = conf->trans_pref;
|
|
|
|
xconf->flags = conf->flags;
|
|
|
|
merge_config(conf, xconf);
|
2017-03-30 16:33:08 +02:00
|
|
|
free(xconf);
|
2016-03-01 19:27:36 +01:00
|
|
|
free(conf);
|
|
|
|
}
|