diff options
author | 2019-01-20 23:27:48 +0000 | |
---|---|---|
committer | 2019-01-20 23:27:48 +0000 | |
commit | 514180ac497bb4e5521952686fc54599ae252d51 (patch) | |
tree | b79d508372db5c355367e387f82f8a9d408f87f1 | |
parent | allow override of ssh-pkcs11-helper binary via $TEST_SSH_SSHPKCS11HELPER (diff) | |
download | wireguard-openbsd-514180ac497bb4e5521952686fc54599ae252d51.tar.xz wireguard-openbsd-514180ac497bb4e5521952686fc54599ae252d51.zip |
Support group descriptions in control messages that accept a neighbor
description. With this it is possible to show rib a group of peers, to show
or signal a group of peers all at once.
OK sthen@ benno@
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/control.c | 167 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 21 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 47 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 3 |
5 files changed, 134 insertions, 108 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index aa6b94a1a3e..ec9001f02fe 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.362 2019/01/18 23:30:45 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.363 2019/01/20 23:27:48 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -668,6 +668,7 @@ struct ctl_neighbor { char descr[PEER_DESCR_LEN]; char shutcomm[SHUT_COMM_LEN]; int show_timers; + int is_group; }; #define F_PREF_ELIGIBLE 0x01 @@ -781,7 +782,6 @@ struct ctl_show_rib_request { struct bgpd_addr prefix; struct filter_as as; struct filter_community community; - u_int32_t peerid; u_int32_t flags; u_int8_t validation_state; pid_t pid; diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c index 1239b5e811f..f740f562e8b 100644 --- a/usr.sbin/bgpd/control.c +++ b/usr.sbin/bgpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.93 2018/12/27 20:23:24 remi Exp $ */ +/* $OpenBSD: control.c,v 1.94 2019/01/20 23:27:48 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -225,7 +225,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) struct imsg imsg; struct ctl_conn *c; ssize_t n; - int verbose; + int verbose, matched; struct peer *p; struct ctl_neighbor *neighbor; struct ctl_show_rib_request *ribreq; @@ -288,24 +288,36 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) case IMSG_NONE: /* message was filtered out, nothing to do */ break; + case IMSG_CTL_FIB_COUPLE: + case IMSG_CTL_FIB_DECOUPLE: + imsg_ctl_parent(imsg.hdr.type, imsg.hdr.peerid, + 0, NULL, 0); + break; + case IMSG_CTL_SHOW_TERSE: + for (p = peers; p != NULL; p = p->next) + 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); + break; case IMSG_CTL_SHOW_NEIGHBOR: c->ibuf.pid = imsg.hdr.pid; + if (imsg.hdr.len == IMSG_HEADER_SIZE + sizeof(struct ctl_neighbor)) { neighbor = imsg.data; - p = getpeerbyaddr(&neighbor->addr); - if (p == NULL) - p = getpeerbydesc(neighbor->descr); - if (p == NULL) { - control_result(c, CTL_RES_NOSUCHPEER); - break; - } - if (!neighbor->show_timers) { + neighbor->descr[PEER_DESCR_LEN - 1] = 0; + } else { + neighbor = NULL; + } + for (matched = 0, p = peers; p != NULL; p = p->next) { + if (!peer_matched(p, neighbor)) + continue; + + matched = 1; + if (!neighbor || !neighbor->show_timers) { imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid, p, sizeof(struct peer)); - imsg_ctl_rde(IMSG_CTL_END, - imsg.hdr.pid, NULL, 0); } else { u_int i; time_t d; @@ -323,45 +335,39 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) IMSG_CTL_SHOW_TIMER, 0, 0, -1, &ct, sizeof(ct)); } - imsg_compose(&c->ibuf, IMSG_CTL_END, - 0, 0, -1, NULL, 0); } - } else { - for (p = peers; p != NULL; p = p->next) - imsg_ctl_rde(imsg.hdr.type, - imsg.hdr.pid, - p, sizeof(struct peer)); + } + if (!matched) { + control_result(c, CTL_RES_NOSUCHPEER); + } else if (!neighbor || !neighbor->show_timers) { imsg_ctl_rde(IMSG_CTL_END, imsg.hdr.pid, - NULL, 0); + NULL, 0); + } else { + imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1, + NULL, 0); } break; - case IMSG_CTL_SHOW_TERSE: - for (p = peers; p != NULL; p = p->next) - 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); - break; - case IMSG_CTL_FIB_COUPLE: - case IMSG_CTL_FIB_DECOUPLE: - imsg_ctl_parent(imsg.hdr.type, imsg.hdr.peerid, - 0, NULL, 0); - break; case IMSG_CTL_NEIGHBOR_UP: 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 + + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_neighbor)) { - neighbor = imsg.data; - neighbor->descr[PEER_DESCR_LEN - 1] = 0; - p = getpeerbyaddr(&neighbor->addr); - if (p == NULL) - p = getpeerbydesc(neighbor->descr); - if (p == NULL) { - control_result(c, CTL_RES_NOSUCHPEER); - break; - } + log_warnx("got IMSG_CTL_NEIGHBOR_ with " + "wrong length"); + break; + } + + neighbor = imsg.data; + neighbor->descr[PEER_DESCR_LEN - 1] = 0; + + for (matched = 0, p = peers; p != NULL; p = p->next) { + if (!peer_matched(p, neighbor)) + continue; + + matched = 1; + switch (imsg.hdr.type) { case IMSG_CTL_NEIGHBOR_UP: bgp_fsm(p, EVNT_START); @@ -419,9 +425,9 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) default: fatal("king bula wants more humppa"); } - } else - log_warnx("got IMSG_CTL_NEIGHBOR_ with " - "wrong length"); + } + if (!matched) + control_result(c, CTL_RES_NOSUCHPEER); break; case IMSG_CTL_RELOAD: case IMSG_CTL_SHOW_INTERFACE: @@ -440,53 +446,38 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) break; case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_RIB_PREFIX: - if (imsg.hdr.len == IMSG_HEADER_SIZE + + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_rib_request)) { - ribreq = imsg.data; - neighbor = &ribreq->neighbor; - neighbor->descr[PEER_DESCR_LEN - 1] = 0; - ribreq->peerid = 0; - p = NULL; - if (neighbor->addr.aid) { - p = getpeerbyaddr(&neighbor->addr); - if (p == NULL) { - control_result(c, - CTL_RES_NOSUCHPEER); - break; - } - ribreq->peerid = p->conf.id; - } else if (neighbor->descr[0]) { - p = getpeerbydesc(neighbor->descr); - if (p == NULL) { - control_result(c, - CTL_RES_NOSUCHPEER); - break; - } - ribreq->peerid = p->conf.id; - } - if ((ribreq->flags & - (F_CTL_ADJ_OUT | F_CTL_ADJ_IN)) && !p) { - /* - * both in and out tables are only - * meaningful if used on a single - * peer. - */ - control_result(c, CTL_RES_NOSUCHPEER); - break; - } - if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) - && (ribreq->prefix.aid == AID_UNSPEC)) { - /* malformed request, must specify af */ - control_result(c, CTL_RES_PARSE_ERROR); - break; - } - c->ibuf.pid = imsg.hdr.pid; - c->terminate = 1; - imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid, - imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); - } else log_warnx("got IMSG_CTL_SHOW_RIB with " "wrong length"); + break; + } + + ribreq = imsg.data; + neighbor = &ribreq->neighbor; + neighbor->descr[PEER_DESCR_LEN - 1] = 0; + + /* check if at least one neighbor exists */ + for (p = peers; p != NULL; p = p->next) + if (peer_matched(p, neighbor)) + break; + if (p == NULL) { + control_result(c, CTL_RES_NOSUCHPEER); + break; + } + + if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX) + && (ribreq->prefix.aid == AID_UNSPEC)) { + /* malformed request, must specify af */ + control_result(c, CTL_RES_PARSE_ERROR); + break; + } + + c->ibuf.pid = imsg.hdr.pid; + c->terminate = 1; + + imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; case IMSG_CTL_SHOW_NETWORK: c->terminate = 1; diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index f3b88b28214..ff3af78edde 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.459 2019/01/18 23:30:45 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.460 2019/01/20 23:27:48 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -2251,12 +2251,29 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) } } +static int +rde_dump_match_peer(struct ctl_neighbor *n, struct rde_peer *p) +{ + char *s; + + if (n && n->addr.aid) { + if (memcmp(&p->conf.remote_addr, &n->addr, + sizeof(p->conf.remote_addr))) + return 0; + } else if (n && n->descr[0]) { + s = n->is_group ? p->conf.group : p->conf.descr; + if (strcmp(s, n->descr)) + return 0; + } + return 1; +} + static void rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req) { struct rde_aspath *asp; - if (req->peerid && req->peerid != prefix_peer(p)->conf.id) + if (!rde_dump_match_peer(&req->neighbor, prefix_peer(p))) return; asp = prefix_aspath(p); diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 4ae322b53f9..b94998b7b00 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.370 2018/10/22 07:46:55 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.371 2019/01/20 23:27:48 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -100,10 +100,10 @@ int session_link_state_is_up(int, int, int); 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 peer *getpeerbyid(u_int32_t); struct bgpd_config *conf, *nconf; struct bgpd_sysdep sysdep; @@ -3114,6 +3114,36 @@ getpeerbyip(struct sockaddr *ip) return (NULL); } +struct peer * +getpeerbyid(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); +} + +int +peer_matched(struct peer *p, struct ctl_neighbor *n) +{ + char *s; + + if (n && n->addr.aid) { + if (memcmp(&p->conf.remote_addr, &n->addr, + sizeof(p->conf.remote_addr))) + return 0; + } else if (n && n->descr[0]) { + s = n->is_group ? p->conf.group : p->conf.descr; + if (strcmp(s, n->descr)) + return 0; + } + return 1; +} + void session_template_clone(struct peer *p, struct sockaddr *ip, u_int32_t id, u_int32_t as) @@ -3172,19 +3202,6 @@ session_match_mask(struct peer *p, struct bgpd_addr *a) return (0); } -struct peer * -getpeerbyid(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); -} - void session_down(struct peer *peer) { diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h index 5a90f294236..5f24a2852f0 100644 --- a/usr.sbin/bgpd/session.h +++ b/usr.sbin/bgpd/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.127 2018/12/27 20:23:24 remi Exp $ */ +/* $OpenBSD: session.h,v 1.128 2019/01/20 23:27:48 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -296,6 +296,7 @@ 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 *); +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); void session_stop(struct peer *, u_int8_t); |