/** * Break the netmaks string and convert them into network_pair elements in * the local_networks array. IP's are in network order. */ void parse_netmasks(const char *str) { char **masks = g_strsplit(str, ";", 0); char *p; guint32 mask_div; int i; free_networks(); if (!masks) return; for (i = 0; masks[i]; i++) /* just count */ ; number_local_networks = i; if (i == 0) { g_strfreev(masks); return; } local_networks = g_malloc(i * sizeof *local_networks); for (i = 0; masks[i]; i++) { /* Network is of the form ip/mask or ip/bits */ if ((p = strchr(masks[i], '/')) && *p) { *p++ = '\0'; if (strchr(p, '.')) { /* get the network address from the user */ if (!string_to_ip_strict(p, &local_networks[i].mask, NULL)) g_warning("parse_netmasks(): Invalid netmask: \"%s\"", p); } else { int error; mask_div = parse_uint32(p, NULL, 10, &error); mask_div = MIN(32, mask_div); if (error) g_warning("parse_netmasks(): " "Invalid CIDR prefixlen: \"%s\"", p); else local_networks[i].mask = (guint32) -1 << (32 - mask_div); } } else { /* Assume single-host */ local_networks[i].mask = -1; /* 255.255.255.255 */ } /* get the network address from the user */ if (!string_to_ip_strict(masks[i], &local_networks[i].net, NULL)) g_warning("parse_netmasks(): Invalid netmask: \"%s\"", masks[i]); } g_strfreev(masks); }
void free_rdomains(struct rdomain_head *rdomains) { struct rdomain *rd; while ((rd = SIMPLEQ_FIRST(rdomains)) != NULL) { SIMPLEQ_REMOVE_HEAD(rdomains, entry); filterset_free(&rd->export); filterset_free(&rd->import); free_networks(&rd->net_l); free(rd); } }
int merge_config(struct bgpd_config *xconf, struct bgpd_config *conf, struct peer *peer_l) { struct listen_addr *nla, *ola, *next; struct network *n; struct rdomain *rd; /* * merge the freshly parsed conf into the running xconf */ if (!conf->as) { log_warnx("configuration error: AS not given"); return (1); } if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0) conf->clusterid = conf->bgpid; /* adjust FIB priority if changed */ /* if xconf is uninitialized we get RTP_NONE */ if (xconf->fib_priority != conf->fib_priority) { kr_fib_decouple_all(xconf->fib_priority); kr_fib_update_prio_all(conf->fib_priority); kr_fib_couple_all(conf->fib_priority); } /* take over the easy config changes */ xconf->flags = conf->flags; xconf->log = conf->log; xconf->bgpid = conf->bgpid; xconf->clusterid = conf->clusterid; xconf->as = conf->as; xconf->short_as = conf->short_as; xconf->holdtime = conf->holdtime; xconf->min_holdtime = conf->min_holdtime; xconf->connectretry = conf->connectretry; xconf->fib_priority = conf->fib_priority; /* clear old control sockets and use new */ free(xconf->csock); free(xconf->rcsock); xconf->csock = conf->csock; xconf->rcsock = conf->rcsock; /* set old one to NULL so we don't double free */ conf->csock = NULL; conf->rcsock = NULL; /* clear all current filters and take over the new ones */ filterlist_free(xconf->filters); xconf->filters = conf->filters; conf->filters = NULL; /* switch the network statements, but first remove the old ones */ free_networks(&xconf->networks); while ((n = TAILQ_FIRST(&conf->networks)) != NULL) { TAILQ_REMOVE(&conf->networks, n, entry); TAILQ_INSERT_TAIL(&xconf->networks, n, entry); } /* switch the rdomain configs, first remove the old ones */ free_rdomains(&xconf->rdomains); while ((rd = SIMPLEQ_FIRST(&conf->rdomains)) != NULL) { SIMPLEQ_REMOVE_HEAD(&conf->rdomains, entry); SIMPLEQ_INSERT_TAIL(&xconf->rdomains, rd, entry); } /* * 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(conf->listen_addrs)) TAILQ_FOREACH(ola, xconf->listen_addrs, entry) if (ola->flags & DEFAULT_LISTENER) ola->reconf = RECONF_KEEP; /* else loop over listeners and merge configs */ for (nla = TAILQ_FIRST(conf->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(conf->listen_addrs, nla, entry); TAILQ_INSERT_TAIL(xconf->listen_addrs, nla, entry); nla->reconf = RECONF_REINIT; } else /* exists, just flag */ ola->reconf = RECONF_KEEP; } /* finally clean up the original list and remove all stale entires */ 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); } } /* conf is merged so free it */ free_config(conf); return (0); }