summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-03-22 13:30:36 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-03-22 13:30:36 +0000
commit66dd0580bda97acb6a7df2d3e4d13f98e018fe54 (patch)
tree9c5f5679b05acb93ee8c25ae3fd08212cb818535 /usr.sbin
parent959f075402b5382286866f3c8a0345297a75b97c (diff)
Change the way bgpd selects nexthops. Up until now every route was considered
when calculating the nexthop. Now only non BGP routes and not the default route are used unless forced with the new config options nexthop qualify via bgp nexthop qualify via default This change is required for complex setups e.g. where an additional IGP is running. OK henning@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/bgpd.c29
-rw-r--r--usr.sbin/bgpd/bgpd.h7
-rw-r--r--usr.sbin/bgpd/kroute.c33
-rw-r--r--usr.sbin/bgpd/parse.y18
-rw-r--r--usr.sbin/bgpd/printconf.c7
5 files changed, 76 insertions, 18 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 7a9853decc2..d5962494440 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.134 2006/03/15 12:54:01 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.135 2006/03/22 13:30:35 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -470,7 +470,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
}
/* redistribute list needs to be reloaded too */
- if (kr_redist_reload() == -1)
+ if (kr_reload() == -1)
return (-1);
/* filters for the RDE */
@@ -720,3 +720,28 @@ bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6)
return (1);
}
+int
+bgpd_filternexthop(struct kroute *kr, struct kroute6 *kr6)
+{
+ /* kernel routes are never filtered */
+ if (kr && kr->flags & F_KERNEL && kr->prefixlen != 0)
+ return (0);
+ if (kr6 && kr6->flags & F_KERNEL && kr6->prefixlen != 0)
+ return (0);
+
+ if (cflags & BGPD_FLAG_NEXTHOP_BGP) {
+ if (kr && kr->flags & F_BGPD_INSERTED)
+ return (0);
+ if (kr6 && kr6->flags & F_BGPD_INSERTED)
+ return (0);
+ }
+
+ if (cflags & BGPD_FLAG_NEXTHOP_DEFAULT) {
+ if (kr && kr->prefixlen == 0)
+ return (0);
+ if (kr6 && kr6->prefixlen == 0)
+ return (0);
+ }
+
+ return (1);
+}
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index fee67e23cab..bb5b101c56f 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.194 2006/03/22 10:18:49 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.195 2006/03/22 13:30:35 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -57,6 +57,8 @@
#define BGPD_FLAG_REDIST_CONNECTED 0x0010
#define BGPD_FLAG_REDIST6_STATIC 0x0020
#define BGPD_FLAG_REDIST6_CONNECTED 0x0040
+#define BGPD_FLAG_NEXTHOP_BGP 0x0080
+#define BGPD_FLAG_NEXTHOP_DEFAULT 0x1000
#define BGPD_FLAG_DECISION_MASK 0x0f00
#define BGPD_FLAG_DECISION_ROUTEAGE 0x0100
#define BGPD_FLAG_DECISION_TRANS_AS 0x0200
@@ -677,6 +679,7 @@ struct rde_memstats {
void send_nexthop_update(struct kroute_nexthop *);
void send_imsg_session(int, pid_t, void *, u_int16_t);
int bgpd_redistribute(int, struct kroute *, struct kroute6 *);
+int bgpd_filternexthop(struct kroute *, struct kroute6 *);
/* buffer.c */
struct buf *buf_open(size_t);
@@ -737,7 +740,7 @@ int kr_nexthop_add(struct bgpd_addr *);
void kr_nexthop_delete(struct bgpd_addr *);
void kr_show_route(struct imsg *);
void kr_ifinfo(char *);
-int kr_redist_reload(void);
+int kr_reload(void);
in_addr_t prefixlen2mask(u_int8_t);
struct in6_addr *prefixlen2mask6(u_int8_t prefixlen);
void inet6applymask(struct in6_addr *, const struct in6_addr *,
diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c
index bc33dddef2d..c16404e0909 100644
--- a/usr.sbin/bgpd/kroute.c
+++ b/usr.sbin/bgpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.144 2006/02/23 15:25:18 claudio Exp $ */
+/* $OpenBSD: kroute.c,v 1.145 2006/03/22 13:30:35 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -116,8 +116,8 @@ int kif_validate(struct kif *);
int kroute_validate(struct kroute *);
int kroute6_validate(struct kroute6 *);
void knexthop_validate(struct knexthop_node *);
-struct kroute_node *kroute_match(in_addr_t);
-struct kroute6_node *kroute6_match(struct in6_addr *);
+struct kroute_node *kroute_match(in_addr_t, int);
+struct kroute6_node *kroute6_match(struct in6_addr *, int);
void kroute_detach_nexthop(struct knexthop_node *);
int protect_lo(void);
@@ -536,13 +536,13 @@ kr_show_route(struct imsg *imsg)
kr = NULL;
switch (addr->af) {
case AF_INET:
- kr = kroute_match(addr->v4.s_addr);
+ kr = kroute_match(addr->v4.s_addr, 1);
if (kr != NULL)
send_imsg_session(IMSG_CTL_KROUTE,
imsg->hdr.pid, &kr->r, sizeof(kr->r));
break;
case AF_INET6:
- kr6 = kroute6_match(&addr->v6);
+ kr6 = kroute6_match(&addr->v6, 1);
if (kr6 != NULL)
send_imsg_session(IMSG_CTL_KROUTE6,
imsg->hdr.pid, &kr6->r, sizeof(kr6->r));
@@ -746,13 +746,18 @@ kr_redistribute6(int type, struct kroute6 *kr6)
}
int
-kr_redist_reload(void)
+kr_reload(void)
{
struct redist_node *rn;
+ struct knexthop_node *nh;
LIST_FOREACH(rn, &redistlist, entry)
if (bgpd_redistribute(IMSG_NETWORK_ADD, rn->kr, rn->kr6) == -1)
return (-1);
+
+ RB_FOREACH(nh, knexthop_tree, &knt)
+ knexthop_validate(nh);
+
return (0);
}
@@ -1307,7 +1312,7 @@ knexthop_validate(struct knexthop_node *kn)
switch (kn->nexthop.af) {
case AF_INET:
- if ((kr = kroute_match(kn->nexthop.v4.s_addr)) == NULL) {
+ if ((kr = kroute_match(kn->nexthop.v4.s_addr, 0)) == NULL) {
if (was_valid)
send_nexthop_update(&n);
} else { /* match */
@@ -1328,7 +1333,7 @@ knexthop_validate(struct knexthop_node *kn)
}
break;
case AF_INET6:
- if ((kr6 = kroute6_match(&kn->nexthop.v6)) == NULL) {
+ if ((kr6 = kroute6_match(&kn->nexthop.v6, 0)) == NULL) {
if (was_valid)
send_nexthop_update(&n);
} else { /* match */
@@ -1355,7 +1360,7 @@ knexthop_validate(struct knexthop_node *kn)
}
struct kroute_node *
-kroute_match(in_addr_t key)
+kroute_match(in_addr_t key, int matchall)
{
int i;
struct kroute_node *kr;
@@ -1367,17 +1372,19 @@ kroute_match(in_addr_t key)
for (i = 32; i > 0; i--)
if ((kr =
kroute_find(htonl(ina & prefixlen2mask(i)), i)) != NULL)
- return (kr);
+ if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
+ return (kr);
/* if we don't have a match yet, try to find a default route */
if ((kr = kroute_find(0, 0)) != NULL)
+ if (matchall || bgpd_filternexthop(&kr->r, NULL) == 0)
return (kr);
return (NULL);
}
struct kroute6_node *
-kroute6_match(struct in6_addr *key)
+kroute6_match(struct in6_addr *key, int matchall)
{
int i;
struct kroute6_node *kr6;
@@ -1387,11 +1394,13 @@ kroute6_match(struct in6_addr *key)
for (i = 128; i > 0; i--) {
inet6applymask(&ina, key, i);
if ((kr6 = kroute6_find(&ina, i)) != NULL)
- return (kr6);
+ if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
+ return (kr6);
}
/* if we don't have a match yet, try to find a default route */
if ((kr6 = kroute6_find(&in6addr_any, 0)) != NULL)
+ if (matchall || bgpd_filternexthop(NULL, &kr6->r) == 0)
return (kr6);
return (NULL);
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 4bf94d4acd8..12ebf8d3611 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.183 2006/03/07 19:47:03 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.184 2006/03/22 13:30:35 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -164,6 +164,7 @@ typedef struct {
%token ERROR
%token IPSEC ESP AH SPI IKE
%token IPV4 IPV6
+%token QUALIFY VIA
%token <v.string> STRING
%type <v.number> number asnumber optnumber yesno inout espah
%type <v.number> family
@@ -433,6 +434,19 @@ conf_main : AS asnumber {
}
free($4);
}
+ | NEXTHOP QUALIFY VIA STRING {
+ if (!strcmp($4, "bgp"))
+ conf->flags |= BGPD_FLAG_NEXTHOP_BGP;
+ else if (!strcmp($4, "default"))
+ conf->flags |= BGPD_FLAG_NEXTHOP_DEFAULT;
+ else {
+ yyerror("nexthop depend on: "
+ "unknown setting \"%s\"", $4);
+ free($4);
+ YYERROR;
+ }
+ free($4);
+ }
;
mrtdump : DUMP STRING inout STRING optnumber {
@@ -1576,6 +1590,7 @@ lookup(char *s)
{ "prefixlen", PREFIXLEN},
{ "prepend-neighbor", PREPEND_PEER},
{ "prepend-self", PREPEND_SELF},
+ { "qualify", QUALIFY},
{ "quick", QUICK},
{ "rde", RDE},
{ "reject", REJECT},
@@ -1593,6 +1608,7 @@ lookup(char *s)
{ "to", TO},
{ "transit-as", TRANSITAS},
{ "transparent-as", TRANSPARENT},
+ { "via", VIA},
{ "weight", WEIGHT}
};
const struct keywords *p;
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 9581937bef3..a7bcf5cb50f 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.53 2006/02/10 14:34:40 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.54 2006/03/22 13:30:35 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -182,6 +182,11 @@ print_mainconf(struct bgpd_config *conf)
printf("listen on %s\n",
log_sockaddr((struct sockaddr *)&la->sa));
+ if (conf->flags & BGPD_FLAG_NEXTHOP_BGP)
+ printf("nexthop qualify via bgp\n");
+ if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT)
+ printf("nexthop qualify via default\n");
+
if (conf->flags & BGPD_FLAG_REDIST_CONNECTED) {
printf("network inet connected");
if (!TAILQ_EMPTY(&conf->connectset))