]>
Commit | Line | Data |
---|---|---|
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. */ | |
32 | static 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. */ | |
43 | int | |
44 | afi2family (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 | ||
55 | int | |
56 | family2afi (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. */ | |
68 | int | |
b04c699e | 69 | prefix_match (const struct prefix *n, const struct prefix *p) |
718e3744 | 70 | { |
71 | int offset; | |
72 | int shift; | |
73 | ||
74 | /* Set both prefix's head pointer. */ | |
8cc4198f | 75 | const u_char *np = (const u_char *)&n->u.prefix; |
76 | const u_char *pp = (const u_char *)&p->u.prefix; | |
718e3744 | 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. */ | |
96 | void | |
b04c699e | 97 | prefix_copy (struct prefix *dest, const struct prefix *src) |
718e3744 | 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 | { | |
b9e7028f | 115 | zlog (NULL, LOG_ERR, "prefix_copy(): Unknown address family %d", |
718e3744 | 116 | src->family); |
117 | assert (0); | |
118 | } | |
119 | } | |
120 | ||
9d24baaa | 121 | /* |
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 | */ | |
718e3744 | 129 | int |
b04c699e | 130 | prefix_same (const struct prefix *p1, const struct prefix *p2) |
718e3744 | 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 | ||
9d24baaa | 146 | /* |
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 | */ | |
718e3744 | 156 | int |
b04c699e | 157 | prefix_cmp (const struct prefix *p1, const struct prefix *p2) |
718e3744 | 158 | { |
159 | int offset; | |
160 | int shift; | |
161 | ||
162 | /* Set both prefix's head pointer. */ | |
8cc4198f | 163 | const u_char *pp1 = (const u_char *)&p1->u.prefix; |
164 | const u_char *pp2 = (const u_char *)&p2->u.prefix; | |
718e3744 | 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. */ | |
b04c699e | 184 | const char * |
185 | prefix_family_str (const struct prefix *p) | |
718e3744 | 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. */ | |
197 | struct prefix_ipv4 * | |
198 | prefix_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. */ | |
208 | void | |
209 | prefix_ipv4_free (struct prefix_ipv4 *p) | |
210 | { | |
211 | XFREE (MTYPE_PREFIX_IPV4, p); | |
212 | } | |
213 | ||
214 | /* When string format is invalid return 0. */ | |
215 | int | |
b04c699e | 216 | str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p) |
718e3744 | 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); | |
3fb9cd6e | 250 | if (plen > IPV4_MAX_PREFIXLEN) |
718e3744 | 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. */ | |
261 | void | |
262 | masklen2ip (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. */ | |
283 | u_char | |
284 | ip_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 | ||
330009f7 | 295 | while ((pnt < end) && (*pnt == 0xff)) |
718e3744 | 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. */ | |
314 | void | |
315 | apply_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. */ | |
337 | int | |
b04c699e | 338 | prefix_ipv4_any (const struct prefix_ipv4 *p) |
718e3744 | 339 | { |
340 | return (p->prefix.s_addr == 0 && p->prefixlen == 0); | |
341 | } | |
342 | \f | |
343 | #ifdef HAVE_IPV6 | |
344 | ||
345 | /* Allocate a new ip version 6 route */ | |
346 | struct prefix_ipv6 * | |
8cc4198f | 347 | prefix_ipv6_new (void) |
718e3744 | 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. */ | |
357 | void | |
358 | prefix_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 */ | |
364 | int | |
b04c699e | 365 | str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p) |
718e3744 | 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 | ||
b04c699e | 402 | /* Convert struct in6_addr netmask into integer. |
403 | * FIXME return u_char as ip_maskleni() does. */ | |
718e3744 | 404 | int |
405 | ip6_masklen (struct in6_addr netmask) | |
406 | { | |
407 | int len = 0; | |
408 | unsigned char val; | |
409 | unsigned char *pnt; | |
410 | ||
411 | pnt = (unsigned char *) & netmask; | |
412 | ||
413 | while ((*pnt == 0xff) && len < 128) | |
414 | { | |
415 | len += 8; | |
416 | pnt++; | |
417 | } | |
418 | ||
419 | if (len < 128) | |
420 | { | |
421 | val = *pnt; | |
422 | while (val) | |
423 | { | |
424 | len++; | |
425 | val <<= 1; | |
426 | } | |
427 | } | |
428 | return len; | |
429 | } | |
430 | ||
431 | void | |
432 | masklen2ip6 (int masklen, struct in6_addr *netmask) | |
433 | { | |
434 | unsigned char *pnt; | |
435 | int bit; | |
436 | int offset; | |
437 | ||
438 | memset (netmask, 0, sizeof (struct in6_addr)); | |
439 | pnt = (unsigned char *) netmask; | |
440 | ||
441 | offset = masklen / 8; | |
442 | bit = masklen % 8; | |
443 | ||
444 | while (offset--) | |
445 | *pnt++ = 0xff; | |
446 | ||
447 | if (bit) | |
448 | *pnt = maskbit[bit]; | |
449 | } | |
450 | ||
451 | void | |
452 | apply_mask_ipv6 (struct prefix_ipv6 *p) | |
453 | { | |
454 | u_char *pnt; | |
455 | int index; | |
456 | int offset; | |
457 | ||
458 | index = p->prefixlen / 8; | |
459 | ||
460 | if (index < 16) | |
461 | { | |
462 | pnt = (u_char *) &p->prefix; | |
463 | offset = p->prefixlen % 8; | |
464 | ||
465 | pnt[index] &= maskbit[offset]; | |
466 | index++; | |
467 | ||
468 | while (index < 16) | |
469 | pnt[index++] = 0; | |
470 | } | |
471 | } | |
472 | ||
473 | void | |
b04c699e | 474 | str2in6_addr (const char *str, struct in6_addr *addr) |
718e3744 | 475 | { |
476 | int i; | |
477 | unsigned int x; | |
478 | ||
479 | /* %x must point to unsinged int */ | |
480 | for (i = 0; i < 16; i++) | |
481 | { | |
482 | sscanf (str + (i * 2), "%02x", &x); | |
483 | addr->s6_addr[i] = x & 0xff; | |
484 | } | |
485 | } | |
486 | #endif /* HAVE_IPV6 */ | |
487 | ||
488 | void | |
489 | apply_mask (struct prefix *p) | |
490 | { | |
491 | switch (p->family) | |
492 | { | |
493 | case AF_INET: | |
494 | apply_mask_ipv4 ((struct prefix_ipv4 *)p); | |
495 | break; | |
496 | #ifdef HAVE_IPV6 | |
497 | case AF_INET6: | |
498 | apply_mask_ipv6 ((struct prefix_ipv6 *)p); | |
499 | break; | |
500 | #endif /* HAVE_IPV6 */ | |
501 | default: | |
502 | break; | |
503 | } | |
504 | return; | |
505 | } | |
506 | ||
b04c699e | 507 | /* Utility function of convert between struct prefix <=> union sockunion. |
508 | * FIXME This function isn't used anywhere. */ | |
718e3744 | 509 | struct prefix * |
b04c699e | 510 | sockunion2prefix (const union sockunion *dest, |
511 | const union sockunion *mask) | |
718e3744 | 512 | { |
513 | if (dest->sa.sa_family == AF_INET) | |
514 | { | |
515 | struct prefix_ipv4 *p; | |
516 | ||
517 | p = prefix_ipv4_new (); | |
518 | p->family = AF_INET; | |
519 | p->prefix = dest->sin.sin_addr; | |
520 | p->prefixlen = ip_masklen (mask->sin.sin_addr); | |
521 | return (struct prefix *) p; | |
522 | } | |
523 | #ifdef HAVE_IPV6 | |
524 | if (dest->sa.sa_family == AF_INET6) | |
525 | { | |
526 | struct prefix_ipv6 *p; | |
527 | ||
528 | p = prefix_ipv6_new (); | |
529 | p->family = AF_INET6; | |
530 | p->prefixlen = ip6_masklen (mask->sin6.sin6_addr); | |
531 | memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr)); | |
532 | return (struct prefix *) p; | |
533 | } | |
534 | #endif /* HAVE_IPV6 */ | |
535 | return NULL; | |
536 | } | |
537 | ||
b04c699e | 538 | /* Utility function of convert between struct prefix <=> union sockunion. */ |
718e3744 | 539 | struct prefix * |
b04c699e | 540 | sockunion2hostprefix (const union sockunion *su) |
718e3744 | 541 | { |
542 | if (su->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 = su->sin.sin_addr; | |
549 | p->prefixlen = IPV4_MAX_BITLEN; | |
550 | return (struct prefix *) p; | |
551 | } | |
552 | #ifdef HAVE_IPV6 | |
553 | if (su->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 = IPV6_MAX_BITLEN; | |
560 | memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr)); | |
561 | return (struct prefix *) p; | |
562 | } | |
563 | #endif /* HAVE_IPV6 */ | |
564 | return NULL; | |
565 | } | |
566 | ||
567 | int | |
b04c699e | 568 | prefix_blen (const struct prefix *p) |
718e3744 | 569 | { |
570 | switch (p->family) | |
571 | { | |
572 | case AF_INET: | |
573 | return IPV4_MAX_BYTELEN; | |
574 | break; | |
575 | #ifdef HAVE_IPV6 | |
576 | case AF_INET6: | |
577 | return IPV6_MAX_BYTELEN; | |
578 | break; | |
579 | #endif /* HAVE_IPV6 */ | |
580 | } | |
581 | return 0; | |
582 | } | |
583 | ||
584 | /* Generic function for conversion string to struct prefix. */ | |
585 | int | |
b04c699e | 586 | str2prefix (const char *str, struct prefix *p) |
718e3744 | 587 | { |
588 | int ret; | |
589 | ||
590 | /* First we try to convert string to struct prefix_ipv4. */ | |
591 | ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p); | |
592 | if (ret) | |
593 | return ret; | |
594 | ||
595 | #ifdef HAVE_IPV6 | |
596 | /* Next we try to convert string to struct prefix_ipv6. */ | |
597 | ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p); | |
598 | if (ret) | |
599 | return ret; | |
600 | #endif /* HAVE_IPV6 */ | |
601 | ||
602 | return 0; | |
603 | } | |
604 | ||
605 | int | |
b04c699e | 606 | prefix2str (const struct prefix *p, char *str, int size) |
718e3744 | 607 | { |
608 | char buf[BUFSIZ]; | |
609 | ||
610 | inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); | |
611 | snprintf (str, size, "%s/%d", buf, p->prefixlen); | |
612 | return 0; | |
613 | } | |
614 | ||
615 | struct prefix * | |
616 | prefix_new () | |
617 | { | |
618 | struct prefix *p; | |
619 | ||
620 | p = XCALLOC (MTYPE_PREFIX, sizeof *p); | |
621 | return p; | |
622 | } | |
623 | ||
624 | /* Free prefix structure. */ | |
625 | void | |
626 | prefix_free (struct prefix *p) | |
627 | { | |
628 | XFREE (MTYPE_PREFIX, p); | |
629 | } | |
630 | ||
631 | /* Utility function. Check the string only contains digit | |
b04c699e | 632 | * character. |
633 | * FIXME str.[c|h] would be better place for this function. */ | |
718e3744 | 634 | int |
b04c699e | 635 | all_digit (const char *str) |
718e3744 | 636 | { |
637 | for (; *str != '\0'; str++) | |
638 | if (!isdigit ((int) *str)) | |
639 | return 0; | |
640 | return 1; | |
641 | } | |
642 | ||
643 | /* Utility function to convert ipv4 prefixes to Classful prefixes */ | |
644 | void apply_classful_mask_ipv4 (struct prefix_ipv4 *p) | |
645 | { | |
646 | ||
647 | u_int32_t destination; | |
648 | ||
649 | destination = ntohl (p->prefix.s_addr); | |
650 | ||
3fb9cd6e | 651 | if (p->prefixlen == IPV4_MAX_PREFIXLEN); |
718e3744 | 652 | /* do nothing for host routes */ |
653 | else if (IN_CLASSC (destination)) | |
654 | { | |
655 | p->prefixlen=24; | |
656 | apply_mask_ipv4(p); | |
657 | } | |
658 | else if (IN_CLASSB(destination)) | |
659 | { | |
660 | p->prefixlen=16; | |
661 | apply_mask_ipv4(p); | |
662 | } | |
663 | else | |
664 | { | |
665 | p->prefixlen=8; | |
666 | apply_mask_ipv4(p); | |
667 | } | |
668 | } | |
669 | ||
3fb9cd6e | 670 | in_addr_t |
671 | ipv4_network_addr (in_addr_t hostaddr, int masklen) | |
672 | { | |
673 | struct in_addr mask; | |
674 | ||
675 | masklen2ip (masklen, &mask); | |
676 | return hostaddr & mask.s_addr; | |
677 | } | |
678 | ||
679 | in_addr_t | |
680 | ipv4_broadcast_addr (in_addr_t hostaddr, int masklen) | |
681 | { | |
682 | struct in_addr mask; | |
683 | ||
684 | masklen2ip (masklen, &mask); | |
685 | return (masklen != IPV4_MAX_PREFIXLEN-1) ? | |
686 | /* normal case */ | |
687 | (hostaddr | ~mask.s_addr) : | |
688 | /* special case for /31 */ | |
689 | (hostaddr ^ ~mask.s_addr); | |
690 | } | |
691 | ||
718e3744 | 692 | /* Utility function to convert ipv4 netmask to prefixes |
693 | ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16" | |
694 | ex.) "1.0.0.0" NULL => "1.0.0.0/8" */ | |
695 | int | |
b04c699e | 696 | netmask_str2prefix_str (const char *net_str, const char *mask_str, |
697 | char *prefix_str) | |
718e3744 | 698 | { |
699 | struct in_addr network; | |
700 | struct in_addr mask; | |
701 | u_char prefixlen; | |
702 | u_int32_t destination; | |
703 | int ret; | |
704 | ||
705 | ret = inet_aton (net_str, &network); | |
706 | if (! ret) | |
707 | return 0; | |
708 | ||
709 | if (mask_str) | |
710 | { | |
711 | ret = inet_aton (mask_str, &mask); | |
712 | if (! ret) | |
713 | return 0; | |
714 | ||
715 | prefixlen = ip_masklen (mask); | |
716 | } | |
717 | else | |
718 | { | |
719 | destination = ntohl (network.s_addr); | |
720 | ||
721 | if (network.s_addr == 0) | |
722 | prefixlen = 0; | |
723 | else if (IN_CLASSC (destination)) | |
724 | prefixlen = 24; | |
725 | else if (IN_CLASSB (destination)) | |
726 | prefixlen = 16; | |
727 | else if (IN_CLASSA (destination)) | |
728 | prefixlen = 8; | |
729 | else | |
730 | return 0; | |
731 | } | |
732 | ||
733 | sprintf (prefix_str, "%s/%d", net_str, prefixlen); | |
734 | ||
735 | return 1; | |
736 | } | |
737 | ||
5920990f | 738 | #ifdef HAVE_IPV6 |
739 | /* Utility function for making IPv6 address string. */ | |
740 | const char * | |
3a2ce6a1 | 741 | inet6_ntoa (struct in6_addr addr) |
5920990f | 742 | { |
743 | static char buf[INET6_ADDRSTRLEN]; | |
744 | ||
3a2ce6a1 | 745 | inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN); |
5920990f | 746 | return buf; |
747 | } | |
748 | #endif /* HAVE_IPV6 */ |