]>
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. */ | |
2d362d10 | 32 | static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, |
718e3744 | 33 | 0xf8, 0xfc, 0xfe, 0xff}; |
9663386f DO |
34 | static 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. */ | |
79 | int | |
4c9641ba | 80 | afi2family (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 | 91 | afi_t |
718e3744 | 92 | family2afi (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. */ | |
104 | int | |
b04c699e | 105 | prefix_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. */ | |
133 | void | |
b04c699e | 134 | prefix_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 | 166 | int |
b04c699e | 167 | prefix_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 | 193 | int |
b04c699e | 194 | prefix_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 | */ | |
226 | int | |
227 | prefix_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 | 261 | const char * |
262 | prefix_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. */ | |
274 | struct prefix_ipv4 * | |
275 | prefix_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. */ | |
288 | void | |
289 | prefix_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. */ | |
295 | int | |
b04c699e | 296 | str2prefix_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. */ | |
341 | void | |
9663386f | 342 | masklen2ip (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. */ | |
350 | u_char | |
351 | ip_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. */ | |
381 | void | |
382 | apply_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. */ | |
404 | int | |
b04c699e | 405 | prefix_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 */ | |
413 | struct prefix_ipv6 * | |
8cc4198f | 414 | prefix_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. */ | |
426 | void | |
427 | prefix_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 */ | |
433 | int | |
b04c699e | 434 | str2prefix_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 | 473 | int |
474 | ip6_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 | ||
500 | void | |
501 | masklen2ip6 (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 | ||
520 | void | |
521 | apply_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 | ||
542 | void | |
b04c699e | 543 | str2in6_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 | ||
557 | void | |
558 | apply_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 | 578 | struct prefix * |
b04c699e | 579 | sockunion2prefix (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 | 608 | struct prefix * |
b04c699e | 609 | sockunion2hostprefix (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 |
636 | void |
637 | prefix2sockunion (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 | 650 | int |
b04c699e | 651 | prefix_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. */ | |
668 | int | |
b04c699e | 669 | str2prefix (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 | ||
688 | int | |
b04c699e | 689 | prefix2str (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 | ||
698 | struct prefix * | |
699 | prefix_new () | |
700 | { | |
701 | struct prefix *p; | |
702 | ||
703 | p = XCALLOC (MTYPE_PREFIX, sizeof *p); | |
704 | return p; | |
705 | } | |
706 | ||
707 | /* Free prefix structure. */ | |
708 | void | |
709 | prefix_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 | 717 | int |
b04c699e | 718 | all_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 */ | |
727 | void 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 | 753 | in_addr_t |
754 | ipv4_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 | ||
762 | in_addr_t | |
763 | ipv4_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" */ | |
778 | int | |
b04c699e | 779 | netmask_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. */ | |
823 | const char * | |
3a2ce6a1 | 824 | inet6_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 */ |