Line data Source code
1 : /*
2 : * Copyright (c) 2016 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <vnet/ip/ip_types.h>
17 : #include <vnet/ip/format.h>
18 : #include <vnet/ip/ip.h>
19 :
20 : u8 *
21 32931 : format_ip_address (u8 * s, va_list * args)
22 : {
23 32931 : ip_address_t *a = va_arg (*args, ip_address_t *);
24 32931 : u8 ver = ip_addr_version (a);
25 32931 : if (ver == AF_IP4)
26 : {
27 18622 : return format (s, "%U", format_ip4_address, &ip_addr_v4 (a));
28 : }
29 14309 : else if (ver == AF_IP6)
30 : {
31 14309 : return format (s, "%U", format_ip6_address, &ip_addr_v6 (a));
32 : }
33 : else
34 : {
35 0 : clib_warning ("Can't format IP version %d!", ver);
36 0 : return 0;
37 : }
38 : }
39 :
40 : uword
41 5 : unformat_ip_address (unformat_input_t * input, va_list * args)
42 : {
43 5 : ip_address_t *a = va_arg (*args, ip_address_t *);
44 5 : ip_address_t tmp, *p_tmp = &tmp;
45 :
46 5 : clib_memset (p_tmp, 0, sizeof (*p_tmp));
47 5 : if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (p_tmp)))
48 5 : ip_addr_version (p_tmp) = AF_IP4;
49 0 : else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (p_tmp)))
50 0 : ip_addr_version (p_tmp) = AF_IP6;
51 : else
52 0 : return 0;
53 5 : *a = *p_tmp;
54 5 : return 1;
55 : }
56 :
57 : u8 *
58 0 : format_ip_prefix (u8 * s, va_list * args)
59 : {
60 0 : ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
61 0 : return format (s, "%U/%d", format_ip_address, &ip_prefix_addr (a),
62 0 : ip_prefix_len (a));
63 : }
64 :
65 : uword
66 0 : unformat_ip_prefix (unformat_input_t * input, va_list * args)
67 : {
68 0 : ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
69 : /* %d writes more than a u8 */
70 : int plen;
71 0 : if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr (a),
72 : &plen))
73 : {
74 0 : ip_prefix_len (a) = plen;
75 0 : if ((ip_prefix_version (a) == AF_IP4 && 32 < ip_prefix_len (a)) ||
76 0 : (ip_prefix_version (a) == AF_IP6 && 128 < ip_prefix_len (a)))
77 : {
78 0 : clib_warning ("Prefix length to big: %d!", ip_prefix_len (a));
79 0 : return 0;
80 : }
81 0 : ip_prefix_normalize (a);
82 : }
83 : else
84 0 : return 0;
85 0 : return 1;
86 : }
87 :
88 : u16
89 666 : ip_address_size (const ip_address_t * a)
90 : {
91 666 : switch (ip_addr_version (a))
92 : {
93 644 : case AF_IP4:
94 644 : return sizeof (ip4_address_t);
95 : break;
96 22 : case AF_IP6:
97 22 : return sizeof (ip6_address_t);
98 : break;
99 : }
100 0 : return 0;
101 : }
102 :
103 : bool
104 255871 : ip_address_is_zero (const ip_address_t * ip)
105 : {
106 255871 : switch (ip_addr_version (ip))
107 : {
108 255534 : case AF_IP4:
109 255534 : return (ip_addr_v4 (ip).as_u32 == 0);
110 337 : case AF_IP6:
111 385 : return (ip_addr_v6 (ip).as_u64[0] == 0 &&
112 48 : ip_addr_v6 (ip).as_u64[1] == 0);
113 : break;
114 : }
115 0 : return false;
116 : }
117 :
118 : int
119 121370 : ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
120 : {
121 121370 : int res = 0;
122 121370 : if (ip_addr_version (ip1) != ip_addr_version (ip2))
123 20780 : return -1;
124 100590 : res = ip46_address_cmp (&ip_addr_46 (ip1), &ip_addr_46 (ip2));
125 :
126 100590 : if (res < 0)
127 97324 : res = 2;
128 3266 : else if (res > 0)
129 3176 : res = 1;
130 :
131 100590 : return res;
132 : }
133 :
134 : void
135 14600 : ip_address_copy (ip_address_t * dst, const ip_address_t * src)
136 : {
137 14600 : if (AF_IP4 == ip_addr_version (src))
138 : {
139 : /* don't copy any garbage from the union */
140 11177 : clib_memset (dst, 0, sizeof (*dst));
141 11177 : ip_addr_v4 (dst) = ip_addr_v4 (src);
142 11177 : dst->version = AF_IP4;
143 : }
144 : else
145 : {
146 3423 : clib_memcpy (dst, src, sizeof (ip_address_t));
147 : }
148 14600 : }
149 :
150 : u8 *
151 78 : ip_addr_bytes (ip_address_t * ip)
152 : {
153 78 : switch (ip->version)
154 : {
155 76 : case AF_IP4:
156 76 : return (u8 *) & ip_addr_v4 (ip);
157 2 : case AF_IP6:
158 2 : return (u8 *) & ip_addr_v6 (ip);
159 : break;
160 : }
161 0 : ASSERT (0);
162 0 : return (NULL);
163 : }
164 :
165 : void
166 222 : ip_address_copy_addr (void *dst, const ip_address_t * src)
167 : {
168 222 : switch (src->version)
169 : {
170 214 : case AF_IP4:
171 214 : clib_memcpy (dst, &ip_addr_v4 (src), ip_address_size (src));
172 214 : break;
173 8 : case AF_IP6:
174 8 : clib_memcpy (dst, &ip_addr_v6 (src), ip_address_size (src));
175 8 : break;
176 : }
177 222 : }
178 :
179 : u16
180 0 : ip_version_to_size (ip_address_family_t af)
181 : {
182 0 : switch (af)
183 : {
184 0 : case AF_IP4:
185 0 : return sizeof (ip4_address_t);
186 : break;
187 0 : case AF_IP6:
188 0 : return sizeof (ip6_address_t);
189 : break;
190 : }
191 0 : return 0;
192 : }
193 :
194 : vnet_link_t
195 0 : ip_address_family_to_link_type (ip_address_family_t af)
196 : {
197 0 : switch (af)
198 : {
199 0 : case AF_IP4:
200 0 : return (VNET_LINK_IP4);
201 0 : case AF_IP6:
202 0 : return (VNET_LINK_IP6);
203 : }
204 0 : ASSERT (0);
205 0 : return (VNET_LINK_IP4);
206 : }
207 :
208 : void
209 9657 : ip_address_set (ip_address_t *dst, const void *src, ip_address_family_t af)
210 : {
211 9657 : ip_addr_version (dst) = af;
212 :
213 9657 : switch (af)
214 : {
215 5524 : case AF_IP4:
216 5524 : ip_addr_v4 (dst) = *(ip4_address_t *) src;
217 5524 : break;
218 4133 : case AF_IP6:
219 4133 : ip_addr_v6 (dst) = *(ip6_address_t *) src;
220 4133 : break;
221 : }
222 9657 : }
223 :
224 : fib_protocol_t
225 52768 : ip_address_family_to_fib_proto (ip_address_family_t af)
226 : {
227 52768 : switch (af)
228 : {
229 28875 : case AF_IP4:
230 28875 : return (FIB_PROTOCOL_IP4);
231 23893 : case AF_IP6:
232 23893 : return (FIB_PROTOCOL_IP6);
233 : }
234 0 : ASSERT (0);
235 0 : return (FIB_PROTOCOL_IP4);
236 : }
237 :
238 : ip_address_family_t
239 11093 : ip_address_family_from_fib_proto (fib_protocol_t fp)
240 : {
241 11093 : switch (fp)
242 : {
243 6549 : case FIB_PROTOCOL_IP4:
244 6549 : return (AF_IP4);
245 4544 : case FIB_PROTOCOL_IP6:
246 4544 : return (AF_IP6);
247 0 : case FIB_PROTOCOL_MPLS:
248 0 : ASSERT (0);
249 : }
250 0 : return (AF_IP4);
251 : }
252 :
253 : fib_protocol_t
254 461 : ip_address_to_46 (const ip_address_t * addr, ip46_address_t * a)
255 : {
256 461 : *a = ip_addr_46 (addr);
257 461 : return (ip_address_family_to_fib_proto (ip_addr_version (addr)));
258 : }
259 :
260 : void
261 10854 : ip_address_from_46 (const ip46_address_t * nh,
262 : fib_protocol_t fproto, ip_address_t * ip)
263 : {
264 10854 : ip_addr_46 (ip) = *nh;
265 10854 : ip_addr_version (ip) = ip_address_family_from_fib_proto (fproto);
266 10854 : }
267 :
268 : /**
269 : * convert from a IP address to a FIB prefix
270 : */
271 : void
272 3835 : ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
273 : {
274 3835 : if (addr->version == AF_IP4)
275 : {
276 2037 : prefix->fp_len = 32;
277 2037 : prefix->fp_proto = FIB_PROTOCOL_IP4;
278 2037 : clib_memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
279 2037 : memcpy (&prefix->fp_addr.ip4, &addr->ip.ip4,
280 : sizeof (prefix->fp_addr.ip4));
281 : }
282 : else
283 : {
284 1798 : prefix->fp_len = 128;
285 1798 : prefix->fp_proto = FIB_PROTOCOL_IP6;
286 1798 : memcpy (&prefix->fp_addr.ip6, &addr->ip.ip6,
287 : sizeof (prefix->fp_addr.ip6));
288 : }
289 3835 : prefix->___fp___pad = 0;
290 3835 : }
291 :
292 : void
293 0 : ip_address_to_prefix (const ip_address_t *addr, ip_prefix_t *prefix)
294 : {
295 0 : prefix->len = (addr->version == AF_IP4 ? 32 : 128);
296 0 : clib_memcpy (&prefix->addr, addr, sizeof (prefix->addr));
297 0 : }
298 :
299 : void
300 5 : ip_address_increment (ip_address_t * ip)
301 : {
302 5 : ip46_address_increment ((ip_addr_version (ip) == AF_IP4 ?
303 : IP46_TYPE_IP4 : IP46_TYPE_IP6), &ip_addr_46 (ip));
304 5 : }
305 :
306 : void
307 15098 : ip_address_reset (ip_address_t * ip)
308 : {
309 15098 : clib_memset (ip, 0, sizeof (*ip));
310 15098 : }
311 :
312 : static void
313 12 : ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
314 : {
315 12 : u32 mask = ~0;
316 :
317 12 : ASSERT (ip4);
318 :
319 12 : if (32 <= preflen)
320 : {
321 5 : return;
322 : }
323 :
324 7 : mask = pow2_mask (preflen) << (32 - preflen);
325 7 : mask = clib_host_to_net_u32 (mask);
326 7 : ip4->data_u32 &= mask;
327 : }
328 :
329 : static void
330 0 : ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
331 : {
332 : u8 mask_6[16];
333 : u32 *m;
334 : u8 j, i0, i1;
335 :
336 0 : ASSERT (ip6);
337 :
338 0 : clib_memset (mask_6, 0, sizeof (mask_6));
339 :
340 0 : if (128 <= preflen)
341 : {
342 0 : return;
343 : }
344 :
345 0 : i1 = preflen % 32;
346 0 : i0 = preflen / 32;
347 0 : m = (u32 *) & mask_6[0];
348 :
349 0 : for (j = 0; j < i0; j++)
350 : {
351 0 : m[j] = ~0;
352 : }
353 :
354 0 : if (i1)
355 : {
356 0 : m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
357 : }
358 :
359 0 : for (j = 0; j < sizeof (mask_6); j++)
360 : {
361 0 : ip6->as_u8[j] &= mask_6[j];
362 : }
363 : }
364 :
365 : void
366 12 : ip_prefix_normalize (ip_prefix_t * a)
367 : {
368 12 : u8 preflen = ip_prefix_len (a);
369 :
370 12 : switch (ip_prefix_version (a))
371 : {
372 12 : case AF_IP4:
373 12 : ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
374 12 : break;
375 :
376 0 : case AF_IP6:
377 0 : ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
378 0 : break;
379 :
380 0 : default:
381 0 : ASSERT (0);
382 : }
383 12 : }
384 :
385 : void
386 21 : ip_prefix_copy (void *dst, void *src)
387 : {
388 21 : clib_memcpy (dst, src, sizeof (ip_prefix_t));
389 21 : }
390 :
391 : int
392 1 : ip_prefix_cmp (const ip_prefix_t *ipp1, const ip_prefix_t *ipp2)
393 : {
394 1 : ip_prefix_t p1 = *ipp1, p2 = *ipp2;
395 1 : int cmp = 0;
396 :
397 1 : ip_prefix_normalize (&p1);
398 1 : ip_prefix_normalize (&p2);
399 :
400 1 : cmp = ip_address_cmp (&ip_prefix_addr (&p1), &ip_prefix_addr (&p2));
401 1 : if (cmp == 0)
402 : {
403 1 : if (ip_prefix_len (&p1) < ip_prefix_len (&p2))
404 : {
405 0 : cmp = 1;
406 : }
407 : else
408 : {
409 1 : if (ip_prefix_len (&p1) > ip_prefix_len (&p2))
410 0 : cmp = 2;
411 : }
412 : }
413 1 : return cmp;
414 : }
415 :
416 : /**
417 : * convert from a LISP to a FIB prefix
418 : */
419 : void
420 2 : ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
421 : fib_prefix_t * fib_prefix)
422 : {
423 2 : ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
424 2 : fib_prefix->fp_len = ip_prefix->len;
425 2 : }
426 :
427 : static bool
428 16558 : ip4_prefix_validate (const ip_prefix_t * ip)
429 : {
430 : ip4_address_t ip4_addr, ip4_mask;
431 :
432 16558 : if (ip_prefix_len (ip) > 32)
433 0 : return (false);
434 :
435 16558 : ip4_addr = ip_prefix_v4 (ip);
436 16558 : ip4_preflen_to_mask (ip_prefix_len (ip), &ip4_mask);
437 :
438 16558 : return ((ip4_addr.as_u32 & ip4_mask.as_u32) == ip4_addr.as_u32);
439 : }
440 :
441 : static bool
442 16500 : ip6_prefix_validate (const ip_prefix_t * ip)
443 : {
444 : ip6_address_t ip6_addr, ip6_mask;
445 :
446 16500 : if (ip_prefix_len (ip) > 128)
447 0 : return (false);
448 :
449 16500 : ip6_addr = ip_prefix_v6 (ip);
450 16500 : ip6_preflen_to_mask (ip_prefix_len (ip), &ip6_mask);
451 :
452 33000 : return (((ip6_addr.as_u64[0] & ip6_mask.as_u64[0]) == ip6_addr.as_u64[0]) &&
453 16500 : ((ip6_addr.as_u64[1] & ip6_mask.as_u64[1]) == ip6_addr.as_u64[1]));
454 : }
455 :
456 : bool
457 33058 : ip_prefix_validate (const ip_prefix_t * ip)
458 : {
459 33058 : switch (ip_prefix_version (ip))
460 : {
461 16558 : case AF_IP4:
462 16558 : return (ip4_prefix_validate (ip));
463 16500 : case AF_IP6:
464 16500 : return (ip6_prefix_validate (ip));
465 : }
466 0 : ASSERT (0);
467 0 : return (false);
468 : }
469 :
470 : void
471 22352 : ip4_address_normalize (ip4_address_t * ip4, u8 preflen)
472 : {
473 22352 : ASSERT (preflen <= 32);
474 22352 : if (preflen == 0)
475 15400 : ip4->data_u32 = 0;
476 : else
477 6952 : ip4->data_u32 &= clib_net_to_host_u32 (0xffffffff << (32 - preflen));
478 22352 : }
479 :
480 : void
481 5923 : ip6_address_normalize (ip6_address_t * ip6, u8 preflen)
482 : {
483 5923 : ASSERT (preflen <= 128);
484 5923 : if (preflen == 0)
485 : {
486 0 : ip6->as_u64[0] = 0;
487 0 : ip6->as_u64[1] = 0;
488 : }
489 5923 : else if (preflen <= 64)
490 : {
491 5923 : ip6->as_u64[0] &=
492 5923 : clib_host_to_net_u64 (0xffffffffffffffffL << (64 - preflen));
493 5923 : ip6->as_u64[1] = 0;
494 : }
495 : else
496 0 : ip6->as_u64[1] &=
497 0 : clib_host_to_net_u64 (0xffffffffffffffffL << (128 - preflen));
498 5923 : }
499 :
500 : void
501 20292 : ip4_preflen_to_mask (u8 pref_len, ip4_address_t * ip)
502 : {
503 20292 : if (pref_len == 0)
504 3825 : ip->as_u32 = 0;
505 : else
506 16467 : ip->as_u32 = clib_host_to_net_u32 (~((1 << (32 - pref_len)) - 1));
507 20292 : }
508 :
509 : u32
510 0 : ip4_mask_to_preflen (ip4_address_t * mask)
511 : {
512 0 : if (mask->as_u32 == 0)
513 0 : return 0;
514 0 : return (32 - log2_first_set (clib_net_to_host_u32 (mask->as_u32)));
515 : }
516 :
517 : void
518 3734 : ip4_prefix_max_address_host_order (ip4_address_t * ip, u8 plen,
519 : ip4_address_t * res)
520 : {
521 : u32 not_mask;
522 3734 : not_mask = (1 << (32 - plen)) - 1;
523 3734 : res->as_u32 = clib_net_to_host_u32 (ip->as_u32) + not_mask;
524 3734 : }
525 :
526 : void
527 20150 : ip6_preflen_to_mask (u8 pref_len, ip6_address_t * mask)
528 : {
529 20150 : if (pref_len == 0)
530 : {
531 3752 : mask->as_u64[0] = 0;
532 3752 : mask->as_u64[1] = 0;
533 : }
534 16398 : else if (pref_len <= 64)
535 : {
536 4 : mask->as_u64[0] =
537 4 : clib_host_to_net_u64 (0xffffffffffffffffL << (64 - pref_len));
538 4 : mask->as_u64[1] = 0;
539 : }
540 : else
541 : {
542 16394 : mask->as_u64[0] = 0xffffffffffffffffL;
543 16394 : mask->as_u64[1] =
544 16394 : clib_host_to_net_u64 (0xffffffffffffffffL << (128 - pref_len));
545 : }
546 20150 : }
547 :
548 : void
549 3650 : ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
550 : ip6_address_t * res)
551 : {
552 : u64 not_mask;
553 3650 : if (plen == 0)
554 : {
555 3650 : res->as_u64[0] = 0xffffffffffffffffL;
556 3650 : res->as_u64[1] = 0xffffffffffffffffL;
557 : }
558 0 : else if (plen <= 64)
559 : {
560 0 : not_mask = ((u64) 1 << (64 - plen)) - 1;
561 0 : res->as_u64[0] = clib_net_to_host_u64 (ip->as_u64[0]) + not_mask;
562 0 : res->as_u64[1] = 0xffffffffffffffffL;
563 : }
564 : else
565 : {
566 0 : not_mask = ((u64) 1 << (128 - plen)) - 1;
567 0 : res->as_u64[1] = clib_net_to_host_u64 (ip->as_u64[1]) + not_mask;
568 : }
569 3650 : }
570 :
571 : u32
572 0 : ip6_mask_to_preflen (ip6_address_t * mask)
573 : {
574 0 : if (mask->as_u64[1] != 0)
575 0 : return 128 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
576 0 : if (mask->as_u64[0] != 0)
577 0 : return 64 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
578 0 : return 0;
579 : }
580 :
581 : /*
582 : * fd.io coding-style-patch-verification: ON
583 : *
584 : * Local Variables:
585 : * eval: (c-set-style "gnu")
586 : * End:
587 : */
|