summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2019-01-20 23:27:48 +0000
committerclaudio <claudio@openbsd.org>2019-01-20 23:27:48 +0000
commit514180ac497bb4e5521952686fc54599ae252d51 (patch)
treeb79d508372db5c355367e387f82f8a9d408f87f1
parentallow override of ssh-pkcs11-helper binary via $TEST_SSH_SSHPKCS11HELPER (diff)
downloadwireguard-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.h4
-rw-r--r--usr.sbin/bgpd/control.c167
-rw-r--r--usr.sbin/bgpd/rde.c21
-rw-r--r--usr.sbin/bgpd/session.c47
-rw-r--r--usr.sbin/bgpd/session.h3
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);