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