summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2009-09-08 15:40:26 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2009-09-08 15:40:26 +0000
commitd2863a322ab754c0b6f3239c0504024a525a789d (patch)
tree218c39b2b470111b32c2a68693288f7938f1528d
parent6e8fc9a1adf30acd4571d405b622b07cb8842abb (diff)
Update irrfilter to support IPv6 and 4-byte AS numbers. IPv6 support based
on work by Tonnerre Lombard I just cleaned it up. OK henning, sthen
-rw-r--r--usr.sbin/bgpctl/irr_parser.c8
-rw-r--r--usr.sbin/bgpctl/irr_prefix.c86
-rw-r--r--usr.sbin/bgpctl/irrfilter.h8
-rw-r--r--usr.sbin/bgpctl/whois.c5
4 files changed, 78 insertions, 29 deletions
diff --git a/usr.sbin/bgpctl/irr_parser.c b/usr.sbin/bgpctl/irr_parser.c
index 063faba1753..33e51e823c5 100644
--- a/usr.sbin/bgpctl/irr_parser.c
+++ b/usr.sbin/bgpctl/irr_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: irr_parser.c,v 1.8 2007/03/05 22:34:08 henning Exp $ */
+/* $OpenBSD: irr_parser.c,v 1.9 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -81,6 +81,7 @@ parse_response(FILE *f, enum qtype qtype)
return (-1);
break;
case QTYPE_ROUTE:
+ case QTYPE_ROUTE6:
if ((n = parse_route(key, val)) == -1)
return (-1);
break;
@@ -281,7 +282,7 @@ parse_policy(char *key, char *val)
!isdigit(tok[2]))
errx(1, "peering spec \"%s\": format "
"error, AS expected", tok);
- pi->peer_as = strtonum(tok + 2, 1, USHRT_MAX,
+ pi->peer_as = strtonum(tok + 2, 1, UINT_MAX,
&errstr);
if (errstr)
errx(1, "peering spec \"%s\": format "
@@ -407,7 +408,8 @@ parse_asset(char *key, char *val)
int
parse_route(char *key, char *val)
{
- if (strcmp(key, "route")) /* ignore everything else */
+ if (strcmp(key, "route") && strcmp(key, "route6"))
+ /* ignore everything else */
return (0);
/* route is single-value, but seen trailing , in the wild */
diff --git a/usr.sbin/bgpctl/irr_prefix.c b/usr.sbin/bgpctl/irr_prefix.c
index 8bc0d7470d5..d8f5a708bdd 100644
--- a/usr.sbin/bgpctl/irr_prefix.c
+++ b/usr.sbin/bgpctl/irr_prefix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: irr_prefix.c,v 1.15 2007/05/27 18:54:25 henning Exp $ */
+/* $OpenBSD: irr_prefix.c,v 1.16 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -29,6 +29,7 @@
#include <arpa/inet.h>
#include "irrfilter.h"
+#include "bgpd.h"
void prefixset_aggregate(struct prefix_set *);
int prefix_aggregate(struct irr_prefix *, const struct irr_prefix *);
@@ -65,6 +66,8 @@ prefixset_get(char *as)
curpfxs = pfxs;
if (whois(as, QTYPE_ROUTE) == -1)
errx(1, "whois error, prefixset_get %s", as);
+ if (whois(as, QTYPE_ROUTE6) == -1)
+ errx(1, "whois error, prefixset_get %s", as);
curpfxs = NULL;
if (irrverbose >= 3)
fprintf(stdout, "done\n");
@@ -80,9 +83,11 @@ prefixset_addmember(char *s)
void *p;
u_int i;
struct irr_prefix *pfx;
- int len;
+ int len, ret;
+ char *slash;
+ const char *errstr;
- if (strchr(s, '/') == NULL) {
+ if ((slash = strchr(s, '/')) == NULL) {
fprintf(stderr, "%s: prefix %s does not have the len "
"specified, ignoring\n", curpfxs->as, s);
return (0);
@@ -92,17 +97,26 @@ prefixset_addmember(char *s)
err(1, "prefixset_addmember calloc");
if ((len = inet_net_pton(AF_INET, s, &pfx->addr.in,
- sizeof(pfx->addr.in))) == -1) {
- if (errno == ENOENT) {
- fprintf(stderr, "%s: prefix \"%s\": parse error\n",
+ sizeof(pfx->addr.in))) != -1) {
+ pfx->af = AF_INET;
+ } else {
+ len = strtonum(slash + 1, 0, 128, &errstr);
+ if (errstr)
+ errx(1, "prefixset_addmember %s prefix %s: prefixlen "
+ "is %s", curpfxs->as, s, errstr);
+ *slash = '\0';
+
+ if ((ret = inet_pton(AF_INET6, s, &pfx->addr.in6)) == -1)
+ err(1, "prefixset_addmember %s prefix \"%s\"",
curpfxs->as, s);
+ else if (ret == 0) {
+ fprintf(stderr, "prefixset_addmember %s prefix \"%s\": "
+ "No matching address family found", curpfxs->as, s);
+ free(pfx);
return (0);
- } else
- err(1, "prefixset_addmember %s inet_net_pton \"%s\"",
- curpfxs->as, s);
+ }
+ pfx->af = AF_INET6;
}
-
- pfx->af = AF_INET;
pfx->len = pfx->maxlen = len;
/* yes, there are dupes... e. g. from multiple sources */
@@ -175,24 +189,47 @@ prefixset_aggregate(struct prefix_set *pfxs)
int
prefix_aggregate(struct irr_prefix *a, const struct irr_prefix *b)
{
- in_addr_t mask;
+ in_addr_t mask;
+ struct in6_addr ma;
+ struct in6_addr mb;
if (a->len == 0)
return (1);
- mask = htonl(0xffffffff << (32 - a->len));
+ if (a->af != b->af)
+ /* We cannot aggregate addresses of different families. */
+ return (0);
- if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask))
- return (1);
+ if (a->af == AF_INET) {
+ mask = htonl(prefixlen2mask(a->len));
+ if ((a->addr.in.s_addr & mask) == (b->addr.in.s_addr & mask))
+ return (1);
+ } else if (a->af == AF_INET6) {
+ inet6applymask(&ma, &a->addr.in6, a->len);
+ inet6applymask(&mb, &b->addr.in6, a->len);
+ if (IN6_ARE_ADDR_EQUAL(&ma, &mb))
+ return (1);
+ }
/* see wether we can fold them in one */
if (a->len == b->len && a->len > 1) {
- mask = htonl(0xffffffff << (32 - (a->len - 1)));
- if ((a->addr.in.s_addr & mask) ==
- (b->addr.in.s_addr & mask)) {
- a->len--;
- a->addr.in.s_addr &= mask;
- return (1);
+ if (a->af == AF_INET) {
+ mask = htonl(prefixlen2mask(a->len - 1));
+ if ((a->addr.in.s_addr & mask) ==
+ (b->addr.in.s_addr & mask)) {
+ a->len--;
+ a->addr.in.s_addr &= mask;
+ return (1);
+ }
+ } else if (a->af == AF_INET6) {
+ inet6applymask(&ma, &a->addr.in6, a->len - 1);
+ inet6applymask(&mb, &b->addr.in6, a->len - 1);
+
+ if (IN6_ARE_ADDR_EQUAL(&ma, &mb)) {
+ a->len--;
+ memcpy(&a->addr.in6, &ma, sizeof(ma));
+ return (1);
+ }
}
}
@@ -219,6 +256,13 @@ irr_prefix_cmp(const void *a, const void *b)
if (ntohl(pa->addr.in.s_addr) >
ntohl(pb->addr.in.s_addr))
return (1);
+ } else if (pa->af == AF_INET6) {
+ for (r = 0; r < 16; r++) {
+ if (pa->addr.in6.s6_addr[r] < pb->addr.in6.s6_addr[r])
+ return (-1);
+ if (pa->addr.in6.s6_addr[r] > pb->addr.in6.s6_addr[r])
+ return (1);
+ }
} else
errx(1, "irr_prefix_cmp unknown af %u", pa->af);
diff --git a/usr.sbin/bgpctl/irrfilter.h b/usr.sbin/bgpctl/irrfilter.h
index 5059240b52e..88370b47045 100644
--- a/usr.sbin/bgpctl/irrfilter.h
+++ b/usr.sbin/bgpctl/irrfilter.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: irrfilter.h,v 1.7 2007/03/06 16:45:34 henning Exp $ */
+/* $OpenBSD: irrfilter.h,v 1.8 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -37,7 +37,7 @@ struct policy_item {
char *action;
char *filter;
enum pdir dir;
- u_int16_t peer_as;
+ u_int32_t peer_as;
};
TAILQ_HEAD(policy_head, policy_item);
@@ -55,7 +55,8 @@ enum qtype {
QTYPE_NONE,
QTYPE_OWNAS,
QTYPE_ASSET,
- QTYPE_ROUTE
+ QTYPE_ROUTE,
+ QTYPE_ROUTE6
};
struct as_set {
@@ -72,6 +73,7 @@ struct as_set {
struct irr_prefix {
union {
struct in_addr in;
+ struct in6_addr in6;
} addr;
sa_family_t af;
u_int8_t len;
diff --git a/usr.sbin/bgpctl/whois.c b/usr.sbin/bgpctl/whois.c
index 839dcbba13a..f14d07d8ed7 100644
--- a/usr.sbin/bgpctl/whois.c
+++ b/usr.sbin/bgpctl/whois.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: whois.c,v 1.3 2007/03/05 16:43:24 henning Exp $ */
+/* $OpenBSD: whois.c,v 1.4 2009/09/08 15:40:25 claudio Exp $ */
/*
* Copyright (c) 2007 Henning Brauer <henning@openbsd.org>
@@ -68,7 +68,8 @@ char *qtype_opts[] = {
"",
"-T aut-num",
"-K -T as-set",
- "-K -T route -i origin"
+ "-K -T route -i origin",
+ "-K -T route6 -i origin"
};
char *server = "whois.radb.net";