MiniDLNA update: 1.0.19.1 to 1.0.20
[tomato.git] / release / src / router / zebra / lib / prefix.c
blob61e0f1955919d38db72a7d34dc76ece027f68d20
1 /*
2 * Prefix related functions.
3 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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.
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.
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.
23 #include <zebra.h>
25 #include "prefix.h"
26 #include "vty.h"
27 #include "sockunion.h"
28 #include "memory.h"
29 #include "log.h"
31 /* Maskbit. */
32 static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
33 0xf8, 0xfc, 0xfe, 0xff};
35 /* Number of bits in prefix type. */
36 #ifndef PNBBY
37 #define PNBBY 8
38 #endif /* PNBBY */
40 #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
42 /* Address Famiy Identifier to Address Family converter. */
43 int
44 afi2family (int afi)
46 if (afi == AFI_IP)
47 return AF_INET;
48 #ifdef HAVE_IPV6
49 else if (afi == AFI_IP6)
50 return AF_INET6;
51 #endif /* HAVE_IPV6 */
52 return 0;
55 int
56 family2afi (int family)
58 if (family == AF_INET)
59 return AFI_IP;
60 #ifdef HAVE_IPV6
61 else if (family == AF_INET6)
62 return AFI_IP6;
63 #endif /* HAVE_IPV6 */
64 return 0;
67 /* If n includes p prefix then return 1 else return 0. */
68 int
69 prefix_match (struct prefix *n, struct prefix *p)
71 int offset;
72 int shift;
74 /* Set both prefix's head pointer. */
75 u_char *np = (u_char *)&n->u.prefix;
76 u_char *pp = (u_char *)&p->u.prefix;
78 /* If n's prefix is longer than p's one return 0. */
79 if (n->prefixlen > p->prefixlen)
80 return 0;
82 offset = n->prefixlen / PNBBY;
83 shift = n->prefixlen % PNBBY;
85 if (shift)
86 if (maskbit[shift] & (np[offset] ^ pp[offset]))
87 return 0;
89 while (offset--)
90 if (np[offset] != pp[offset])
91 return 0;
92 return 1;
95 /* Copy prefix from src to dest. */
96 void
97 prefix_copy (struct prefix *dest, struct prefix *src)
99 dest->family = src->family;
100 dest->prefixlen = src->prefixlen;
102 if (src->family == AF_INET)
103 dest->u.prefix4 = src->u.prefix4;
104 #ifdef HAVE_IPV6
105 else if (src->family == AF_INET6)
106 dest->u.prefix6 = src->u.prefix6;
107 #endif /* HAVE_IPV6 */
108 else if (src->family == AF_UNSPEC)
110 dest->u.lp.id = src->u.lp.id;
111 dest->u.lp.adv_router = src->u.lp.adv_router;
113 else
115 zlog (NULL, LOG_INFO, "prefix_copy(): Unknown address family %d",
116 src->family);
117 assert (0);
121 /* If both prefix structure is same then return 1 else return 0. */
123 prefix_same (struct prefix *p1, struct prefix *p2)
125 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
127 if (p1->family == AF_INET)
128 if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
129 return 1;
130 #ifdef HAVE_IPV6
131 if (p1->family == AF_INET6 )
132 if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
133 return 1;
134 #endif /* HAVE_IPV6 */
136 return 0;
139 /* When both prefix structure is not same, but will be same after
140 applying mask, return 0. otherwise, return 1 */
142 prefix_cmp (struct prefix *p1, struct prefix *p2)
144 int offset;
145 int shift;
147 /* Set both prefix's head pointer. */
148 u_char *pp1 = (u_char *)&p1->u.prefix;
149 u_char *pp2 = (u_char *)&p2->u.prefix;
151 if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
152 return 1;
154 offset = p1->prefixlen / 8;
155 shift = p1->prefixlen % 8;
157 if (shift)
158 if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
159 return 1;
161 while (offset--)
162 if (pp1[offset] != pp2[offset])
163 return 1;
165 return 0;
168 /* Return prefix family type string. */
169 char *
170 prefix_family_str (struct prefix *p)
172 if (p->family == AF_INET)
173 return "inet";
174 #ifdef HAVE_IPV6
175 if (p->family == AF_INET6)
176 return "inet6";
177 #endif /* HAVE_IPV6 */
178 return "unspec";
181 /* Allocate new prefix_ipv4 structure. */
182 struct prefix_ipv4 *
183 prefix_ipv4_new ()
185 struct prefix_ipv4 *p;
187 p = XCALLOC (MTYPE_PREFIX_IPV4, sizeof *p);
188 p->family = AF_INET;
189 return p;
192 /* Free prefix_ipv4 structure. */
193 void
194 prefix_ipv4_free (struct prefix_ipv4 *p)
196 XFREE (MTYPE_PREFIX_IPV4, p);
199 /* When string format is invalid return 0. */
201 str2prefix_ipv4 (char *str, struct prefix_ipv4 *p)
203 int ret;
204 int plen;
205 char *pnt;
206 char *cp;
208 /* Find slash inside string. */
209 pnt = strchr (str, '/');
211 /* String doesn't contail slash. */
212 if (pnt == NULL)
214 /* Convert string to prefix. */
215 ret = inet_aton (str, &p->prefix);
216 if (ret == 0)
217 return 0;
219 /* If address doesn't contain slash we assume it host address. */
220 p->family = AF_INET;
221 p->prefixlen = IPV4_MAX_BITLEN;
223 return ret;
225 else
227 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
228 strncpy (cp, str, pnt - str);
229 *(cp + (pnt - str)) = '\0';
230 ret = inet_aton (cp, &p->prefix);
231 XFREE (MTYPE_TMP, cp);
233 /* Get prefix length. */
234 plen = (u_char) atoi (++pnt);
235 if (plen > 32)
236 return 0;
238 p->family = AF_INET;
239 p->prefixlen = plen;
242 return ret;
245 /* Convert masklen into IP address's netmask. */
246 void
247 masklen2ip (int masklen, struct in_addr *netmask)
249 u_char *pnt;
250 int bit;
251 int offset;
253 memset (netmask, 0, sizeof (struct in_addr));
254 pnt = (unsigned char *) netmask;
256 offset = masklen / 8;
257 bit = masklen % 8;
259 while (offset--)
260 *pnt++ = 0xff;
262 if (bit)
263 *pnt = maskbit[bit];
266 /* Convert IP address's netmask into integer. We assume netmask is
267 sequential one. Argument netmask should be network byte order. */
268 u_char
269 ip_masklen (struct in_addr netmask)
271 u_char len;
272 u_char *pnt;
273 u_char *end;
274 u_char val;
276 len = 0;
277 pnt = (u_char *) &netmask;
278 end = pnt + 4;
280 while ((*pnt == 0xff) && pnt < end)
282 len+= 8;
283 pnt++;
286 if (pnt < end)
288 val = *pnt;
289 while (val)
291 len++;
292 val <<= 1;
295 return len;
298 /* Apply mask to IPv4 prefix. */
299 void
300 apply_mask_ipv4 (struct prefix_ipv4 *p)
302 u_char *pnt;
303 int index;
304 int offset;
306 index = p->prefixlen / 8;
308 if (index < 4)
310 pnt = (u_char *) &p->prefix;
311 offset = p->prefixlen % 8;
313 pnt[index] &= maskbit[offset];
314 index++;
316 while (index < 4)
317 pnt[index++] = 0;
321 /* If prefix is 0.0.0.0/0 then return 1 else return 0. */
323 prefix_ipv4_any (struct prefix_ipv4 *p)
325 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
328 #ifdef HAVE_IPV6
330 /* Allocate a new ip version 6 route */
331 struct prefix_ipv6 *
332 prefix_ipv6_new ()
334 struct prefix_ipv6 *p;
336 p = XCALLOC (MTYPE_PREFIX_IPV6, sizeof (struct prefix_ipv6));
337 p->family = AF_INET6;
338 return p;
341 /* Free prefix for IPv6. */
342 void
343 prefix_ipv6_free (struct prefix_ipv6 *p)
345 XFREE (MTYPE_PREFIX_IPV6, p);
348 /* If given string is valid return pin6 else return NULL */
350 str2prefix_ipv6 (char *str, struct prefix_ipv6 *p)
352 char *pnt;
353 char *cp;
354 int ret;
356 pnt = strchr (str, '/');
358 /* If string doesn't contain `/' treat it as host route. */
359 if (pnt == NULL)
361 ret = inet_pton (AF_INET6, str, &p->prefix);
362 if (ret != 1)
363 return 0;
364 p->prefixlen = IPV6_MAX_BITLEN;
366 else
368 int plen;
370 cp = XMALLOC (0, (pnt - str) + 1);
371 strncpy (cp, str, pnt - str);
372 *(cp + (pnt - str)) = '\0';
373 ret = inet_pton (AF_INET6, cp, &p->prefix);
374 free (cp);
375 if (ret != 1)
376 return 0;
377 plen = (u_char) atoi (++pnt);
378 if (plen > 128)
379 return 0;
380 p->prefixlen = plen;
382 p->family = AF_INET6;
384 return ret;
387 /* Convert struct in6_addr netmask into integer. */
389 ip6_masklen (struct in6_addr netmask)
391 int len = 0;
392 unsigned char val;
393 unsigned char *pnt;
395 pnt = (unsigned char *) & netmask;
397 while ((*pnt == 0xff) && len < 128)
399 len += 8;
400 pnt++;
403 if (len < 128)
405 val = *pnt;
406 while (val)
408 len++;
409 val <<= 1;
412 return len;
415 void
416 masklen2ip6 (int masklen, struct in6_addr *netmask)
418 unsigned char *pnt;
419 int bit;
420 int offset;
422 memset (netmask, 0, sizeof (struct in6_addr));
423 pnt = (unsigned char *) netmask;
425 offset = masklen / 8;
426 bit = masklen % 8;
428 while (offset--)
429 *pnt++ = 0xff;
431 if (bit)
432 *pnt = maskbit[bit];
435 void
436 apply_mask_ipv6 (struct prefix_ipv6 *p)
438 u_char *pnt;
439 int index;
440 int offset;
442 index = p->prefixlen / 8;
444 if (index < 16)
446 pnt = (u_char *) &p->prefix;
447 offset = p->prefixlen % 8;
449 pnt[index] &= maskbit[offset];
450 index++;
452 while (index < 16)
453 pnt[index++] = 0;
457 void
458 str2in6_addr (char *str, struct in6_addr *addr)
460 int i;
461 unsigned int x;
463 /* %x must point to unsinged int */
464 for (i = 0; i < 16; i++)
466 sscanf (str + (i * 2), "%02x", &x);
467 addr->s6_addr[i] = x & 0xff;
470 #endif /* HAVE_IPV6 */
472 void
473 apply_mask (struct prefix *p)
475 switch (p->family)
477 case AF_INET:
478 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
479 break;
480 #ifdef HAVE_IPV6
481 case AF_INET6:
482 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
483 break;
484 #endif /* HAVE_IPV6 */
485 default:
486 break;
488 return;
491 /* Utility function of convert between struct prefix <=> union sockunion */
492 struct prefix *
493 sockunion2prefix (union sockunion *dest,
494 union sockunion *mask)
496 if (dest->sa.sa_family == AF_INET)
498 struct prefix_ipv4 *p;
500 p = prefix_ipv4_new ();
501 p->family = AF_INET;
502 p->prefix = dest->sin.sin_addr;
503 p->prefixlen = ip_masklen (mask->sin.sin_addr);
504 return (struct prefix *) p;
506 #ifdef HAVE_IPV6
507 if (dest->sa.sa_family == AF_INET6)
509 struct prefix_ipv6 *p;
511 p = prefix_ipv6_new ();
512 p->family = AF_INET6;
513 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
514 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
515 return (struct prefix *) p;
517 #endif /* HAVE_IPV6 */
518 return NULL;
521 /* Utility function of convert between struct prefix <=> union sockunion */
522 struct prefix *
523 sockunion2hostprefix (union sockunion *su)
525 if (su->sa.sa_family == AF_INET)
527 struct prefix_ipv4 *p;
529 p = prefix_ipv4_new ();
530 p->family = AF_INET;
531 p->prefix = su->sin.sin_addr;
532 p->prefixlen = IPV4_MAX_BITLEN;
533 return (struct prefix *) p;
535 #ifdef HAVE_IPV6
536 if (su->sa.sa_family == AF_INET6)
538 struct prefix_ipv6 *p;
540 p = prefix_ipv6_new ();
541 p->family = AF_INET6;
542 p->prefixlen = IPV6_MAX_BITLEN;
543 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
544 return (struct prefix *) p;
546 #endif /* HAVE_IPV6 */
547 return NULL;
551 prefix_blen (struct prefix *p)
553 switch (p->family)
555 case AF_INET:
556 return IPV4_MAX_BYTELEN;
557 break;
558 #ifdef HAVE_IPV6
559 case AF_INET6:
560 return IPV6_MAX_BYTELEN;
561 break;
562 #endif /* HAVE_IPV6 */
564 return 0;
567 /* Generic function for conversion string to struct prefix. */
569 str2prefix (char *str, struct prefix *p)
571 int ret;
573 /* First we try to convert string to struct prefix_ipv4. */
574 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
575 if (ret)
576 return ret;
578 #ifdef HAVE_IPV6
579 /* Next we try to convert string to struct prefix_ipv6. */
580 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
581 if (ret)
582 return ret;
583 #endif /* HAVE_IPV6 */
585 return 0;
589 prefix2str (struct prefix *p, char *str, int size)
591 char buf[BUFSIZ];
593 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
594 snprintf (str, size, "%s/%d", buf, p->prefixlen);
595 return 0;
598 struct prefix *
599 prefix_new ()
601 struct prefix *p;
603 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
604 return p;
607 /* Free prefix structure. */
608 void
609 prefix_free (struct prefix *p)
611 XFREE (MTYPE_PREFIX, p);
614 /* Utility function. Check the string only contains digit
615 character. */
617 all_digit (char *str)
619 for (; *str != '\0'; str++)
620 if (!isdigit ((int) *str))
621 return 0;
622 return 1;
625 /* Utility function to convert ipv4 prefixes to Classful prefixes */
626 void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
629 u_int32_t destination;
631 destination = ntohl (p->prefix.s_addr);
633 if (p->prefixlen == 32);
634 /* do nothing for host routes */
635 else if (IN_CLASSC (destination))
637 p->prefixlen=24;
638 apply_mask_ipv4(p);
640 else if (IN_CLASSB(destination))
642 p->prefixlen=16;
643 apply_mask_ipv4(p);
645 else
647 p->prefixlen=8;
648 apply_mask_ipv4(p);
652 /* Utility function to convert ipv4 netmask to prefixes
653 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
654 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
656 netmask_str2prefix_str (char *net_str, char *mask_str, char *prefix_str)
658 struct in_addr network;
659 struct in_addr mask;
660 u_char prefixlen;
661 u_int32_t destination;
662 int ret;
664 ret = inet_aton (net_str, &network);
665 if (! ret)
666 return 0;
668 if (mask_str)
670 ret = inet_aton (mask_str, &mask);
671 if (! ret)
672 return 0;
674 prefixlen = ip_masklen (mask);
676 else
678 destination = ntohl (network.s_addr);
680 if (network.s_addr == 0)
681 prefixlen = 0;
682 else if (IN_CLASSC (destination))
683 prefixlen = 24;
684 else if (IN_CLASSB (destination))
685 prefixlen = 16;
686 else if (IN_CLASSA (destination))
687 prefixlen = 8;
688 else
689 return 0;
692 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
694 return 1;