1 
2 #include "nest/bird.h"
3 #include "lib/ip.h"
4 #include "lib/net.h"
5 #include "lib/flowspec.h"
6 
7 
8 const char * const net_label[] = {
9   [NET_IP4]	= "ipv4",
10   [NET_IP6]	= "ipv6",
11   [NET_VPN4]	= "vpn4",
12   [NET_VPN6]	= "vpn6",
13   [NET_ROA4]	= "roa4",
14   [NET_ROA6]	= "roa6",
15   [NET_FLOW4]	= "flow4",
16   [NET_FLOW6]	= "flow6",
17   [NET_IP6_SADR]= "ipv6-sadr",
18   [NET_MPLS]	= "mpls",
19 };
20 
21 const u16 net_addr_length[] = {
22   [NET_IP4]	= sizeof(net_addr_ip4),
23   [NET_IP6]	= sizeof(net_addr_ip6),
24   [NET_VPN4]	= sizeof(net_addr_vpn4),
25   [NET_VPN6]	= sizeof(net_addr_vpn6),
26   [NET_ROA4]	= sizeof(net_addr_roa4),
27   [NET_ROA6]	= sizeof(net_addr_roa6),
28   [NET_FLOW4]	= 0,
29   [NET_FLOW6]	= 0,
30   [NET_IP6_SADR]= sizeof(net_addr_ip6_sadr),
31   [NET_MPLS]	= sizeof(net_addr_mpls),
32 };
33 
34 const u8 net_max_prefix_length[] = {
35   [NET_IP4]	= IP4_MAX_PREFIX_LENGTH,
36   [NET_IP6]	= IP6_MAX_PREFIX_LENGTH,
37   [NET_VPN4]	= IP4_MAX_PREFIX_LENGTH,
38   [NET_VPN6]	= IP6_MAX_PREFIX_LENGTH,
39   [NET_ROA4]	= IP4_MAX_PREFIX_LENGTH,
40   [NET_ROA6]	= IP6_MAX_PREFIX_LENGTH,
41   [NET_FLOW4]	= IP4_MAX_PREFIX_LENGTH,
42   [NET_FLOW6]	= IP6_MAX_PREFIX_LENGTH,
43   [NET_IP6_SADR]= IP6_MAX_PREFIX_LENGTH,
44   [NET_MPLS]	= 0,
45 };
46 
47 const u16 net_max_text_length[] = {
48   [NET_IP4]	= 18,	/* "255.255.255.255/32" */
49   [NET_IP6]	= 43,	/* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
50   [NET_VPN4]	= 40,	/* "4294967296:4294967296 255.255.255.255/32" */
51   [NET_VPN6]	= 65,	/* "4294967296:4294967296 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
52   [NET_ROA4]	= 34,	/* "255.255.255.255/32-32 AS4294967295" */
53   [NET_ROA6]	= 60,	/* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128-128 AS4294967295" */
54   [NET_FLOW4]	= 0,	/* "flow4 { ... }" */
55   [NET_FLOW6]	= 0,	/* "flow6 { ... }" */
56   [NET_IP6_SADR]= 92,	/* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128 from ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
57   [NET_MPLS]	= 7,	/* "1048575" */
58 };
59 
60 
61 int
rd_format(const u64 rd,char * buf,int buflen)62 rd_format(const u64 rd, char *buf, int buflen)
63 {
64   switch (rd >> 48)
65   {
66     case 0: return bsnprintf(buf, buflen, "%u:%u", (u32) (rd >> 32), (u32) rd);
67     case 1: return bsnprintf(buf, buflen, "%I4:%u", ip4_from_u32(rd >> 16), (u32) (rd & 0xffff));
68     case 2: if (((u32) (rd >> 16)) >> 16)
69 	      return bsnprintf(buf, buflen, "%u:%u", (u32) (rd >> 16), (u32) (rd & 0xffff));
70 	    else
71 	      return bsnprintf(buf, buflen, "2:%u:%u", (u32) (rd >> 16), (u32) (rd & 0xffff));
72     default: return bsnprintf(buf, buflen, "X:%08x:%08x", (u32) (rd >> 32), (u32) rd);
73   }
74 }
75 
76 int
net_format(const net_addr * N,char * buf,int buflen)77 net_format(const net_addr *N, char *buf, int buflen)
78 {
79   net_addr_union *n = (void *) N;
80   buf[0] = 0;
81 
82   switch (n->n.type)
83   {
84   case NET_IP4:
85     return bsnprintf(buf, buflen, "%I4/%d", n->ip4.prefix, n->ip4.pxlen);
86   case NET_IP6:
87     return bsnprintf(buf, buflen, "%I6/%d", n->ip6.prefix, n->ip6.pxlen);
88   case NET_VPN4:
89     {
90     int c = rd_format(n->vpn4.rd, buf, buflen);
91     ADVANCE(buf, buflen, c);
92     return bsnprintf(buf, buflen, " %I4/%d", n->vpn4.prefix, n->vpn4.pxlen);
93     }
94   case NET_VPN6:
95     {
96     /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4 */
97     int c = rd_format(n->vpn6.rd, buf, buflen);
98     ADVANCE(buf, buflen, c);
99     return bsnprintf(buf, buflen, " %I6/%d", n->vpn6.prefix, n->vpn6.pxlen);
100     }
101   case NET_ROA4:
102     return bsnprintf(buf, buflen, "%I4/%u-%u AS%u",  n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
103   case NET_ROA6:
104     return bsnprintf(buf, buflen, "%I6/%u-%u AS%u",  n->roa6.prefix, n->roa6.pxlen, n->roa6.max_pxlen, n->roa6.asn);
105   case NET_FLOW4:
106     return flow4_net_format(buf, buflen, &n->flow4);
107   case NET_FLOW6:
108     return flow6_net_format(buf, buflen, &n->flow6);
109   case NET_IP6_SADR:
110     return bsnprintf(buf, buflen, "%I6/%d from %I6/%d", n->ip6_sadr.dst_prefix, n->ip6_sadr.dst_pxlen, n->ip6_sadr.src_prefix, n->ip6_sadr.src_pxlen);
111   case NET_MPLS:
112     return bsnprintf(buf, buflen, "%u", n->mpls.label);
113   }
114 
115   bug("unknown network type");
116 }
117 
118 ip_addr
net_pxmask(const net_addr * a)119 net_pxmask(const net_addr *a)
120 {
121   switch (a->type)
122   {
123   case NET_IP4:
124   case NET_VPN4:
125   case NET_ROA4:
126   case NET_FLOW4:
127     return ipa_from_ip4(ip4_mkmask(net4_pxlen(a)));
128 
129   case NET_IP6:
130   case NET_VPN6:
131   case NET_ROA6:
132   case NET_FLOW6:
133   case NET_IP6_SADR:
134     return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
135 
136   case NET_MPLS:
137   default:
138     return IPA_NONE;
139   }
140 }
141 
142 int
net_compare(const net_addr * a,const net_addr * b)143 net_compare(const net_addr *a, const net_addr *b)
144 {
145   if (a->type != b->type)
146     return uint_cmp(a->type, b->type);
147 
148   switch (a->type)
149   {
150   case NET_IP4:
151     return net_compare_ip4((const net_addr_ip4 *) a, (const net_addr_ip4 *) b);
152   case NET_IP6:
153     return net_compare_ip6((const net_addr_ip6 *) a, (const net_addr_ip6 *) b);
154   case NET_VPN4:
155     return net_compare_vpn4((const net_addr_vpn4 *) a, (const net_addr_vpn4 *) b);
156   case NET_VPN6:
157     return net_compare_vpn6((const net_addr_vpn6 *) a, (const net_addr_vpn6 *) b);
158   case NET_ROA4:
159     return net_compare_roa4((const net_addr_roa4 *) a, (const net_addr_roa4 *) b);
160   case NET_ROA6:
161     return net_compare_roa6((const net_addr_roa6 *) a, (const net_addr_roa6 *) b);
162   case NET_FLOW4:
163     return net_compare_flow4((const net_addr_flow4 *) a, (const net_addr_flow4 *) b);
164   case NET_FLOW6:
165     return net_compare_flow6((const net_addr_flow6 *) a, (const net_addr_flow6 *) b);
166   case NET_IP6_SADR:
167     return net_compare_ip6_sadr((const net_addr_ip6_sadr *) a, (const net_addr_ip6_sadr *) b);
168   case NET_MPLS:
169     return net_compare_mpls((const net_addr_mpls *) a, (const net_addr_mpls *) b);
170   }
171   return 0;
172 }
173 
174 #define NET_HASH(a,t) net_hash_##t((const net_addr_##t *) a)
175 
176 u32
net_hash(const net_addr * n)177 net_hash(const net_addr *n)
178 {
179   switch (n->type)
180   {
181   case NET_IP4: return NET_HASH(n, ip4);
182   case NET_IP6: return NET_HASH(n, ip6);
183   case NET_VPN4: return NET_HASH(n, vpn4);
184   case NET_VPN6: return NET_HASH(n, vpn6);
185   case NET_ROA4: return NET_HASH(n, roa4);
186   case NET_ROA6: return NET_HASH(n, roa6);
187   case NET_FLOW4: return NET_HASH(n, flow4);
188   case NET_FLOW6: return NET_HASH(n, flow6);
189   case NET_IP6_SADR: return NET_HASH(n, ip6_sadr);
190   case NET_MPLS: return NET_HASH(n, mpls);
191   default: bug("invalid type");
192   }
193 }
194 
195 
196 #define NET_VALIDATE(a,t) net_validate_##t((const net_addr_##t *) a)
197 
198 int
net_validate(const net_addr * n)199 net_validate(const net_addr *n)
200 {
201   switch (n->type)
202   {
203   case NET_IP4: return NET_VALIDATE(n, ip4);
204   case NET_IP6: return NET_VALIDATE(n, ip6);
205   case NET_VPN4: return NET_VALIDATE(n, vpn4);
206   case NET_VPN6: return NET_VALIDATE(n, vpn6);
207   case NET_ROA4: return NET_VALIDATE(n, roa4);
208   case NET_ROA6: return NET_VALIDATE(n, roa6);
209   case NET_FLOW4: return NET_VALIDATE(n, flow4);
210   case NET_FLOW6: return NET_VALIDATE(n, flow6);
211   case NET_IP6_SADR: return NET_VALIDATE(n, ip6_sadr);
212   case NET_MPLS: return NET_VALIDATE(n, mpls);
213   default: return 0;
214   }
215 }
216 
217 void
net_normalize(net_addr * N)218 net_normalize(net_addr *N)
219 {
220   net_addr_union *n = (void *) N;
221 
222   switch (n->n.type)
223   {
224   case NET_IP4:
225   case NET_VPN4:
226   case NET_ROA4:
227   case NET_FLOW4:
228     return net_normalize_ip4(&n->ip4);
229 
230   case NET_IP6:
231   case NET_VPN6:
232   case NET_ROA6:
233   case NET_FLOW6:
234     return net_normalize_ip6(&n->ip6);
235 
236   case NET_IP6_SADR:
237     return net_normalize_ip6_sadr(&n->ip6_sadr);
238 
239   case NET_MPLS:
240     return;
241   }
242 }
243 
244 int
net_classify(const net_addr * N)245 net_classify(const net_addr *N)
246 {
247   net_addr_union *n = (void *) N;
248 
249   switch (n->n.type)
250   {
251   case NET_IP4:
252   case NET_VPN4:
253   case NET_ROA4:
254   case NET_FLOW4:
255     return ip4_zero(n->ip4.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip4_classify(n->ip4.prefix);
256 
257   case NET_IP6:
258   case NET_VPN6:
259   case NET_ROA6:
260   case NET_FLOW6:
261     return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
262 
263   case NET_IP6_SADR:
264     return ip6_zero(n->ip6_sadr.dst_prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6_sadr.dst_prefix);
265 
266   case NET_MPLS:
267     return IADDR_HOST | SCOPE_UNIVERSE;
268   }
269 
270   return IADDR_INVALID;
271 }
272 
273 int
ipa_in_netX(const ip_addr a,const net_addr * n)274 ipa_in_netX(const ip_addr a, const net_addr *n)
275 {
276   switch (n->type)
277   {
278   case NET_IP4:
279   case NET_VPN4:
280   case NET_ROA4:
281   case NET_FLOW4:
282     if (!ipa_is_ip4(a)) return 0;
283     return ip4_zero(ip4_and(ip4_xor(ipa_to_ip4(a), net4_prefix(n)),
284 			    ip4_mkmask(net4_pxlen(n))));
285 
286   case NET_IP6:
287   case NET_VPN6:
288   case NET_ROA6:
289   case NET_FLOW6:
290     if (ipa_is_ip4(a)) return 0;
291     return ip6_zero(ip6_and(ip6_xor(ipa_to_ip6(a), net6_prefix(n)),
292 			    ip6_mkmask(net6_pxlen(n))));
293 
294   case NET_IP6_SADR:
295     if (ipa_is_ip4(a)) return 0;
296     return ip6_zero(ip6_and(ip6_xor(ipa_to_ip6(a), net6_prefix(n)),
297 			    ip6_mkmask(net6_pxlen(n))));
298 
299   case NET_MPLS:
300   default:
301     return 0;
302   }
303 }
304 
305 int
net_in_netX(const net_addr * a,const net_addr * n)306 net_in_netX(const net_addr *a, const net_addr *n)
307 {
308   if (a->type != n->type)
309     return 0;
310 
311   return (net_pxlen(n) <= net_pxlen(a)) && ipa_in_netX(net_prefix(a), n);
312 }
313 
314 #define CHECK_NET(T,S) \
315   ({ if (sizeof(T) != S) die("sizeof %s is %d/%d", #T, (int) sizeof(T), S); })
316 
317 void
net_init(void)318 net_init(void)
319 {
320   CHECK_NET(net_addr,		24);
321   CHECK_NET(net_addr_ip4,	 8);
322   CHECK_NET(net_addr_ip6,	20);
323   CHECK_NET(net_addr_vpn4,	16);
324   CHECK_NET(net_addr_vpn6,	32);
325   CHECK_NET(net_addr_roa4,	16);
326   CHECK_NET(net_addr_roa6,	28);
327   CHECK_NET(net_addr_flow4,	 8);
328   CHECK_NET(net_addr_flow6,	20);
329   CHECK_NET(net_addr_ip6_sadr,	40);
330   CHECK_NET(net_addr_mpls,	 8);
331 }
332