1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
Index: bgpctl/irr_prefix.c
===================================================================
RCS file: /home/cvs/private/hrs/openbgpd/bgpctl/irr_prefix.c,v
retrieving revision 1.1.1.5
retrieving revision 1.1.1.8
diff -u -p -r1.1.1.5 -r1.1.1.8
--- bgpctl/irr_prefix.c 14 Feb 2010 20:20:14 -0000 1.1.1.5
+++ bgpctl/irr_prefix.c 13 Oct 2012 18:22:52 -0000 1.1.1.8
@@ -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.17 2009/09/08 16:11:36 sthen 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 *);
@@ -63,7 +64,11 @@ prefixset_get(char *as)
fflush(stdout);
}
curpfxs = pfxs;
- if (whois(as, QTYPE_ROUTE) == -1)
+ if ((irrflags & F_IPV4) && whois(as, QTYPE_ROUTE) == -1)
+ errx(1, "whois error, prefixset_get %s", as);
+ if ((irrflags & F_IPV6) && whois(as, QTYPE_ROUTE6) == -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)
@@ -80,9 +85,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 +99,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 +191,47 @@ prefixset_aggregate(struct prefix_set *p
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 */
+ /* see whether 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 +258,13 @@ irr_prefix_cmp(const void *a, const void
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);
|