blob: ff8abd1bb903ace3f2772b5a5f903d636f396e40 [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. */
Stephen Hemminger2d362d12009-12-21 12:54:58 +030032static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
paul718e3742002-12-13 20:15:29 +000033 0xf8, 0xfc, 0xfe, 0xff};
Denis Ovsienkocc6647f2011-10-08 18:15:21 +040034static const u_int32_t maskbytes[] =
35{
36 0x00000000, /* /0 0.0.0.0 */
37 0x80000000, /* /1 128.0.0.0 */
38 0xc0000000, /* /2 192.0.0.0 */
39 0xe0000000, /* /3 224.0.0.0 */
40 0xf0000000, /* /4 240.0.0.0 */
41 0xf8000000, /* /5 248.0.0.0 */
42 0xfc000000, /* /6 252.0.0.0 */
43 0xfe000000, /* /7 254.0.0.0 */
44 0xff000000, /* /8 255.0.0.0 */
45 0xff800000, /* /9 255.128.0.0 */
46 0xffc00000, /* /10 255.192.0.0 */
47 0xffe00000, /* /11 255.224.0.0 */
48 0xfff00000, /* /12 255.240.0.0 */
49 0xfff80000, /* /13 255.248.0.0 */
50 0xfffc0000, /* /14 255.252.0.0 */
51 0xfffe0000, /* /15 255.254.0.0 */
52 0xffff0000, /* /16 255.255.0.0 */
53 0xffff8000, /* /17 255.255.128.0 */
54 0xffffc000, /* /18 255.255.192.0 */
55 0xffffe000, /* /19 255.255.224.0 */
56 0xfffff000, /* /20 255.255.240.0 */
57 0xfffff800, /* /21 255.255.248.0 */
58 0xfffffc00, /* /22 255.255.252.0 */
59 0xfffffe00, /* /23 255.255.254.0 */
60 0xffffff00, /* /24 255.255.255.0 */
61 0xffffff80, /* /25 255.255.255.128 */
62 0xffffffc0, /* /26 255.255.255.192 */
63 0xffffffe0, /* /27 255.255.255.224 */
64 0xfffffff0, /* /28 255.255.255.240 */
65 0xfffffff8, /* /29 255.255.255.248 */
66 0xfffffffc, /* /30 255.255.255.252 */
67 0xfffffffe, /* /31 255.255.255.254 */
68 0xffffffff /* /32 255.255.255.255 */
69};
paul718e3742002-12-13 20:15:29 +000070
71/* Number of bits in prefix type. */
72#ifndef PNBBY
73#define PNBBY 8
74#endif /* PNBBY */
75
76#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
77
78/* Address Famiy Identifier to Address Family converter. */
79int
Michael Lambert4c9641b2010-07-22 13:20:55 -040080afi2family (afi_t afi)
paul718e3742002-12-13 20:15:29 +000081{
82 if (afi == AFI_IP)
83 return AF_INET;
84#ifdef HAVE_IPV6
85 else if (afi == AFI_IP6)
86 return AF_INET6;
87#endif /* HAVE_IPV6 */
88 return 0;
89}
90
Michael Lambert4c9641b2010-07-22 13:20:55 -040091afi_t
paul718e3742002-12-13 20:15:29 +000092family2afi (int family)
93{
94 if (family == AF_INET)
95 return AFI_IP;
96#ifdef HAVE_IPV6
97 else if (family == AF_INET6)
98 return AFI_IP6;
99#endif /* HAVE_IPV6 */
100 return 0;
101}
102
103/* If n includes p prefix then return 1 else return 0. */
104int
hassob04c6992004-10-04 19:10:31 +0000105prefix_match (const struct prefix *n, const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000106{
107 int offset;
108 int shift;
Paul Jakmae9e42172010-01-24 21:41:02 +0000109 const u_char *np, *pp;
paul718e3742002-12-13 20:15:29 +0000110
111 /* If n's prefix is longer than p's one return 0. */
112 if (n->prefixlen > p->prefixlen)
113 return 0;
114
Paul Jakmae9e42172010-01-24 21:41:02 +0000115 /* Set both prefix's head pointer. */
116 np = (const u_char *)&n->u.prefix;
117 pp = (const u_char *)&p->u.prefix;
118
paul718e3742002-12-13 20:15:29 +0000119 offset = n->prefixlen / PNBBY;
120 shift = n->prefixlen % PNBBY;
121
122 if (shift)
123 if (maskbit[shift] & (np[offset] ^ pp[offset]))
124 return 0;
125
126 while (offset--)
127 if (np[offset] != pp[offset])
128 return 0;
129 return 1;
130}
131
132/* Copy prefix from src to dest. */
133void
hassob04c6992004-10-04 19:10:31 +0000134prefix_copy (struct prefix *dest, const struct prefix *src)
paul718e3742002-12-13 20:15:29 +0000135{
136 dest->family = src->family;
137 dest->prefixlen = src->prefixlen;
138
139 if (src->family == AF_INET)
140 dest->u.prefix4 = src->u.prefix4;
141#ifdef HAVE_IPV6
142 else if (src->family == AF_INET6)
143 dest->u.prefix6 = src->u.prefix6;
144#endif /* HAVE_IPV6 */
145 else if (src->family == AF_UNSPEC)
146 {
147 dest->u.lp.id = src->u.lp.id;
148 dest->u.lp.adv_router = src->u.lp.adv_router;
149 }
150 else
151 {
ajsb9e70282004-12-08 17:14:45 +0000152 zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
paul718e3742002-12-13 20:15:29 +0000153 src->family);
154 assert (0);
155 }
156}
157
gdt9d24baa2004-01-13 14:55:40 +0000158/*
159 * Return 1 if the address/netmask contained in the prefix structure
160 * is the same, and else return 0. For this routine, 'same' requires
161 * that not only the prefix length and the network part be the same,
162 * but also the host part. Thus, 10.0.0.1/8 and 10.0.0.2/8 are not
163 * the same. Note that this routine has the same return value sense
164 * as '==' (which is different from prefix_cmp).
165 */
paul718e3742002-12-13 20:15:29 +0000166int
hassob04c6992004-10-04 19:10:31 +0000167prefix_same (const struct prefix *p1, const struct prefix *p2)
paul718e3742002-12-13 20:15:29 +0000168{
169 if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
170 {
171 if (p1->family == AF_INET)
172 if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
173 return 1;
174#ifdef HAVE_IPV6
175 if (p1->family == AF_INET6 )
176 if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
177 return 1;
178#endif /* HAVE_IPV6 */
179 }
180 return 0;
181}
182
gdt9d24baa2004-01-13 14:55:40 +0000183/*
184 * Return 0 if the network prefixes represented by the struct prefix
185 * arguments are the same prefix, and 1 otherwise. Network prefixes
186 * are considered the same if the prefix lengths are equal and the
187 * network parts are the same. Host bits (which are considered masked
188 * by the prefix length) are not significant. Thus, 10.0.0.1/8 and
189 * 10.0.0.2/8 are considered equivalent by this routine. Note that
190 * this routine has the same return sense as strcmp (which is different
191 * from prefix_same).
192 */
paul718e3742002-12-13 20:15:29 +0000193int
hassob04c6992004-10-04 19:10:31 +0000194prefix_cmp (const struct prefix *p1, const struct prefix *p2)
paul718e3742002-12-13 20:15:29 +0000195{
196 int offset;
197 int shift;
198
199 /* Set both prefix's head pointer. */
paul8cc41982005-05-06 21:25:49 +0000200 const u_char *pp1 = (const u_char *)&p1->u.prefix;
201 const u_char *pp2 = (const u_char *)&p2->u.prefix;
paul718e3742002-12-13 20:15:29 +0000202
203 if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
204 return 1;
205
206 offset = p1->prefixlen / 8;
207 shift = p1->prefixlen % 8;
208
209 if (shift)
210 if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
211 return 1;
212
213 while (offset--)
214 if (pp1[offset] != pp2[offset])
215 return 1;
216
217 return 0;
218}
219
220/* Return prefix family type string. */
hassob04c6992004-10-04 19:10:31 +0000221const char *
222prefix_family_str (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000223{
224 if (p->family == AF_INET)
225 return "inet";
226#ifdef HAVE_IPV6
227 if (p->family == AF_INET6)
228 return "inet6";
229#endif /* HAVE_IPV6 */
230 return "unspec";
231}
232
233/* Allocate new prefix_ipv4 structure. */
234struct prefix_ipv4 *
235prefix_ipv4_new ()
236{
237 struct prefix_ipv4 *p;
238
ajs7907c6c2005-07-26 19:55:31 +0000239 /* Call prefix_new to allocate a full-size struct prefix to avoid problems
240 where the struct prefix_ipv4 is cast to struct prefix and unallocated
241 bytes were being referenced (e.g. in structure assignments). */
242 p = (struct prefix_ipv4 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000243 p->family = AF_INET;
244 return p;
245}
246
247/* Free prefix_ipv4 structure. */
248void
249prefix_ipv4_free (struct prefix_ipv4 *p)
250{
ajs7907c6c2005-07-26 19:55:31 +0000251 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000252}
253
254/* When string format is invalid return 0. */
255int
hassob04c6992004-10-04 19:10:31 +0000256str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000257{
258 int ret;
259 int plen;
260 char *pnt;
261 char *cp;
262
263 /* Find slash inside string. */
264 pnt = strchr (str, '/');
265
266 /* String doesn't contail slash. */
267 if (pnt == NULL)
268 {
269 /* Convert string to prefix. */
270 ret = inet_aton (str, &p->prefix);
271 if (ret == 0)
272 return 0;
273
274 /* If address doesn't contain slash we assume it host address. */
275 p->family = AF_INET;
276 p->prefixlen = IPV4_MAX_BITLEN;
277
278 return ret;
279 }
280 else
281 {
282 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
283 strncpy (cp, str, pnt - str);
284 *(cp + (pnt - str)) = '\0';
285 ret = inet_aton (cp, &p->prefix);
286 XFREE (MTYPE_TMP, cp);
287
288 /* Get prefix length. */
289 plen = (u_char) atoi (++pnt);
hasso3fb9cd62004-10-19 19:44:43 +0000290 if (plen > IPV4_MAX_PREFIXLEN)
paul718e3742002-12-13 20:15:29 +0000291 return 0;
292
293 p->family = AF_INET;
294 p->prefixlen = plen;
295 }
296
297 return ret;
298}
299
300/* Convert masklen into IP address's netmask. */
301void
Denis Ovsienkocc6647f2011-10-08 18:15:21 +0400302masklen2ip (const int masklen, struct in_addr *netmask)
paul718e3742002-12-13 20:15:29 +0000303{
Denis Ovsienkocc6647f2011-10-08 18:15:21 +0400304 assert (masklen >= 0 && masklen <= 32);
305 netmask->s_addr = maskbytes[masklen];
paul718e3742002-12-13 20:15:29 +0000306}
307
308/* Convert IP address's netmask into integer. We assume netmask is
309 sequential one. Argument netmask should be network byte order. */
310u_char
311ip_masklen (struct in_addr netmask)
312{
313 u_char len;
314 u_char *pnt;
315 u_char *end;
316 u_char val;
317
318 len = 0;
319 pnt = (u_char *) &netmask;
320 end = pnt + 4;
321
ajs330009f2005-07-26 14:35:37 +0000322 while ((pnt < end) && (*pnt == 0xff))
paul718e3742002-12-13 20:15:29 +0000323 {
324 len+= 8;
325 pnt++;
326 }
327
328 if (pnt < end)
329 {
330 val = *pnt;
331 while (val)
332 {
333 len++;
334 val <<= 1;
335 }
336 }
337 return len;
338}
339
340/* Apply mask to IPv4 prefix. */
341void
342apply_mask_ipv4 (struct prefix_ipv4 *p)
343{
344 u_char *pnt;
345 int index;
346 int offset;
347
348 index = p->prefixlen / 8;
349
350 if (index < 4)
351 {
352 pnt = (u_char *) &p->prefix;
353 offset = p->prefixlen % 8;
354
355 pnt[index] &= maskbit[offset];
356 index++;
357
358 while (index < 4)
359 pnt[index++] = 0;
360 }
361}
362
363/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
364int
hassob04c6992004-10-04 19:10:31 +0000365prefix_ipv4_any (const struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000366{
367 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
368}
369
370#ifdef HAVE_IPV6
371
372/* Allocate a new ip version 6 route */
373struct prefix_ipv6 *
paul8cc41982005-05-06 21:25:49 +0000374prefix_ipv6_new (void)
paul718e3742002-12-13 20:15:29 +0000375{
376 struct prefix_ipv6 *p;
377
ajs7907c6c2005-07-26 19:55:31 +0000378 /* Allocate a full-size struct prefix to avoid problems with structure
379 size mismatches. */
380 p = (struct prefix_ipv6 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000381 p->family = AF_INET6;
382 return p;
383}
384
385/* Free prefix for IPv6. */
386void
387prefix_ipv6_free (struct prefix_ipv6 *p)
388{
ajs7907c6c2005-07-26 19:55:31 +0000389 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000390}
391
392/* If given string is valid return pin6 else return NULL */
393int
hassob04c6992004-10-04 19:10:31 +0000394str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
paul718e3742002-12-13 20:15:29 +0000395{
396 char *pnt;
397 char *cp;
398 int ret;
399
400 pnt = strchr (str, '/');
401
402 /* If string doesn't contain `/' treat it as host route. */
403 if (pnt == NULL)
404 {
405 ret = inet_pton (AF_INET6, str, &p->prefix);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100406 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000407 return 0;
408 p->prefixlen = IPV6_MAX_BITLEN;
409 }
410 else
411 {
412 int plen;
413
414 cp = XMALLOC (0, (pnt - str) + 1);
415 strncpy (cp, str, pnt - str);
416 *(cp + (pnt - str)) = '\0';
417 ret = inet_pton (AF_INET6, cp, &p->prefix);
418 free (cp);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100419 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000420 return 0;
421 plen = (u_char) atoi (++pnt);
422 if (plen > 128)
423 return 0;
424 p->prefixlen = plen;
425 }
426 p->family = AF_INET6;
427
428 return ret;
429}
430
hassob04c6992004-10-04 19:10:31 +0000431/* Convert struct in6_addr netmask into integer.
432 * FIXME return u_char as ip_maskleni() does. */
paul718e3742002-12-13 20:15:29 +0000433int
434ip6_masklen (struct in6_addr netmask)
435{
436 int len = 0;
437 unsigned char val;
438 unsigned char *pnt;
439
440 pnt = (unsigned char *) & netmask;
441
442 while ((*pnt == 0xff) && len < 128)
443 {
444 len += 8;
445 pnt++;
446 }
447
448 if (len < 128)
449 {
450 val = *pnt;
451 while (val)
452 {
453 len++;
454 val <<= 1;
455 }
456 }
457 return len;
458}
459
460void
461masklen2ip6 (int masklen, struct in6_addr *netmask)
462{
463 unsigned char *pnt;
464 int bit;
465 int offset;
466
467 memset (netmask, 0, sizeof (struct in6_addr));
468 pnt = (unsigned char *) netmask;
469
470 offset = masklen / 8;
471 bit = masklen % 8;
472
473 while (offset--)
474 *pnt++ = 0xff;
475
476 if (bit)
477 *pnt = maskbit[bit];
478}
479
480void
481apply_mask_ipv6 (struct prefix_ipv6 *p)
482{
483 u_char *pnt;
484 int index;
485 int offset;
486
487 index = p->prefixlen / 8;
488
489 if (index < 16)
490 {
491 pnt = (u_char *) &p->prefix;
492 offset = p->prefixlen % 8;
493
494 pnt[index] &= maskbit[offset];
495 index++;
496
497 while (index < 16)
498 pnt[index++] = 0;
499 }
500}
501
502void
hassob04c6992004-10-04 19:10:31 +0000503str2in6_addr (const char *str, struct in6_addr *addr)
paul718e3742002-12-13 20:15:29 +0000504{
505 int i;
506 unsigned int x;
507
508 /* %x must point to unsinged int */
509 for (i = 0; i < 16; i++)
510 {
511 sscanf (str + (i * 2), "%02x", &x);
512 addr->s6_addr[i] = x & 0xff;
513 }
514}
515#endif /* HAVE_IPV6 */
516
517void
518apply_mask (struct prefix *p)
519{
520 switch (p->family)
521 {
522 case AF_INET:
523 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
524 break;
525#ifdef HAVE_IPV6
526 case AF_INET6:
527 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
528 break;
529#endif /* HAVE_IPV6 */
530 default:
531 break;
532 }
533 return;
534}
535
hassob04c6992004-10-04 19:10:31 +0000536/* Utility function of convert between struct prefix <=> union sockunion.
537 * FIXME This function isn't used anywhere. */
paul718e3742002-12-13 20:15:29 +0000538struct prefix *
hassob04c6992004-10-04 19:10:31 +0000539sockunion2prefix (const union sockunion *dest,
540 const union sockunion *mask)
paul718e3742002-12-13 20:15:29 +0000541{
542 if (dest->sa.sa_family == AF_INET)
543 {
544 struct prefix_ipv4 *p;
545
546 p = prefix_ipv4_new ();
547 p->family = AF_INET;
548 p->prefix = dest->sin.sin_addr;
549 p->prefixlen = ip_masklen (mask->sin.sin_addr);
550 return (struct prefix *) p;
551 }
552#ifdef HAVE_IPV6
553 if (dest->sa.sa_family == AF_INET6)
554 {
555 struct prefix_ipv6 *p;
556
557 p = prefix_ipv6_new ();
558 p->family = AF_INET6;
559 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
560 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
561 return (struct prefix *) p;
562 }
563#endif /* HAVE_IPV6 */
564 return NULL;
565}
566
hassob04c6992004-10-04 19:10:31 +0000567/* Utility function of convert between struct prefix <=> union sockunion. */
paul718e3742002-12-13 20:15:29 +0000568struct prefix *
hassob04c6992004-10-04 19:10:31 +0000569sockunion2hostprefix (const union sockunion *su)
paul718e3742002-12-13 20:15:29 +0000570{
571 if (su->sa.sa_family == AF_INET)
572 {
573 struct prefix_ipv4 *p;
574
575 p = prefix_ipv4_new ();
576 p->family = AF_INET;
577 p->prefix = su->sin.sin_addr;
578 p->prefixlen = IPV4_MAX_BITLEN;
579 return (struct prefix *) p;
580 }
581#ifdef HAVE_IPV6
582 if (su->sa.sa_family == AF_INET6)
583 {
584 struct prefix_ipv6 *p;
585
586 p = prefix_ipv6_new ();
587 p->family = AF_INET6;
588 p->prefixlen = IPV6_MAX_BITLEN;
589 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
590 return (struct prefix *) p;
591 }
592#endif /* HAVE_IPV6 */
593 return NULL;
594}
595
596int
hassob04c6992004-10-04 19:10:31 +0000597prefix_blen (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000598{
599 switch (p->family)
600 {
601 case AF_INET:
602 return IPV4_MAX_BYTELEN;
603 break;
604#ifdef HAVE_IPV6
605 case AF_INET6:
606 return IPV6_MAX_BYTELEN;
607 break;
608#endif /* HAVE_IPV6 */
609 }
610 return 0;
611}
612
613/* Generic function for conversion string to struct prefix. */
614int
hassob04c6992004-10-04 19:10:31 +0000615str2prefix (const char *str, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000616{
617 int ret;
618
619 /* First we try to convert string to struct prefix_ipv4. */
620 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
621 if (ret)
622 return ret;
623
624#ifdef HAVE_IPV6
625 /* Next we try to convert string to struct prefix_ipv6. */
626 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
627 if (ret)
628 return ret;
629#endif /* HAVE_IPV6 */
630
631 return 0;
632}
633
634int
hassob04c6992004-10-04 19:10:31 +0000635prefix2str (const struct prefix *p, char *str, int size)
paul718e3742002-12-13 20:15:29 +0000636{
637 char buf[BUFSIZ];
638
639 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
640 snprintf (str, size, "%s/%d", buf, p->prefixlen);
641 return 0;
642}
643
644struct prefix *
645prefix_new ()
646{
647 struct prefix *p;
648
649 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
650 return p;
651}
652
653/* Free prefix structure. */
654void
655prefix_free (struct prefix *p)
656{
657 XFREE (MTYPE_PREFIX, p);
658}
659
660/* Utility function. Check the string only contains digit
hassob04c6992004-10-04 19:10:31 +0000661 * character.
662 * FIXME str.[c|h] would be better place for this function. */
paul718e3742002-12-13 20:15:29 +0000663int
hassob04c6992004-10-04 19:10:31 +0000664all_digit (const char *str)
paul718e3742002-12-13 20:15:29 +0000665{
666 for (; *str != '\0'; str++)
667 if (!isdigit ((int) *str))
668 return 0;
669 return 1;
670}
671
672/* Utility function to convert ipv4 prefixes to Classful prefixes */
673void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
674{
675
676 u_int32_t destination;
677
678 destination = ntohl (p->prefix.s_addr);
679
hasso3fb9cd62004-10-19 19:44:43 +0000680 if (p->prefixlen == IPV4_MAX_PREFIXLEN);
paul718e3742002-12-13 20:15:29 +0000681 /* do nothing for host routes */
682 else if (IN_CLASSC (destination))
683 {
684 p->prefixlen=24;
685 apply_mask_ipv4(p);
686 }
687 else if (IN_CLASSB(destination))
688 {
689 p->prefixlen=16;
690 apply_mask_ipv4(p);
691 }
692 else
693 {
694 p->prefixlen=8;
695 apply_mask_ipv4(p);
696 }
697}
698
hasso3fb9cd62004-10-19 19:44:43 +0000699in_addr_t
700ipv4_network_addr (in_addr_t hostaddr, int masklen)
701{
702 struct in_addr mask;
703
704 masklen2ip (masklen, &mask);
705 return hostaddr & mask.s_addr;
706}
707
708in_addr_t
709ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
710{
711 struct in_addr mask;
712
713 masklen2ip (masklen, &mask);
714 return (masklen != IPV4_MAX_PREFIXLEN-1) ?
715 /* normal case */
716 (hostaddr | ~mask.s_addr) :
717 /* special case for /31 */
718 (hostaddr ^ ~mask.s_addr);
719}
720
paul718e3742002-12-13 20:15:29 +0000721/* Utility function to convert ipv4 netmask to prefixes
722 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
723 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
724int
hassob04c6992004-10-04 19:10:31 +0000725netmask_str2prefix_str (const char *net_str, const char *mask_str,
726 char *prefix_str)
paul718e3742002-12-13 20:15:29 +0000727{
728 struct in_addr network;
729 struct in_addr mask;
730 u_char prefixlen;
731 u_int32_t destination;
732 int ret;
733
734 ret = inet_aton (net_str, &network);
735 if (! ret)
736 return 0;
737
738 if (mask_str)
739 {
740 ret = inet_aton (mask_str, &mask);
741 if (! ret)
742 return 0;
743
744 prefixlen = ip_masklen (mask);
745 }
746 else
747 {
748 destination = ntohl (network.s_addr);
749
750 if (network.s_addr == 0)
751 prefixlen = 0;
752 else if (IN_CLASSC (destination))
753 prefixlen = 24;
754 else if (IN_CLASSB (destination))
755 prefixlen = 16;
756 else if (IN_CLASSA (destination))
757 prefixlen = 8;
758 else
759 return 0;
760 }
761
762 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
763
764 return 1;
765}
766
hasso59209902005-04-05 14:36:49 +0000767#ifdef HAVE_IPV6
768/* Utility function for making IPv6 address string. */
769const char *
hasso3a2ce6a2005-04-08 01:30:51 +0000770inet6_ntoa (struct in6_addr addr)
hasso59209902005-04-05 14:36:49 +0000771{
772 static char buf[INET6_ADDRSTRLEN];
773
hasso3a2ce6a2005-04-08 01:30:51 +0000774 inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
hasso59209902005-04-05 14:36:49 +0000775 return buf;
776}
777#endif /* HAVE_IPV6 */