summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2019-03-31 16:57:38 +0000
committerclaudio <claudio@openbsd.org>2019-03-31 16:57:38 +0000
commit82fc6237928a854e2841e7ebcf3e3e13fffb60a7 (patch)
tree79b557fe161bfc5bd499e9679cef3ca41c96185e
parentUpdate Jewish holiday dates for this year. While here, add Tu B'Shevat. (diff)
downloadwireguard-openbsd-82fc6237928a854e2841e7ebcf3e3e13fffb60a7.tar.xz
wireguard-openbsd-82fc6237928a854e2841e7ebcf3e3e13fffb60a7.zip
Move the struct peer into bgpd_config and switch it to a TAILQ instead of
the hand-rolled list. This changes the way peers are reloaded since now both parent and session engine are now merging the lists. OK denis@
-rw-r--r--usr.sbin/bgpd/bgpd.c33
-rw-r--r--usr.sbin/bgpd/bgpd.h7
-rw-r--r--usr.sbin/bgpd/config.c33
-rw-r--r--usr.sbin/bgpd/control.c21
-rw-r--r--usr.sbin/bgpd/parse.y107
-rw-r--r--usr.sbin/bgpd/printconf.c43
-rw-r--r--usr.sbin/bgpd/session.c220
-rw-r--r--usr.sbin/bgpd/session.h24
8 files changed, 238 insertions, 250 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index a198a4f30a9..6aecc7b7fd5 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.214 2019/03/31 03:36:18 yasuoka Exp $ */
+/* $OpenBSD: bgpd.c,v 1.215 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -43,7 +43,7 @@ __dead void usage(void);
int main(int, char *[]);
pid_t start_child(enum bgpd_process, char *, int, int, int);
int send_filterset(struct imsgbuf *, struct filter_set_head *);
-int reconfigure(char *, struct bgpd_config *, struct peer **);
+int reconfigure(char *, struct bgpd_config *);
int dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *);
int control_setup(struct bgpd_config *);
int imsg_send_sockets(struct imsgbuf *, struct imsgbuf *);
@@ -100,7 +100,6 @@ int
main(int argc, char *argv[])
{
struct bgpd_config *conf;
- struct peer *peer_l, *p;
struct rde_rib *rr;
struct pollfd pfd[POLL_MAX];
time_t timeout;
@@ -125,8 +124,6 @@ main(int argc, char *argv[])
if (saved_argv0 == NULL)
saved_argv0 = "bgpd";
- peer_l = NULL;
-
while ((ch = getopt(argc, argv, "cdD:f:nRSv")) != -1) {
switch (ch) {
case 'c':
@@ -169,20 +166,14 @@ main(int argc, char *argv[])
usage();
if (cmd_opts & BGPD_OPT_NOACTION) {
- conf = new_config();
- if (parse_config(conffile, conf, &peer_l))
+ if ((conf = parse_config(conffile, NULL)) == NULL)
exit(1);
if (cmd_opts & BGPD_OPT_VERBOSE)
- print_config(conf, &ribnames, &conf->networks, peer_l,
- conf->filters, conf->mrt, &conf->l3vpns);
+ print_config(conf, &ribnames);
else
fprintf(stderr, "configuration OK\n");
- while ((p = peer_l) != NULL) {
- peer_l = p->next;
- free(p);
- }
while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
free(rr);
@@ -261,7 +252,7 @@ BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
if (imsg_send_sockets(ibuf_se, ibuf_rde))
fatal("could not establish imsg links");
conf = new_config();
- quit = reconfigure(conffile, conf, &peer_l);
+ quit = reconfigure(conffile, conf);
if (pftable_clear_all() != 0)
quit = 1;
@@ -317,7 +308,7 @@ BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
u_int error;
reconfig = 0;
- switch (reconfigure(conffile, conf, &peer_l)) {
+ switch (reconfigure(conffile, conf)) {
case -1: /* fatal error */
quit = 1;
break;
@@ -358,10 +349,6 @@ BROKEN if (pledge("stdio rpath wpath cpath fattr unix route recvfd sendfd",
ibuf_rde = NULL;
}
- while ((p = peer_l) != NULL) {
- peer_l = p->next;
- free(p);
- }
while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
free(rr);
@@ -454,8 +441,9 @@ send_filterset(struct imsgbuf *i, struct filter_set_head *set)
}
int
-reconfigure(char *conffile, struct bgpd_config *conf, struct peer **peer_l)
+reconfigure(char *conffile, struct bgpd_config *conf)
{
+ struct bgpd_config *new_conf;
struct peer *p;
struct filter_rule *r;
struct listen_addr *la;
@@ -472,12 +460,13 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct peer **peer_l)
reconfpending = 2; /* one per child */
log_info("rereading config");
- if (parse_config(conffile, conf, peer_l)) {
+ if ((new_conf = parse_config(conffile, &conf->peers)) == NULL) {
log_warnx("config file %s has errors, not reloading",
conffile);
reconfpending = 0;
return (1);
}
+ merge_config(conf, new_conf);
if (prepare_listeners(conf) == -1) {
reconfpending = 0;
@@ -527,7 +516,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct peer **peer_l)
}
/* send peer list to the SE */
- for (p = *peer_l; p != NULL; p = p->next) {
+ TAILQ_FOREACH(p, &conf->peers, entry) {
if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
&p->conf, sizeof(struct peer_config)) == -1)
return (-1);
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index a8480fbf88a..0909afe3b71 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.377 2019/03/07 07:42:36 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.378 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -231,6 +231,9 @@ struct listen_addr {
TAILQ_HEAD(listen_addrs, listen_addr);
TAILQ_HEAD(filter_set_head, filter_set);
+struct peer;
+TAILQ_HEAD(peer_head, peer);
+
struct l3vpn;
SIMPLEQ_HEAD(l3vpn_head, l3vpn);
@@ -267,6 +270,7 @@ struct filter_rule;
TAILQ_HEAD(filter_head, filter_rule);
struct bgpd_config {
+ struct peer_head peers;
struct l3vpn_head l3vpns;
struct network_head networks;
struct filter_head *filters;
@@ -376,7 +380,6 @@ struct peer_config {
enum export_type export_type;
enum enforce_as enforce_as;
enum enforce_as enforce_local_as;
- enum reconf_action reconf_action;
u_int16_t max_prefix_restart;
u_int16_t holdtime;
u_int16_t min_holdtime;
diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c
index e3a9a93fe61..f263fa6e202 100644
--- a/usr.sbin/bgpd/config.c
+++ b/usr.sbin/bgpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.86 2019/03/15 09:54:54 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.87 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -54,6 +54,7 @@ new_config(void)
fatal(NULL);
/* init the various list for later */
+ TAILQ_INIT(&conf->peers);
TAILQ_INIT(&conf->networks);
SIMPLEQ_INIT(&conf->l3vpns);
SIMPLEQ_INIT(&conf->prefixsets);
@@ -156,6 +157,7 @@ free_prefixtree(struct prefixset_tree *p)
void
free_config(struct bgpd_config *conf)
{
+ struct peer *p;
struct listen_addr *la;
struct mrt *m;
@@ -181,6 +183,11 @@ free_config(struct bgpd_config *conf)
}
free(conf->mrt);
+ while ((p = TAILQ_FIRST(&conf->peers)) != NULL) {
+ TAILQ_REMOVE(&conf->peers, p, entry);
+ free(p);
+ }
+
free(conf->csock);
free(conf->rcsock);
@@ -188,11 +195,11 @@ free_config(struct bgpd_config *conf)
}
void
-merge_config(struct bgpd_config *xconf, struct bgpd_config *conf,
- struct peer *peer_l)
+merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
{
struct listen_addr *nla, *ola, *next;
struct network *n;
+ struct peer *p, *np;
/*
* merge the freshly parsed conf into the running xconf
@@ -299,6 +306,26 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf,
}
}
+ /*
+ * merge peers:
+ * - need to know which peers are new, replaced and removed
+ * - first mark all new peers as RECONF_REINIT
+ * - walk over old peers and check if there is a corresponding new
+ * peer if so mark it RECONF_KEEP. Remove all old peers.
+ * - swap lists (old peer list is actually empty).
+ */
+ TAILQ_FOREACH(p, &conf->peers, entry)
+ p->reconf_action = RECONF_REINIT;
+ while ((p = TAILQ_FIRST(&xconf->peers)) != NULL) {
+ np = getpeerbyid(conf, p->conf.id);
+ if (np != NULL)
+ np->reconf_action = RECONF_KEEP;
+
+ TAILQ_REMOVE(&xconf->peers, p, entry);
+ free(p);
+ }
+ TAILQ_CONCAT(&xconf->peers, &conf->peers, entry);
+
/* conf is merged so free it */
free_config(conf);
}
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index f856ee5187c..b6684e9bfe4 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.95 2019/02/12 13:30:39 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.96 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -220,7 +220,8 @@ control_close(int fd)
}
int
-control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
+control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt,
+ struct peer_head *peers)
{
struct imsg imsg;
struct ctl_conn *c;
@@ -294,7 +295,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
0, NULL, 0);
break;
case IMSG_CTL_SHOW_TERSE:
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, peers, entry)
imsg_compose(&c->ibuf, IMSG_CTL_SHOW_NEIGHBOR,
0, 0, -1, p, sizeof(struct peer));
imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
@@ -309,7 +310,8 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
} else {
neighbor = NULL;
}
- for (matched = 0, p = peers; p != NULL; p = p->next) {
+ matched = 0;
+ TAILQ_FOREACH(p, peers, entry) {
if (!peer_matched(p, neighbor))
continue;
@@ -337,7 +339,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
}
}
}
- if (!matched && peers != NULL) {
+ if (!matched && TAILQ_EMPTY(peers)) {
control_result(c, CTL_RES_NOSUCHPEER);
} else if (!neighbor || !neighbor->show_timers) {
imsg_ctl_rde(IMSG_CTL_END, imsg.hdr.pid,
@@ -362,7 +364,8 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
neighbor = imsg.data;
neighbor->descr[PEER_DESCR_LEN - 1] = 0;
- for (matched = 0, p = peers; p != NULL; p = p->next) {
+ matched = 0;
+ TAILQ_FOREACH(p, peers, entry) {
if (!peer_matched(p, neighbor))
continue;
@@ -417,7 +420,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
* Mark as deleted, will be
* collected on next poll loop.
*/
- p->conf.reconf_action =
+ p->reconf_action =
RECONF_DELETE;
control_result(c, CTL_RES_OK);
}
@@ -458,10 +461,10 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
neighbor->descr[PEER_DESCR_LEN - 1] = 0;
/* check if at least one neighbor exists */
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, peers, entry)
if (peer_matched(p, neighbor))
break;
- if (p == NULL && peers != NULL) {
+ if (p == NULL && TAILQ_EMPTY(peers)) {
control_result(c, CTL_RES_NOSUCHPEER);
break;
}
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index a0bca769d66..3ce72c061e9 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.384 2019/03/15 09:54:54 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.385 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -88,7 +88,7 @@ char *symget(const char *);
static struct bgpd_config *conf;
static struct network_head *netconf;
-static struct peer *peer_l, *peer_l_old;
+static struct peer_head *new_peers, *cur_peers;
static struct peer *curpeer;
static struct peer *curgroup;
static struct l3vpn *curvpn;
@@ -99,7 +99,6 @@ static struct filter_head *peerfilter_l;
static struct filter_head *groupfilter_l;
static struct filter_rule *curpeer_filter[2];
static struct filter_rule *curgroup_filter[2];
-static u_int32_t id;
struct filter_rib_l {
struct filter_rib_l *next;
@@ -1203,8 +1202,7 @@ neighbor : { curpeer = new_peer(); }
if (neighbor_consistent(curpeer) == -1)
YYERROR;
- curpeer->next = peer_l;
- peer_l = curpeer;
+ TAILQ_INSERT_TAIL(new_peers, curpeer, entry);
curpeer = curgroup;
}
;
@@ -1812,7 +1810,7 @@ filter_peer : ANY {
fatal(NULL);
$$->p.remote_as = $$->p.groupid = $$->p.peerid = 0;
$$->next = NULL;
- for (p = peer_l; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, new_peers, entry)
if (!memcmp(&p->conf.remote_addr,
&$1, sizeof(p->conf.remote_addr))) {
$$->p.peerid = p->conf.id;
@@ -1839,7 +1837,7 @@ filter_peer : ANY {
fatal(NULL);
$$->p.remote_as = $$->p.peerid = 0;
$$->next = NULL;
- for (p = peer_l; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, new_peers, entry)
if (!strcmp(p->conf.group, $2)) {
$$->p.groupid = p->conf.groupid;
break;
@@ -3263,11 +3261,10 @@ init_config(struct bgpd_config *c)
fatal(NULL);
}
-int
-parse_config(char *filename, struct bgpd_config *xconf, struct peer **xpeers)
+struct bgpd_config *
+parse_config(char *filename, struct peer_head *ph)
{
struct sym *sym, *next;
- struct peer *p, *pnext;
struct rde_rib *rr;
struct network *n;
int errors = 0;
@@ -3285,12 +3282,11 @@ parse_config(char *filename, struct bgpd_config *xconf, struct peer **xpeers)
TAILQ_INIT(peerfilter_l);
TAILQ_INIT(groupfilter_l);
- peer_l = NULL;
- peer_l_old = *xpeers;
curpeer = NULL;
curgroup = NULL;
- id = 1;
+ cur_peers = ph;
+ new_peers = &conf->peers;
netconf = &conf->networks;
add_rib("Adj-RIB-In", conf->default_tableid,
@@ -3334,13 +3330,15 @@ parse_config(char *filename, struct bgpd_config *xconf, struct peer **xpeers)
errors++;
}
+ /* clear the globals */
+ curpeer = NULL;
+ curgroup = NULL;
+ cur_peers = NULL;
+ new_peers = NULL;
+ netconf = NULL;
+
if (errors) {
errors:
- for (p = peer_l; p != NULL; p = pnext) {
- pnext = p->next;
- free(p);
- }
-
while ((rr = SIMPLEQ_FIRST(&ribnames)) != NULL) {
SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
free(rr);
@@ -3351,7 +3349,7 @@ errors:
filterlist_free(groupfilter_l);
free_config(conf);
- return -1;
+ return (NULL);
} else {
/*
* Concatenate filter list and static group and peer filtersets
@@ -3364,18 +3362,11 @@ errors:
optimize_filters(conf->filters);
- merge_config(xconf, conf, peer_l);
- *xpeers = peer_l;
-
- for (p = peer_l_old; p != NULL; p = pnext) {
- pnext = p->next;
- free(p);
- }
-
free(filter_l);
free(peerfilter_l);
free(groupfilter_l);
- return 0;
+
+ return (conf);
}
}
@@ -3784,7 +3775,6 @@ alloc_peer(void)
/* some sane defaults */
p->state = STATE_NONE;
- p->next = NULL;
p->conf.distance = 1;
p->conf.export_type = EXPORT_UNSET;
p->conf.announce_capa = 1;
@@ -3796,6 +3786,9 @@ alloc_peer(void)
p->conf.local_as = conf->as;
p->conf.local_short_as = conf->short_as;
+ if (conf->flags & BGPD_FLAG_DECISION_TRANS_AS)
+ p->conf.flags |= PEERFLAG_TRANS_AS;
+
return (p);
}
@@ -3818,9 +3811,6 @@ new_peer(void)
p->conf.local_as = curgroup->conf.local_as;
p->conf.local_short_as = curgroup->conf.local_short_as;
}
- p->next = NULL;
- if (conf->flags & BGPD_FLAG_DECISION_TRANS_AS)
- p->conf.flags |= PEERFLAG_TRANS_AS;
return (p);
}
@@ -3962,34 +3952,41 @@ find_prefixset(char *name, struct prefixset_head *p)
int
get_id(struct peer *newpeer)
{
- struct peer *p;
-
- for (p = peer_l_old; p != NULL; p = p->next)
- if (newpeer->conf.remote_addr.aid) {
- if (!memcmp(&p->conf.remote_addr,
- &newpeer->conf.remote_addr,
- sizeof(p->conf.remote_addr))) {
- newpeer->conf.id = p->conf.id;
- return (0);
- }
- } else { /* newpeer is a group */
- if (strcmp(newpeer->conf.group, p->conf.group) == 0) {
- newpeer->conf.id = p->conf.groupid;
- return (0);
- }
+ static u_int32_t id = 1;
+ struct peer *p = NULL;
+
+ /* check if the peer already existed before */
+ if (newpeer->conf.remote_addr.aid) {
+ /* neighbor */
+ if (cur_peers)
+ TAILQ_FOREACH(p, cur_peers, entry)
+ if (memcmp(&p->conf.remote_addr,
+ &newpeer->conf.remote_addr,
+ sizeof(p->conf.remote_addr)) == 0)
+ break;
+ if (p) {
+ newpeer->conf.id = p->conf.id;
+ return (0);
}
-
- /* new one */
- for (; id < UINT_MAX / 2; id++) {
- for (p = peer_l_old; p != NULL &&
- p->conf.id != id && p->conf.groupid != id; p = p->next)
- ; /* nothing */
- if (p == NULL) { /* we found a free id */
- newpeer->conf.id = id++;
+ } else {
+ /* group */
+ if (cur_peers)
+ TAILQ_FOREACH(p, cur_peers, entry)
+ if (strcmp(p->conf.group,
+ newpeer->conf.group) == 0)
+ break;
+ if (p) {
+ newpeer->conf.id = p->conf.groupid;
return (0);
}
}
+ /* else new one */
+ if (id < UINT_MAX / 2) {
+ newpeer->conf.id = id++;
+ return (0);
+ }
+
return (-1);
}
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 51019f1ecea..9a4e99d4785 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.133 2019/03/15 09:54:54 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.134 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -49,11 +49,11 @@ const char *print_auth_alg(u_int8_t);
const char *print_enc_alg(u_int8_t);
void print_announce(struct peer_config *, const char *);
void print_as(struct filter_rule *);
-void print_rule(struct peer *, struct filter_rule *);
+void print_rule(struct bgpd_config *, struct filter_rule *);
const char *mrt_type(enum mrt_type);
void print_mrt(struct bgpd_config *, u_int32_t, u_int32_t,
const char *, const char *);
-void print_groups(struct bgpd_config *, struct peer *);
+void print_groups(struct bgpd_config *);
int peer_compare(const void *, const void *);
void
@@ -759,7 +759,7 @@ print_as(struct filter_rule *r)
}
void
-print_rule(struct peer *peer_l, struct filter_rule *r)
+print_rule(struct bgpd_config *conf, struct filter_rule *r)
{
struct peer *p;
int i;
@@ -784,17 +784,17 @@ print_rule(struct peer *peer_l, struct filter_rule *r)
printf("eeeeeeeps. ");
if (r->peer.peerid) {
- for (p = peer_l; p != NULL && p->conf.id != r->peer.peerid;
- p = p->next)
- ; /* nothing */
+ TAILQ_FOREACH(p, &conf->peers, entry)
+ if (p->conf.id == r->peer.peerid)
+ break;
if (p == NULL)
printf("? ");
else
printf("%s ", log_addr(&p->conf.remote_addr));
} else if (r->peer.groupid) {
- for (p = peer_l; p != NULL &&
- p->conf.groupid != r->peer.groupid; p = p->next)
- ; /* nothing */
+ TAILQ_FOREACH(p, &conf->peers, entry)
+ if (p->conf.groupid == r->peer.groupid)
+ break;
if (p == NULL)
printf("group ? ");
else
@@ -928,7 +928,7 @@ print_mrt(struct bgpd_config *conf, u_int32_t pid, u_int32_t gid,
}
void
-print_groups(struct bgpd_config *conf, struct peer *peer_l)
+print_groups(struct bgpd_config *conf)
{
struct peer_config **peerlist;
struct peer *p;
@@ -939,14 +939,14 @@ print_groups(struct bgpd_config *conf, struct peer *peer_l)
const char *c;
peer_cnt = 0;
- for (p = peer_l; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &conf->peers, entry)
peer_cnt++;
if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL)
fatal("print_groups calloc");
i = 0;
- for (p = peer_l; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &conf->peers, entry)
peerlist[i++] = &p->conf;
qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare);
@@ -986,10 +986,7 @@ peer_compare(const void *aa, const void *bb)
}
void
-print_config(struct bgpd_config *conf, struct rib_names *rib_l,
- struct network_head *net_l, struct peer *peer_l,
- struct filter_head *rules_l, struct mrt_head *mrt_l,
- struct l3vpn_head *vpns_l)
+print_config(struct bgpd_config *conf, struct rib_names *rib_l)
{
struct filter_rule *r;
struct network *n;
@@ -1001,11 +998,11 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l,
print_as_sets(conf->as_sets);
print_prefixsets(&conf->prefixsets);
print_originsets(&conf->originsets);
- TAILQ_FOREACH(n, net_l, entry)
+ TAILQ_FOREACH(n, &conf->networks, entry)
print_network(&n->net, "");
- if (!SIMPLEQ_EMPTY(vpns_l))
+ if (!SIMPLEQ_EMPTY(&conf->l3vpns))
printf("\n");
- SIMPLEQ_FOREACH(vpn, vpns_l, entry)
+ SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry)
print_l3vpn(vpn);
printf("\n");
SIMPLEQ_FOREACH(rr, rib_l, entry) {
@@ -1020,7 +1017,7 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l,
}
printf("\n");
print_mrt(conf, 0, 0, "", "");
- print_groups(conf, peer_l);
- TAILQ_FOREACH(r, rules_l, entry)
- print_rule(peer_l, r);
+ print_groups(conf);
+ TAILQ_FOREACH(r, conf->filters, entry)
+ print_rule(conf, r);
}
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index a4e242450fa..3844916ee39 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.376 2019/03/15 09:54:54 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.377 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -94,17 +94,15 @@ void session_up(struct peer *);
void session_down(struct peer *);
int imsg_rde(int, u_int32_t, void *, u_int16_t);
void session_demote(struct peer *, int);
+void merge_peers(struct bgpd_config *, struct bgpd_config *);
int la_cmp(struct listen_addr *, struct listen_addr *);
-struct peer *getpeerbyip(struct sockaddr *);
-struct peer *getpeerbyid(u_int32_t);
void session_template_clone(struct peer *, struct sockaddr *,
u_int32_t, u_int32_t);
int session_match_mask(struct peer *, struct bgpd_addr *);
struct bgpd_config *conf, *nconf;
struct bgpd_sysdep sysdep;
-struct peer *peers, *npeers;
volatile sig_atomic_t session_quit;
int pending_reconf;
int csock = -1, rcsock = -1;
@@ -196,7 +194,7 @@ session_main(int debug, int verbose)
u_int listener_cnt, ctl_cnt, mrt_cnt;
u_int new_cnt;
struct passwd *pw;
- struct peer *p, **peer_l = NULL, *last, *next;
+ struct peer *p, **peer_l = NULL, *next;
struct mrt *m, *xm, **mrt_l = NULL;
struct pollfd *pfd = NULL;
struct ctl_conn *ctl_conn;
@@ -251,46 +249,43 @@ session_main(int debug, int verbose)
while (session_quit == 0) {
/* check for peers to be initialized or deleted */
- last = NULL;
if (!pending_reconf) {
- for (p = peers; p != NULL; p = next) {
- next = p->next;
+ for (p = TAILQ_FIRST(&conf->peers); p != NULL;
+ p = next) {
+ next = TAILQ_NEXT(p, entry);
/* cloned peer that idled out? */
if (p->template && (p->state == STATE_IDLE ||
p->state == STATE_ACTIVE) &&
time(NULL) - p->stats.last_updown >=
INTERVAL_HOLD_CLONED)
- p->conf.reconf_action = RECONF_DELETE;
+ p->reconf_action = RECONF_DELETE;
/* new peer that needs init? */
if (p->state == STATE_NONE)
init_peer(p);
/* reinit due? */
- if (p->conf.reconf_action == RECONF_REINIT) {
+ if (p->reconf_action == RECONF_REINIT) {
session_stop(p, ERR_CEASE_ADMIN_RESET);
if (!p->conf.down)
timer_set(p, Timer_IdleHold, 0);
}
/* deletion due? */
- if (p->conf.reconf_action == RECONF_DELETE) {
+ if (p->reconf_action == RECONF_DELETE) {
if (p->demoted)
session_demote(p, -1);
p->conf.demote_group[0] = 0;
session_stop(p, ERR_CEASE_PEER_UNCONF);
log_peer_warnx(&p->conf, "removed");
- if (last != NULL)
- last->next = next;
- else
- peers = next;
+ TAILQ_REMOVE(&conf->peers, p, entry);
timer_remove_all(p);
+ pfkey_remove(p);
free(p);
peer_cnt--;
continue;
}
- p->conf.reconf_action = RECONF_NONE;
- last = p;
+ p->reconf_action = RECONF_NONE;
}
}
@@ -375,7 +370,7 @@ session_main(int debug, int verbose)
idx_listeners = i;
timeout = 240; /* loop every 240s at least */
- for (p = peers; p != NULL; p = p->next) {
+ TAILQ_FOREACH(p, &conf->peers, entry) {
time_t nextaction;
struct peer_timer *pt;
@@ -526,7 +521,7 @@ session_main(int debug, int verbose)
session_dispatch_msg(&pfd[j],
peer_l[j - idx_listeners]);
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &conf->peers, entry)
if (p->rbuf && p->rbuf->wpos)
session_process_msg(p);
@@ -535,11 +530,11 @@ session_main(int debug, int verbose)
mrt_write(mrt_l[j - idx_peers]);
for (; j < i; j++)
- control_dispatch_msg(&pfd[j], &ctl_cnt);
+ control_dispatch_msg(&pfd[j], &ctl_cnt, &conf->peers);
}
- while ((p = peers) != NULL) {
- peers = p->next;
+ while ((p = TAILQ_FIRST(&conf->peers)) != NULL) {
+ TAILQ_REMOVE(&conf->peers, p, entry);
strlcpy(p->conf.shutcomm,
"bgpd shutting down",
sizeof(p->conf.shutcomm));
@@ -608,7 +603,7 @@ init_peer(struct peer *p)
* do not handle new peers. they must reach ESTABLISHED beforehands.
* peers added at runtime have reconf_action set to RECONF_REINIT.
*/
- if (p->conf.reconf_action != RECONF_REINIT && p->conf.demote_group[0])
+ if (p->reconf_action != RECONF_REINIT && p->conf.demote_group[0])
session_demote(p, +1);
}
@@ -1008,7 +1003,7 @@ session_accept(int listenfd)
return;
}
- p = getpeerbyip((struct sockaddr *)&cliaddr);
+ p = getpeerbyip(conf, (struct sockaddr *)&cliaddr);
if (p != NULL && p->state == STATE_IDLE && p->errcnt < 2) {
if (timer_running(p, Timer_IdleHold, NULL)) {
@@ -1523,7 +1518,7 @@ session_update(u_int32_t peerid, void *data, size_t datalen)
struct peer *p;
struct bgp_msg *buf;
- if ((p = getpeerbyid(peerid)) == NULL) {
+ if ((p = getpeerbyid(conf, peerid)) == NULL) {
log_warnx("no such peer: id=%u", peerid);
return;
}
@@ -2555,12 +2550,10 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
struct mrt xmrt;
struct mrt *mrt;
struct imsgbuf *i;
- struct peer_config *pconf;
- struct peer *p, *next;
+ struct peer *p;
struct listen_addr *la, *nla;
struct kif *kif;
u_char *data;
- enum reconf_action reconf;
int n, fd, depend_ok, restricted;
u_int8_t aid, errcode, subcode;
@@ -2606,7 +2599,6 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
if (idx != PFD_PIPE_MAIN)
fatalx("reconf request not from parent");
nconf = new_config();
- npeers = NULL;
copy_config(nconf, imsg.data);
pending_reconf = 1;
@@ -2614,45 +2606,12 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
case IMSG_RECONF_PEER:
if (idx != PFD_PIPE_MAIN)
fatalx("reconf request not from parent");
- pconf = imsg.data;
- p = getpeerbyaddr(&pconf->remote_addr);
- if (p == NULL) {
- if ((p = calloc(1, sizeof(struct peer))) ==
- NULL)
- fatal("new_peer");
- p->state = p->prev_state = STATE_NONE;
- p->next = npeers;
- npeers = p;
- reconf = RECONF_REINIT;
- } else
- reconf = RECONF_KEEP;
-
- memcpy(&p->conf, pconf, sizeof(struct peer_config));
- p->conf.reconf_action = reconf;
-
- /* sync the RDE in case we keep the peer */
- if (reconf == RECONF_KEEP) {
- if (imsg_rde(IMSG_SESSION_ADD, p->conf.id,
- &p->conf, sizeof(struct peer_config)) == -1)
- fatalx("imsg_compose error");
- if (p->conf.template) {
- /* apply the conf to all clones */
- struct peer *np;
- for (np = peers; np; np = np->next) {
- if (np->template != p)
- continue;
- session_template_clone(np,
- NULL, np->conf.id,
- np->conf.remote_as);
- if (imsg_rde(IMSG_SESSION_ADD,
- np->conf.id, &np->conf,
- sizeof(struct peer_config))
- == -1)
- fatalx("imsg_compose"
- " error");
- }
- }
- }
+ if ((p = calloc(1, sizeof(struct peer))) == NULL)
+ fatal("new_peer");
+ memcpy(&p->conf, imsg.data, sizeof(struct peer_config));
+ p->state = p->prev_state = STATE_NONE;
+ p->reconf_action = RECONF_REINIT;
+ TAILQ_INSERT_TAIL(&nconf->peers, p, entry);
break;
case IMSG_RECONF_LISTENER:
if (idx != PFD_PIPE_MAIN)
@@ -2723,23 +2682,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
if (nconf == NULL)
fatalx("got IMSG_RECONF_DONE but no config");
copy_config(conf, nconf);
-
- /* add new peers */
- for (p = npeers; p != NULL; p = next) {
- next = p->next;
- p->next = peers;
- peers = p;
- }
- /* find ones that need attention */
- for (p = peers; p != NULL; p = p->next) {
- /* needs to be deleted? */
- if (p->conf.reconf_action == RECONF_NONE &&
- !p->template)
- p->conf.reconf_action = RECONF_DELETE;
- /* had demotion, is demoted, demote removed? */
- if (p->demoted && !p->conf.demote_group[0])
- session_demote(p, -1);
- }
+ merge_peers(conf, nconf);
/* delete old listeners */
for (la = TAILQ_FIRST(conf->listen_addrs); la != NULL;
@@ -2781,7 +2724,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
kif = imsg.data;
depend_ok = kif->depend_state;
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &conf->peers, entry)
if (!strcmp(p->conf.if_depend, kif->ifname)) {
if (depend_ok && !p->depend_ok) {
p->depend_ok = depend_ok;
@@ -2876,7 +2819,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
log_warnx("RDE sent invalid notification");
break;
}
- if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) {
+ if ((p = getpeerbyid(conf, imsg.hdr.peerid)) == NULL) {
log_warnx("no such peer: id=%u",
imsg.hdr.peerid);
break;
@@ -2916,7 +2859,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
log_warnx("RDE sent invalid restart msg");
break;
}
- if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) {
+ if ((p = getpeerbyid(conf, imsg.hdr.peerid)) == NULL) {
log_warnx("no such peer: id=%u",
imsg.hdr.peerid);
break;
@@ -2943,7 +2886,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
case IMSG_SESSION_DOWN:
if (idx != PFD_PIPE_ROUTE)
fatalx("update request not from RDE");
- if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) {
+ if ((p = getpeerbyid(conf, imsg.hdr.peerid)) == NULL) {
log_warnx("no such peer: id=%u",
imsg.hdr.peerid);
break;
@@ -2993,26 +2936,12 @@ la_cmp(struct listen_addr *a, struct listen_addr *b)
}
struct peer *
-getpeerbyaddr(struct bgpd_addr *addr)
-{
- struct peer *p;
-
- /* we might want a more effective way to find peers by IP */
- for (p = peers; p != NULL &&
- memcmp(&p->conf.remote_addr, addr, sizeof(p->conf.remote_addr));
- p = p->next)
- ; /* nothing */
-
- return (p);
-}
-
-struct peer *
-getpeerbydesc(const char *descr)
+getpeerbydesc(struct bgpd_config *c, const char *descr)
{
struct peer *p, *res = NULL;
int match = 0;
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &c->peers, entry)
if (!strcmp(p->conf.descr, descr)) {
res = p;
match++;
@@ -3029,7 +2958,7 @@ getpeerbydesc(const char *descr)
}
struct peer *
-getpeerbyip(struct sockaddr *ip)
+getpeerbyip(struct bgpd_config *c, struct sockaddr *ip)
{
struct bgpd_addr addr;
struct peer *p, *newpeer, *loose = NULL;
@@ -3038,13 +2967,13 @@ getpeerbyip(struct sockaddr *ip)
sa2addr(ip, &addr, NULL);
/* we might want a more effective way to find peers by IP */
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &c->peers, entry)
if (!p->conf.template &&
!memcmp(&addr, &p->conf.remote_addr, sizeof(addr)))
return (p);
/* try template matching */
- for (p = peers; p != NULL; p = p->next)
+ TAILQ_FOREACH(p, &c->peers, entry)
if (p->conf.template &&
p->conf.remote_addr.aid == addr.aid &&
session_match_mask(p, &addr))
@@ -3058,22 +2987,20 @@ getpeerbyip(struct sockaddr *ip)
fatal(NULL);
memcpy(newpeer, loose, sizeof(struct peer));
for (id = UINT_MAX; id > UINT_MAX / 2; id--) {
- for (p = peers; p != NULL && p->conf.id != id;
- p = p->next)
- ; /* nothing */
- if (p == NULL) { /* we found a free id */
+ TAILQ_FOREACH(p, &c->peers, entry)
+ if (p->conf.id == id)
+ break;
+ if (p == NULL) /* we found a free id */
break;
- }
}
newpeer->template = loose;
session_template_clone(newpeer, ip, id, 0);
newpeer->state = newpeer->prev_state = STATE_NONE;
- newpeer->conf.reconf_action = RECONF_KEEP;
+ newpeer->reconf_action = RECONF_KEEP;
newpeer->rbuf = NULL;
init_peer(newpeer);
bgp_fsm(newpeer, EVNT_START);
- newpeer->next = peers;
- peers = newpeer;
+ TAILQ_INSERT_TAIL(&c->peers, newpeer, entry);
return (newpeer);
}
@@ -3081,16 +3008,15 @@ getpeerbyip(struct sockaddr *ip)
}
struct peer *
-getpeerbyid(u_int32_t peerid)
+getpeerbyid(struct bgpd_config *c, u_int32_t peerid)
{
struct peer *p;
- /* we might want a more effective way to find peers by IP */
- for (p = peers; p != NULL &&
- p->conf.id != peerid; p = p->next)
- ; /* nothing */
-
- return (p);
+ /* we might want a more effective way to find peers by id */
+ TAILQ_FOREACH(p, &c->peers, entry)
+ if (p->conf.id == peerid)
+ return (p);
+ return (NULL);
}
int
@@ -3286,3 +3212,51 @@ session_stop(struct peer *peer, u_int8_t subcode)
}
bgp_fsm(peer, EVNT_STOP);
}
+
+void
+merge_peers(struct bgpd_config *c, struct bgpd_config *nc)
+{
+ struct peer *p, *np;
+
+ TAILQ_FOREACH(p, &c->peers, entry) {
+ /* templates are handled specially */
+ if (p->template != NULL)
+ continue;
+ np = getpeerbyid(nc, p->conf.id);
+ if (np == NULL) {
+ p->reconf_action = RECONF_DELETE;
+ continue;
+ }
+
+ memcpy(&p->conf, &np->conf, sizeof(p->conf));
+ TAILQ_REMOVE(&nc->peers, np, entry);
+ free(np);
+
+ p->reconf_action = RECONF_KEEP;
+
+ /* had demotion, is demoted, demote removed? */
+ if (p->demoted && !p->conf.demote_group[0])
+ session_demote(p, -1);
+
+ /* sync the RDE in case we keep the peer */
+ if (imsg_rde(IMSG_SESSION_ADD, p->conf.id,
+ &p->conf, sizeof(struct peer_config)) == -1)
+ fatalx("imsg_compose error");
+
+ /* apply the config to all clones of a template */
+ if (p->conf.template) {
+ struct peer *xp;
+ TAILQ_FOREACH(xp, &conf->peers, entry) {
+ if (xp->template != p)
+ continue;
+ session_template_clone(xp, NULL, xp->conf.id,
+ xp->conf.remote_as);
+ if (imsg_rde(IMSG_SESSION_ADD, xp->conf.id,
+ &xp->conf, sizeof(xp->conf)) == -1)
+ fatalx("imsg_compose error");
+ }
+ }
+ }
+
+ TAILQ_CONCAT(&c->peers, &nc->peers, entry);
+}
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index ead763c2711..22183e2f8e2 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.134 2019/03/07 07:42:36 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.135 2019/03/31 16:57:38 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -196,6 +196,7 @@ TAILQ_HEAD(peer_timer_head, peer_timer);
struct peer {
struct peer_config conf;
struct peer_stats stats;
+ TAILQ_ENTRY(peer) entry;
struct {
struct capabilities ann;
struct capabilities peer;
@@ -207,13 +208,12 @@ struct peer {
u_int32_t spi_out;
enum auth_method method;
u_int8_t established;
- } auth;
+ } auth;
struct bgpd_addr local;
struct bgpd_addr remote;
struct peer_timer_head timers;
struct msgbuf wbuf;
struct ibuf_read *rbuf;
- struct peer *next;
struct peer *template;
int fd;
int lasterr;
@@ -222,6 +222,7 @@ struct peer {
u_int32_t remote_bgpid;
enum session_state state;
enum session_state prev_state;
+ enum reconf_action reconf_action;
u_int16_t short_as;
u_int16_t holdtime;
u_int16_t local_port;
@@ -232,7 +233,6 @@ struct peer {
u_int8_t throttled;
};
-extern struct peer *peers;
extern time_t pauseaccept;
struct ctl_timer {
@@ -247,8 +247,7 @@ int carp_demote_get(char *);
int carp_demote_set(char *, int);
/* config.c */
-void merge_config(struct bgpd_config *, struct bgpd_config *,
- struct peer *);
+void merge_config(struct bgpd_config *, struct bgpd_config *);
int prepare_listeners(struct bgpd_config *);
/* control.c */
@@ -256,7 +255,7 @@ int control_check(char *);
int control_init(int, char *);
int control_listen(int);
void control_shutdown(int);
-int control_dispatch_msg(struct pollfd *, u_int *);
+int control_dispatch_msg(struct pollfd *, u_int *, struct peer_head *);
unsigned int control_accept(int, int);
/* log.c */
@@ -276,7 +275,7 @@ void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t,
void mrt_done(struct mrt *);
/* parse.y */
-int parse_config(char *, struct bgpd_config *, struct peer **);
+struct bgpd_config *parse_config(char *, struct peer_head *);
/* pfkey.c */
int pfkey_read(int, struct sadb_msg *);
@@ -285,9 +284,7 @@ int pfkey_remove(struct peer *);
int pfkey_init(struct bgpd_sysdep *);
/* printconf.c */
-void print_config(struct bgpd_config *, struct rib_names *,
- struct network_head *, struct peer *, struct filter_head *,
- struct mrt_head *, struct l3vpn_head *);
+void print_config(struct bgpd_config *, struct rib_names *);
/* rde.c */
void rde_main(int, int);
@@ -296,8 +293,9 @@ void rde_main(int, int);
void session_main(int, int);
void bgp_fsm(struct peer *, enum session_events);
int session_neighbor_rrefresh(struct peer *p);
-struct peer *getpeerbyaddr(struct bgpd_addr *);
-struct peer *getpeerbydesc(const char *);
+struct peer *getpeerbydesc(struct bgpd_config *, const char *);
+struct peer *getpeerbyip(struct bgpd_config *, struct sockaddr *);
+struct peer *getpeerbyid(struct bgpd_config *, u_int32_t);
int peer_matched(struct peer *, struct ctl_neighbor *);
int imsg_ctl_parent(int, u_int32_t, pid_t, void *, u_int16_t);
int imsg_ctl_rde(int, pid_t, void *, u_int16_t);