summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-08-23 08:13:05 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-08-23 08:13:05 +0000
commitae64b77bf4c8892086dffe7f47515b2fd04d0f1d (patch)
tree9f37556320791fc746d0db017d23a0e8de183b74 /usr.sbin/bgpd
parentce7a8ba8c04f6be11323324c248d6e8299d590fc (diff)
Extend show rib interface code so that it is possible to show the adj-rib-in
and adj-rib-out. Additionally it is now possible to limit the output to a specified peer. OK henning@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.h6
-rw-r--r--usr.sbin/bgpd/control.c43
-rw-r--r--usr.sbin/bgpd/rde.c115
3 files changed, 129 insertions, 35 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index f3d83ce7db7..38d719cf7d8 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.205 2006/08/04 12:01:48 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.206 2006/08/23 08:13:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -80,6 +80,8 @@
#define F_BLACKHOLE 0x0100
#define F_LONGER 0x0200
#define F_CTL_DETAIL 0x1000 /* only used by bgpctl */
+#define F_CTL_ADJ_IN 0x2000
+#define F_CTL_ADJ_OUT 0x4000
enum {
PROC_MAIN,
@@ -518,8 +520,10 @@ struct filter_as {
};
struct ctl_show_rib_request {
+ struct ctl_neighbor neighbor;
struct bgpd_addr prefix;
struct filter_as as;
+ u_int32_t peerid;
pid_t pid;
u_int16_t flags;
sa_family_t af;
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index d3a2ab64d0f..95d47958c7b 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.52 2006/05/27 21:24:36 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.53 2006/08/23 08:13:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -193,6 +193,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
int n;
struct peer *p;
struct ctl_neighbor *neighbor;
+ struct ctl_show_rib_request *ribreq;
if ((c = control_connbyfd(pfd->fd)) == NULL) {
log_warn("control_dispatch_msg: fd %d: not found", pfd->fd);
@@ -331,6 +332,46 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt)
case IMSG_CTL_SHOW_RIB:
case IMSG_CTL_SHOW_RIB_AS:
case IMSG_CTL_SHOW_RIB_PREFIX:
+ 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.af) {
+ 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_IN) && p &&
+ !p->conf.softreconfig_in) {
+ /*
+ * if no neighbor was specified we
+ * try our best.
+ */
+ control_result(c, CTL_RES_NOCAP);
+ break;
+ }
+ c->ibuf.pid = imsg.hdr.pid;
+ imsg_compose_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;
case IMSG_CTL_SHOW_RIB_MEM:
case IMSG_CTL_SHOW_NETWORK:
c->ibuf.pid = imsg.hdr.pid;
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 9e899a3f555..b51cc4c78ad 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.210 2006/08/22 15:02:07 henning Exp $ */
+/* $OpenBSD: rde.c,v 1.211 2006/08/23 08:13:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -58,7 +58,12 @@ void rde_update_log(const char *,
const struct rde_peer *, const struct bgpd_addr *,
const struct bgpd_addr *, u_int8_t);
int rde_reflector(struct rde_peer *, struct rde_aspath *);
-void rde_dump_rib_as(struct prefix *, pid_t, int);
+void rde_dump_rib_as(struct prefix *, struct rde_aspath *,pid_t,
+ int);
+void rde_dump_filter(struct prefix *,
+ struct ctl_show_rib_request *);
+void rde_dump_filterout(struct rde_peer *, struct prefix *,
+ struct ctl_show_rib_request *);
void rde_dump_upcall(struct pt_entry *, void *);
void rde_dump_as(struct ctl_show_rib_request *);
void rde_dump_prefix_upcall(struct pt_entry *, void *);
@@ -1510,7 +1515,7 @@ rde_reflector(struct rde_peer *peer, struct rde_aspath *asp)
* control specific functions
*/
void
-rde_dump_rib_as(struct prefix *p, pid_t pid, int flags)
+rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags)
{
struct ctl_show_rib rib;
struct buf *wbuf;
@@ -1520,19 +1525,19 @@ rde_dump_rib_as(struct prefix *p, pid_t pid, int flags)
bzero(&rib, sizeof(rib));
rib.lastchange = p->lastchange;
- rib.local_pref = p->aspath->lpref;
- rib.med = p->aspath->med;
- rib.prefix_cnt = p->aspath->prefix_cnt;
- rib.active_cnt = p->aspath->active_cnt;
- rib.adjrib_cnt = p->aspath->adjrib_cnt;
- strlcpy(rib.descr, p->aspath->peer->conf.descr, sizeof(rib.descr));
- memcpy(&rib.remote_addr, &p->aspath->peer->remote_addr,
+ rib.local_pref = asp->lpref;
+ rib.med = asp->med;
+ rib.prefix_cnt = asp->prefix_cnt;
+ rib.active_cnt = asp->active_cnt;
+ rib.adjrib_cnt = asp->adjrib_cnt;
+ strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr));
+ memcpy(&rib.remote_addr, &asp->peer->remote_addr,
sizeof(rib.remote_addr));
- rib.remote_id = p->aspath->peer->remote_bgpid;
- if (p->aspath->nexthop != NULL) {
- memcpy(&rib.true_nexthop, &p->aspath->nexthop->true_nexthop,
+ rib.remote_id = asp->peer->remote_bgpid;
+ if (asp->nexthop != NULL) {
+ memcpy(&rib.true_nexthop, &asp->nexthop->true_nexthop,
sizeof(rib.true_nexthop));
- memcpy(&rib.exit_nexthop, &p->aspath->nexthop->exit_nexthop,
+ memcpy(&rib.exit_nexthop, &asp->nexthop->exit_nexthop,
sizeof(rib.exit_nexthop));
} else {
/* announced network may have a NULL nexthop */
@@ -1543,32 +1548,31 @@ rde_dump_rib_as(struct prefix *p, pid_t pid, int flags)
}
pt_getaddr(p->prefix, &rib.prefix);
rib.prefixlen = p->prefix->prefixlen;
- rib.origin = p->aspath->origin;
+ rib.origin = asp->origin;
rib.flags = 0;
if (p->prefix->active == p)
rib.flags |= F_RIB_ACTIVE;
- if (p->aspath->peer->conf.ebgp == 0)
+ if (asp->peer->conf.ebgp == 0)
rib.flags |= F_RIB_INTERNAL;
- if (p->aspath->flags & F_PREFIX_ANNOUNCED)
+ if (asp->flags & F_PREFIX_ANNOUNCED)
rib.flags |= F_RIB_ANNOUNCE;
- if (p->aspath->nexthop == NULL ||
- p->aspath->nexthop->state == NEXTHOP_REACH)
+ if (asp->nexthop == NULL || asp->nexthop->state == NEXTHOP_REACH)
rib.flags |= F_RIB_ELIGIBLE;
- rib.aspath_len = aspath_length(p->aspath->aspath);
+ rib.aspath_len = aspath_length(asp->aspath);
if ((wbuf = imsg_create(ibuf_se, IMSG_CTL_SHOW_RIB, 0, pid,
sizeof(rib) + rib.aspath_len)) == NULL)
return;
if (imsg_add(wbuf, &rib, sizeof(rib)) == -1 ||
- imsg_add(wbuf, aspath_dump(p->aspath->aspath),
+ imsg_add(wbuf, aspath_dump(asp->aspath),
rib.aspath_len) == -1)
return;
if (imsg_close(ibuf_se, wbuf) == -1)
return;
if (flags & F_CTL_DETAIL)
- for (l = 0; l < p->aspath->others_len; l++) {
- if ((a = p->aspath->others[l]) == NULL)
+ for (l = 0; l < asp->others_len; l++) {
+ if ((a = asp->others[l]) == NULL)
break;
if ((wbuf = imsg_create(ibuf_se, IMSG_CTL_SHOW_RIB_ATTR,
0, pid, attr_optlen(a))) == NULL)
@@ -1588,15 +1592,65 @@ rde_dump_rib_as(struct prefix *p, pid_t pid, int flags)
}
void
+rde_dump_filterout(struct rde_peer *peer, struct prefix *p,
+ struct ctl_show_rib_request *req)
+{
+ struct bgpd_addr addr;
+ struct rde_aspath *asp;
+ enum filter_actions a;
+
+ if (up_test_update(peer, p) != 1)
+ return;
+
+ pt_getaddr(p->prefix, &addr);
+ a = rde_filter(&asp, rules_l, peer, p->aspath, &addr,
+ p->prefix->prefixlen, p->aspath->peer, DIR_OUT);
+ if (asp)
+ asp->peer = p->aspath->peer;
+ else
+ asp = p->aspath;
+
+ if (a == ACTION_ALLOW)
+ rde_dump_rib_as(p, asp, req->pid, req->flags);
+
+ if (asp != p->aspath)
+ path_put(asp);
+}
+
+void
+rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req)
+{
+ struct rde_peer *peer;
+
+ if ((req->flags & F_CTL_ADJ_IN && p->flags & F_ORIGINAL) ||
+ (!(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT)) &&
+ p->flags & F_LOCAL)) {
+ if (req->peerid && req->peerid != p->aspath->peer->conf.id)
+ return;
+ rde_dump_rib_as(p, p->aspath, req->pid, req->flags);
+ } else if (req->flags & F_CTL_ADJ_OUT && p->flags & F_LOCAL) {
+ if (p->prefix->active != p)
+ /* only consider active prefix */
+ return;
+
+ if (req->peerid) {
+ if ((peer = peer_get(req->peerid)) != NULL)
+ rde_dump_filterout(peer, p, req);
+ return;
+ }
+ LIST_FOREACH(peer, &peerlist, peer_l)
+ rde_dump_filterout(peer, p, req);
+ }
+}
+
+void
rde_dump_upcall(struct pt_entry *pt, void *ptr)
{
struct prefix *p;
struct ctl_show_rib_request *req = ptr;
LIST_FOREACH(p, &pt->prefix_h, prefix_l)
- /* for now dump only stuff from the local-RIB */
- if (p->flags & F_LOCAL)
- rde_dump_rib_as(p, req->pid, req->flags);
+ rde_dump_filter(p, req);
}
void
@@ -1614,10 +1668,7 @@ rde_dump_as(struct ctl_show_rib_request *req)
continue;
/* match found */
LIST_FOREACH(p, &asp->prefix_h, path_l)
- /* for now dump only stuff from the local-RIB */
- if (p->flags & F_LOCAL)
- rde_dump_rib_as(p, req->pid,
- req->flags);
+ rde_dump_filter(p, req);
}
}
}
@@ -1636,9 +1687,7 @@ rde_dump_prefix_upcall(struct pt_entry *pt, void *ptr)
return;
if (!prefix_compare(&req->prefix, &addr, req->prefixlen))
LIST_FOREACH(p, &pt->prefix_h, prefix_l)
- /* for now dump only stuff from the local-RIB */
- if (p->flags & F_LOCAL)
- rde_dump_rib_as(p, req->pid, req->flags);
+ rde_dump_filter(p, req);
}
void