blob: 61e0f1955919d38db72a7d34dc76ece027f68d20 [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
121/* If both prefix structure is same then return 1 else return 0. */
122int
123prefix_same (struct prefix *p1, struct prefix *p2)
124{
125 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
126 {
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 */
135 }
136 return 0;
137}
138
139/* When both prefix structure is not same, but will be same after
140 applying mask, return 0. otherwise, return 1 */
141int
142prefix_cmp (struct prefix *p1, struct prefix *p2)
143{
144 int offset;
145 int shift;
146
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;
150
151 if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
152 return 1;
153
154 offset = p1->prefixlen / 8;
155 shift = p1->prefixlen % 8;
156
157 if (shift)
158 if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
159 return 1;
160
161 while (offset--)
162 if (pp1[offset] != pp2[offset])
163 return 1;
164
165 return 0;
166}
167
168/* Return prefix family type string. */
169char *
170prefix_family_str (struct prefix *p)
171{
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";
179}
180
181/* Allocate new prefix_ipv4 structure. */
182struct prefix_ipv4 *
183prefix_ipv4_new ()
184{
185 struct prefix_ipv4 *p;
186
187 p = XCALLOC (MTYPE_PREFIX_IPV4, sizeof *p);
188 p->family = AF_INET;
189 return p;
190}
191
192/* Free prefix_ipv4 structure. */
193void
194prefix_ipv4_free (struct prefix_ipv4 *p)
195{
196 XFREE (MTYPE_PREFIX_IPV4, p);
197}
198
199/* When string format is invalid return 0. */
200int
201str2prefix_ipv4 (char *str, struct prefix_ipv4 *p)
202{
203 int ret;
204 int plen;
205 char *pnt;
206 char *cp;
207
208 /* Find slash inside string. */
209 pnt = strchr (str, '/');
210
211 /* String doesn't contail slash. */
212 if (pnt == NULL)
213 {
214 /* Convert string to prefix. */
215 ret = inet_aton (str, &p->prefix);
216 if (ret == 0)
217 return 0;
218
219 /* If address doesn't contain slash we assume it host address. */
220 p->family = AF_INET;
221 p->prefixlen = IPV4_MAX_BITLEN;
222
223 return ret;
224 }
225 else
226 {
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);
232
233 /* Get prefix length. */
234 plen = (u_char) atoi (++pnt);
235 if (plen > 32)
236 return 0;
237
238 p->family = AF_INET;
239 p->prefixlen = plen;
240 }
241
242 return ret;
243}
244
245/* Convert masklen into IP address's netmask. */
246void
247masklen2ip (int masklen, struct in_addr *netmask)
248{
249 u_char *pnt;
250 int bit;
251 int offset;
252
253 memset (netmask, 0, sizeof (struct in_addr));
254 pnt = (unsigned char *) netmask;
255
256 offset = masklen / 8;
257 bit = masklen % 8;
258
259 while (offset--)
260 *pnt++ = 0xff;
261
262 if (bit)
263 *pnt = maskbit[bit];
264}
265
266/* Convert IP address's netmask into integer. We assume netmask is
267 sequential one. Argument netmask should be network byte order. */
268u_char
269ip_masklen (struct in_addr netmask)
270{
271 u_char len;
272 u_char *pnt;
273 u_char *end;
274 u_char val;
275
276 len = 0;
277 pnt = (u_char *) &netmask;
278 end = pnt + 4;
279
280 while ((*pnt == 0xff) && pnt < end)
281 {
282 len+= 8;
283 pnt++;
284 }
285
286 if (pnt < end)
287 {
288 val = *pnt;
289 while (val)
290 {
291 len++;
292 val <<= 1;
293 }
294 }
295 return len;
296}
297
298/* Apply mask to IPv4 prefix. */
299void
300apply_mask_ipv4 (struct prefix_ipv4 *p)
301{
302 u_char *pnt;
303 int index;
304 int offset;
305
306 index = p->prefixlen / 8;
307
308 if (index < 4)
309 {
310 pnt = (u_char *) &p->prefix;
311 offset = p->prefixlen % 8;
312
313 pnt[index] &= maskbit[offset];
314 index++;
315
316 while (index < 4)
317 pnt[index++] = 0;
318 }
319}
320
321/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
322int
323prefix_ipv4_any (struct prefix_ipv4 *p)
324{
325 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
326}
327
328#ifdef HAVE_IPV6
329
330/* Allocate a new ip version 6 route */
331struct prefix_ipv6 *
332prefix_ipv6_new ()
333{
334 struct prefix_ipv6 *p;
335
336 p = XCALLOC (MTYPE_PREFIX_IPV6, sizeof (struct prefix_ipv6));
337 p->family = AF_INET6;
338 return p;
339}
340
341/* Free prefix for IPv6. */
342void
343prefix_ipv6_free (struct prefix_ipv6 *p)
344{
345 XFREE (MTYPE_PREFIX_IPV6, p);
346}
347
348/* If given string is valid return pin6 else return NULL */
349int
350str2prefix_ipv6 (char *str, struct prefix_ipv6 *p)
351{
352 char *pnt;
353 char *cp;
354 int ret;
355
356 pnt = strchr (str, '/');
357
358 /* If string doesn't contain `/' treat it as host route. */
359 if (pnt == NULL)
360 {
361 ret = inet_pton (AF_INET6, str, &p->prefix);
362 if (ret != 1)
363 return 0;
364 p->prefixlen = IPV6_MAX_BITLEN;
365 }
366 else
367 {
368 int plen;
369
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;
381 }
382 p->family = AF_INET6;
383
384 return ret;
385}
386
387/* Convert struct in6_addr netmask into integer. */
388int
389ip6_masklen (struct in6_addr netmask)
390{
391 int len = 0;
392 unsigned char val;
393 unsigned char *pnt;
394
395 pnt = (unsigned char *) & netmask;
396
397 while ((*pnt == 0xff) && len < 128)
398 {
399 len += 8;
400 pnt++;
401 }
402
403 if (len < 128)
404 {
405 val = *pnt;
406 while (val)
407 {
408 len++;
409 val <<= 1;
410 }
411 }
412 return len;
413}
414
415void
416masklen2ip6 (int masklen, struct in6_addr *netmask)
417{
418 unsigned char *pnt;
419 int bit;
420 int offset;
421
422 memset (netmask, 0, sizeof (struct in6_addr));
423 pnt = (unsigned char *) netmask;
424
425 offset = masklen / 8;
426 bit = masklen % 8;
427
428 while (offset--)
429 *pnt++ = 0xff;
430
431 if (bit)
432 *pnt = maskbit[bit];
433}
434
435void
436apply_mask_ipv6 (struct prefix_ipv6 *p)
437{
438 u_char *pnt;
439 int index;
440 int offset;
441
442 index = p->prefixlen / 8;
443
444 if (index < 16)
445 {
446 pnt = (u_char *) &p->prefix;
447 offset = p->prefixlen % 8;
448
449 pnt[index] &= maskbit[offset];
450 index++;
451
452 while (index < 16)
453 pnt[index++] = 0;
454 }
455}
456
457void
458str2in6_addr (char *str, struct in6_addr *addr)
459{
460 int i;
461 unsigned int x;
462
463 /* %x must point to unsinged int */
464 for (i = 0; i < 16; i++)
465 {
466 sscanf (str + (i * 2), "%02x", &x);
467 addr->s6_addr[i] = x & 0xff;
468 }
469}
470#endif /* HAVE_IPV6 */
471
472void
473apply_mask (struct prefix *p)
474{
475 switch (p->family)
476 {
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;
487 }
488 return;
489}
490
491/* Utility function of convert between struct prefix <=> union sockunion */
492struct prefix *
493sockunion2prefix (union sockunion *dest,
494 union sockunion *mask)
495{
496 if (dest->sa.sa_family == AF_INET)
497 {
498 struct prefix_ipv4 *p;
499
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;
505 }
506#ifdef HAVE_IPV6
507 if (dest->sa.sa_family == AF_INET6)
508 {
509 struct prefix_ipv6 *p;
510
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;
516 }
517#endif /* HAVE_IPV6 */
518 return NULL;
519}
520
521/* Utility function of convert between struct prefix <=> union sockunion */
522struct prefix *
523sockunion2hostprefix (union sockunion *su)
524{
525 if (su->sa.sa_family == AF_INET)
526 {
527 struct prefix_ipv4 *p;
528
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;
534 }
535#ifdef HAVE_IPV6
536 if (su->sa.sa_family == AF_INET6)
537 {
538 struct prefix_ipv6 *p;
539
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;
545 }
546#endif /* HAVE_IPV6 */
547 return NULL;
548}
549
550int
551prefix_blen (struct prefix *p)
552{
553 switch (p->family)
554 {
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 */
563 }
564 return 0;
565}
566
567/* Generic function for conversion string to struct prefix. */
568int
569str2prefix (char *str, struct prefix *p)
570{
571 int ret;
572
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;
577
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 */
584
585 return 0;
586}
587
588int
589prefix2str (struct prefix *p, char *str, int size)
590{
591 char buf[BUFSIZ];
592
593 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
594 snprintf (str, size, "%s/%d", buf, p->prefixlen);
595 return 0;
596}
597
598struct prefix *
599prefix_new ()
600{
601 struct prefix *p;
602
603 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
604 return p;
605}
606
607/* Free prefix structure. */
608void
609prefix_free (struct prefix *p)
610{
611 XFREE (MTYPE_PREFIX, p);
612}
613
614/* Utility function. Check the string only contains digit
615 character. */
616int
617all_digit (char *str)
618{
619 for (; *str != '\0'; str++)
620 if (!isdigit ((int) *str))
621 return 0;
622 return 1;
623}
624
625/* Utility function to convert ipv4 prefixes to Classful prefixes */
626void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
627{
628
629 u_int32_t destination;
630
631 destination = ntohl (p->prefix.s_addr);
632
633 if (p->prefixlen == 32);
634 /* do nothing for host routes */
635 else if (IN_CLASSC (destination))
636 {
637 p->prefixlen=24;
638 apply_mask_ipv4(p);
639 }
640 else if (IN_CLASSB(destination))
641 {
642 p->prefixlen=16;
643 apply_mask_ipv4(p);
644 }
645 else
646 {
647 p->prefixlen=8;
648 apply_mask_ipv4(p);
649 }
650}
651
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" */
655int
656netmask_str2prefix_str (char *net_str, char *mask_str, char *prefix_str)
657{
658 struct in_addr network;
659 struct in_addr mask;
660 u_char prefixlen;
661 u_int32_t destination;
662 int ret;
663
664 ret = inet_aton (net_str, &network);
665 if (! ret)
666 return 0;
667
668 if (mask_str)
669 {
670 ret = inet_aton (mask_str, &mask);
671 if (! ret)
672 return 0;
673
674 prefixlen = ip_masklen (mask);
675 }
676 else
677 {
678 destination = ntohl (network.s_addr);
679
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;
690 }
691
692 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
693
694 return 1;
695}
696