diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2013-03-07 21:26:29 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2013-03-07 21:26:29 +0000 |
commit | bbc36091a439968012b5b5bc303451041597204b (patch) | |
tree | 64cd418c24cab49da5fc68d30ebd01b6ceee1f7e /usr.sbin/bgpd | |
parent | df1dcad0f10f44fc8129846246dc20bf4db6fae8 (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.c | 15 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/control.c | 20 | ||||
-rw-r--r-- | usr.sbin/bgpd/log.h | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 94 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 3 |
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; |