blob: 9633a89473ba5a896473544154d22625b7f82fd8 [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 Ovsienko89a7fd12011-10-11 15:17:45 +040034static const u_int32_t maskbytes_host[] =
Denis Ovsienkocc6647f2011-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 Ovsienko89a7fd12011-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 Jakmae9e42172010-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 Jakmae9e42172010-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
256/* Return prefix family type string. */
hassob04c6992004-10-04 19:10:31 +0000257const char *
258prefix_family_str (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000259{
260 if (p->family == AF_INET)
261 return "inet";
262#ifdef HAVE_IPV6
263 if (p->family == AF_INET6)
264 return "inet6";
265#endif /* HAVE_IPV6 */
266 return "unspec";
267}
268
269/* Allocate new prefix_ipv4 structure. */
270struct prefix_ipv4 *
271prefix_ipv4_new ()
272{
273 struct prefix_ipv4 *p;
274
ajs7907c6c2005-07-26 19:55:31 +0000275 /* Call prefix_new to allocate a full-size struct prefix to avoid problems
276 where the struct prefix_ipv4 is cast to struct prefix and unallocated
277 bytes were being referenced (e.g. in structure assignments). */
278 p = (struct prefix_ipv4 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000279 p->family = AF_INET;
280 return p;
281}
282
283/* Free prefix_ipv4 structure. */
284void
285prefix_ipv4_free (struct prefix_ipv4 *p)
286{
ajs7907c6c2005-07-26 19:55:31 +0000287 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000288}
289
290/* When string format is invalid return 0. */
291int
hassob04c6992004-10-04 19:10:31 +0000292str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000293{
294 int ret;
295 int plen;
296 char *pnt;
297 char *cp;
298
299 /* Find slash inside string. */
300 pnt = strchr (str, '/');
301
302 /* String doesn't contail slash. */
303 if (pnt == NULL)
304 {
305 /* Convert string to prefix. */
306 ret = inet_aton (str, &p->prefix);
307 if (ret == 0)
308 return 0;
309
310 /* If address doesn't contain slash we assume it host address. */
311 p->family = AF_INET;
312 p->prefixlen = IPV4_MAX_BITLEN;
313
314 return ret;
315 }
316 else
317 {
318 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
319 strncpy (cp, str, pnt - str);
320 *(cp + (pnt - str)) = '\0';
321 ret = inet_aton (cp, &p->prefix);
322 XFREE (MTYPE_TMP, cp);
323
324 /* Get prefix length. */
325 plen = (u_char) atoi (++pnt);
hasso3fb9cd62004-10-19 19:44:43 +0000326 if (plen > IPV4_MAX_PREFIXLEN)
paul718e3742002-12-13 20:15:29 +0000327 return 0;
328
329 p->family = AF_INET;
330 p->prefixlen = plen;
331 }
332
333 return ret;
334}
335
Denis Ovsienko89a7fd12011-10-11 15:17:45 +0400336/* Convert masklen into IP address's netmask (network byte order). */
paul718e3742002-12-13 20:15:29 +0000337void
Denis Ovsienkocc6647f2011-10-08 18:15:21 +0400338masklen2ip (const int masklen, struct in_addr *netmask)
paul718e3742002-12-13 20:15:29 +0000339{
Denis Ovsienkocc6647f2011-10-08 18:15:21 +0400340 assert (masklen >= 0 && masklen <= 32);
Denis Ovsienko89a7fd12011-10-11 15:17:45 +0400341 netmask->s_addr = maskbytes_network[masklen];
paul718e3742002-12-13 20:15:29 +0000342}
343
344/* Convert IP address's netmask into integer. We assume netmask is
345 sequential one. Argument netmask should be network byte order. */
346u_char
347ip_masklen (struct in_addr netmask)
348{
349 u_char len;
350 u_char *pnt;
351 u_char *end;
352 u_char val;
353
354 len = 0;
355 pnt = (u_char *) &netmask;
356 end = pnt + 4;
357
ajs330009f2005-07-26 14:35:37 +0000358 while ((pnt < end) && (*pnt == 0xff))
paul718e3742002-12-13 20:15:29 +0000359 {
360 len+= 8;
361 pnt++;
362 }
363
364 if (pnt < end)
365 {
366 val = *pnt;
367 while (val)
368 {
369 len++;
370 val <<= 1;
371 }
372 }
373 return len;
374}
375
376/* Apply mask to IPv4 prefix. */
377void
378apply_mask_ipv4 (struct prefix_ipv4 *p)
379{
380 u_char *pnt;
381 int index;
382 int offset;
383
384 index = p->prefixlen / 8;
385
386 if (index < 4)
387 {
388 pnt = (u_char *) &p->prefix;
389 offset = p->prefixlen % 8;
390
391 pnt[index] &= maskbit[offset];
392 index++;
393
394 while (index < 4)
395 pnt[index++] = 0;
396 }
397}
398
399/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
400int
hassob04c6992004-10-04 19:10:31 +0000401prefix_ipv4_any (const struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000402{
403 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
404}
405
406#ifdef HAVE_IPV6
407
408/* Allocate a new ip version 6 route */
409struct prefix_ipv6 *
paul8cc41982005-05-06 21:25:49 +0000410prefix_ipv6_new (void)
paul718e3742002-12-13 20:15:29 +0000411{
412 struct prefix_ipv6 *p;
413
ajs7907c6c2005-07-26 19:55:31 +0000414 /* Allocate a full-size struct prefix to avoid problems with structure
415 size mismatches. */
416 p = (struct prefix_ipv6 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000417 p->family = AF_INET6;
418 return p;
419}
420
421/* Free prefix for IPv6. */
422void
423prefix_ipv6_free (struct prefix_ipv6 *p)
424{
ajs7907c6c2005-07-26 19:55:31 +0000425 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000426}
427
428/* If given string is valid return pin6 else return NULL */
429int
hassob04c6992004-10-04 19:10:31 +0000430str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
paul718e3742002-12-13 20:15:29 +0000431{
432 char *pnt;
433 char *cp;
434 int ret;
435
436 pnt = strchr (str, '/');
437
438 /* If string doesn't contain `/' treat it as host route. */
439 if (pnt == NULL)
440 {
441 ret = inet_pton (AF_INET6, str, &p->prefix);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100442 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000443 return 0;
444 p->prefixlen = IPV6_MAX_BITLEN;
445 }
446 else
447 {
448 int plen;
449
450 cp = XMALLOC (0, (pnt - str) + 1);
451 strncpy (cp, str, pnt - str);
452 *(cp + (pnt - str)) = '\0';
453 ret = inet_pton (AF_INET6, cp, &p->prefix);
454 free (cp);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100455 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000456 return 0;
457 plen = (u_char) atoi (++pnt);
458 if (plen > 128)
459 return 0;
460 p->prefixlen = plen;
461 }
462 p->family = AF_INET6;
463
464 return ret;
465}
466
hassob04c6992004-10-04 19:10:31 +0000467/* Convert struct in6_addr netmask into integer.
468 * FIXME return u_char as ip_maskleni() does. */
paul718e3742002-12-13 20:15:29 +0000469int
470ip6_masklen (struct in6_addr netmask)
471{
472 int len = 0;
473 unsigned char val;
474 unsigned char *pnt;
475
476 pnt = (unsigned char *) & netmask;
477
478 while ((*pnt == 0xff) && len < 128)
479 {
480 len += 8;
481 pnt++;
482 }
483
484 if (len < 128)
485 {
486 val = *pnt;
487 while (val)
488 {
489 len++;
490 val <<= 1;
491 }
492 }
493 return len;
494}
495
496void
497masklen2ip6 (int masklen, struct in6_addr *netmask)
498{
499 unsigned char *pnt;
500 int bit;
501 int offset;
502
503 memset (netmask, 0, sizeof (struct in6_addr));
504 pnt = (unsigned char *) netmask;
505
506 offset = masklen / 8;
507 bit = masklen % 8;
508
509 while (offset--)
510 *pnt++ = 0xff;
511
512 if (bit)
513 *pnt = maskbit[bit];
514}
515
516void
517apply_mask_ipv6 (struct prefix_ipv6 *p)
518{
519 u_char *pnt;
520 int index;
521 int offset;
522
523 index = p->prefixlen / 8;
524
525 if (index < 16)
526 {
527 pnt = (u_char *) &p->prefix;
528 offset = p->prefixlen % 8;
529
530 pnt[index] &= maskbit[offset];
531 index++;
532
533 while (index < 16)
534 pnt[index++] = 0;
535 }
536}
537
538void
hassob04c6992004-10-04 19:10:31 +0000539str2in6_addr (const char *str, struct in6_addr *addr)
paul718e3742002-12-13 20:15:29 +0000540{
541 int i;
542 unsigned int x;
543
544 /* %x must point to unsinged int */
545 for (i = 0; i < 16; i++)
546 {
547 sscanf (str + (i * 2), "%02x", &x);
548 addr->s6_addr[i] = x & 0xff;
549 }
550}
551#endif /* HAVE_IPV6 */
552
553void
554apply_mask (struct prefix *p)
555{
556 switch (p->family)
557 {
558 case AF_INET:
559 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
560 break;
561#ifdef HAVE_IPV6
562 case AF_INET6:
563 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
564 break;
565#endif /* HAVE_IPV6 */
566 default:
567 break;
568 }
569 return;
570}
571
hassob04c6992004-10-04 19:10:31 +0000572/* Utility function of convert between struct prefix <=> union sockunion.
573 * FIXME This function isn't used anywhere. */
paul718e3742002-12-13 20:15:29 +0000574struct prefix *
hassob04c6992004-10-04 19:10:31 +0000575sockunion2prefix (const union sockunion *dest,
576 const union sockunion *mask)
paul718e3742002-12-13 20:15:29 +0000577{
578 if (dest->sa.sa_family == AF_INET)
579 {
580 struct prefix_ipv4 *p;
581
582 p = prefix_ipv4_new ();
583 p->family = AF_INET;
584 p->prefix = dest->sin.sin_addr;
585 p->prefixlen = ip_masklen (mask->sin.sin_addr);
586 return (struct prefix *) p;
587 }
588#ifdef HAVE_IPV6
589 if (dest->sa.sa_family == AF_INET6)
590 {
591 struct prefix_ipv6 *p;
592
593 p = prefix_ipv6_new ();
594 p->family = AF_INET6;
595 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
596 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
597 return (struct prefix *) p;
598 }
599#endif /* HAVE_IPV6 */
600 return NULL;
601}
602
hassob04c6992004-10-04 19:10:31 +0000603/* Utility function of convert between struct prefix <=> union sockunion. */
paul718e3742002-12-13 20:15:29 +0000604struct prefix *
hassob04c6992004-10-04 19:10:31 +0000605sockunion2hostprefix (const union sockunion *su)
paul718e3742002-12-13 20:15:29 +0000606{
607 if (su->sa.sa_family == AF_INET)
608 {
609 struct prefix_ipv4 *p;
610
611 p = prefix_ipv4_new ();
612 p->family = AF_INET;
613 p->prefix = su->sin.sin_addr;
614 p->prefixlen = IPV4_MAX_BITLEN;
615 return (struct prefix *) p;
616 }
617#ifdef HAVE_IPV6
618 if (su->sa.sa_family == AF_INET6)
619 {
620 struct prefix_ipv6 *p;
621
622 p = prefix_ipv6_new ();
623 p->family = AF_INET6;
624 p->prefixlen = IPV6_MAX_BITLEN;
625 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
626 return (struct prefix *) p;
627 }
628#endif /* HAVE_IPV6 */
629 return NULL;
630}
631
632int
hassob04c6992004-10-04 19:10:31 +0000633prefix_blen (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000634{
635 switch (p->family)
636 {
637 case AF_INET:
638 return IPV4_MAX_BYTELEN;
639 break;
640#ifdef HAVE_IPV6
641 case AF_INET6:
642 return IPV6_MAX_BYTELEN;
643 break;
644#endif /* HAVE_IPV6 */
645 }
646 return 0;
647}
648
649/* Generic function for conversion string to struct prefix. */
650int
hassob04c6992004-10-04 19:10:31 +0000651str2prefix (const char *str, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000652{
653 int ret;
654
655 /* First we try to convert string to struct prefix_ipv4. */
656 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
657 if (ret)
658 return ret;
659
660#ifdef HAVE_IPV6
661 /* Next we try to convert string to struct prefix_ipv6. */
662 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
663 if (ret)
664 return ret;
665#endif /* HAVE_IPV6 */
666
667 return 0;
668}
669
670int
hassob04c6992004-10-04 19:10:31 +0000671prefix2str (const struct prefix *p, char *str, int size)
paul718e3742002-12-13 20:15:29 +0000672{
673 char buf[BUFSIZ];
674
675 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
676 snprintf (str, size, "%s/%d", buf, p->prefixlen);
677 return 0;
678}
679
680struct prefix *
681prefix_new ()
682{
683 struct prefix *p;
684
685 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
686 return p;
687}
688
689/* Free prefix structure. */
690void
691prefix_free (struct prefix *p)
692{
693 XFREE (MTYPE_PREFIX, p);
694}
695
696/* Utility function. Check the string only contains digit
hassob04c6992004-10-04 19:10:31 +0000697 * character.
698 * FIXME str.[c|h] would be better place for this function. */
paul718e3742002-12-13 20:15:29 +0000699int
hassob04c6992004-10-04 19:10:31 +0000700all_digit (const char *str)
paul718e3742002-12-13 20:15:29 +0000701{
702 for (; *str != '\0'; str++)
703 if (!isdigit ((int) *str))
704 return 0;
705 return 1;
706}
707
708/* Utility function to convert ipv4 prefixes to Classful prefixes */
709void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
710{
711
712 u_int32_t destination;
713
714 destination = ntohl (p->prefix.s_addr);
715
hasso3fb9cd62004-10-19 19:44:43 +0000716 if (p->prefixlen == IPV4_MAX_PREFIXLEN);
paul718e3742002-12-13 20:15:29 +0000717 /* do nothing for host routes */
718 else if (IN_CLASSC (destination))
719 {
720 p->prefixlen=24;
721 apply_mask_ipv4(p);
722 }
723 else if (IN_CLASSB(destination))
724 {
725 p->prefixlen=16;
726 apply_mask_ipv4(p);
727 }
728 else
729 {
730 p->prefixlen=8;
731 apply_mask_ipv4(p);
732 }
733}
734
hasso3fb9cd62004-10-19 19:44:43 +0000735in_addr_t
736ipv4_network_addr (in_addr_t hostaddr, int masklen)
737{
738 struct in_addr mask;
739
740 masklen2ip (masklen, &mask);
741 return hostaddr & mask.s_addr;
742}
743
744in_addr_t
745ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
746{
747 struct in_addr mask;
748
749 masklen2ip (masklen, &mask);
750 return (masklen != IPV4_MAX_PREFIXLEN-1) ?
751 /* normal case */
752 (hostaddr | ~mask.s_addr) :
753 /* special case for /31 */
754 (hostaddr ^ ~mask.s_addr);
755}
756
paul718e3742002-12-13 20:15:29 +0000757/* Utility function to convert ipv4 netmask to prefixes
758 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
759 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
760int
hassob04c6992004-10-04 19:10:31 +0000761netmask_str2prefix_str (const char *net_str, const char *mask_str,
762 char *prefix_str)
paul718e3742002-12-13 20:15:29 +0000763{
764 struct in_addr network;
765 struct in_addr mask;
766 u_char prefixlen;
767 u_int32_t destination;
768 int ret;
769
770 ret = inet_aton (net_str, &network);
771 if (! ret)
772 return 0;
773
774 if (mask_str)
775 {
776 ret = inet_aton (mask_str, &mask);
777 if (! ret)
778 return 0;
779
780 prefixlen = ip_masklen (mask);
781 }
782 else
783 {
784 destination = ntohl (network.s_addr);
785
786 if (network.s_addr == 0)
787 prefixlen = 0;
788 else if (IN_CLASSC (destination))
789 prefixlen = 24;
790 else if (IN_CLASSB (destination))
791 prefixlen = 16;
792 else if (IN_CLASSA (destination))
793 prefixlen = 8;
794 else
795 return 0;
796 }
797
798 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
799
800 return 1;
801}
802
hasso59209902005-04-05 14:36:49 +0000803#ifdef HAVE_IPV6
804/* Utility function for making IPv6 address string. */
805const char *
hasso3a2ce6a2005-04-08 01:30:51 +0000806inet6_ntoa (struct in6_addr addr)
hasso59209902005-04-05 14:36:49 +0000807{
808 static char buf[INET6_ADDRSTRLEN];
809
hasso3a2ce6a2005-04-08 01:30:51 +0000810 inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
hasso59209902005-04-05 14:36:49 +0000811 return buf;
812}
813#endif /* HAVE_IPV6 */