]> git.proxmox.com Git - mirror_frr.git/blame - lib/prefix.c
lib: make masklen2ip() safer and faster
[mirror_frr.git] / lib / prefix.c
CommitLineData
718e3744 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\f
31/* Maskbit. */
2d362d10 32static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
718e3744 33 0xf8, 0xfc, 0xfe, 0xff};
9663386f
DO
34static 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};
718e3744 70
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
4c9641ba 80afi2family (afi_t afi)
718e3744 81{
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
4c9641ba 91afi_t
718e3744 92family2afi (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
b04c699e 105prefix_match (const struct prefix *n, const struct prefix *p)
718e3744 106{
107 int offset;
108 int shift;
d3583447 109 const u_char *np, *pp;
718e3744 110
111 /* If n's prefix is longer than p's one return 0. */
112 if (n->prefixlen > p->prefixlen)
113 return 0;
114
d3583447
PJ
115 /* Set both prefix's head pointer. */
116 np = (const u_char *)&n->u.prefix;
117 pp = (const u_char *)&p->u.prefix;
118
718e3744 119 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
b04c699e 134prefix_copy (struct prefix *dest, const struct prefix *src)
718e3744 135{
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 {
b9e7028f 152 zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d",
718e3744 153 src->family);
154 assert (0);
155 }
156}
157
9d24baaa 158/*
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 */
718e3744 166int
b04c699e 167prefix_same (const struct prefix *p1, const struct prefix *p2)
718e3744 168{
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
9d24baaa 183/*
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 */
718e3744 193int
b04c699e 194prefix_cmp (const struct prefix *p1, const struct prefix *p2)
718e3744 195{
196 int offset;
197 int shift;
198
199 /* Set both prefix's head pointer. */
8cc4198f 200 const u_char *pp1 = (const u_char *)&p1->u.prefix;
201 const u_char *pp2 = (const u_char *)&p2->u.prefix;
718e3744 202
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
17e52061
DL
220/*
221 * Count the number of common bits in 2 prefixes. The prefix length is
222 * ignored for this function; the whole prefix is compared. If the prefix
223 * address families don't match, return -1; otherwise the return value is
224 * in range 0 ... maximum prefix length for the address family.
225 */
226int
227prefix_common_bits (const struct prefix *p1, const struct prefix *p2)
228{
229 int pos, bit;
230 int length = 0;
231 u_char xor;
232
233 /* Set both prefix's head pointer. */
234 const u_char *pp1 = (const u_char *)&p1->u.prefix;
235 const u_char *pp2 = (const u_char *)&p2->u.prefix;
236
237 if (p1->family == AF_INET)
238 length = IPV4_MAX_BYTELEN;
239#ifdef HAVE_IPV6
240 if (p1->family == AF_INET6)
241 length = IPV6_MAX_BYTELEN;
242#endif
243 if (p1->family != p2->family || !length)
244 return -1;
245
246 for (pos = 0; pos < length; pos++)
247 if (pp1[pos] != pp2[pos])
248 break;
249 if (pos == length)
250 return pos * 8;
251
252 xor = pp1[pos] ^ pp2[pos];
253 for (bit = 0; bit < 8; bit++)
254 if (xor & (1 << (7 - bit)))
255 break;
256
257 return pos * 8 + bit;
258}
259
718e3744 260/* Return prefix family type string. */
b04c699e 261const char *
262prefix_family_str (const struct prefix *p)
718e3744 263{
264 if (p->family == AF_INET)
265 return "inet";
266#ifdef HAVE_IPV6
267 if (p->family == AF_INET6)
268 return "inet6";
269#endif /* HAVE_IPV6 */
270 return "unspec";
271}
272
273/* Allocate new prefix_ipv4 structure. */
274struct prefix_ipv4 *
275prefix_ipv4_new ()
276{
277 struct prefix_ipv4 *p;
278
7907c6c9 279 /* Call prefix_new to allocate a full-size struct prefix to avoid problems
280 where the struct prefix_ipv4 is cast to struct prefix and unallocated
281 bytes were being referenced (e.g. in structure assignments). */
282 p = (struct prefix_ipv4 *)prefix_new();
718e3744 283 p->family = AF_INET;
284 return p;
285}
286
287/* Free prefix_ipv4 structure. */
288void
289prefix_ipv4_free (struct prefix_ipv4 *p)
290{
7907c6c9 291 prefix_free((struct prefix *)p);
718e3744 292}
293
294/* When string format is invalid return 0. */
295int
b04c699e 296str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p)
718e3744 297{
298 int ret;
299 int plen;
300 char *pnt;
301 char *cp;
302
303 /* Find slash inside string. */
304 pnt = strchr (str, '/');
305
306 /* String doesn't contail slash. */
307 if (pnt == NULL)
308 {
309 /* Convert string to prefix. */
310 ret = inet_aton (str, &p->prefix);
311 if (ret == 0)
312 return 0;
313
314 /* If address doesn't contain slash we assume it host address. */
315 p->family = AF_INET;
316 p->prefixlen = IPV4_MAX_BITLEN;
317
318 return ret;
319 }
320 else
321 {
322 cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
323 strncpy (cp, str, pnt - str);
324 *(cp + (pnt - str)) = '\0';
325 ret = inet_aton (cp, &p->prefix);
326 XFREE (MTYPE_TMP, cp);
327
328 /* Get prefix length. */
329 plen = (u_char) atoi (++pnt);
3fb9cd6e 330 if (plen > IPV4_MAX_PREFIXLEN)
718e3744 331 return 0;
332
333 p->family = AF_INET;
334 p->prefixlen = plen;
335 }
336
337 return ret;
338}
339
340/* Convert masklen into IP address's netmask. */
341void
9663386f 342masklen2ip (const int masklen, struct in_addr *netmask)
718e3744 343{
9663386f
DO
344 assert (masklen >= 0 && masklen <= 32);
345 netmask->s_addr = maskbytes[masklen];
718e3744 346}
347
348/* Convert IP address's netmask into integer. We assume netmask is
349 sequential one. Argument netmask should be network byte order. */
350u_char
351ip_masklen (struct in_addr netmask)
352{
353 u_char len;
354 u_char *pnt;
355 u_char *end;
356 u_char val;
357
358 len = 0;
359 pnt = (u_char *) &netmask;
360 end = pnt + 4;
361
330009f7 362 while ((pnt < end) && (*pnt == 0xff))
718e3744 363 {
364 len+= 8;
365 pnt++;
366 }
367
368 if (pnt < end)
369 {
370 val = *pnt;
371 while (val)
372 {
373 len++;
374 val <<= 1;
375 }
376 }
377 return len;
378}
379
380/* Apply mask to IPv4 prefix. */
381void
382apply_mask_ipv4 (struct prefix_ipv4 *p)
383{
384 u_char *pnt;
385 int index;
386 int offset;
387
388 index = p->prefixlen / 8;
389
390 if (index < 4)
391 {
392 pnt = (u_char *) &p->prefix;
393 offset = p->prefixlen % 8;
394
395 pnt[index] &= maskbit[offset];
396 index++;
397
398 while (index < 4)
399 pnt[index++] = 0;
400 }
401}
402
403/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
404int
b04c699e 405prefix_ipv4_any (const struct prefix_ipv4 *p)
718e3744 406{
407 return (p->prefix.s_addr == 0 && p->prefixlen == 0);
408}
409\f
410#ifdef HAVE_IPV6
411
412/* Allocate a new ip version 6 route */
413struct prefix_ipv6 *
8cc4198f 414prefix_ipv6_new (void)
718e3744 415{
416 struct prefix_ipv6 *p;
417
7907c6c9 418 /* Allocate a full-size struct prefix to avoid problems with structure
419 size mismatches. */
420 p = (struct prefix_ipv6 *)prefix_new();
718e3744 421 p->family = AF_INET6;
422 return p;
423}
424
425/* Free prefix for IPv6. */
426void
427prefix_ipv6_free (struct prefix_ipv6 *p)
428{
7907c6c9 429 prefix_free((struct prefix *)p);
718e3744 430}
431
432/* If given string is valid return pin6 else return NULL */
433int
b04c699e 434str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p)
718e3744 435{
436 char *pnt;
437 char *cp;
438 int ret;
439
440 pnt = strchr (str, '/');
441
442 /* If string doesn't contain `/' treat it as host route. */
443 if (pnt == NULL)
444 {
445 ret = inet_pton (AF_INET6, str, &p->prefix);
c4cf095e 446 if (ret == 0)
718e3744 447 return 0;
448 p->prefixlen = IPV6_MAX_BITLEN;
449 }
450 else
451 {
452 int plen;
453
454 cp = XMALLOC (0, (pnt - str) + 1);
455 strncpy (cp, str, pnt - str);
456 *(cp + (pnt - str)) = '\0';
457 ret = inet_pton (AF_INET6, cp, &p->prefix);
458 free (cp);
c4cf095e 459 if (ret == 0)
718e3744 460 return 0;
461 plen = (u_char) atoi (++pnt);
462 if (plen > 128)
463 return 0;
464 p->prefixlen = plen;
465 }
466 p->family = AF_INET6;
467
468 return ret;
469}
470
b04c699e 471/* Convert struct in6_addr netmask into integer.
472 * FIXME return u_char as ip_maskleni() does. */
718e3744 473int
474ip6_masklen (struct in6_addr netmask)
475{
476 int len = 0;
477 unsigned char val;
478 unsigned char *pnt;
479
480 pnt = (unsigned char *) & netmask;
481
482 while ((*pnt == 0xff) && len < 128)
483 {
484 len += 8;
485 pnt++;
486 }
487
488 if (len < 128)
489 {
490 val = *pnt;
491 while (val)
492 {
493 len++;
494 val <<= 1;
495 }
496 }
497 return len;
498}
499
500void
501masklen2ip6 (int masklen, struct in6_addr *netmask)
502{
503 unsigned char *pnt;
504 int bit;
505 int offset;
506
507 memset (netmask, 0, sizeof (struct in6_addr));
508 pnt = (unsigned char *) netmask;
509
510 offset = masklen / 8;
511 bit = masklen % 8;
512
513 while (offset--)
514 *pnt++ = 0xff;
515
516 if (bit)
517 *pnt = maskbit[bit];
518}
519
520void
521apply_mask_ipv6 (struct prefix_ipv6 *p)
522{
523 u_char *pnt;
524 int index;
525 int offset;
526
527 index = p->prefixlen / 8;
528
529 if (index < 16)
530 {
531 pnt = (u_char *) &p->prefix;
532 offset = p->prefixlen % 8;
533
534 pnt[index] &= maskbit[offset];
535 index++;
536
537 while (index < 16)
538 pnt[index++] = 0;
539 }
540}
541
542void
b04c699e 543str2in6_addr (const char *str, struct in6_addr *addr)
718e3744 544{
545 int i;
546 unsigned int x;
547
548 /* %x must point to unsinged int */
549 for (i = 0; i < 16; i++)
550 {
551 sscanf (str + (i * 2), "%02x", &x);
552 addr->s6_addr[i] = x & 0xff;
553 }
554}
555#endif /* HAVE_IPV6 */
556
557void
558apply_mask (struct prefix *p)
559{
560 switch (p->family)
561 {
562 case AF_INET:
563 apply_mask_ipv4 ((struct prefix_ipv4 *)p);
564 break;
565#ifdef HAVE_IPV6
566 case AF_INET6:
567 apply_mask_ipv6 ((struct prefix_ipv6 *)p);
568 break;
569#endif /* HAVE_IPV6 */
570 default:
571 break;
572 }
573 return;
574}
575
b04c699e 576/* Utility function of convert between struct prefix <=> union sockunion.
577 * FIXME This function isn't used anywhere. */
718e3744 578struct prefix *
b04c699e 579sockunion2prefix (const union sockunion *dest,
580 const union sockunion *mask)
718e3744 581{
582 if (dest->sa.sa_family == AF_INET)
583 {
584 struct prefix_ipv4 *p;
585
586 p = prefix_ipv4_new ();
587 p->family = AF_INET;
588 p->prefix = dest->sin.sin_addr;
589 p->prefixlen = ip_masklen (mask->sin.sin_addr);
590 return (struct prefix *) p;
591 }
592#ifdef HAVE_IPV6
593 if (dest->sa.sa_family == AF_INET6)
594 {
595 struct prefix_ipv6 *p;
596
597 p = prefix_ipv6_new ();
598 p->family = AF_INET6;
599 p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
600 memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
601 return (struct prefix *) p;
602 }
603#endif /* HAVE_IPV6 */
604 return NULL;
605}
606
b04c699e 607/* Utility function of convert between struct prefix <=> union sockunion. */
718e3744 608struct prefix *
b04c699e 609sockunion2hostprefix (const union sockunion *su)
718e3744 610{
611 if (su->sa.sa_family == AF_INET)
612 {
613 struct prefix_ipv4 *p;
614
615 p = prefix_ipv4_new ();
616 p->family = AF_INET;
617 p->prefix = su->sin.sin_addr;
618 p->prefixlen = IPV4_MAX_BITLEN;
619 return (struct prefix *) p;
620 }
621#ifdef HAVE_IPV6
622 if (su->sa.sa_family == AF_INET6)
623 {
624 struct prefix_ipv6 *p;
625
626 p = prefix_ipv6_new ();
627 p->family = AF_INET6;
628 p->prefixlen = IPV6_MAX_BITLEN;
629 memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
630 return (struct prefix *) p;
631 }
632#endif /* HAVE_IPV6 */
633 return NULL;
634}
635
17e52061
DL
636void
637prefix2sockunion (const struct prefix *p, union sockunion *su)
638{
639 memset (su, 0, sizeof (*su));
640
641 su->sa.sa_family = p->family;
642 if (p->family == AF_INET)
643 su->sin.sin_addr = p->u.prefix4;
644#ifdef HAVE_IPV6
645 if (p->family == AF_INET6)
646 memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr));
647#endif /* HAVE_IPV6 */
648}
649
718e3744 650int
b04c699e 651prefix_blen (const struct prefix *p)
718e3744 652{
653 switch (p->family)
654 {
655 case AF_INET:
656 return IPV4_MAX_BYTELEN;
657 break;
658#ifdef HAVE_IPV6
659 case AF_INET6:
660 return IPV6_MAX_BYTELEN;
661 break;
662#endif /* HAVE_IPV6 */
663 }
664 return 0;
665}
666
667/* Generic function for conversion string to struct prefix. */
668int
b04c699e 669str2prefix (const char *str, struct prefix *p)
718e3744 670{
671 int ret;
672
673 /* First we try to convert string to struct prefix_ipv4. */
674 ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
675 if (ret)
676 return ret;
677
678#ifdef HAVE_IPV6
679 /* Next we try to convert string to struct prefix_ipv6. */
680 ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
681 if (ret)
682 return ret;
683#endif /* HAVE_IPV6 */
684
685 return 0;
686}
687
688int
b04c699e 689prefix2str (const struct prefix *p, char *str, int size)
718e3744 690{
691 char buf[BUFSIZ];
692
693 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
694 snprintf (str, size, "%s/%d", buf, p->prefixlen);
695 return 0;
696}
697
698struct prefix *
699prefix_new ()
700{
701 struct prefix *p;
702
703 p = XCALLOC (MTYPE_PREFIX, sizeof *p);
704 return p;
705}
706
707/* Free prefix structure. */
708void
709prefix_free (struct prefix *p)
710{
711 XFREE (MTYPE_PREFIX, p);
712}
713
714/* Utility function. Check the string only contains digit
b04c699e 715 * character.
716 * FIXME str.[c|h] would be better place for this function. */
718e3744 717int
b04c699e 718all_digit (const char *str)
718e3744 719{
720 for (; *str != '\0'; str++)
721 if (!isdigit ((int) *str))
722 return 0;
723 return 1;
724}
725
726/* Utility function to convert ipv4 prefixes to Classful prefixes */
727void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
728{
729
730 u_int32_t destination;
731
732 destination = ntohl (p->prefix.s_addr);
733
3fb9cd6e 734 if (p->prefixlen == IPV4_MAX_PREFIXLEN);
718e3744 735 /* do nothing for host routes */
736 else if (IN_CLASSC (destination))
737 {
738 p->prefixlen=24;
739 apply_mask_ipv4(p);
740 }
741 else if (IN_CLASSB(destination))
742 {
743 p->prefixlen=16;
744 apply_mask_ipv4(p);
745 }
746 else
747 {
748 p->prefixlen=8;
749 apply_mask_ipv4(p);
750 }
751}
752
3fb9cd6e 753in_addr_t
754ipv4_network_addr (in_addr_t hostaddr, int masklen)
755{
756 struct in_addr mask;
757
758 masklen2ip (masklen, &mask);
759 return hostaddr & mask.s_addr;
760}
761
762in_addr_t
763ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
764{
765 struct in_addr mask;
766
767 masklen2ip (masklen, &mask);
768 return (masklen != IPV4_MAX_PREFIXLEN-1) ?
769 /* normal case */
770 (hostaddr | ~mask.s_addr) :
771 /* special case for /31 */
772 (hostaddr ^ ~mask.s_addr);
773}
774
718e3744 775/* Utility function to convert ipv4 netmask to prefixes
776 ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
777 ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
778int
b04c699e 779netmask_str2prefix_str (const char *net_str, const char *mask_str,
780 char *prefix_str)
718e3744 781{
782 struct in_addr network;
783 struct in_addr mask;
784 u_char prefixlen;
785 u_int32_t destination;
786 int ret;
787
788 ret = inet_aton (net_str, &network);
789 if (! ret)
790 return 0;
791
792 if (mask_str)
793 {
794 ret = inet_aton (mask_str, &mask);
795 if (! ret)
796 return 0;
797
798 prefixlen = ip_masklen (mask);
799 }
800 else
801 {
802 destination = ntohl (network.s_addr);
803
804 if (network.s_addr == 0)
805 prefixlen = 0;
806 else if (IN_CLASSC (destination))
807 prefixlen = 24;
808 else if (IN_CLASSB (destination))
809 prefixlen = 16;
810 else if (IN_CLASSA (destination))
811 prefixlen = 8;
812 else
813 return 0;
814 }
815
816 sprintf (prefix_str, "%s/%d", net_str, prefixlen);
817
818 return 1;
819}
820
5920990f 821#ifdef HAVE_IPV6
822/* Utility function for making IPv6 address string. */
823const char *
3a2ce6a1 824inet6_ntoa (struct in6_addr addr)
5920990f 825{
826 static char buf[INET6_ADDRSTRLEN];
827
3a2ce6a1 828 inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
5920990f 829 return buf;
830}
831#endif /* HAVE_IPV6 */