Tomato 1.28
[tomato.git] / release / src / router / zebra / lib / prefix.c
blob723b98ccb413ee9d8701a63cc2ce37a7df4d72c1
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 = XMALLOC (MTYPE_PREFIX_IPV4, sizeof *p);
188 bzero (p, sizeof (struct prefix_ipv4));
189 p->family = AF_INET;
190 return p;
193 /* Free prefix_ipv4 structure. */
194 void
195 prefix_ipv4_free (struct prefix_ipv4 *p)
197 XFREE (MTYPE_PREFIX_IPV4, p);
200 /* When string format is invalid return 0. */
202 str2prefix_ipv4 (char *str, struct prefix_ipv4 *p)
204 int ret;
205 int plen;
206 char *pnt;
207 char *cp;
209 /* Find slash inside string. */
210 pnt = strchr (str, '/');
212 /* String doesn't contail slash. */
213 if (pnt == NULL)
215 /* Convert string to prefix. */
216 ret = inet_aton (str, &p->prefix);
217 if (ret == 0)
218 return 0;
220 /* If address doesn't contain slash we assume it host address. */
221 p->family = AF_INET;
222 p->prefixlen = IPV4_MAX_BITLEN;
224 return ret;
226 else
228 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
229 strncpy (cp, str, pnt - str);
230 *(cp + (pnt - str)) = '\0';
231 ret = inet_aton (cp, &p->prefix);
232 XFREE (MTYPE_TMP, cp);
234 /* Get prefix length. */
235 plen = (u_char) atoi (++pnt);
236 if (plen > 32)
237 return 0;
239 p->family = AF_INET;
240 p->prefixlen = plen;
243 return ret;
246 /* Convert masklen into IP address's netmask. */
247 void
248 masklen2ip (int masklen, struct in_addr *netmask)
250 u_char *pnt;
251 int bit;
252 int offset;
254 bzero (netmask, sizeof (struct in_addr));
255 pnt = (unsigned char *) netmask;
257 offset = masklen / 8;
258 bit = masklen % 8;
260 while (offset--)
261 *pnt++ = 0xff;
263 if (bit)
264 *pnt = maskbit[bit];
267 /* Convert IP address's netmask into integer. We assume netmask is
268 sequential one. Argument netmask should be network byte order. */
269 u_char
270 ip_masklen (struct in_addr netmask)
272 u_char len;
273 u_char *pnt;
274 u_char *end;
275 u_char val;
277 len = 0;
278 pnt = (u_char *) &netmask;
279 end = pnt + 4;
281 while ((*pnt == 0xff) && pnt < end)
283 len+= 8;
284 pnt++;
287 if (pnt < end)
289 val = *pnt;
290 while (val)
292 len++;
293 val <<= 1;
296 return len;
299 /* Apply mask to IPv4 prefix. */
300 void
301 apply_mask_ipv4 (struct prefix_ipv4 *p)
303 u_char *pnt;
304 int index;
305 int offset;
307 index = p->prefixlen / 8;
309 if (index < 4)
311 pnt = (u_char *) &p->prefix;
312 offset = p->prefixlen % 8;
314 pnt[index] &= maskbit[offset];
315 index++;
317 while (index < 4)
318 pnt[index++] = 0;
322 /* If prefix is 0.0.0.0/0 then return 1 else return 0. */
324 prefix_ipv4_any (struct prefix_ipv4 *p)
326 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
329 #ifdef HAVE_IPV6
331 /* Allocate a new ip version 6 route */
332 struct prefix_ipv6 *
333 prefix_ipv6_new ()
335 struct prefix_ipv6 *p;
337 p = XMALLOC (MTYPE_PREFIX_IPV6, sizeof (struct prefix_ipv6));
338 bzero (p, sizeof (struct prefix_ipv6));
339 p->family = AF_INET6;
340 return p;
343 /* Free prefix for IPv6. */
344 void
345 prefix_ipv6_free (struct prefix_ipv6 *p)
347 XFREE (MTYPE_PREFIX_IPV6, p);
350 /* If given string is valid return pin6 else return NULL */
352 str2prefix_ipv6 (char *str, struct prefix_ipv6 *p)
354 char *pnt;
355 char *cp;
356 int ret;
358 pnt = strchr (str, '/');
360 /* If string doesn't contain `/' treat it as host route. */
361 if (pnt == NULL)
363 ret = inet_pton (AF_INET6, str, &p->prefix);
364 if (ret != 1)
365 return 0;
366 p->prefixlen = IPV6_MAX_BITLEN;
368 else
370 int plen;
372 cp = XMALLOC (0, (pnt - str) + 1);
373 strncpy (cp, str, pnt - str);
374 *(cp + (pnt - str)) = '\0';
375 ret = inet_pton (AF_INET6, cp, &p->prefix);
376 free (cp);
377 if (ret != 1)
378 return 0;
379 plen = (u_char) atoi (++pnt);
380 if (plen > 128)
381 return 0;
382 p->prefixlen = plen;
384 p->family = AF_INET6;
386 return ret;
389 /* Convert struct in6_addr netmask into integer. */
391 ip6_masklen (struct in6_addr netmask)
393 int len = 0;
394 unsigned char val;
395 unsigned char *pnt;
397 pnt = (unsigned char *) & netmask;
399 while ((*pnt == 0xff) && len < 128)
401 len += 8;
402 pnt++;
405 if (len < 128)
407 val = *pnt;
408 while (val)
410 len++;
411 val <<= 1;
414 return len;
417 void
418 masklen2ip6 (int masklen, struct in6_addr *netmask)
420 unsigned char *pnt;
421 int bit;
422 int offset;
424 bzero (netmask, sizeof (struct in6_addr));
425 pnt = (unsigned char *) netmask;
427 offset = masklen / 8;
428 bit = masklen % 8;
430 while (offset--)
431 *pnt++ = 0xff;
433 if (bit)
434 *pnt = maskbit[bit];
437 void
438 apply_mask_ipv6 (struct prefix_ipv6 *p)
440 u_char *pnt;
441 int index;
442 int offset;
444 index = p->prefixlen / 8;
446 if (index < 16)
448 pnt = (u_char *) &p->prefix;
449 offset = p->prefixlen % 8;
451 pnt[index] &= maskbit[offset];
452 index++;
454 while (index < 16)
455 pnt[index++] = 0;
459 void
460 str2in6_addr (char *str, struct in6_addr *addr)
462 int i;
463 unsigned int x;
465 /* %x must point to unsinged int */
466 for (i = 0; i < 16; i++)
468 sscanf (str + (i * 2), "%02x", &x);
469 addr->s6_addr[i] = x & 0xff;
472 #endif /* HAVE_IPV6 */
474 void
475 apply_mask (struct prefix *p)
477 switch (p->family)
479 case AF_INET:
480 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
481 break;
482 #ifdef HAVE_IPV6
483 case AF_INET6:
484 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
485 break;
486 #endif /* HAVE_IPV6 */
487 default:
488 break;
490 return;
493 /* Utility function of convert between struct prefix <=> union sockunion */
494 struct prefix *
495 sockunion2prefix (union sockunion *dest,
496 union sockunion *mask)
498 if (dest->sa.sa_family == AF_INET)
500 struct prefix_ipv4 *p;
502 p = prefix_ipv4_new ();
503 p->family = AF_INET;
504 p->prefix = dest->sin.sin_addr;
505 p->prefixlen = ip_masklen (mask->sin.sin_addr);
506 return (struct prefix *) p;
508 #ifdef HAVE_IPV6
509 if (dest->sa.sa_family == AF_INET6)
511 struct prefix_ipv6 *p;
513 p = prefix_ipv6_new ();
514 p->family = AF_INET6;
515 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
516 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
517 return (struct prefix *) p;
519 #endif /* HAVE_IPV6 */
520 return NULL;
523 /* Utility function of convert between struct prefix <=> union sockunion */
524 struct prefix *
525 sockunion2hostprefix (union sockunion *su)
527 if (su->sa.sa_family == AF_INET)
529 struct prefix_ipv4 *p;
531 p = prefix_ipv4_new ();
532 p->family = AF_INET;
533 p->prefix = su->sin.sin_addr;
534 p->prefixlen = IPV4_MAX_BITLEN;
535 return (struct prefix *) p;
537 #ifdef HAVE_IPV6
538 if (su->sa.sa_family == AF_INET6)
540 struct prefix_ipv6 *p;
542 p = prefix_ipv6_new ();
543 p->family = AF_INET6;
544 p->prefixlen = IPV6_MAX_BITLEN;
545 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
546 return (struct prefix *) p;
548 #endif /* HAVE_IPV6 */
549 return NULL;
553 prefix_blen (struct prefix *p)
555 switch (p->family)
557 case AF_INET:
558 return IPV4_MAX_BYTELEN;
559 break;
560 #ifdef HAVE_IPV6
561 case AF_INET6:
562 return IPV6_MAX_BYTELEN;
563 break;
564 #endif /* HAVE_IPV6 */
566 return 0;
569 /* Generic function for conversion string to struct prefix. */
571 str2prefix (char *str, struct prefix *p)
573 int ret;
575 /* First we try to convert string to struct prefix_ipv4. */
576 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
577 if (ret)
578 return ret;
580 #ifdef HAVE_IPV6
581 /* Next we try to convert string to struct prefix_ipv6. */
582 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
583 if (ret)
584 return ret;
585 #endif /* HAVE_IPV6 */
587 return 0;
591 prefix2str (struct prefix *p, char *str, int size)
593 char buf[BUFSIZ];
595 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
596 snprintf (str, size, "%s/%d", buf, p->prefixlen);
597 return 0;
600 struct prefix *
601 prefix_new ()
603 struct prefix *p;
605 p = XMALLOC (MTYPE_PREFIX, sizeof *p);
606 bzero (p, sizeof (struct prefix));
607 return p;
610 /* Free prefix structure. */
611 void
612 prefix_free (struct prefix *p)
614 XFREE (MTYPE_PREFIX, p);
617 /* Utility function. Check the string only contains digit
618 character. */
620 all_digit (char *str)
622 for (; *str != '\0'; str++)
623 if (!isdigit ((int) *str))
624 return 0;
625 return 1;
628 /* Utility function to convert ipv4 prefixes to Classful prefixes */
629 void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
632 u_int32_t destination;
634 destination = ntohl (p->prefix.s_addr);
636 if (p->prefixlen == 32);
637 /* do nothing for host routes */
638 else if (IN_CLASSC (destination))
640 p->prefixlen=24;
641 apply_mask_ipv4(p);
643 else if (IN_CLASSB(destination))
645 p->prefixlen=16;
646 apply_mask_ipv4(p);
648 else
650 p->prefixlen=8;
651 apply_mask_ipv4(p);
655 /* Utility function to convert ipv4 netmask to prefixes
656 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
657 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
659 netmask_str2prefix_str (char *net_str, char *mask_str, char *prefix_str)
661 struct in_addr network;
662 struct in_addr mask;
663 char masklen_str[3];
664 u_int32_t destination;
665 int ret;
667 ret = inet_aton (net_str, &network);
668 if (! ret)
669 return 0;
671 if (mask_str)
673 ret = inet_aton (mask_str, &mask);
674 if (! ret)
675 return 0;
677 sprintf (masklen_str, "%d", ip_masklen (mask));
679 else
681 destination = ntohl (network.s_addr);
683 if (network.s_addr == 0)
684 strcpy (masklen_str, "0");
685 else if (IN_CLASSC (destination))
686 strcpy (masklen_str, "24");
687 else if (IN_CLASSB (destination))
688 strcpy (masklen_str, "16");
689 else if (IN_CLASSA (destination))
690 strcpy (masklen_str, "8");
691 else
692 return 0;
695 strcpy (prefix_str, net_str);
696 strcat (prefix_str, "/");
697 strcat (prefix_str, masklen_str);
699 return 1;