summaryrefslogtreecommitdiff
path: root/net/openbgpd/files/patch-bgpctl_irr_prefix.c
blob: 4c97de2a4c7d17228262c906ce9c764690dd6067 (plain) (blame)
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);