summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2013-03-07 21:26:29 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2013-03-07 21:26:29 +0000
commitbbc36091a439968012b5b5bc303451041597204b (patch)
tree64cd418c24cab49da5fc68d30ebd01b6ceee1f7e /usr.sbin/bgpd
parentdf1dcad0f10f44fc8129846246dc20bf4db6fae8 (diff)
Implements a few missing bits for better templates support:
- on config reload also adjust the cloned neighbors so that they get the config changes as well. - clean up sessions that are 1h idle but in state active (instead of down) - add bits to allow bgpctl to destroy cloned neighbors Tested by sthen@ some time ago, OK phessler@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.c15
-rw-r--r--usr.sbin/bgpd/bgpd.h9
-rw-r--r--usr.sbin/bgpd/control.c20
-rw-r--r--usr.sbin/bgpd/log.h6
-rw-r--r--usr.sbin/bgpd/session.c94
-rw-r--r--usr.sbin/bgpd/session.h3
6 files changed, 111 insertions, 36 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 72746e2c6e6..86aaabca976 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.170 2012/11/02 18:02:45 florian Exp $ */
+/* $OpenBSD: bgpd.c,v 1.171 2013/03/07 21:26:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -479,14 +479,11 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
free(rr);
}
- /* send peer list and listeners to the SE and RDE */
+ /* send peer list to the SE */
for (p = *peer_l; p != NULL; p = p->next) {
if (imsg_compose(ibuf_se, IMSG_RECONF_PEER, p->conf.id, 0, -1,
&p->conf, sizeof(struct peer_config)) == -1)
return (-1);
- if (imsg_compose(ibuf_rde, IMSG_RECONF_PEER, p->conf.id, 0, -1,
- &p->conf, sizeof(struct peer_config)) == -1)
- return (-1);
}
/* networks go via kroute to the RDE */
@@ -544,9 +541,8 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
free(rd);
}
- /* signal both childs to replace their config */
- if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1 ||
- imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1)
+ /* signal the SE first then the RDE to activate the new config */
+ if (imsg_compose(ibuf_se, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0) == -1)
return (-1);
/* fix kroute information */
@@ -710,6 +706,9 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx)
case IMSG_RECONF_DONE:
if (reconfpending == 0)
log_warnx("unexpected RECONF_DONE received");
+ else if (reconfpending == 2)
+ imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0,
+ 0, -1, NULL, 0);
reconfpending--;
break;
default:
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index efb0490eb4e..5e64703cab7 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.275 2013/01/09 08:04:25 phessler Exp $ */
+/* $OpenBSD: bgpd.h,v 1.276 2013/03/07 21:26:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -297,7 +297,6 @@ struct peer_config {
u_int16_t local_short_as;
u_int8_t template;
u_int8_t remote_masklen;
- u_int8_t cloned;
u_int8_t ebgp; /* 0 = ibgp else ebgp */
u_int8_t distance; /* 1 = direct, >1 = multihop */
u_int8_t passive;
@@ -308,7 +307,6 @@ struct peer_config {
u_int8_t softreconfig_out;
u_int8_t ttlsec; /* TTL security hack */
u_int8_t flags;
- u_int8_t pad[3];
};
#define PEERFLAG_TRANS_AS 0x01
@@ -347,6 +345,7 @@ enum imsg_type {
IMSG_CTL_NEIGHBOR_DOWN,
IMSG_CTL_NEIGHBOR_CLEAR,
IMSG_CTL_NEIGHBOR_RREFRESH,
+ IMSG_CTL_NEIGHBOR_DESTROY,
IMSG_CTL_KROUTE,
IMSG_CTL_KROUTE_ADDR,
IMSG_CTL_RESULT,
@@ -418,7 +417,9 @@ enum ctl_results {
CTL_RES_NOCAP,
CTL_RES_PARSE_ERROR,
CTL_RES_PENDING,
- CTL_RES_NOMEM
+ CTL_RES_NOMEM,
+ CTL_RES_BADPEER,
+ CTL_RES_BADSTATE
};
/* needed for session.h parse prototype */
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index b6b1d9ffb0e..37e67bb280e 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.72 2012/05/27 18:52:07 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.73 2013/03/07 21:26:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -316,6 +316,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
case IMSG_CTL_NEIGHBOR_DOWN:
case IMSG_CTL_NEIGHBOR_CLEAR:
case IMSG_CTL_NEIGHBOR_RREFRESH:
+ case IMSG_CTL_NEIGHBOR_DESTROY:
if (imsg.hdr.len == IMSG_HEADER_SIZE +
sizeof(struct ctl_neighbor)) {
neighbor = imsg.data;
@@ -355,6 +356,23 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
else
control_result(c, CTL_RES_OK);
break;
+ case IMSG_CTL_NEIGHBOR_DESTROY:
+ if (!p->template)
+ control_result(c,
+ CTL_RES_BADPEER);
+ else if (p->state != STATE_IDLE)
+ control_result(c,
+ CTL_RES_BADSTATE);
+ else {
+ /*
+ * Mark as deleted, will be
+ * collected on next poll loop.
+ */
+ p->conf.reconf_action =
+ RECONF_DELETE;
+ control_result(c, CTL_RES_OK);
+ }
+ break;
default:
fatal("king bula wants more humppa");
}
diff --git a/usr.sbin/bgpd/log.h b/usr.sbin/bgpd/log.h
index c15f482e343..bd5a139bc91 100644
--- a/usr.sbin/bgpd/log.h
+++ b/usr.sbin/bgpd/log.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.14 2012/09/18 09:45:51 claudio Exp $ */
+/* $OpenBSD: log.h,v 1.15 2013/03/07 21:26:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -118,7 +118,9 @@ static const char * const ctl_res_strerror[] = {
"neighbor does not have this capability",
"config file has errors, reload failed",
"previous reload still running",
- "out of memory"
+ "out of memory",
+ "not a cloned peer",
+ "peer still active, down peer first"
};
static const char * const timernames[] = {
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index cab4895abee..ae8d7a503bb 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.326 2012/12/01 10:35:17 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.327 2013/03/07 21:26:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -97,6 +97,8 @@ void session_demote(struct peer *, int);
int la_cmp(struct listen_addr *, struct listen_addr *);
struct peer *getpeerbyip(struct sockaddr *);
+void session_template_clone(struct peer *, struct sockaddr *,
+ u_int32_t, u_int32_t);
int session_match_mask(struct peer *, struct bgpd_addr *);
struct peer *getpeerbyid(u_int32_t);
@@ -265,11 +267,12 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
while (session_quit == 0) {
/* check for peers to be initialized or deleted */
last = NULL;
- for (p = peers; p != NULL; p = next) {
- next = p->next;
- if (!pending_reconf) {
+ if (!pending_reconf) {
+ for (p = peers; p != NULL; p = next) {
+ next = p->next;
/* cloned peer that idled out? */
- if (p->state == STATE_IDLE && p->conf.cloned &&
+ 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;
@@ -302,8 +305,8 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
continue;
}
p->conf.reconf_action = RECONF_NONE;
+ last = p;
}
- last = p;
}
if (peer_cnt > peer_l_elms) {
@@ -2148,7 +2151,7 @@ parse_open(struct peer *peer)
}
/* if remote-as is zero and it's a cloned neighbor, accept any */
- if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) {
+ if (peer->template && !peer->conf.remote_as && as != AS_TRANS) {
peer->conf.remote_as = as;
peer->conf.ebgp = (peer->conf.remote_as != conf->as);
if (!peer->conf.ebgp)
@@ -2603,6 +2606,32 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
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_compose(ibuf_rde, IMSG_RECONF_PEER,
+ p->conf.id, 0, -1, &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_compose(ibuf_rde,
+ IMSG_RECONF_PEER,
+ np->conf.id, 0, -1,
+ &np->conf,
+ sizeof(struct peer_config))
+ == -1)
+ fatalx("imsg_compose error");
+ }
+ }
+ }
break;
case IMSG_RECONF_LISTENER:
if (idx != PFD_PIPE_MAIN)
@@ -2688,7 +2717,7 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
for (p = peers; p != NULL; p = p->next) {
/* needs to be deleted? */
if (p->conf.reconf_action == RECONF_NONE &&
- !p->conf.cloned)
+ !p->template)
p->conf.reconf_action = RECONF_DELETE;
/* had demotion, is demoted, demote removed? */
if (p->demoted && !p->conf.demote_group[0])
@@ -3013,21 +3042,11 @@ getpeerbyip(struct sockaddr *ip)
p = p->next)
; /* nothing */
if (p == NULL) { /* we found a free id */
- newpeer->conf.id = id;
break;
}
}
- sa2addr(ip, &newpeer->conf.remote_addr);
- switch (ip->sa_family) {
- case AF_INET:
- newpeer->conf.remote_masklen = 32;
- break;
- case AF_INET6:
- newpeer->conf.remote_masklen = 128;
- break;
- }
- newpeer->conf.template = 0;
- newpeer->conf.cloned = 1;
+ newpeer->template = loose;
+ session_template_clone(newpeer, ip, id, 0);
newpeer->state = newpeer->prev_state = STATE_NONE;
newpeer->conf.reconf_action = RECONF_KEEP;
newpeer->rbuf = NULL;
@@ -3041,6 +3060,41 @@ getpeerbyip(struct sockaddr *ip)
return (NULL);
}
+void
+session_template_clone(struct peer *p, struct sockaddr *ip, u_int32_t id,
+ u_int32_t as)
+{
+ struct bgpd_addr remote_addr;
+
+ if (ip)
+ sa2addr(ip, &remote_addr);
+ else
+ memcpy(&remote_addr, &p->conf.remote_addr, sizeof(remote_addr));
+
+ memcpy(&p->conf, &p->template->conf, sizeof(struct peer_config));
+
+ p->conf.id = id;
+
+ if (as) {
+ p->conf.remote_as = as;
+ p->conf.ebgp = (p->conf.remote_as != conf->as);
+ if (!p->conf.ebgp)
+ /* force enforce_as off for iBGP sessions */
+ p->conf.enforce_as = ENFORCE_AS_OFF;
+ }
+
+ memcpy(&p->conf.remote_addr, &remote_addr, sizeof(remote_addr));
+ switch (p->conf.remote_addr.aid) {
+ case AID_INET:
+ p->conf.remote_masklen = 32;
+ break;
+ case AID_INET6:
+ p->conf.remote_masklen = 128;
+ break;
+ }
+ p->conf.template = 0;
+}
+
int
session_match_mask(struct peer *p, struct bgpd_addr *a)
{
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index fcd63884458..a7f8aa674fd 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.114 2012/09/12 05:56:22 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.115 2013/03/07 21:26:28 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -214,6 +214,7 @@ struct peer {
struct msgbuf wbuf;
struct ibuf_read *rbuf;
struct peer *next;
+ struct peer *template;
int fd;
int lasterr;
u_int errcnt;