struct bgpd_config * new_config(void) { struct bgpd_config *conf; if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) fatal(NULL); conf->min_holdtime = MIN_HOLDTIME; conf->bgpid = get_bgpid(); conf->fib_priority = RTP_BGP; if ((conf->csock = strdup(SOCKET_NAME)) == NULL) fatal(NULL); if ((conf->filters = calloc(1, sizeof(struct filter_head))) == NULL) fatal(NULL); if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) == NULL) fatal(NULL); if ((conf->mrt = calloc(1, sizeof(struct mrt_head))) == NULL) fatal(NULL); /* init the various list for later */ TAILQ_INIT(&conf->networks); SIMPLEQ_INIT(&conf->rdomains); TAILQ_INIT(conf->filters); TAILQ_INIT(conf->listen_addrs); LIST_INIT(conf->mrt); return (conf); }
int merge_config(struct bgpd_config *xconf, struct bgpd_config *conf, struct peer *peer_l, struct listen_addrs *listen_addrs) { struct listen_addr *nla, *ola, *next; /* * merge the freshly parsed conf into the running xconf */ /* preserve cmd line opts */ conf->opts = xconf->opts; conf->csock = xconf->csock; conf->rcsock = xconf->rcsock; if (!conf->as) { log_warnx("configuration error: AS not given"); return (1); } if (!conf->min_holdtime) conf->min_holdtime = MIN_HOLDTIME; if (!conf->bgpid) conf->bgpid = get_bgpid(); if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0) conf->clusterid = conf->bgpid; conf->listen_addrs = xconf->listen_addrs; memcpy(xconf, conf, sizeof(struct bgpd_config)); if (conf->listen_addrs == NULL) { /* there is no old conf, just copy new one over */ xconf->listen_addrs = listen_addrs; TAILQ_FOREACH(nla, xconf->listen_addrs, entry) nla->reconf = RECONF_REINIT; } else { /* * merge new listeners: * -flag all existing ones as to be deleted * -those that are in both new and old: flag to keep * -new ones get inserted and flagged as to reinit * -remove all that are still flagged for deletion */ TAILQ_FOREACH(nla, xconf->listen_addrs, entry) nla->reconf = RECONF_DELETE; /* no new listeners? preserve default ones */ if (TAILQ_EMPTY(listen_addrs)) TAILQ_FOREACH(ola, xconf->listen_addrs, entry) if (ola->flags & DEFAULT_LISTENER) ola->reconf = RECONF_KEEP; for (nla = TAILQ_FIRST(listen_addrs); nla != NULL; nla = next) { next = TAILQ_NEXT(nla, entry); TAILQ_FOREACH(ola, xconf->listen_addrs, entry) if (!memcmp(&nla->sa, &ola->sa, sizeof(nla->sa))) break; if (ola == NULL) { /* new listener, copy over */ TAILQ_REMOVE(listen_addrs, nla, entry); TAILQ_INSERT_TAIL(xconf->listen_addrs, nla, entry); nla->reconf = RECONF_REINIT; } else /* exists, just flag */ ola->reconf = RECONF_KEEP; } for (nla = TAILQ_FIRST(xconf->listen_addrs); nla != NULL; nla = next) { next = TAILQ_NEXT(nla, entry); if (nla->reconf == RECONF_DELETE) { TAILQ_REMOVE(xconf->listen_addrs, nla, entry); free(nla); } } while ((ola = TAILQ_FIRST(listen_addrs)) != NULL) { TAILQ_REMOVE(listen_addrs, ola, entry); free(ola); } free(listen_addrs); } return (0); }