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