blob: 4be3ba20151ddd94b01c4d9007047d2beeb1b1ad [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Prefix related functions.
3 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "prefix.h"
26#include "vty.h"
27#include "sockunion.h"
28#include "memory.h"
29#include "log.h"
30
31/* Maskbit. */
Stephen Hemminger2d362d12009-12-21 12:54:58 +030032static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
paul718e3742002-12-13 20:15:29 +000033 0xf8, 0xfc, 0xfe, 0xff};
Denis Ovsienko051954f2011-10-11 15:17:45 +040034static const u_int32_t maskbytes_host[] =
Denis Ovsienko96633862011-10-08 18:15:21 +040035{
36 0x00000000, /* /0 0.0.0.0 */
37 0x80000000, /* /1 128.0.0.0 */
38 0xc0000000, /* /2 192.0.0.0 */
39 0xe0000000, /* /3 224.0.0.0 */
40 0xf0000000, /* /4 240.0.0.0 */
41 0xf8000000, /* /5 248.0.0.0 */
42 0xfc000000, /* /6 252.0.0.0 */
43 0xfe000000, /* /7 254.0.0.0 */
44 0xff000000, /* /8 255.0.0.0 */
45 0xff800000, /* /9 255.128.0.0 */
46 0xffc00000, /* /10 255.192.0.0 */
47 0xffe00000, /* /11 255.224.0.0 */
48 0xfff00000, /* /12 255.240.0.0 */
49 0xfff80000, /* /13 255.248.0.0 */
50 0xfffc0000, /* /14 255.252.0.0 */
51 0xfffe0000, /* /15 255.254.0.0 */
52 0xffff0000, /* /16 255.255.0.0 */
53 0xffff8000, /* /17 255.255.128.0 */
54 0xffffc000, /* /18 255.255.192.0 */
55 0xffffe000, /* /19 255.255.224.0 */
56 0xfffff000, /* /20 255.255.240.0 */
57 0xfffff800, /* /21 255.255.248.0 */
58 0xfffffc00, /* /22 255.255.252.0 */
59 0xfffffe00, /* /23 255.255.254.0 */
60 0xffffff00, /* /24 255.255.255.0 */
61 0xffffff80, /* /25 255.255.255.128 */
62 0xffffffc0, /* /26 255.255.255.192 */
63 0xffffffe0, /* /27 255.255.255.224 */
64 0xfffffff0, /* /28 255.255.255.240 */
65 0xfffffff8, /* /29 255.255.255.248 */
66 0xfffffffc, /* /30 255.255.255.252 */
67 0xfffffffe, /* /31 255.255.255.254 */
68 0xffffffff /* /32 255.255.255.255 */
69};
Denis Ovsienko051954f2011-10-11 15:17:45 +040070static const u_int32_t maskbytes_network[] =
71{
72 0x00000000, /* /0 0.0.0.0 */
73 0x00000080, /* /1 128.0.0.0 */
74 0x000000c0, /* /2 192.0.0.0 */
75 0x000000e0, /* /3 224.0.0.0 */
76 0x000000f0, /* /4 240.0.0.0 */
77 0x000000f8, /* /5 248.0.0.0 */
78 0x000000fc, /* /6 252.0.0.0 */
79 0x000000fe, /* /7 254.0.0.0 */
80 0x000000ff, /* /8 255.0.0.0 */
81 0x000080ff, /* /9 255.128.0.0 */
82 0x0000c0ff, /* /10 255.192.0.0 */
83 0x0000e0ff, /* /11 255.224.0.0 */
84 0x0000f0ff, /* /12 255.240.0.0 */
85 0x0000f8ff, /* /13 255.248.0.0 */
86 0x0000fcff, /* /14 255.252.0.0 */
87 0x0000feff, /* /15 255.254.0.0 */
88 0x0000ffff, /* /16 255.255.0.0 */
89 0x0080ffff, /* /17 255.255.128.0 */
90 0x00c0ffff, /* /18 255.255.192.0 */
91 0x00e0ffff, /* /19 255.255.224.0 */
92 0x00f0ffff, /* /20 255.255.240.0 */
93 0x00f8ffff, /* /21 255.255.248.0 */
94 0x00fcffff, /* /22 255.255.252.0 */
95 0x00feffff, /* /23 255.255.254.0 */
96 0x00ffffff, /* /24 255.255.255.0 */
97 0x80ffffff, /* /25 255.255.255.128 */
98 0xc0ffffff, /* /26 255.255.255.192 */
99 0xe0ffffff, /* /27 255.255.255.224 */
100 0xf0ffffff, /* /28 255.255.255.240 */
101 0xf8ffffff, /* /29 255.255.255.248 */
102 0xfcffffff, /* /30 255.255.255.252 */
103 0xfeffffff, /* /31 255.255.255.254 */
104 0xffffffff /* /32 255.255.255.255 */
105};
paul718e3742002-12-13 20:15:29 +0000106
107/* Number of bits in prefix type. */
108#ifndef PNBBY
109#define PNBBY 8
110#endif /* PNBBY */
111
112#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
113
114/* Address Famiy Identifier to Address Family converter. */
115int
Michael Lambert4c9641b2010-07-22 13:20:55 -0400116afi2family (afi_t afi)
paul718e3742002-12-13 20:15:29 +0000117{
118 if (afi == AFI_IP)
119 return AF_INET;
120#ifdef HAVE_IPV6
121 else if (afi == AFI_IP6)
122 return AF_INET6;
123#endif /* HAVE_IPV6 */
124 return 0;
125}
126
Michael Lambert4c9641b2010-07-22 13:20:55 -0400127afi_t
paul718e3742002-12-13 20:15:29 +0000128family2afi (int family)
129{
130 if (family == AF_INET)
131 return AFI_IP;
132#ifdef HAVE_IPV6
133 else if (family == AF_INET6)
134 return AFI_IP6;
135#endif /* HAVE_IPV6 */
136 return 0;
137}
138
139/* If n includes p prefix then return 1 else return 0. */
140int
hassob04c6992004-10-04 19:10:31 +0000141prefix_match (const struct prefix *n, const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000142{
143 int offset;
144 int shift;
Paul Jakmad3583442010-01-24 21:41:02 +0000145 const u_char *np, *pp;
paul718e3742002-12-13 20:15:29 +0000146
147 /* If n's prefix is longer than p's one return 0. */
148 if (n->prefixlen > p->prefixlen)
149 return 0;
150
Paul Jakmad3583442010-01-24 21:41:02 +0000151 /* Set both prefix's head pointer. */
152 np = (const u_char *)&n->u.prefix;
153 pp = (const u_char *)&p->u.prefix;
154
paul718e3742002-12-13 20:15:29 +0000155 offset = n->prefixlen / PNBBY;
156 shift = n->prefixlen % PNBBY;
157
158 if (shift)
159 if (maskbit[shift] & (np[offset] ^ pp[offset]))
160 return 0;
161
162 while (offset--)
163 if (np[offset] != pp[offset])
164 return 0;
165 return 1;
166}
167
168/* Copy prefix from src to dest. */
169void
hassob04c6992004-10-04 19:10:31 +0000170prefix_copy (struct prefix *dest, const struct prefix *src)
paul718e3742002-12-13 20:15:29 +0000171{
172 dest->family = src->family;
173 dest->prefixlen = src->prefixlen;
174
175 if (src->family == AF_INET)
176 dest->u.prefix4 = src->u.prefix4;
177#ifdef HAVE_IPV6
178 else if (src->family == AF_INET6)
179 dest->u.prefix6 = src->u.prefix6;
180#endif /* HAVE_IPV6 */
181 else if (src->family == AF_UNSPEC)
182 {
183 dest->u.lp.id = src->u.lp.id;
184 dest->u.lp.adv_router = src->u.lp.adv_router;
185 }
186 else
187 {
ajsb9e70282004-12-08 17:14:45 +0000188 zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
paul718e3742002-12-13 20:15:29 +0000189 src->family);
190 assert (0);
191 }
192}
193
gdt9d24baa2004-01-13 14:55:40 +0000194/*
195 * Return 1 if the address/netmask contained in the prefix structure
196 * is the same, and else return 0. For this routine, 'same' requires
197 * that not only the prefix length and the network part be the same,
198 * but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
199 * the same. Note that this routine has the same return value sense
200 * as '==' (which is different from prefix_cmp).
201 */
paul718e3742002-12-13 20:15:29 +0000202int
hassob04c6992004-10-04 19:10:31 +0000203prefix_same (const struct prefix *p1, const struct prefix *p2)
paul718e3742002-12-13 20:15:29 +0000204{
205 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
206 {
207 if (p1->family == AF_INET)
208 if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
209 return 1;
210#ifdef HAVE_IPV6
211 if (p1->family == AF_INET6 )
212 if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
213 return 1;
214#endif /* HAVE_IPV6 */
215 }
216 return 0;
217}
218
gdt9d24baa2004-01-13 14:55:40 +0000219/*
220 * Return 0 if the network prefixes represented by the struct prefix
221 * arguments are the same prefix, and 1 otherwise. Network prefixes
222 * are considered the same if the prefix lengths are equal and the
223 * network parts are the same. Host bits (which are considered masked
224 * by the prefix length) are not significant. Thus, 10.0.0.1/8 and
225 * 10.0.0.2/8 are considered equivalent by this routine. Note that
226 * this routine has the same return sense as strcmp (which is different
227 * from prefix_same).
228 */
paul718e3742002-12-13 20:15:29 +0000229int
hassob04c6992004-10-04 19:10:31 +0000230prefix_cmp (const struct prefix *p1, const struct prefix *p2)
paul718e3742002-12-13 20:15:29 +0000231{
232 int offset;
233 int shift;
234
235 /* Set both prefix's head pointer. */
paul8cc41982005-05-06 21:25:49 +0000236 const u_char *pp1 = (const u_char *)&p1->u.prefix;
237 const u_char *pp2 = (const u_char *)&p2->u.prefix;
paul718e3742002-12-13 20:15:29 +0000238
239 if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
240 return 1;
241
242 offset = p1->prefixlen / 8;
243 shift = p1->prefixlen % 8;
244
245 if (shift)
246 if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
247 return 1;
248
249 while (offset--)
250 if (pp1[offset] != pp2[offset])
251 return 1;
252
253 return 0;
254}
255
David Lamparter17e52062010-02-02 20:16:35 +0100256/*
257 * Count the number of common bits in 2 prefixes. The prefix length is
258 * ignored for this function; the whole prefix is compared. If the prefix
259 * address families don't match, return -1; otherwise the return value is
260 * in range 0 ... maximum prefix length for the address family.
261 */
262int
263prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
264{
265 int pos, bit;
266 int length = 0;
267 u_char xor;
268
269 /* Set both prefix's head pointer. */
270 const u_char *pp1 = (const u_char *)&p1->u.prefix;
271 const u_char *pp2 = (const u_char *)&p2->u.prefix;
272
273 if (p1->family == AF_INET)
274 length = IPV4_MAX_BYTELEN;
275#ifdef HAVE_IPV6
276 if (p1->family == AF_INET6)
277 length = IPV6_MAX_BYTELEN;
278#endif
279 if (p1->family != p2->family || !length)
280 return -1;
281
282 for (pos = 0; pos < length; pos++)
283 if (pp1[pos] != pp2[pos])
284 break;
285 if (pos == length)
286 return pos * 8;
287
288 xor = pp1[pos] ^ pp2[pos];
289 for (bit = 0; bit < 8; bit++)
290 if (xor & (1 << (7 - bit)))
291 break;
292
293 return pos * 8 + bit;
294}
295
paul718e3742002-12-13 20:15:29 +0000296/* Return prefix family type string. */
hassob04c6992004-10-04 19:10:31 +0000297const char *
298prefix_family_str (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000299{
300 if (p->family == AF_INET)
301 return "inet";
302#ifdef HAVE_IPV6
303 if (p->family == AF_INET6)
304 return "inet6";
305#endif /* HAVE_IPV6 */
306 return "unspec";
307}
308
309/* Allocate new prefix_ipv4 structure. */
310struct prefix_ipv4 *
311prefix_ipv4_new ()
312{
313 struct prefix_ipv4 *p;
314
ajs7907c6c2005-07-26 19:55:31 +0000315 /* Call prefix_new to allocate a full-size struct prefix to avoid problems
316 where the struct prefix_ipv4 is cast to struct prefix and unallocated
317 bytes were being referenced (e.g. in structure assignments). */
318 p = (struct prefix_ipv4 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000319 p->family = AF_INET;
320 return p;
321}
322
323/* Free prefix_ipv4 structure. */
324void
325prefix_ipv4_free (struct prefix_ipv4 *p)
326{
ajs7907c6c2005-07-26 19:55:31 +0000327 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000328}
329
330/* When string format is invalid return 0. */
331int
hassob04c6992004-10-04 19:10:31 +0000332str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000333{
334 int ret;
335 int plen;
336 char *pnt;
337 char *cp;
338
339 /* Find slash inside string. */
340 pnt = strchr (str, '/');
341
342 /* String doesn't contail slash. */
343 if (pnt == NULL)
344 {
345 /* Convert string to prefix. */
346 ret = inet_aton (str, &p->prefix);
347 if (ret == 0)
348 return 0;
349
350 /* If address doesn't contain slash we assume it host address. */
351 p->family = AF_INET;
352 p->prefixlen = IPV4_MAX_BITLEN;
353
354 return ret;
355 }
356 else
357 {
358 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
359 strncpy (cp, str, pnt - str);
360 *(cp + (pnt - str)) = '\0';
361 ret = inet_aton (cp, &p->prefix);
362 XFREE (MTYPE_TMP, cp);
363
364 /* Get prefix length. */
365 plen = (u_char) atoi (++pnt);
hasso3fb9cd62004-10-19 19:44:43 +0000366 if (plen > IPV4_MAX_PREFIXLEN)
paul718e3742002-12-13 20:15:29 +0000367 return 0;
368
369 p->family = AF_INET;
370 p->prefixlen = plen;
371 }
372
373 return ret;
374}
375
Denis Ovsienko051954f2011-10-11 15:17:45 +0400376/* Convert masklen into IP address's netmask (network byte order). */
paul718e3742002-12-13 20:15:29 +0000377void
Denis Ovsienko96633862011-10-08 18:15:21 +0400378masklen2ip (const int masklen, struct in_addr *netmask)
paul718e3742002-12-13 20:15:29 +0000379{
Denis Ovsienko96633862011-10-08 18:15:21 +0400380 assert (masklen >= 0 && masklen <= 32);
Denis Ovsienko051954f2011-10-11 15:17:45 +0400381 netmask->s_addr = maskbytes_network[masklen];
paul718e3742002-12-13 20:15:29 +0000382}
383
384/* Convert IP address's netmask into integer. We assume netmask is
385 sequential one. Argument netmask should be network byte order. */
386u_char
387ip_masklen (struct in_addr netmask)
388{
389 u_char len;
390 u_char *pnt;
391 u_char *end;
392 u_char val;
393
394 len = 0;
395 pnt = (u_char *) &netmask;
396 end = pnt + 4;
397
ajs330009f2005-07-26 14:35:37 +0000398 while ((pnt < end) && (*pnt == 0xff))
paul718e3742002-12-13 20:15:29 +0000399 {
400 len+= 8;
401 pnt++;
402 }
403
404 if (pnt < end)
405 {
406 val = *pnt;
407 while (val)
408 {
409 len++;
410 val <<= 1;
411 }
412 }
413 return len;
414}
415
416/* Apply mask to IPv4 prefix. */
417void
418apply_mask_ipv4 (struct prefix_ipv4 *p)
419{
420 u_char *pnt;
421 int index;
422 int offset;
423
424 index = p->prefixlen / 8;
425
426 if (index < 4)
427 {
428 pnt = (u_char *) &p->prefix;
429 offset = p->prefixlen % 8;
430
431 pnt[index] &= maskbit[offset];
432 index++;
433
434 while (index < 4)
435 pnt[index++] = 0;
436 }
437}
438
439/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
440int
hassob04c6992004-10-04 19:10:31 +0000441prefix_ipv4_any (const struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000442{
443 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
444}
445
446#ifdef HAVE_IPV6
447
448/* Allocate a new ip version 6 route */
449struct prefix_ipv6 *
paul8cc41982005-05-06 21:25:49 +0000450prefix_ipv6_new (void)
paul718e3742002-12-13 20:15:29 +0000451{
452 struct prefix_ipv6 *p;
453
ajs7907c6c2005-07-26 19:55:31 +0000454 /* Allocate a full-size struct prefix to avoid problems with structure
455 size mismatches. */
456 p = (struct prefix_ipv6 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000457 p->family = AF_INET6;
458 return p;
459}
460
461/* Free prefix for IPv6. */
462void
463prefix_ipv6_free (struct prefix_ipv6 *p)
464{
ajs7907c6c2005-07-26 19:55:31 +0000465 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000466}
467
468/* If given string is valid return pin6 else return NULL */
469int
hassob04c6992004-10-04 19:10:31 +0000470str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
paul718e3742002-12-13 20:15:29 +0000471{
472 char *pnt;
473 char *cp;
474 int ret;
475
476 pnt = strchr (str, '/');
477
478 /* If string doesn't contain `/' treat it as host route. */
479 if (pnt == NULL)
480 {
481 ret = inet_pton (AF_INET6, str, &p->prefix);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100482 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000483 return 0;
484 p->prefixlen = IPV6_MAX_BITLEN;
485 }
486 else
487 {
488 int plen;
489
490 cp = XMALLOC (0, (pnt - str) + 1);
491 strncpy (cp, str, pnt - str);
492 *(cp + (pnt - str)) = '\0';
493 ret = inet_pton (AF_INET6, cp, &p->prefix);
494 free (cp);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100495 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000496 return 0;
497 plen = (u_char) atoi (++pnt);
498 if (plen > 128)
499 return 0;
500 p->prefixlen = plen;
501 }
502 p->family = AF_INET6;
503
504 return ret;
505}
506
hassob04c6992004-10-04 19:10:31 +0000507/* Convert struct in6_addr netmask into integer.
508 * FIXME return u_char as ip_maskleni() does. */
paul718e3742002-12-13 20:15:29 +0000509int
510ip6_masklen (struct in6_addr netmask)
511{
512 int len = 0;
513 unsigned char val;
514 unsigned char *pnt;
515
516 pnt = (unsigned char *) & netmask;
517
518 while ((*pnt == 0xff) && len < 128)
519 {
520 len += 8;
521 pnt++;
522 }
523
524 if (len < 128)
525 {
526 val = *pnt;
527 while (val)
528 {
529 len++;
530 val <<= 1;
531 }
532 }
533 return len;
534}
535
536void
537masklen2ip6 (int masklen, struct in6_addr *netmask)
538{
539 unsigned char *pnt;
540 int bit;
541 int offset;
542
543 memset (netmask, 0, sizeof (struct in6_addr));
544 pnt = (unsigned char *) netmask;
545
546 offset = masklen / 8;
547 bit = masklen % 8;
548
549 while (offset--)
550 *pnt++ = 0xff;
551
552 if (bit)
553 *pnt = maskbit[bit];
554}
555
556void
557apply_mask_ipv6 (struct prefix_ipv6 *p)
558{
559 u_char *pnt;
560 int index;
561 int offset;
562
563 index = p->prefixlen / 8;
564
565 if (index < 16)
566 {
567 pnt = (u_char *) &p->prefix;
568 offset = p->prefixlen % 8;
569
570 pnt[index] &= maskbit[offset];
571 index++;
572
573 while (index < 16)
574 pnt[index++] = 0;
575 }
576}
577
578void
hassob04c6992004-10-04 19:10:31 +0000579str2in6_addr (const char *str, struct in6_addr *addr)
paul718e3742002-12-13 20:15:29 +0000580{
581 int i;
582 unsigned int x;
583
584 /* %x must point to unsinged int */
585 for (i = 0; i < 16; i++)
586 {
587 sscanf (str + (i * 2), "%02x", &x);
588 addr->s6_addr[i] = x & 0xff;
589 }
590}
591#endif /* HAVE_IPV6 */
592
593void
594apply_mask (struct prefix *p)
595{
596 switch (p->family)
597 {
598 case AF_INET:
599 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
600 break;
601#ifdef HAVE_IPV6
602 case AF_INET6:
603 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
604 break;
605#endif /* HAVE_IPV6 */
606 default:
607 break;
608 }
609 return;
610}
611
hassob04c6992004-10-04 19:10:31 +0000612/* Utility function of convert between struct prefix <=> union sockunion.
613 * FIXME This function isn't used anywhere. */
paul718e3742002-12-13 20:15:29 +0000614struct prefix *
hassob04c6992004-10-04 19:10:31 +0000615sockunion2prefix (const union sockunion *dest,
616 const union sockunion *mask)
paul718e3742002-12-13 20:15:29 +0000617{
618 if (dest->sa.sa_family == AF_INET)
619 {
620 struct prefix_ipv4 *p;
621
622 p = prefix_ipv4_new ();
623 p->family = AF_INET;
624 p->prefix = dest->sin.sin_addr;
625 p->prefixlen = ip_masklen (mask->sin.sin_addr);
626 return (struct prefix *) p;
627 }
628#ifdef HAVE_IPV6
629 if (dest->sa.sa_family == AF_INET6)
630 {
631 struct prefix_ipv6 *p;
632
633 p = prefix_ipv6_new ();
634 p->family = AF_INET6;
635 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
636 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
637 return (struct prefix *) p;
638 }
639#endif /* HAVE_IPV6 */
640 return NULL;
641}
642
hassob04c6992004-10-04 19:10:31 +0000643/* Utility function of convert between struct prefix <=> union sockunion. */
paul718e3742002-12-13 20:15:29 +0000644struct prefix *
hassob04c6992004-10-04 19:10:31 +0000645sockunion2hostprefix (const union sockunion *su)
paul718e3742002-12-13 20:15:29 +0000646{
647 if (su->sa.sa_family == AF_INET)
648 {
649 struct prefix_ipv4 *p;
650
651 p = prefix_ipv4_new ();
652 p->family = AF_INET;
653 p->prefix = su->sin.sin_addr;
654 p->prefixlen = IPV4_MAX_BITLEN;
655 return (struct prefix *) p;
656 }
657#ifdef HAVE_IPV6
658 if (su->sa.sa_family == AF_INET6)
659 {
660 struct prefix_ipv6 *p;
661
662 p = prefix_ipv6_new ();
663 p->family = AF_INET6;
664 p->prefixlen = IPV6_MAX_BITLEN;
665 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
666 return (struct prefix *) p;
667 }
668#endif /* HAVE_IPV6 */
669 return NULL;
670}
671
David Lamparter17e52062010-02-02 20:16:35 +0100672void
673prefix2sockunion (const struct prefix *p, union sockunion *su)
674{
675 memset (su, 0, sizeof (*su));
676
677 su->sa.sa_family = p->family;
678 if (p->family == AF_INET)
679 su->sin.sin_addr = p->u.prefix4;
680#ifdef HAVE_IPV6
681 if (p->family == AF_INET6)
682 memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr));
683#endif /* HAVE_IPV6 */
684}
685
paul718e3742002-12-13 20:15:29 +0000686int
hassob04c6992004-10-04 19:10:31 +0000687prefix_blen (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000688{
689 switch (p->family)
690 {
691 case AF_INET:
692 return IPV4_MAX_BYTELEN;
693 break;
694#ifdef HAVE_IPV6
695 case AF_INET6:
696 return IPV6_MAX_BYTELEN;
697 break;
698#endif /* HAVE_IPV6 */
699 }
700 return 0;
701}
702
703/* Generic function for conversion string to struct prefix. */
704int
hassob04c6992004-10-04 19:10:31 +0000705str2prefix (const char *str, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000706{
707 int ret;
708
709 /* First we try to convert string to struct prefix_ipv4. */
710 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
711 if (ret)
712 return ret;
713
714#ifdef HAVE_IPV6
715 /* Next we try to convert string to struct prefix_ipv6. */
716 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
717 if (ret)
718 return ret;
719#endif /* HAVE_IPV6 */
720
721 return 0;
722}
723
724int
hassob04c6992004-10-04 19:10:31 +0000725prefix2str (const struct prefix *p, char *str, int size)
paul718e3742002-12-13 20:15:29 +0000726{
727 char buf[BUFSIZ];
728
729 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
730 snprintf (str, size, "%s/%d", buf, p->prefixlen);
731 return 0;
732}
733
734struct prefix *
735prefix_new ()
736{
737 struct prefix *p;
738
739 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
740 return p;
741}
742
743/* Free prefix structure. */
744void
745prefix_free (struct prefix *p)
746{
747 XFREE (MTYPE_PREFIX, p);
748}
749
750/* Utility function. Check the string only contains digit
hassob04c6992004-10-04 19:10:31 +0000751 * character.
752 * FIXME str.[c|h] would be better place for this function. */
paul718e3742002-12-13 20:15:29 +0000753int
hassob04c6992004-10-04 19:10:31 +0000754all_digit (const char *str)
paul718e3742002-12-13 20:15:29 +0000755{
756 for (; *str != '\0'; str++)
757 if (!isdigit ((int) *str))
758 return 0;
759 return 1;
760}
761
762/* Utility function to convert ipv4 prefixes to Classful prefixes */
763void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
764{
765
766 u_int32_t destination;
767
768 destination = ntohl (p->prefix.s_addr);
769
hasso3fb9cd62004-10-19 19:44:43 +0000770 if (p->prefixlen == IPV4_MAX_PREFIXLEN);
paul718e3742002-12-13 20:15:29 +0000771 /* do nothing for host routes */
772 else if (IN_CLASSC (destination))
773 {
774 p->prefixlen=24;
775 apply_mask_ipv4(p);
776 }
777 else if (IN_CLASSB(destination))
778 {
779 p->prefixlen=16;
780 apply_mask_ipv4(p);
781 }
782 else
783 {
784 p->prefixlen=8;
785 apply_mask_ipv4(p);
786 }
787}
788
hasso3fb9cd62004-10-19 19:44:43 +0000789in_addr_t
790ipv4_network_addr (in_addr_t hostaddr, int masklen)
791{
792 struct in_addr mask;
793
794 masklen2ip (masklen, &mask);
795 return hostaddr & mask.s_addr;
796}
797
798in_addr_t
799ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
800{
801 struct in_addr mask;
802
803 masklen2ip (masklen, &mask);
804 return (masklen != IPV4_MAX_PREFIXLEN-1) ?
805 /* normal case */
806 (hostaddr | ~mask.s_addr) :
807 /* special case for /31 */
808 (hostaddr ^ ~mask.s_addr);
809}
810
paul718e3742002-12-13 20:15:29 +0000811/* Utility function to convert ipv4 netmask to prefixes
812 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
813 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
814int
hassob04c6992004-10-04 19:10:31 +0000815netmask_str2prefix_str (const char *net_str, const char *mask_str,
816 char *prefix_str)
paul718e3742002-12-13 20:15:29 +0000817{
818 struct in_addr network;
819 struct in_addr mask;
820 u_char prefixlen;
821 u_int32_t destination;
822 int ret;
823
824 ret = inet_aton (net_str, &network);
825 if (! ret)
826 return 0;
827
828 if (mask_str)
829 {
830 ret = inet_aton (mask_str, &mask);
831 if (! ret)
832 return 0;
833
834 prefixlen = ip_masklen (mask);
835 }
836 else
837 {
838 destination = ntohl (network.s_addr);
839
840 if (network.s_addr == 0)
841 prefixlen = 0;
842 else if (IN_CLASSC (destination))
843 prefixlen = 24;
844 else if (IN_CLASSB (destination))
845 prefixlen = 16;
846 else if (IN_CLASSA (destination))
847 prefixlen = 8;
848 else
849 return 0;
850 }
851
852 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
853
854 return 1;
855}
856
hasso59209902005-04-05 14:36:49 +0000857#ifdef HAVE_IPV6
858/* Utility function for making IPv6 address string. */
859const char *
hasso3a2ce6a2005-04-08 01:30:51 +0000860inet6_ntoa (struct in6_addr addr)
hasso59209902005-04-05 14:36:49 +0000861{
862 static char buf[INET6_ADDRSTRLEN];
863
hasso3a2ce6a2005-04-08 01:30:51 +0000864 inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
hasso59209902005-04-05 14:36:49 +0000865 return buf;
866}
867#endif /* HAVE_IPV6 */