blob: fff09326d401e104379c7c1ce71ce5f31a5a8377 [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};
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
Michael Lambert4c9641b2010-07-22 13:20:55 -040044afi2family (afi_t afi)
paul718e3742002-12-13 20:15:29 +000045{
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
Michael Lambert4c9641b2010-07-22 13:20:55 -040055afi_t
paul718e3742002-12-13 20:15:29 +000056family2afi (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
hassob04c6992004-10-04 19:10:31 +000069prefix_match (const struct prefix *n, const struct prefix *p)
paul718e3742002-12-13 20:15:29 +000070{
71 int offset;
72 int shift;
Paul Jakmad3583442010-01-24 21:41:02 +000073 const u_char *np, *pp;
paul718e3742002-12-13 20:15:29 +000074
75 /* If n's prefix is longer than p's one return 0. */
76 if (n->prefixlen > p->prefixlen)
77 return 0;
78
Paul Jakmad3583442010-01-24 21:41:02 +000079 /* Set both prefix's head pointer. */
80 np = (const u_char *)&n->u.prefix;
81 pp = (const u_char *)&p->u.prefix;
82
paul718e3742002-12-13 20:15:29 +000083 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. */
97void
hassob04c6992004-10-04 19:10:31 +000098prefix_copy (struct prefix *dest, const struct prefix *src)
paul718e3742002-12-13 20:15:29 +000099{
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 {
ajsb9e70282004-12-08 17:14:45 +0000116 zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
paul718e3742002-12-13 20:15:29 +0000117 src->family);
118 assert (0);
119 }
120}
121
gdt9d24baa2004-01-13 14:55:40 +0000122/*
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 */
paul718e3742002-12-13 20:15:29 +0000130int
hassob04c6992004-10-04 19:10:31 +0000131prefix_same (const struct prefix *p1, const struct prefix *p2)
paul718e3742002-12-13 20:15:29 +0000132{
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
gdt9d24baa2004-01-13 14:55:40 +0000147/*
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 */
paul718e3742002-12-13 20:15:29 +0000157int
hassob04c6992004-10-04 19:10:31 +0000158prefix_cmp (const struct prefix *p1, const struct prefix *p2)
paul718e3742002-12-13 20:15:29 +0000159{
160 int offset;
161 int shift;
162
163 /* Set both prefix's head pointer. */
paul8cc41982005-05-06 21:25:49 +0000164 const u_char *pp1 = (const u_char *)&p1->u.prefix;
165 const u_char *pp2 = (const u_char *)&p2->u.prefix;
paul718e3742002-12-13 20:15:29 +0000166
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
David Lamparter17e52062010-02-02 20:16:35 +0100184/*
185 * Count the number of common bits in 2 prefixes. The prefix length is
186 * ignored for this function; the whole prefix is compared. If the prefix
187 * address families don't match, return -1; otherwise the return value is
188 * in range 0 ... maximum prefix length for the address family.
189 */
190int
191prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
192{
193 int pos, bit;
194 int length = 0;
195 u_char xor;
196
197 /* Set both prefix's head pointer. */
198 const u_char *pp1 = (const u_char *)&p1->u.prefix;
199 const u_char *pp2 = (const u_char *)&p2->u.prefix;
200
201 if (p1->family == AF_INET)
202 length = IPV4_MAX_BYTELEN;
203#ifdef HAVE_IPV6
204 if (p1->family == AF_INET6)
205 length = IPV6_MAX_BYTELEN;
206#endif
207 if (p1->family != p2->family || !length)
208 return -1;
209
210 for (pos = 0; pos < length; pos++)
211 if (pp1[pos] != pp2[pos])
212 break;
213 if (pos == length)
214 return pos * 8;
215
216 xor = pp1[pos] ^ pp2[pos];
217 for (bit = 0; bit < 8; bit++)
218 if (xor & (1 << (7 - bit)))
219 break;
220
221 return pos * 8 + bit;
222}
223
paul718e3742002-12-13 20:15:29 +0000224/* Return prefix family type string. */
hassob04c6992004-10-04 19:10:31 +0000225const char *
226prefix_family_str (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000227{
228 if (p->family == AF_INET)
229 return "inet";
230#ifdef HAVE_IPV6
231 if (p->family == AF_INET6)
232 return "inet6";
233#endif /* HAVE_IPV6 */
234 return "unspec";
235}
236
237/* Allocate new prefix_ipv4 structure. */
238struct prefix_ipv4 *
239prefix_ipv4_new ()
240{
241 struct prefix_ipv4 *p;
242
ajs7907c6c2005-07-26 19:55:31 +0000243 /* Call prefix_new to allocate a full-size struct prefix to avoid problems
244 where the struct prefix_ipv4 is cast to struct prefix and unallocated
245 bytes were being referenced (e.g. in structure assignments). */
246 p = (struct prefix_ipv4 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000247 p->family = AF_INET;
248 return p;
249}
250
251/* Free prefix_ipv4 structure. */
252void
253prefix_ipv4_free (struct prefix_ipv4 *p)
254{
ajs7907c6c2005-07-26 19:55:31 +0000255 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000256}
257
258/* When string format is invalid return 0. */
259int
hassob04c6992004-10-04 19:10:31 +0000260str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000261{
262 int ret;
263 int plen;
264 char *pnt;
265 char *cp;
266
267 /* Find slash inside string. */
268 pnt = strchr (str, '/');
269
270 /* String doesn't contail slash. */
271 if (pnt == NULL)
272 {
273 /* Convert string to prefix. */
274 ret = inet_aton (str, &p->prefix);
275 if (ret == 0)
276 return 0;
277
278 /* If address doesn't contain slash we assume it host address. */
279 p->family = AF_INET;
280 p->prefixlen = IPV4_MAX_BITLEN;
281
282 return ret;
283 }
284 else
285 {
286 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
287 strncpy (cp, str, pnt - str);
288 *(cp + (pnt - str)) = '\0';
289 ret = inet_aton (cp, &p->prefix);
290 XFREE (MTYPE_TMP, cp);
291
292 /* Get prefix length. */
293 plen = (u_char) atoi (++pnt);
hasso3fb9cd62004-10-19 19:44:43 +0000294 if (plen > IPV4_MAX_PREFIXLEN)
paul718e3742002-12-13 20:15:29 +0000295 return 0;
296
297 p->family = AF_INET;
298 p->prefixlen = plen;
299 }
300
301 return ret;
302}
303
304/* Convert masklen into IP address's netmask. */
305void
306masklen2ip (int masklen, struct in_addr *netmask)
307{
308 u_char *pnt;
309 int bit;
310 int offset;
311
312 memset (netmask, 0, sizeof (struct in_addr));
313 pnt = (unsigned char *) netmask;
314
315 offset = masklen / 8;
316 bit = masklen % 8;
317
318 while (offset--)
319 *pnt++ = 0xff;
320
321 if (bit)
322 *pnt = maskbit[bit];
323}
324
325/* Convert IP address's netmask into integer. We assume netmask is
326 sequential one. Argument netmask should be network byte order. */
327u_char
328ip_masklen (struct in_addr netmask)
329{
330 u_char len;
331 u_char *pnt;
332 u_char *end;
333 u_char val;
334
335 len = 0;
336 pnt = (u_char *) &netmask;
337 end = pnt + 4;
338
ajs330009f2005-07-26 14:35:37 +0000339 while ((pnt < end) && (*pnt == 0xff))
paul718e3742002-12-13 20:15:29 +0000340 {
341 len+= 8;
342 pnt++;
343 }
344
345 if (pnt < end)
346 {
347 val = *pnt;
348 while (val)
349 {
350 len++;
351 val <<= 1;
352 }
353 }
354 return len;
355}
356
357/* Apply mask to IPv4 prefix. */
358void
359apply_mask_ipv4 (struct prefix_ipv4 *p)
360{
361 u_char *pnt;
362 int index;
363 int offset;
364
365 index = p->prefixlen / 8;
366
367 if (index < 4)
368 {
369 pnt = (u_char *) &p->prefix;
370 offset = p->prefixlen % 8;
371
372 pnt[index] &= maskbit[offset];
373 index++;
374
375 while (index < 4)
376 pnt[index++] = 0;
377 }
378}
379
380/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
381int
hassob04c6992004-10-04 19:10:31 +0000382prefix_ipv4_any (const struct prefix_ipv4 *p)
paul718e3742002-12-13 20:15:29 +0000383{
384 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
385}
386
387#ifdef HAVE_IPV6
388
389/* Allocate a new ip version 6 route */
390struct prefix_ipv6 *
paul8cc41982005-05-06 21:25:49 +0000391prefix_ipv6_new (void)
paul718e3742002-12-13 20:15:29 +0000392{
393 struct prefix_ipv6 *p;
394
ajs7907c6c2005-07-26 19:55:31 +0000395 /* Allocate a full-size struct prefix to avoid problems with structure
396 size mismatches. */
397 p = (struct prefix_ipv6 *)prefix_new();
paul718e3742002-12-13 20:15:29 +0000398 p->family = AF_INET6;
399 return p;
400}
401
402/* Free prefix for IPv6. */
403void
404prefix_ipv6_free (struct prefix_ipv6 *p)
405{
ajs7907c6c2005-07-26 19:55:31 +0000406 prefix_free((struct prefix *)p);
paul718e3742002-12-13 20:15:29 +0000407}
408
409/* If given string is valid return pin6 else return NULL */
410int
hassob04c6992004-10-04 19:10:31 +0000411str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
paul718e3742002-12-13 20:15:29 +0000412{
413 char *pnt;
414 char *cp;
415 int ret;
416
417 pnt = strchr (str, '/');
418
419 /* If string doesn't contain `/' treat it as host route. */
420 if (pnt == NULL)
421 {
422 ret = inet_pton (AF_INET6, str, &p->prefix);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100423 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000424 return 0;
425 p->prefixlen = IPV6_MAX_BITLEN;
426 }
427 else
428 {
429 int plen;
430
431 cp = XMALLOC (0, (pnt - str) + 1);
432 strncpy (cp, str, pnt - str);
433 *(cp + (pnt - str)) = '\0';
434 ret = inet_pton (AF_INET6, cp, &p->prefix);
435 free (cp);
Paul Jakmac4cf0952009-08-08 20:41:39 +0100436 if (ret == 0)
paul718e3742002-12-13 20:15:29 +0000437 return 0;
438 plen = (u_char) atoi (++pnt);
439 if (plen > 128)
440 return 0;
441 p->prefixlen = plen;
442 }
443 p->family = AF_INET6;
444
445 return ret;
446}
447
hassob04c6992004-10-04 19:10:31 +0000448/* Convert struct in6_addr netmask into integer.
449 * FIXME return u_char as ip_maskleni() does. */
paul718e3742002-12-13 20:15:29 +0000450int
451ip6_masklen (struct in6_addr netmask)
452{
453 int len = 0;
454 unsigned char val;
455 unsigned char *pnt;
456
457 pnt = (unsigned char *) & netmask;
458
459 while ((*pnt == 0xff) && len < 128)
460 {
461 len += 8;
462 pnt++;
463 }
464
465 if (len < 128)
466 {
467 val = *pnt;
468 while (val)
469 {
470 len++;
471 val <<= 1;
472 }
473 }
474 return len;
475}
476
477void
478masklen2ip6 (int masklen, struct in6_addr *netmask)
479{
480 unsigned char *pnt;
481 int bit;
482 int offset;
483
484 memset (netmask, 0, sizeof (struct in6_addr));
485 pnt = (unsigned char *) netmask;
486
487 offset = masklen / 8;
488 bit = masklen % 8;
489
490 while (offset--)
491 *pnt++ = 0xff;
492
493 if (bit)
494 *pnt = maskbit[bit];
495}
496
497void
498apply_mask_ipv6 (struct prefix_ipv6 *p)
499{
500 u_char *pnt;
501 int index;
502 int offset;
503
504 index = p->prefixlen / 8;
505
506 if (index < 16)
507 {
508 pnt = (u_char *) &p->prefix;
509 offset = p->prefixlen % 8;
510
511 pnt[index] &= maskbit[offset];
512 index++;
513
514 while (index < 16)
515 pnt[index++] = 0;
516 }
517}
518
519void
hassob04c6992004-10-04 19:10:31 +0000520str2in6_addr (const char *str, struct in6_addr *addr)
paul718e3742002-12-13 20:15:29 +0000521{
522 int i;
523 unsigned int x;
524
525 /* %x must point to unsinged int */
526 for (i = 0; i < 16; i++)
527 {
528 sscanf (str + (i * 2), "%02x", &x);
529 addr->s6_addr[i] = x & 0xff;
530 }
531}
532#endif /* HAVE_IPV6 */
533
534void
535apply_mask (struct prefix *p)
536{
537 switch (p->family)
538 {
539 case AF_INET:
540 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
541 break;
542#ifdef HAVE_IPV6
543 case AF_INET6:
544 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
545 break;
546#endif /* HAVE_IPV6 */
547 default:
548 break;
549 }
550 return;
551}
552
hassob04c6992004-10-04 19:10:31 +0000553/* Utility function of convert between struct prefix <=> union sockunion.
554 * FIXME This function isn't used anywhere. */
paul718e3742002-12-13 20:15:29 +0000555struct prefix *
hassob04c6992004-10-04 19:10:31 +0000556sockunion2prefix (const union sockunion *dest,
557 const union sockunion *mask)
paul718e3742002-12-13 20:15:29 +0000558{
559 if (dest->sa.sa_family == AF_INET)
560 {
561 struct prefix_ipv4 *p;
562
563 p = prefix_ipv4_new ();
564 p->family = AF_INET;
565 p->prefix = dest->sin.sin_addr;
566 p->prefixlen = ip_masklen (mask->sin.sin_addr);
567 return (struct prefix *) p;
568 }
569#ifdef HAVE_IPV6
570 if (dest->sa.sa_family == AF_INET6)
571 {
572 struct prefix_ipv6 *p;
573
574 p = prefix_ipv6_new ();
575 p->family = AF_INET6;
576 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
577 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
578 return (struct prefix *) p;
579 }
580#endif /* HAVE_IPV6 */
581 return NULL;
582}
583
hassob04c6992004-10-04 19:10:31 +0000584/* Utility function of convert between struct prefix <=> union sockunion. */
paul718e3742002-12-13 20:15:29 +0000585struct prefix *
hassob04c6992004-10-04 19:10:31 +0000586sockunion2hostprefix (const union sockunion *su)
paul718e3742002-12-13 20:15:29 +0000587{
588 if (su->sa.sa_family == AF_INET)
589 {
590 struct prefix_ipv4 *p;
591
592 p = prefix_ipv4_new ();
593 p->family = AF_INET;
594 p->prefix = su->sin.sin_addr;
595 p->prefixlen = IPV4_MAX_BITLEN;
596 return (struct prefix *) p;
597 }
598#ifdef HAVE_IPV6
599 if (su->sa.sa_family == AF_INET6)
600 {
601 struct prefix_ipv6 *p;
602
603 p = prefix_ipv6_new ();
604 p->family = AF_INET6;
605 p->prefixlen = IPV6_MAX_BITLEN;
606 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
607 return (struct prefix *) p;
608 }
609#endif /* HAVE_IPV6 */
610 return NULL;
611}
612
David Lamparter17e52062010-02-02 20:16:35 +0100613void
614prefix2sockunion (const struct prefix *p, union sockunion *su)
615{
616 memset (su, 0, sizeof (*su));
617
618 su->sa.sa_family = p->family;
619 if (p->family == AF_INET)
620 su->sin.sin_addr = p->u.prefix4;
621#ifdef HAVE_IPV6
622 if (p->family == AF_INET6)
623 memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr));
624#endif /* HAVE_IPV6 */
625}
626
paul718e3742002-12-13 20:15:29 +0000627int
hassob04c6992004-10-04 19:10:31 +0000628prefix_blen (const struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000629{
630 switch (p->family)
631 {
632 case AF_INET:
633 return IPV4_MAX_BYTELEN;
634 break;
635#ifdef HAVE_IPV6
636 case AF_INET6:
637 return IPV6_MAX_BYTELEN;
638 break;
639#endif /* HAVE_IPV6 */
640 }
641 return 0;
642}
643
644/* Generic function for conversion string to struct prefix. */
645int
hassob04c6992004-10-04 19:10:31 +0000646str2prefix (const char *str, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000647{
648 int ret;
649
650 /* First we try to convert string to struct prefix_ipv4. */
651 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
652 if (ret)
653 return ret;
654
655#ifdef HAVE_IPV6
656 /* Next we try to convert string to struct prefix_ipv6. */
657 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
658 if (ret)
659 return ret;
660#endif /* HAVE_IPV6 */
661
662 return 0;
663}
664
665int
hassob04c6992004-10-04 19:10:31 +0000666prefix2str (const struct prefix *p, char *str, int size)
paul718e3742002-12-13 20:15:29 +0000667{
668 char buf[BUFSIZ];
669
670 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
671 snprintf (str, size, "%s/%d", buf, p->prefixlen);
672 return 0;
673}
674
675struct prefix *
676prefix_new ()
677{
678 struct prefix *p;
679
680 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
681 return p;
682}
683
684/* Free prefix structure. */
685void
686prefix_free (struct prefix *p)
687{
688 XFREE (MTYPE_PREFIX, p);
689}
690
691/* Utility function. Check the string only contains digit
hassob04c6992004-10-04 19:10:31 +0000692 * character.
693 * FIXME str.[c|h] would be better place for this function. */
paul718e3742002-12-13 20:15:29 +0000694int
hassob04c6992004-10-04 19:10:31 +0000695all_digit (const char *str)
paul718e3742002-12-13 20:15:29 +0000696{
697 for (; *str != '\0'; str++)
698 if (!isdigit ((int) *str))
699 return 0;
700 return 1;
701}
702
703/* Utility function to convert ipv4 prefixes to Classful prefixes */
704void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
705{
706
707 u_int32_t destination;
708
709 destination = ntohl (p->prefix.s_addr);
710
hasso3fb9cd62004-10-19 19:44:43 +0000711 if (p->prefixlen == IPV4_MAX_PREFIXLEN);
paul718e3742002-12-13 20:15:29 +0000712 /* do nothing for host routes */
713 else if (IN_CLASSC (destination))
714 {
715 p->prefixlen=24;
716 apply_mask_ipv4(p);
717 }
718 else if (IN_CLASSB(destination))
719 {
720 p->prefixlen=16;
721 apply_mask_ipv4(p);
722 }
723 else
724 {
725 p->prefixlen=8;
726 apply_mask_ipv4(p);
727 }
728}
729
hasso3fb9cd62004-10-19 19:44:43 +0000730in_addr_t
731ipv4_network_addr (in_addr_t hostaddr, int masklen)
732{
733 struct in_addr mask;
734
735 masklen2ip (masklen, &mask);
736 return hostaddr & mask.s_addr;
737}
738
739in_addr_t
740ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
741{
742 struct in_addr mask;
743
744 masklen2ip (masklen, &mask);
745 return (masklen != IPV4_MAX_PREFIXLEN-1) ?
746 /* normal case */
747 (hostaddr | ~mask.s_addr) :
748 /* special case for /31 */
749 (hostaddr ^ ~mask.s_addr);
750}
751
paul718e3742002-12-13 20:15:29 +0000752/* Utility function to convert ipv4 netmask to prefixes
753 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
754 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
755int
hassob04c6992004-10-04 19:10:31 +0000756netmask_str2prefix_str (const char *net_str, const char *mask_str,
757 char *prefix_str)
paul718e3742002-12-13 20:15:29 +0000758{
759 struct in_addr network;
760 struct in_addr mask;
761 u_char prefixlen;
762 u_int32_t destination;
763 int ret;
764
765 ret = inet_aton (net_str, &network);
766 if (! ret)
767 return 0;
768
769 if (mask_str)
770 {
771 ret = inet_aton (mask_str, &mask);
772 if (! ret)
773 return 0;
774
775 prefixlen = ip_masklen (mask);
776 }
777 else
778 {
779 destination = ntohl (network.s_addr);
780
781 if (network.s_addr == 0)
782 prefixlen = 0;
783 else if (IN_CLASSC (destination))
784 prefixlen = 24;
785 else if (IN_CLASSB (destination))
786 prefixlen = 16;
787 else if (IN_CLASSA (destination))
788 prefixlen = 8;
789 else
790 return 0;
791 }
792
793 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
794
795 return 1;
796}
797
hasso59209902005-04-05 14:36:49 +0000798#ifdef HAVE_IPV6
799/* Utility function for making IPv6 address string. */
800const char *
hasso3a2ce6a2005-04-08 01:30:51 +0000801inet6_ntoa (struct in6_addr addr)
hasso59209902005-04-05 14:36:49 +0000802{
803 static char buf[INET6_ADDRSTRLEN];
804
hasso3a2ce6a2005-04-08 01:30:51 +0000805 inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
hasso59209902005-04-05 14:36:49 +0000806 return buf;
807}
808#endif /* HAVE_IPV6 */