Annotation of embedaddon/quagga/lib/prefix.c, revision 1.1.1.1
1.1 misho 1: /*
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. */
32: static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
33: 0xf8, 0xfc, 0xfe, 0xff};
34:
35: /* Number of bits in prefix type. */
36: #ifndef PNBBY
37: #define PNBBY 8
38: #endif /* PNBBY */
39:
40: #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
41:
42: /* Address Famiy Identifier to Address Family converter. */
43: int
44: afi2family (afi_t afi)
45: {
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;
53: }
54:
55: afi_t
56: family2afi (int family)
57: {
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;
65: }
66:
67: /* If n includes p prefix then return 1 else return 0. */
68: int
69: prefix_match (const struct prefix *n, const struct prefix *p)
70: {
71: int offset;
72: int shift;
73: const u_char *np, *pp;
74:
75: /* If n's prefix is longer than p's one return 0. */
76: if (n->prefixlen > p->prefixlen)
77: return 0;
78:
79: /* Set both prefix's head pointer. */
80: np = (const u_char *)&n->u.prefix;
81: pp = (const u_char *)&p->u.prefix;
82:
83: offset = n->prefixlen / PNBBY;
84: shift = n->prefixlen % PNBBY;
85:
86: if (shift)
87: if (maskbit[shift] & (np[offset] ^ pp[offset]))
88: return 0;
89:
90: while (offset--)
91: if (np[offset] != pp[offset])
92: return 0;
93: return 1;
94: }
95:
96: /* Copy prefix from src to dest. */
97: void
98: prefix_copy (struct prefix *dest, const struct prefix *src)
99: {
100: dest->family = src->family;
101: dest->prefixlen = src->prefixlen;
102:
103: if (src->family == AF_INET)
104: dest->u.prefix4 = src->u.prefix4;
105: #ifdef HAVE_IPV6
106: else if (src->family == AF_INET6)
107: dest->u.prefix6 = src->u.prefix6;
108: #endif /* HAVE_IPV6 */
109: else if (src->family == AF_UNSPEC)
110: {
111: dest->u.lp.id = src->u.lp.id;
112: dest->u.lp.adv_router = src->u.lp.adv_router;
113: }
114: else
115: {
116: zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
117: src->family);
118: assert (0);
119: }
120: }
121:
122: /*
123: * Return 1 if the address/netmask contained in the prefix structure
124: * is the same, and else return 0. For this routine, 'same' requires
125: * that not only the prefix length and the network part be the same,
126: * but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
127: * the same. Note that this routine has the same return value sense
128: * as '==' (which is different from prefix_cmp).
129: */
130: int
131: prefix_same (const struct prefix *p1, const struct prefix *p2)
132: {
133: if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
134: {
135: if (p1->family == AF_INET)
136: if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
137: return 1;
138: #ifdef HAVE_IPV6
139: if (p1->family == AF_INET6 )
140: if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
141: return 1;
142: #endif /* HAVE_IPV6 */
143: }
144: return 0;
145: }
146:
147: /*
148: * Return 0 if the network prefixes represented by the struct prefix
149: * arguments are the same prefix, and 1 otherwise. Network prefixes
150: * are considered the same if the prefix lengths are equal and the
151: * network parts are the same. Host bits (which are considered masked
152: * by the prefix length) are not significant. Thus, 10.0.0.1/8 and
153: * 10.0.0.2/8 are considered equivalent by this routine. Note that
154: * this routine has the same return sense as strcmp (which is different
155: * from prefix_same).
156: */
157: int
158: prefix_cmp (const struct prefix *p1, const struct prefix *p2)
159: {
160: int offset;
161: int shift;
162:
163: /* Set both prefix's head pointer. */
164: const u_char *pp1 = (const u_char *)&p1->u.prefix;
165: const u_char *pp2 = (const u_char *)&p2->u.prefix;
166:
167: if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
168: return 1;
169:
170: offset = p1->prefixlen / 8;
171: shift = p1->prefixlen % 8;
172:
173: if (shift)
174: if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
175: return 1;
176:
177: while (offset--)
178: if (pp1[offset] != pp2[offset])
179: return 1;
180:
181: return 0;
182: }
183:
184: /* Return prefix family type string. */
185: const char *
186: prefix_family_str (const struct prefix *p)
187: {
188: if (p->family == AF_INET)
189: return "inet";
190: #ifdef HAVE_IPV6
191: if (p->family == AF_INET6)
192: return "inet6";
193: #endif /* HAVE_IPV6 */
194: return "unspec";
195: }
196:
197: /* Allocate new prefix_ipv4 structure. */
198: struct prefix_ipv4 *
199: prefix_ipv4_new ()
200: {
201: struct prefix_ipv4 *p;
202:
203: /* Call prefix_new to allocate a full-size struct prefix to avoid problems
204: where the struct prefix_ipv4 is cast to struct prefix and unallocated
205: bytes were being referenced (e.g. in structure assignments). */
206: p = (struct prefix_ipv4 *)prefix_new();
207: p->family = AF_INET;
208: return p;
209: }
210:
211: /* Free prefix_ipv4 structure. */
212: void
213: prefix_ipv4_free (struct prefix_ipv4 *p)
214: {
215: prefix_free((struct prefix *)p);
216: }
217:
218: /* When string format is invalid return 0. */
219: int
220: str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
221: {
222: int ret;
223: int plen;
224: char *pnt;
225: char *cp;
226:
227: /* Find slash inside string. */
228: pnt = strchr (str, '/');
229:
230: /* String doesn't contail slash. */
231: if (pnt == NULL)
232: {
233: /* Convert string to prefix. */
234: ret = inet_aton (str, &p->prefix);
235: if (ret == 0)
236: return 0;
237:
238: /* If address doesn't contain slash we assume it host address. */
239: p->family = AF_INET;
240: p->prefixlen = IPV4_MAX_BITLEN;
241:
242: return ret;
243: }
244: else
245: {
246: cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
247: strncpy (cp, str, pnt - str);
248: *(cp + (pnt - str)) = '\0';
249: ret = inet_aton (cp, &p->prefix);
250: XFREE (MTYPE_TMP, cp);
251:
252: /* Get prefix length. */
253: plen = (u_char) atoi (++pnt);
254: if (plen > IPV4_MAX_PREFIXLEN)
255: return 0;
256:
257: p->family = AF_INET;
258: p->prefixlen = plen;
259: }
260:
261: return ret;
262: }
263:
264: /* Convert masklen into IP address's netmask. */
265: void
266: masklen2ip (int masklen, struct in_addr *netmask)
267: {
268: u_char *pnt;
269: int bit;
270: int offset;
271:
272: memset (netmask, 0, sizeof (struct in_addr));
273: pnt = (unsigned char *) netmask;
274:
275: offset = masklen / 8;
276: bit = masklen % 8;
277:
278: while (offset--)
279: *pnt++ = 0xff;
280:
281: if (bit)
282: *pnt = maskbit[bit];
283: }
284:
285: /* Convert IP address's netmask into integer. We assume netmask is
286: sequential one. Argument netmask should be network byte order. */
287: u_char
288: ip_masklen (struct in_addr netmask)
289: {
290: u_char len;
291: u_char *pnt;
292: u_char *end;
293: u_char val;
294:
295: len = 0;
296: pnt = (u_char *) &netmask;
297: end = pnt + 4;
298:
299: while ((pnt < end) && (*pnt == 0xff))
300: {
301: len+= 8;
302: pnt++;
303: }
304:
305: if (pnt < end)
306: {
307: val = *pnt;
308: while (val)
309: {
310: len++;
311: val <<= 1;
312: }
313: }
314: return len;
315: }
316:
317: /* Apply mask to IPv4 prefix. */
318: void
319: apply_mask_ipv4 (struct prefix_ipv4 *p)
320: {
321: u_char *pnt;
322: int index;
323: int offset;
324:
325: index = p->prefixlen / 8;
326:
327: if (index < 4)
328: {
329: pnt = (u_char *) &p->prefix;
330: offset = p->prefixlen % 8;
331:
332: pnt[index] &= maskbit[offset];
333: index++;
334:
335: while (index < 4)
336: pnt[index++] = 0;
337: }
338: }
339:
340: /* If prefix is 0.0.0.0/0 then return 1 else return 0. */
341: int
342: prefix_ipv4_any (const struct prefix_ipv4 *p)
343: {
344: return (p->prefix.s_addr == 0 && p->prefixlen == 0);
345: }
346:
347: #ifdef HAVE_IPV6
348:
349: /* Allocate a new ip version 6 route */
350: struct prefix_ipv6 *
351: prefix_ipv6_new (void)
352: {
353: struct prefix_ipv6 *p;
354:
355: /* Allocate a full-size struct prefix to avoid problems with structure
356: size mismatches. */
357: p = (struct prefix_ipv6 *)prefix_new();
358: p->family = AF_INET6;
359: return p;
360: }
361:
362: /* Free prefix for IPv6. */
363: void
364: prefix_ipv6_free (struct prefix_ipv6 *p)
365: {
366: prefix_free((struct prefix *)p);
367: }
368:
369: /* If given string is valid return pin6 else return NULL */
370: int
371: str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
372: {
373: char *pnt;
374: char *cp;
375: int ret;
376:
377: pnt = strchr (str, '/');
378:
379: /* If string doesn't contain `/' treat it as host route. */
380: if (pnt == NULL)
381: {
382: ret = inet_pton (AF_INET6, str, &p->prefix);
383: if (ret == 0)
384: return 0;
385: p->prefixlen = IPV6_MAX_BITLEN;
386: }
387: else
388: {
389: int plen;
390:
391: cp = XMALLOC (0, (pnt - str) + 1);
392: strncpy (cp, str, pnt - str);
393: *(cp + (pnt - str)) = '\0';
394: ret = inet_pton (AF_INET6, cp, &p->prefix);
395: free (cp);
396: if (ret == 0)
397: return 0;
398: plen = (u_char) atoi (++pnt);
399: if (plen > 128)
400: return 0;
401: p->prefixlen = plen;
402: }
403: p->family = AF_INET6;
404:
405: return ret;
406: }
407:
408: /* Convert struct in6_addr netmask into integer.
409: * FIXME return u_char as ip_maskleni() does. */
410: int
411: ip6_masklen (struct in6_addr netmask)
412: {
413: int len = 0;
414: unsigned char val;
415: unsigned char *pnt;
416:
417: pnt = (unsigned char *) & netmask;
418:
419: while ((*pnt == 0xff) && len < 128)
420: {
421: len += 8;
422: pnt++;
423: }
424:
425: if (len < 128)
426: {
427: val = *pnt;
428: while (val)
429: {
430: len++;
431: val <<= 1;
432: }
433: }
434: return len;
435: }
436:
437: void
438: masklen2ip6 (int masklen, struct in6_addr *netmask)
439: {
440: unsigned char *pnt;
441: int bit;
442: int offset;
443:
444: memset (netmask, 0, sizeof (struct in6_addr));
445: pnt = (unsigned char *) netmask;
446:
447: offset = masklen / 8;
448: bit = masklen % 8;
449:
450: while (offset--)
451: *pnt++ = 0xff;
452:
453: if (bit)
454: *pnt = maskbit[bit];
455: }
456:
457: void
458: apply_mask_ipv6 (struct prefix_ipv6 *p)
459: {
460: u_char *pnt;
461: int index;
462: int offset;
463:
464: index = p->prefixlen / 8;
465:
466: if (index < 16)
467: {
468: pnt = (u_char *) &p->prefix;
469: offset = p->prefixlen % 8;
470:
471: pnt[index] &= maskbit[offset];
472: index++;
473:
474: while (index < 16)
475: pnt[index++] = 0;
476: }
477: }
478:
479: void
480: str2in6_addr (const char *str, struct in6_addr *addr)
481: {
482: int i;
483: unsigned int x;
484:
485: /* %x must point to unsinged int */
486: for (i = 0; i < 16; i++)
487: {
488: sscanf (str + (i * 2), "%02x", &x);
489: addr->s6_addr[i] = x & 0xff;
490: }
491: }
492: #endif /* HAVE_IPV6 */
493:
494: void
495: apply_mask (struct prefix *p)
496: {
497: switch (p->family)
498: {
499: case AF_INET:
500: apply_mask_ipv4 ((struct prefix_ipv4 *)p);
501: break;
502: #ifdef HAVE_IPV6
503: case AF_INET6:
504: apply_mask_ipv6 ((struct prefix_ipv6 *)p);
505: break;
506: #endif /* HAVE_IPV6 */
507: default:
508: break;
509: }
510: return;
511: }
512:
513: /* Utility function of convert between struct prefix <=> union sockunion.
514: * FIXME This function isn't used anywhere. */
515: struct prefix *
516: sockunion2prefix (const union sockunion *dest,
517: const union sockunion *mask)
518: {
519: if (dest->sa.sa_family == AF_INET)
520: {
521: struct prefix_ipv4 *p;
522:
523: p = prefix_ipv4_new ();
524: p->family = AF_INET;
525: p->prefix = dest->sin.sin_addr;
526: p->prefixlen = ip_masklen (mask->sin.sin_addr);
527: return (struct prefix *) p;
528: }
529: #ifdef HAVE_IPV6
530: if (dest->sa.sa_family == AF_INET6)
531: {
532: struct prefix_ipv6 *p;
533:
534: p = prefix_ipv6_new ();
535: p->family = AF_INET6;
536: p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
537: memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
538: return (struct prefix *) p;
539: }
540: #endif /* HAVE_IPV6 */
541: return NULL;
542: }
543:
544: /* Utility function of convert between struct prefix <=> union sockunion. */
545: struct prefix *
546: sockunion2hostprefix (const union sockunion *su)
547: {
548: if (su->sa.sa_family == AF_INET)
549: {
550: struct prefix_ipv4 *p;
551:
552: p = prefix_ipv4_new ();
553: p->family = AF_INET;
554: p->prefix = su->sin.sin_addr;
555: p->prefixlen = IPV4_MAX_BITLEN;
556: return (struct prefix *) p;
557: }
558: #ifdef HAVE_IPV6
559: if (su->sa.sa_family == AF_INET6)
560: {
561: struct prefix_ipv6 *p;
562:
563: p = prefix_ipv6_new ();
564: p->family = AF_INET6;
565: p->prefixlen = IPV6_MAX_BITLEN;
566: memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
567: return (struct prefix *) p;
568: }
569: #endif /* HAVE_IPV6 */
570: return NULL;
571: }
572:
573: int
574: prefix_blen (const struct prefix *p)
575: {
576: switch (p->family)
577: {
578: case AF_INET:
579: return IPV4_MAX_BYTELEN;
580: break;
581: #ifdef HAVE_IPV6
582: case AF_INET6:
583: return IPV6_MAX_BYTELEN;
584: break;
585: #endif /* HAVE_IPV6 */
586: }
587: return 0;
588: }
589:
590: /* Generic function for conversion string to struct prefix. */
591: int
592: str2prefix (const char *str, struct prefix *p)
593: {
594: int ret;
595:
596: /* First we try to convert string to struct prefix_ipv4. */
597: ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
598: if (ret)
599: return ret;
600:
601: #ifdef HAVE_IPV6
602: /* Next we try to convert string to struct prefix_ipv6. */
603: ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
604: if (ret)
605: return ret;
606: #endif /* HAVE_IPV6 */
607:
608: return 0;
609: }
610:
611: int
612: prefix2str (const struct prefix *p, char *str, int size)
613: {
614: char buf[BUFSIZ];
615:
616: inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
617: snprintf (str, size, "%s/%d", buf, p->prefixlen);
618: return 0;
619: }
620:
621: struct prefix *
622: prefix_new ()
623: {
624: struct prefix *p;
625:
626: p = XCALLOC (MTYPE_PREFIX, sizeof *p);
627: return p;
628: }
629:
630: /* Free prefix structure. */
631: void
632: prefix_free (struct prefix *p)
633: {
634: XFREE (MTYPE_PREFIX, p);
635: }
636:
637: /* Utility function. Check the string only contains digit
638: * character.
639: * FIXME str.[c|h] would be better place for this function. */
640: int
641: all_digit (const char *str)
642: {
643: for (; *str != '\0'; str++)
644: if (!isdigit ((int) *str))
645: return 0;
646: return 1;
647: }
648:
649: /* Utility function to convert ipv4 prefixes to Classful prefixes */
650: void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
651: {
652:
653: u_int32_t destination;
654:
655: destination = ntohl (p->prefix.s_addr);
656:
657: if (p->prefixlen == IPV4_MAX_PREFIXLEN);
658: /* do nothing for host routes */
659: else if (IN_CLASSC (destination))
660: {
661: p->prefixlen=24;
662: apply_mask_ipv4(p);
663: }
664: else if (IN_CLASSB(destination))
665: {
666: p->prefixlen=16;
667: apply_mask_ipv4(p);
668: }
669: else
670: {
671: p->prefixlen=8;
672: apply_mask_ipv4(p);
673: }
674: }
675:
676: in_addr_t
677: ipv4_network_addr (in_addr_t hostaddr, int masklen)
678: {
679: struct in_addr mask;
680:
681: masklen2ip (masklen, &mask);
682: return hostaddr & mask.s_addr;
683: }
684:
685: in_addr_t
686: ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
687: {
688: struct in_addr mask;
689:
690: masklen2ip (masklen, &mask);
691: return (masklen != IPV4_MAX_PREFIXLEN-1) ?
692: /* normal case */
693: (hostaddr | ~mask.s_addr) :
694: /* special case for /31 */
695: (hostaddr ^ ~mask.s_addr);
696: }
697:
698: /* Utility function to convert ipv4 netmask to prefixes
699: ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
700: ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
701: int
702: netmask_str2prefix_str (const char *net_str, const char *mask_str,
703: char *prefix_str)
704: {
705: struct in_addr network;
706: struct in_addr mask;
707: u_char prefixlen;
708: u_int32_t destination;
709: int ret;
710:
711: ret = inet_aton (net_str, &network);
712: if (! ret)
713: return 0;
714:
715: if (mask_str)
716: {
717: ret = inet_aton (mask_str, &mask);
718: if (! ret)
719: return 0;
720:
721: prefixlen = ip_masklen (mask);
722: }
723: else
724: {
725: destination = ntohl (network.s_addr);
726:
727: if (network.s_addr == 0)
728: prefixlen = 0;
729: else if (IN_CLASSC (destination))
730: prefixlen = 24;
731: else if (IN_CLASSB (destination))
732: prefixlen = 16;
733: else if (IN_CLASSA (destination))
734: prefixlen = 8;
735: else
736: return 0;
737: }
738:
739: sprintf (prefix_str, "%s/%d", net_str, prefixlen);
740:
741: return 1;
742: }
743:
744: #ifdef HAVE_IPV6
745: /* Utility function for making IPv6 address string. */
746: const char *
747: inet6_ntoa (struct in6_addr addr)
748: {
749: static char buf[INET6_ADDRSTRLEN];
750:
751: inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
752: return buf;
753: }
754: #endif /* HAVE_IPV6 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>