1 /*
2 ** Copyright (C) 2007-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 
9 /*
10 **  Miscellaneous functions for dealing with IP addresses.
11 **
12 */
13 
14 
15 #include <silk/silk.h>
16 
17 RCSIDENT("$SiLK: sku-ips.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
18 
19 #include <silk/skipaddr.h>
20 #include <silk/utils.h>
21 
22 
23 /* TYPEDEFS AND MACROS */
24 
25 #define SILK_IPV6_POLICY_ENVAR  "SILK_IPV6_POLICY"
26 
27 
28 /* PUBLIC CONSTANTS USED IN MACROS */
29 
30 const uint8_t sk_ipv6_zero[SK_IPV6_ZERO_LEN] =
31     {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
32 const uint8_t sk_ipv6_v4inv6[SK_IPV6_V4INV6_LEN] =
33     {0,0,0,0, 0,0,0,0, 0,0,0xFF,0xFF};
34 
35 /* Constant returned by skSockaddrArrayGetHostname() when no
36  * host-name/-address was specified to skStringParseHostPortPair(). */
37 const char *sk_sockaddr_array_anyhostname = "*";
38 
39 
40 /* LOCAL VARIABLES */
41 
42 #if SK_ENABLE_IPV6
43 static const uint8_t max_ip6[16] = {
44     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
45     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
46 };
47 #endif
48 
49 /* masks of various sizes used when computing CIDR blocks */
50 static const uint32_t bitmask[] = {
51     /*  0- 3 */ 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
52     /*  4- 7 */  0xfffffff,  0x7ffffff,  0x3ffffff,  0x1ffffff,
53     /*  8-11 */   0xffffff,   0x7fffff,   0x3fffff,   0x1fffff,
54     /* 12-15 */    0xfffff,    0x7ffff,    0x3ffff,    0x1ffff,
55     /* 16-19 */     0xffff,     0x7fff,     0x3fff,     0x1fff,
56     /* 20-23 */      0xfff,      0x7ff,      0x3ff,      0x1ff,
57     /* 24-27 */       0xff,       0x7f,       0x3f,       0x1f,
58     /* 28-31 */        0xf,        0x7,        0x3,        0x1,
59     /* 32    */        0x0
60 };
61 
62 
63 /* this is used to find the log-base-2 of the CIDR block difference.
64  * http://graphics.stanford.edu/~seander/bithacks.html */
65 static const uint8_t log_table_256[256] =
66 {
67     /*   0- 15 */  0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
68     /*  16- 31 */  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
69     /*  32- 47 */  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
70     /*  48- 63 */  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
71     /*  64- 79 */  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
72     /*  80- 95 */  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
73     /*  96-111 */  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
74     /* 112-127 */  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
75     /* 128-143 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
76     /* 144-159 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
77     /* 160-175 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
78     /* 176-191 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
79     /* 192-207 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
80     /* 208-223 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
81     /* 224-239 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
82     /* 240-255 */  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
83 };
84 
85 
86 
87 /* FUNCTION DEFINITIONS */
88 
89 
90 /* compute the log2() of 'value' */
91 int
skIntegerLog2(uint64_t value)92 skIntegerLog2(
93     uint64_t            value)
94 {
95     uint64_t tmp1;
96     uint64_t tmp2;
97 
98     /* The comments use 63 for most significant bit and 0 for LSB */
99 
100     if ((tmp1 = value >> 32)) {          /* MSB is in bits 63-32 */
101         if ((tmp2 = tmp1 >> 16)) {       /* MSB is in bits 63-48 */
102             if ((tmp1 = tmp2 >> 8)) {    /* MSB is in bits 63-56 */
103                 return 56 + log_table_256[tmp1];
104             } else {                     /* MSB is in bits 55-48 */
105                 return 48 + log_table_256[tmp2];
106             }
107         } else {                         /* MSB is in bits 47-32 */
108             if ((tmp2 = tmp1 >> 8)) {    /* MSB is in bits 47-40 */
109                 return 40 + log_table_256[tmp2];
110             } else {                     /* MSB is in bits 39-32 */
111                 return 32 + log_table_256[tmp1];
112             }
113         }
114     } else {                             /* MSB is in bits 31- 0 */
115         if ((tmp1 = value >> 16)) {      /* MSB is in bits 31-16 */
116             if ((tmp2 = tmp1 >> 8)) {    /* MSB is in bits 31-24 */
117                 return 24 + log_table_256[tmp2];
118             } else {                     /* MSB is in bits 23-16 */
119                 return 16 + log_table_256[tmp1];
120             }
121         } else {                         /* MSB is in bits 15- 0 */
122             if ((tmp1 = value >> 8)) {   /* MSB is in bits 15- 8 */
123                 return 8 + log_table_256[tmp1];
124             } else {                     /* MSB is in bits  7- 0 */
125                 return log_table_256[value];
126             }
127         }
128     }
129 }
130 
131 
132 /* compute a CIDR block */
133 int
skComputeCIDR(uint32_t start_ip,uint32_t end_ip,uint32_t * new_start_ip)134 skComputeCIDR(
135     uint32_t            start_ip,
136     uint32_t            end_ip,
137     uint32_t           *new_start_ip)
138 {
139     skipaddr_t start_addr;
140     skipaddr_t end_addr;
141     skipaddr_t new_start_addr;
142     int prefix;
143 
144     skipaddrSetV4(&start_addr, &start_ip);
145     skipaddrSetV4(&end_addr, &end_ip);
146     if (new_start_ip) {
147         prefix = skCIDRComputePrefix(&start_addr, &end_addr, &new_start_addr);
148         if (-1 != prefix) {
149             *new_start_ip = skipaddrGetV4(&new_start_addr);
150         }
151     } else {
152         prefix = skCIDRComputePrefix(&start_addr, &end_addr, NULL);
153     }
154 
155     return prefix;
156 }
157 
158 
159 /* compute the prefix to hold 'start_addr' through 'end_addr' */
160 int
skCIDRComputePrefix(const skipaddr_t * start_addr,const skipaddr_t * end_addr,skipaddr_t * new_start_addr)161 skCIDRComputePrefix(
162     const skipaddr_t   *start_addr,
163     const skipaddr_t   *end_addr,
164     skipaddr_t         *new_start_addr)
165 {
166     int prefix = -1;
167 
168 #if SK_ENABLE_IPV6
169     if (skipaddrIsV6(start_addr) || skipaddrIsV6(end_addr)) {
170         uint8_t start_ip6[16];
171         uint8_t end_ip6[16];
172         uint8_t range_start[16];
173         int i;
174         int tmp1;
175         uint8_t tmp2 = 0;
176 
177         tmp1 = skipaddrCompare(start_addr, end_addr);
178         if (tmp1 > 0) {
179             /* bad range, start_addr > end_addr */
180             return -1;
181         }
182 
183         /* handle a range that contains a single IP */
184         if (tmp1 == 0) {
185             if (new_start_addr) {
186                 skipaddrClear(new_start_addr);
187             }
188             return 128;
189         }
190 
191         skipaddrGetAsV6(start_addr, start_ip6);
192 
193         /* handle an odd start_addr */
194         if (start_ip6[15] & 0x1) {
195             if (new_start_addr) {
196                 skipaddrCopy(new_start_addr, start_addr);
197                 skipaddrIncrement(new_start_addr);
198             }
199             return 128;
200         }
201 
202         skipaddrGetAsV6(end_addr, end_ip6);
203         memset(range_start, 0, sizeof(range_start));
204 
205         /* find the most significant bit where start_addr and end_addr
206          * differ */
207         for (i = 0; i < 16; ++i) {
208             if (start_ip6[i] != end_ip6[i]) {
209                 /* copy first i+1 bytes of start_ip6 into range_start */
210                 memcpy(range_start, start_ip6, i+1);
211 
212                 /* find number of IPs in the range */
213                 tmp1 = end_ip6[i] - start_ip6[i];
214 
215                 /* see if we need to add one */
216                 if ((i == 15)
217                     || ((0 == memcmp(start_ip6 + i + 1, sk_ipv6_zero, (15-i)))
218                         && (0 == memcmp(end_ip6 + i + 1, max_ip6, (15-i)))))
219                 {
220                     ++tmp1;
221                 }
222                 if (256 == tmp1) {
223                     tmp2 = 8;
224                     prefix = 8 * i;
225                 } else {
226                     tmp2 = log_table_256[tmp1];
227                     prefix = 8 * (i + 1) - tmp2;
228                     range_start[i] &= (0xFF << tmp2);
229                 }
230                 break;
231             }
232         }
233 
234         while (memcmp(range_start, start_ip6, sizeof(range_start)) < 0) {
235             ++prefix;
236             if (tmp2 != 0) {
237                 --tmp2;
238             } else {
239                 ++i;
240                 tmp2 = 7;
241             }
242             range_start[i] = start_ip6[i] & (0xFF << tmp2);
243         }
244 
245         if (new_start_addr) {
246             /* compute the start of the next CIDR block, which is the
247              * IP after the block we just finished.  In the case of
248              * roll-over, the 'else' clause will be invoked, and we
249              * will return 0. */
250             range_start[i] |= ~(0xFF << tmp2);
251             ++i;
252             memset(range_start + i, 0xFF, (sizeof(range_start) - i));
253             if (0 == memcmp(range_start, end_ip6, sizeof(range_start))) {
254                 skipaddrClear(new_start_addr);
255             } else {
256                 skipaddrSetV6(new_start_addr, range_start);
257                 skipaddrIncrement(new_start_addr);
258             }
259         }
260 
261         return prefix;
262 
263     } else
264 #endif  /* SK_ENABLE_IPV6 */
265     {
266         uint32_t start_ip4 = skipaddrGetV4(start_addr);
267         uint32_t end_ip4 = skipaddrGetV4(end_addr);
268         uint32_t range_start;
269 
270         if (end_ip4 < start_ip4) {
271             return -1;
272         }
273 
274         /* handle a range that contains a single IP */
275         if (end_ip4 == start_ip4) {
276             if (new_start_addr) {
277                 skipaddrClear(new_start_addr);
278             }
279             return 32;
280         }
281         /* handle an odd start_addr */
282         if (start_ip4 & 0x1) {
283             if (new_start_addr) {
284                 ++start_ip4;
285                 skipaddrSetV4(new_start_addr, &start_ip4);
286             }
287             return 32;
288         }
289 
290         /* compute the log-base-2 (position of most significant bit)
291          * of the number of IPs in the range, and subtract that from
292          * 32 to get the widest possible CIDR block */
293         prefix = 32 - skIntegerLog2(UINT64_C(1) + end_ip4 - start_ip4);
294 
295         /* tighten the range if we need to, in case the IPs don't fall
296          * into a single CIDR block (e.g., 10.0.0.6--10.0.0.9) */
297         while ((range_start = (start_ip4 & ~(bitmask[prefix]))) < start_ip4) {
298             ++prefix;
299         }
300 
301         /* assert that the CIDR block is within the limits */
302         assert(range_start == start_ip4);
303         assert((range_start | (bitmask[prefix])) <= end_ip4);
304 
305         if (new_start_addr) {
306             /* compute the start of the next CIDR block, which is the
307              * IP after the block we just finished.  In the case of
308              * roll-over, the 'else' clause will be invoked, and we
309              * will return 0. */
310             start_ip4 = 1 + (range_start | (bitmask[prefix]));
311             if (start_ip4 > end_ip4) {
312                 skipaddrClear(new_start_addr);
313             } else {
314                 skipaddrSetV4(new_start_addr, &start_ip4);
315             }
316         }
317     }
318 
319     return prefix;
320 }
321 
322 
323 int
skCIDR2IPRange(const skipaddr_t * ipaddr,uint32_t cidr,skipaddr_t * min_ip,skipaddr_t * max_ip)324 skCIDR2IPRange(
325     const skipaddr_t   *ipaddr,
326     uint32_t            cidr,
327     skipaddr_t         *min_ip,
328     skipaddr_t         *max_ip)
329 {
330     uint32_t ip4;
331 
332 #if SK_ENABLE_IPV6
333     if (skipaddrIsV6(ipaddr)) {
334         uint8_t ip6[16];
335         uint32_t i;
336 
337         if (cidr >= 128) {
338             if (cidr > 128) {
339                 return -1;
340             }
341             /* don't use skipaddrCopy() in case caller supplied
342              * pointers are the same */
343             skipaddrGetV6(ipaddr, ip6);
344             skipaddrSetV6(min_ip, ip6);
345             skipaddrSetV6(max_ip, ip6);
346             return 0;
347         }
348 
349         skipaddrGetV6(ipaddr, ip6);
350 
351         /* first byte of address where there is any effect */
352         i = cidr >> 3;
353 
354         /* handle max: apply mask to this byte, remaining bits all 1 */
355         ip6[i] |= (0xFF >> (cidr & 0x07));
356         memset(&ip6[i+1], 0xFF, (15 - i));
357         skipaddrSetV6(max_ip, ip6);
358 
359         /* handle min: apply mask, remaining bits all 0 */
360         ip6[i] &= ~(0xFF >> (cidr & 0x07));
361         memset(&ip6[i+1], 0, (15 - i));
362         skipaddrSetV6(min_ip, ip6);
363 
364         return 0;
365     }
366 #endif /* SK_ENABLE_IPV6 */
367 
368     if (cidr >= 32) {
369         if (cidr > 32) {
370             return -1;
371         }
372         ip4 = skipaddrGetV4(ipaddr);
373         skipaddrSetV4(min_ip, &ip4);
374         skipaddrSetV4(max_ip, &ip4);
375         return 0;
376     }
377 
378     /* handle max IP */
379     ip4 = (UINT32_MAX >> cidr) | skipaddrGetV4(ipaddr);
380     skipaddrSetV4(max_ip, &ip4);
381 
382     /* handle min IP */
383     ip4 &= ~(UINT32_MAX >> cidr);
384     skipaddrSetV4(min_ip, &ip4);
385 
386     return 0;
387 }
388 
389 
390 int
skCIDRComputeStart(const skipaddr_t * ipaddr,uint32_t cidr,skipaddr_t * min_ip)391 skCIDRComputeStart(
392     const skipaddr_t   *ipaddr,
393     uint32_t            cidr,
394     skipaddr_t         *min_ip)
395 {
396     uint32_t ip4;
397 
398 #if SK_ENABLE_IPV6
399     if (skipaddrIsV6(ipaddr)) {
400         uint8_t ip6[16];
401         uint32_t i;
402 
403         if (cidr >= 128) {
404             if (cidr > 128) {
405                 return -1;
406             }
407             if (ipaddr != min_ip) {
408                 skipaddrCopy(min_ip, ipaddr);
409             }
410             return 0;
411         }
412 
413         skipaddrGetV6(ipaddr, ip6);
414 
415         /* first byte of address where there is any effect */
416         i = cidr >> 3;
417 
418         /* handle min: apply mask to this byte, remaining bits all 0 */
419         ip6[i] &= ~(0xFF >> (cidr & 0x07));
420         memset(&ip6[i+1], 0, (15 - i));
421         skipaddrSetV6(min_ip, ip6);
422 
423         return 0;
424     }
425 #endif /* SK_ENABLE_IPV6 */
426 
427     if (cidr >= 32) {
428         if (cidr > 32) {
429             return -1;
430         }
431         ip4 = skipaddrGetV4(ipaddr);
432         skipaddrSetV4(min_ip, &ip4);
433         return 0;
434     }
435 
436     /* handle min IP */
437     ip4 = ~(UINT32_MAX >> cidr) & skipaddrGetV4(ipaddr);
438     skipaddrSetV4(min_ip, &ip4);
439 
440     return 0;
441 }
442 
443 
444 int
skCIDRComputeEnd(const skipaddr_t * ipaddr,uint32_t cidr,skipaddr_t * max_ip)445 skCIDRComputeEnd(
446     const skipaddr_t   *ipaddr,
447     uint32_t            cidr,
448     skipaddr_t         *max_ip)
449 {
450     uint32_t ip4;
451 
452 #if SK_ENABLE_IPV6
453     if (skipaddrIsV6(ipaddr)) {
454         uint8_t ip6[16];
455         uint32_t i;
456 
457         if (cidr >= 128) {
458             if (cidr > 128) {
459                 return -1;
460             }
461             if (ipaddr != max_ip) {
462                 skipaddrCopy(max_ip, ipaddr);
463             }
464             return 0;
465         }
466 
467         skipaddrGetV6(ipaddr, ip6);
468 
469         /* first byte of address where there is any effect */
470         i = cidr >> 3;
471 
472         /* handle max: apply mask to this byte, remaining bits all 1 */
473         ip6[i] |= (0xFF >> (cidr & 0x07));
474         memset(&ip6[i+1], 0xFF, (15 - i));
475         skipaddrSetV6(max_ip, ip6);
476 
477         return 0;
478     }
479 #endif /* SK_ENABLE_IPV6 */
480 
481     if (cidr >= 32) {
482         if (cidr > 32) {
483             return -1;
484         }
485         ip4 = skipaddrGetV4(ipaddr);
486         skipaddrSetV4(max_ip, &ip4);
487         return 0;
488     }
489 
490     /* handle max IP */
491     ip4 = (UINT32_MAX >> cidr) | skipaddrGetV4(ipaddr);
492     skipaddrSetV4(max_ip, &ip4);
493 
494     return 0;
495 }
496 
497 
498 #if SK_ENABLE_IPV6
499 int
skipaddrV6toV4(const skipaddr_t * srcaddr,skipaddr_t * dstaddr)500 skipaddrV6toV4(
501     const skipaddr_t   *srcaddr,
502     skipaddr_t         *dstaddr)
503 {
504     uint32_t ipv4;
505 
506     if (!SK_IPV6_IS_V4INV6(srcaddr->ip_ip.ipu_ipv6)) {
507         return -1;
508     }
509     memcpy(&ipv4, &(srcaddr->ip_ip.ipu_ipv6[12]), 4);
510     ipv4 = ntohl(ipv4);
511     skipaddrSetV4(dstaddr, &ipv4);
512     return 0;
513 }
514 
515 
516 int
skipaddrGetAsV4(const skipaddr_t * ipaddr,uint32_t * ipv4)517 skipaddrGetAsV4(
518     const skipaddr_t   *ipaddr,
519     uint32_t           *ipv4)
520 {
521     if (skipaddrIsV6(ipaddr)) {
522         if (!SK_IPV6_IS_V4INV6(ipaddr->ip_ip.ipu_ipv6)) {
523             return -1;
524         }
525         memcpy(ipv4, &(ipaddr->ip_ip.ipu_ipv6[12]), 4);
526         *ipv4 = ntohl(*ipv4);
527     } else {
528         *ipv4 = skipaddrGetV4(ipaddr);
529     }
530     return 0;
531 }
532 #endif  /* SK_ENABLE_IPV6 */
533 
534 
535 static char *
ipaddrString(char * outbuf,const skipaddr_t * ipaddr,uint32_t ip_flags,int * is_ipv6)536 ipaddrString(
537     char               *outbuf,
538     const skipaddr_t   *ipaddr,
539     uint32_t            ip_flags,
540     int                *is_ipv6)
541 {
542     uint8_t ipv6[16];
543     uint32_t ipv4;
544 
545 #if SK_ENABLE_IPV6
546     if (skipaddrIsV6(ipaddr)) {
547         if ((ip_flags & SKIPADDR_UNMAP_V6)
548             && (0 == skipaddrGetAsV4(ipaddr, &ipv4)))
549         {
550             *is_ipv6 = 0;
551         } else {
552             *is_ipv6 = 1;
553             skipaddrGetV6(ipaddr, ipv6);
554         }
555     } else
556 #endif  /* SK_ENABLE_IPV6 */
557     {
558         if (ip_flags & SKIPADDR_MAP_V4) {
559 #ifdef skipaddrGetAsV6
560             skipaddrGetAsV6(ipaddr, ipv6);
561 #else
562             uint32_t tmp;
563             memcpy(ipv6, sk_ipv6_v4inv6, sizeof(sk_ipv6_v4inv6));
564             tmp = htonl(skipaddrGetV4(ipaddr));
565             memcpy(&ipv6[12], &tmp, sizeof(tmp));
566 #endif  /* #else of #ifdef skipaddrGetAsV6 */
567             *is_ipv6 = 1;
568         } else {
569             *is_ipv6 = 0;
570             ipv4 = skipaddrGetV4(ipaddr);
571         }
572     }
573 
574     ip_flags &= ~(uint32_t)(SKIPADDR_MAP_V4 | SKIPADDR_UNMAP_V6);
575 
576     if (*is_ipv6) {
577         /* to represent a 128 bit number, divide the number into 4
578          * 64-bit values where each value represents 10 decimal digits
579          * of the number, with position 0 holding the least
580          * significant bits. */
581         static const uint64_t map_ipv6_to_dec[][3] = {
582             /* 1 << 64 */
583             { UINT64_C(3709551616), UINT64_C(1844674407), 0},
584             /* 1 <<  96 */
585             { UINT64_C(3543950336), UINT64_C(1426433759), UINT64_C(792281625)}
586         };
587         /* our 10 decimal digits */
588         static const uint64_t lim = UINT64_C(10000000000);
589         /* the decimal value being calculated */
590         uint64_t decimal[4] = {0, 0, 0, 0};
591         /* when doing our own IPv6 printing, this holds each 16bit
592          * section of the address */
593         uint16_t hexdec[8];
594         /* following two values used when finding the longest run of
595          * 0s in an IPv6 address */
596         unsigned int longest_zero_pos;
597         unsigned int longest_zero_len;
598         uint64_t tmp;
599         char tmpbuf[SKIPADDR_STRLEN];
600         char *pos;
601         unsigned int len;
602         unsigned int i, j;
603         int zero_pad = 0;
604 
605         if (0 == memcmp(ipv6, sk_ipv6_zero, sizeof(sk_ipv6_zero))) {
606             switch (ip_flags) {
607               case SKIPADDR_CANONICAL:
608               case SKIPADDR_NO_MIXED:
609                 snprintf(outbuf, SKIPADDR_STRLEN, "::");
610                 break;
611 
612               case SKIPADDR_DECIMAL:
613               case SKIPADDR_HEXADECIMAL:
614                 snprintf(outbuf, SKIPADDR_STRLEN, "0");
615                 break;
616 
617               case SKIPADDR_ZEROPAD | SKIPADDR_CANONICAL:
618               case SKIPADDR_ZEROPAD | SKIPADDR_NO_MIXED:
619                 snprintf(outbuf, SKIPADDR_STRLEN,
620                          "0000:0000:0000:0000:0000:0000:0000:0000");
621                 break;
622 
623               case SKIPADDR_ZEROPAD | SKIPADDR_DECIMAL:
624                 snprintf(outbuf, SKIPADDR_STRLEN,
625                          "000000000000000000000000000000000000000");
626                 break;
627 
628               case SKIPADDR_ZEROPAD | SKIPADDR_HEXADECIMAL:
629                 snprintf(outbuf, SKIPADDR_STRLEN,
630                          "00000000000000000000000000000000");
631                 break;
632 
633               default:
634                 skAbortBadCase(ip_flags);
635             }
636             outbuf[SKIPADDR_STRLEN-1] = '\0';
637             return outbuf;
638         }
639 
640         switch (ip_flags) {
641           case SKIPADDR_CANONICAL:
642 #ifdef SK_HAVE_INET_NTOP
643 #  if    SKIPADDR_STRLEN < INET6_ADDRSTRLEN
644 #    error "SKIPADDR_STRLEN is not big enough"
645 #  endif
646             if (NULL == inet_ntop(AF_INET6, &(ipv6), outbuf,
647                                   SKIPADDR_STRLEN))
648             {
649                 outbuf[0] = '\0';
650             }
651             break;
652 #endif /* SK_HAVE_INET_NTOP */
653 
654           case SKIPADDR_NO_MIXED:
655             /* do our own IPV6 printing with no IPv4 representation;
656              * follows Section 4 of RFC5952 */
657             /* compute each hexadectet */
658             hexdec[0] = (ipv6[ 0] << 8) | ipv6[ 1];
659             hexdec[1] = (ipv6[ 2] << 8) | ipv6[ 3];
660             hexdec[2] = (ipv6[ 4] << 8) | ipv6[ 5];
661             hexdec[3] = (ipv6[ 6] << 8) | ipv6[ 7];
662             hexdec[4] = (ipv6[ 8] << 8) | ipv6[ 9];
663             hexdec[5] = (ipv6[10] << 8) | ipv6[11];
664             hexdec[6] = (ipv6[12] << 8) | ipv6[13];
665             hexdec[7] = (ipv6[14] << 8) | ipv6[15];
666             /* find the starting position and length of the longest
667              * run of 0s */
668             longest_zero_pos = 8;
669             longest_zero_len = 0;
670             i = 0;
671             while (i < 8) {
672                 if (hexdec[i]) {
673                     ++i;
674                 } else if (i == 7 || hexdec[i+1]) {
675                     /* do not shorten a single 0 */
676                     ++i;
677                 } else {
678                     /* we know i+1 is zero */
679                     j = i;
680                     for (i += 2; i < 8 && (0 == hexdec[i]); ++i){};/*empty*/
681                     if ((i - j) > longest_zero_len) {
682                         longest_zero_len = i - j;
683                         longest_zero_pos = j;
684                     }
685                 }
686             }
687             /* print the ip; we build the result in pieces */
688             if (0 == longest_zero_len) {
689                 snprintf(outbuf, SKIPADDR_STRLEN, "%x:%x:%x:%x:%x:%x:%x:%x",
690                          hexdec[0], hexdec[1], hexdec[2], hexdec[3],
691                          hexdec[4], hexdec[5], hexdec[6], hexdec[7]);
692             } else {
693                 i = 0;
694                 pos = outbuf;
695                 len = SKIPADDR_STRLEN;
696                 while (i < 8) {
697                     if (i == longest_zero_pos) {
698                         i += longest_zero_len;
699                         if (8 == i) {
700                             j = snprintf(pos, len, "::");
701                         } else {
702                             j = snprintf(pos, len, ":");
703                         }
704                     } else if (0 == i) {
705                         j = snprintf(pos, len, "%x", hexdec[i]);
706                         ++i;
707                     } else {
708                         j = snprintf(pos, len, ":%x", hexdec[i]);
709                         ++i;
710                     }
711                     if (j >= len) {
712                         skAbort();
713                     }
714                     pos += j;
715                     len -= j;
716                 }
717             }
718             break;
719 
720           case SKIPADDR_ZEROPAD | SKIPADDR_CANONICAL:
721           case SKIPADDR_ZEROPAD | SKIPADDR_NO_MIXED:
722             /* Convert integer 0 to string
723                "0000:0000:0000:0000:0000:0000:0000:0000" */
724             snprintf(outbuf, SKIPADDR_STRLEN,
725                      ("%02x%02x:%02x%02x:%02x%02x:%02x%02x"
726                       ":%02x%02x:%02x%02x:%02x%02x:%02x%02x"),
727                      ipv6[ 0], ipv6[ 1], ipv6[ 2], ipv6[ 3],
728                      ipv6[ 4], ipv6[ 5], ipv6[ 6], ipv6[ 7],
729                      ipv6[ 8], ipv6[ 9], ipv6[10], ipv6[11],
730                      ipv6[12], ipv6[13], ipv6[14], ipv6[15]);
731             break;
732 
733           case SKIPADDR_ZEROPAD | SKIPADDR_HEXADECIMAL:
734             zero_pad = 1;
735             /* FALLTHROUGH */
736           case SKIPADDR_HEXADECIMAL:
737             /* Fill buffer with a string representation of an integer
738              * in hexadecimal format; this works by printing the value
739              * then stripping leading 0's. */
740             snprintf(tmpbuf, sizeof(tmpbuf),
741                      ("%02x%02x%02x%02x%02x%02x%02x%02x"
742                       "%02x%02x%02x%02x%02x%02x%02x%02x"),
743                      ipv6[ 0], ipv6[ 1], ipv6[ 2], ipv6[ 3],
744                      ipv6[ 4], ipv6[ 5], ipv6[ 6], ipv6[ 7],
745                      ipv6[ 8], ipv6[ 9], ipv6[10], ipv6[11],
746                      ipv6[12], ipv6[13], ipv6[14], ipv6[15]);
747             i = ((zero_pad) ? 0 : strspn(tmpbuf, "0"));
748             /* checked for an IP of 0 above, so 'i' must be on some
749              * non-zero hex-digit */
750             assert('\0' != tmpbuf[i]);
751             strncpy(outbuf, &tmpbuf[i], SKIPADDR_STRLEN);
752             break;
753 
754           case SKIPADDR_ZEROPAD | SKIPADDR_DECIMAL:
755             zero_pad = 1;
756             /* FALLTHROUGH */
757           case SKIPADDR_DECIMAL:
758             /* the lower 64 bits of the IPv6 address */
759             tmp = ((  (uint64_t)ipv6[ 8] << UINT64_C(56))
760                    | ((uint64_t)ipv6[ 9] << UINT64_C(48))
761                    | ((uint64_t)ipv6[10] << UINT64_C(40))
762                    | ((uint64_t)ipv6[11] << UINT64_C(32))
763                    | ((uint64_t)ipv6[12] << UINT64_C(24))
764                    | ((uint64_t)ipv6[13] << UINT64_C(16))
765                    | ((uint64_t)ipv6[14] << UINT64_C( 8))
766                    | ((uint64_t)ipv6[15]));
767             decimal[0] = tmp % lim;
768             decimal[1] = tmp / lim;
769             /* the middle-upper 32 bits, must be multipled by 1<<64 */
770             tmp = ((  (uint64_t)ipv6[4] << UINT64_C(24))
771                    | ((uint64_t)ipv6[5] << UINT64_C(16))
772                    | ((uint64_t)ipv6[6] << UINT64_C( 8))
773                    | ((uint64_t)ipv6[7]));
774             if (tmp) {
775                 decimal[0] += tmp * map_ipv6_to_dec[0][0];
776                 if (decimal[0] >= lim) {
777                     decimal[1] += decimal[0] / lim;
778                     decimal[0] %= lim;
779                 }
780                 decimal[1] += tmp * map_ipv6_to_dec[0][1];
781                 if (decimal[1] >= lim) {
782                     decimal[2] += decimal[1] / lim;
783                     decimal[1] %= lim;
784                 }
785             }
786             /* the upper 32 bits, must be multipled by 1<<96 */
787             tmp = ((  (uint64_t)ipv6[0] << UINT64_C(24))
788                    | ((uint64_t)ipv6[1] << UINT64_C(16))
789                    | ((uint64_t)ipv6[2] << UINT64_C( 8))
790                    | ((uint64_t)ipv6[3]));
791             if (tmp) {
792                 decimal[0] += tmp * map_ipv6_to_dec[1][0];
793                 if (decimal[0] >= lim) {
794                     decimal[1] += decimal[0] / lim;
795                     decimal[0] %= lim;
796                 }
797                 decimal[1] += tmp * map_ipv6_to_dec[1][1];
798                 if (decimal[1] >= lim) {
799                     decimal[2] += decimal[1] / lim;
800                     decimal[1] %= lim;
801                 }
802                 decimal[2] += tmp * map_ipv6_to_dec[1][2];
803                 if (decimal[2] >= lim) {
804                     decimal[3] += decimal[2] / lim;
805                     decimal[2] %= lim;
806                 }
807             }
808             /* print the results */
809             if (zero_pad) {
810                 snprintf(outbuf, SKIPADDR_STRLEN,
811                          "%09" PRIu64 "%010" PRIu64 "%010" PRIu64
812                          "%010" PRIu64,
813                          decimal[3], decimal[2], decimal[1], decimal[0]);
814             } else if (decimal[3]) {
815                 snprintf(outbuf, SKIPADDR_STRLEN,
816                          "%" PRIu64 "%010" PRIu64 "%010" PRIu64 "%010" PRIu64,
817                          decimal[3], decimal[2], decimal[1], decimal[0]);
818             } else if (decimal[2]) {
819                 snprintf(outbuf, SKIPADDR_STRLEN,
820                          "%" PRIu64 "%010" PRIu64 "%010" PRIu64,
821                          decimal[2], decimal[1], decimal[0]);
822             } else if (decimal[1]) {
823                 snprintf(outbuf, SKIPADDR_STRLEN,
824                          "%" PRIu64 "%010" PRIu64,
825                          decimal[1], decimal[0]);
826             } else {
827                 snprintf(outbuf, SKIPADDR_STRLEN,
828                          "%" PRIu64, decimal[0]);
829             }
830             break;
831 
832           default:
833             skAbortBadCase(ip_flags);
834         }
835     } else {
836         /* address is IPv4 */
837         switch (ip_flags) {
838           case SKIPADDR_CANONICAL:
839           case SKIPADDR_NO_MIXED:
840             /* Convert integer 0 to string "0.0.0.0" */
841             snprintf(outbuf, SKIPADDR_STRLEN,
842                      "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32,
843                      ((ipv4 >> 24) & 0xFF),
844                      ((ipv4 >> 16) & 0xFF),
845                      ((ipv4 >>  8) & 0xFF),
846                      ((ipv4      ) & 0xFF));
847             break;
848 
849           case SKIPADDR_DECIMAL:
850             snprintf(outbuf, SKIPADDR_STRLEN, ("%" PRIu32), ipv4);
851             break;
852 
853           case SKIPADDR_HEXADECIMAL:
854             snprintf(outbuf, SKIPADDR_STRLEN, ("%" PRIx32), ipv4);
855             break;
856 
857           case SKIPADDR_ZEROPAD | SKIPADDR_CANONICAL:
858           case SKIPADDR_ZEROPAD | SKIPADDR_NO_MIXED:
859             snprintf(outbuf, SKIPADDR_STRLEN,
860                      "%03" PRIu32 ".%03" PRIu32 ".%03" PRIu32 ".%03" PRIu32,
861                      ((ipv4 >> 24) & 0xFF),
862                      ((ipv4 >> 16) & 0xFF),
863                      ((ipv4 >>  8) & 0xFF),
864                      ((ipv4      ) & 0xFF));
865             break;
866 
867           case SKIPADDR_ZEROPAD | SKIPADDR_DECIMAL:
868             snprintf(outbuf, SKIPADDR_STRLEN, ("%010" PRIu32), ipv4);
869             break;
870 
871           case SKIPADDR_ZEROPAD | SKIPADDR_HEXADECIMAL:
872             snprintf(outbuf, SKIPADDR_STRLEN, ("%08" PRIx32), ipv4);
873             break;
874 
875           case SKIPADDR_FORCE_IPV6:
876           case SKIPADDR_MAP_V4:
877           case SKIPADDR_UNMAP_V6:
878           default:
879             skAbortBadCase(ip_flags);
880         }
881     }
882 
883     outbuf[SKIPADDR_STRLEN-1] = '\0';
884     return outbuf;
885 }
886 
887 
888 static int
ipaddrStringMaxlen(unsigned int allow_ipv6,uint32_t ip_flags,int * is_ipv6)889 ipaddrStringMaxlen(
890     unsigned int        allow_ipv6,
891     uint32_t            ip_flags,
892     int                *is_ipv6)
893 {
894 #if !SK_ENABLE_IPV6
895     allow_ipv6 = 0;
896 #endif
897     /* ignore the SKIPADDR_UNMAP_V6 flag since no way to know whether
898      * all IPv6 data falls in the ::ffff:0:0/96 netblock */
899 
900     if (allow_ipv6 || (((SKIPADDR_ZEROPAD | SKIPADDR_MAP_V4) & ip_flags)
901                        == (SKIPADDR_ZEROPAD | SKIPADDR_MAP_V4)))
902     {
903         /* data is IPv6 or data is IPv4 being mapped to IPv6 and
904          * zero-pad is enabled */
905         *is_ipv6 = 1;
906         switch (ip_flags & (SKIPADDR_ZEROPAD - 1)) {
907           case SKIPADDR_CANONICAL:
908           case SKIPADDR_NO_MIXED:
909           case SKIPADDR_DECIMAL:
910             return 39;
911           case SKIPADDR_HEXADECIMAL:
912             return 32;
913           default:
914             skAbortBadCase(ip_flags);
915         }
916     } else if (ip_flags & SKIPADDR_MAP_V4) {
917         /* IPv4 mapped to v6; max ip is ::ffff:255.255.255.255 */
918         *is_ipv6 = 1;
919         switch (ip_flags & (SKIPADDR_ZEROPAD - 1)) {
920           case SKIPADDR_CANONICAL:
921             return 22;
922           case SKIPADDR_NO_MIXED:
923             return 16;
924           case SKIPADDR_DECIMAL:
925             return 15;
926           case SKIPADDR_HEXADECIMAL:
927             return 12;
928           default:
929             skAbortBadCase(ip_flags);
930         }
931     } else {
932         /* IPv4 */
933         *is_ipv6 = 0;
934         switch (ip_flags & (SKIPADDR_ZEROPAD - 1)) {
935           case SKIPADDR_CANONICAL:
936           case SKIPADDR_NO_MIXED:
937             return 15;
938           case SKIPADDR_DECIMAL:
939             return 10;
940           case SKIPADDR_HEXADECIMAL:
941             return 8;
942           default:
943             skAbortBadCase(ip_flags);
944         }
945     }
946 }
947 
948 
949 char *
skipaddrString(char * outbuf,const skipaddr_t * ipaddr,uint32_t ip_flags)950 skipaddrString(
951     char               *outbuf,
952     const skipaddr_t   *ipaddr,
953     uint32_t            ip_flags)
954 {
955     int is_ipv6;
956     return ipaddrString(outbuf, ipaddr, ip_flags, &is_ipv6);
957 }
958 
959 
960 char *
skipaddrCidrString(char * outbuf,const skipaddr_t * ipaddr,uint32_t prefix,uint32_t ip_flags)961 skipaddrCidrString(
962     char               *outbuf,
963     const skipaddr_t   *ipaddr,
964     uint32_t            prefix,
965     uint32_t            ip_flags)
966 {
967     int orig_ipv6;
968     int is_ipv6;
969     size_t sz;
970 
971 #if SK_ENABLE_IPV6
972     if (skipaddrIsV6(ipaddr)) {
973         if (prefix > 128) {
974             return NULL;
975         }
976         if (prefix < 96 && (ip_flags & SKIPADDR_UNMAP_V6)) {
977             ip_flags &= ~SKIPADDR_UNMAP_V6;
978         }
979         orig_ipv6 = 1;
980     } else
981 #endif  /* SK_ENABLE_IPV6 */
982     {
983         if (prefix > 32) {
984             return NULL;
985         }
986         orig_ipv6 = 0;
987     }
988 
989     if (ipaddrString(outbuf, ipaddr, ip_flags, &is_ipv6) == NULL) {
990         return NULL;
991     }
992 
993     if (is_ipv6 != orig_ipv6) {
994         if (is_ipv6) {
995             assert(!orig_ipv6);
996             assert(prefix <= 32);
997             prefix += 96;
998         } else {
999             assert(!is_ipv6);
1000             assert(orig_ipv6);
1001             assert(prefix >= 96);
1002             prefix -= 96;
1003         }
1004     }
1005 
1006     sz = strlen(outbuf);
1007     if (ip_flags & SKIPADDR_ZEROPAD) {
1008         snprintf(outbuf + sz, 5, "/%0*u", (is_ipv6 ? 3 : 2), prefix);
1009     } else {
1010         snprintf(outbuf + sz, 5, "/%u", prefix);
1011     }
1012     return outbuf;
1013 }
1014 
1015 
1016 int
skipaddrStringMaxlen(unsigned int allow_ipv6,uint32_t ip_flags)1017 skipaddrStringMaxlen(
1018     unsigned int        allow_ipv6,
1019     uint32_t            ip_flags)
1020 {
1021     int is_ipv6;
1022     return ipaddrStringMaxlen(allow_ipv6, ip_flags, &is_ipv6);
1023 }
1024 
1025 
1026 int
skipaddrCidrStringMaxlen(unsigned int allow_ipv6,uint32_t ip_flags)1027 skipaddrCidrStringMaxlen(
1028     unsigned int        allow_ipv6,
1029     uint32_t            ip_flags)
1030 {
1031     int is_ipv6;
1032     int len = ipaddrStringMaxlen(allow_ipv6, ip_flags, &is_ipv6);
1033     return len + 3 + is_ipv6;
1034 }
1035 
1036 
1037 static struct policies_st {
1038     sk_ipv6policy_t     policy;
1039     const char         *name;
1040     const char         *description;
1041 } policies[] = {
1042     {SK_IPV6POLICY_IGNORE, "ignore",
1043      "Completely ignore IPv6 flows"},
1044     {SK_IPV6POLICY_ASV4,   "asv4",
1045      "Convert IPv6 flows to IPv4 if possible, else ignore"},
1046     {SK_IPV6POLICY_MIX,    "mix",
1047      "Process a mixture of IPv4 and IPv6 flows"},
1048     {SK_IPV6POLICY_FORCE,  "force",
1049      "Force IPv4 flows to be converted to IPv6"},
1050     {SK_IPV6POLICY_ONLY,   "only",
1051      "Only process flows that were marked as IPv6"}
1052 };
1053 
1054 
1055 /* Parse an IPv6 policy.  Return 0 if it is valid, -1 otherwise. */
1056 int
skIPv6PolicyParse(sk_ipv6policy_t * ipv6_policy,const char * policy_name,const char * option_name)1057 skIPv6PolicyParse(
1058     sk_ipv6policy_t    *ipv6_policy,
1059     const char         *policy_name,
1060     const char         *option_name)
1061 {
1062     size_t len = strlen(policy_name);
1063     size_t i;
1064 
1065     for (i = 0; i < sizeof(policies)/sizeof(struct policies_st); ++i) {
1066         if (len < strlen(policies[i].name)) {
1067             if (0 == strncmp(policies[i].name, policy_name, len)) {
1068                 *ipv6_policy = policies[i].policy;
1069                 return 0;
1070             }
1071         } else if (0 == strcmp(policies[i].name, policy_name)) {
1072             *ipv6_policy = policies[i].policy;
1073             return 0;
1074         }
1075     }
1076 
1077     if (option_name) {
1078         skAppPrintErr("Invalid %s '%s'", option_name, policy_name);
1079     }
1080     return -1;
1081 }
1082 
1083 
1084 /* store the default policy from the application */
1085 static sk_ipv6policy_t ipv6_default;
1086 
1087 /* support for the option */
1088 #define OPT_IPV6_POLICY  0
1089 
1090 static struct option ipv6_policy_options[] = {
1091     {"ipv6-policy",         REQUIRED_ARG, 0, OPT_IPV6_POLICY},
1092     {0,0,0,0}               /* sentinel */
1093 };
1094 
1095 /* handler for the option */
1096 static int
ipv6PolicyHandler(clientData cData,int opt_index,char * opt_arg)1097 ipv6PolicyHandler(
1098     clientData          cData,
1099     int                 opt_index,
1100     char               *opt_arg)
1101 {
1102     sk_ipv6policy_t *ipv6_policy = (sk_ipv6policy_t*)cData;
1103 
1104     switch (opt_index) {
1105       case OPT_IPV6_POLICY:
1106         if (skIPv6PolicyParse(ipv6_policy, opt_arg,
1107                               ipv6_policy_options[opt_index].name))
1108         {
1109             return 1;
1110         }
1111         break;
1112 
1113       default:
1114         skAbortBadCase(opt_index);
1115     }
1116 
1117     return 0;
1118 }
1119 
1120 
1121 int
skIPv6PolicyOptionsRegister(sk_ipv6policy_t * ipv6_policy)1122 skIPv6PolicyOptionsRegister(
1123     sk_ipv6policy_t    *ipv6_policy)
1124 {
1125     sk_ipv6policy_t tmp_policy;
1126     char *env;
1127 
1128     assert(ipv6_policy);
1129 
1130     /* store the default policy wanted by the application */
1131     ipv6_default = *ipv6_policy;
1132 
1133     /* get the default from the environment */
1134     env = getenv(SILK_IPV6_POLICY_ENVAR);
1135     if (env) {
1136         if (skIPv6PolicyParse(&tmp_policy, env, SILK_IPV6_POLICY_ENVAR) == 0) {
1137             *ipv6_policy = tmp_policy;
1138         }
1139     }
1140 
1141 #if !SK_ENABLE_IPV6
1142     /* Force an IPv4-only SiLK to ignore any IPv6 flows */
1143     ipv6_default = SK_IPV6POLICY_IGNORE;
1144     *ipv6_policy = ipv6_default;
1145 
1146     /* Register the option for compatibility with an IPv6-enabled
1147      * silk, but pass 'ipv6_default' as the clientData, so the user's
1148      * value does not modify the value the application uses. */
1149     return skOptionsRegister(ipv6_policy_options, &ipv6PolicyHandler,
1150                              (clientData)&ipv6_default);
1151 #else
1152     /* add the option */
1153     return skOptionsRegister(ipv6_policy_options, &ipv6PolicyHandler,
1154                              (clientData)ipv6_policy);
1155 #endif  /* SK_ENABLE_IPV6 */
1156 }
1157 
1158 
1159 void
skIPv6PolicyUsage(FILE * fh)1160 skIPv6PolicyUsage(
1161     FILE               *fh)
1162 {
1163     size_t i;
1164 
1165     fprintf(fh, "--%s %s. ",
1166             ipv6_policy_options[OPT_IPV6_POLICY].name,
1167             SK_OPTION_HAS_ARG(ipv6_policy_options[OPT_IPV6_POLICY]));
1168 #if !SK_ENABLE_IPV6
1169     fprintf(fh, ("No IPv6 support available; IPv6 flows are always ignored\n"
1170                  "\tregardless of the value passed to this switch."
1171                  " Legal values:\n"));
1172 #else
1173     fprintf(fh, "Set policy for handling IPv4 and IPv6 flows.");
1174     for (i = 0; i < sizeof(policies)/sizeof(struct policies_st); ++i) {
1175         if (ipv6_default != policies[i].policy) {
1176             continue;
1177         }
1178         fprintf(fh, "\n\tDef. $" SILK_IPV6_POLICY_ENVAR " or %s. ",
1179                 policies[i].name);
1180         break;
1181     }
1182     fprintf(fh, "Choices:\n");
1183 #endif
1184     for (i = 0; i < sizeof(policies)/sizeof(struct policies_st); ++i) {
1185         fprintf(fh, "\t%-6s  - %s\n",
1186                 policies[i].name, policies[i].description);
1187     }
1188 }
1189 
1190 
1191 #if SK_ENABLE_IPV6
1192 int
skipaddrCompare(const skipaddr_t * addr1,const skipaddr_t * addr2)1193 skipaddrCompare(
1194     const skipaddr_t   *addr1,
1195     const skipaddr_t   *addr2)
1196 {
1197     skipaddr_t tmp;
1198 
1199     if (addr1->ip_is_v6) {
1200         if (addr2->ip_is_v6) {
1201             return memcmp(addr1->ip_ip.ipu_ipv6, addr2->ip_ip.ipu_ipv6, 16);
1202         }
1203         skipaddrV4toV6(addr2, &tmp);
1204         return memcmp(addr1->ip_ip.ipu_ipv6, tmp.ip_ip.ipu_ipv6, 16);
1205     }
1206     if (addr2->ip_is_v6) {
1207         skipaddrV4toV6(addr1, &tmp);
1208         return memcmp(tmp.ip_ip.ipu_ipv6, addr2->ip_ip.ipu_ipv6, 16);
1209     }
1210     /* both addresses are IPv4 */
1211     if (addr1->ip_ip.ipu_ipv4 < addr2->ip_ip.ipu_ipv4) {
1212         return -1;
1213     }
1214     if (addr1->ip_ip.ipu_ipv4 > addr2->ip_ip.ipu_ipv4) {
1215         return 1;
1216     }
1217     return 0;
1218 }
1219 
1220 
1221 /* apply the bit-mask in 'mask_ip' to 'ipaddr' */
1222 void
skipaddrMask(skipaddr_t * ipaddr,const skipaddr_t * mask_ip)1223 skipaddrMask(
1224     skipaddr_t         *ipaddr,
1225     const skipaddr_t   *mask_ip)
1226 {
1227     skipaddr_t tmp;
1228     uint32_t mask_v4;
1229 
1230     if (ipaddr->ip_is_v6) {
1231         if (mask_ip->ip_is_v6) {
1232             /* both addresses are IPv6 */
1233             skIPUnionApplyMaskV6(&ipaddr->ip_ip, mask_ip->ip_ip.ipu_ipv6);
1234             return;
1235         }
1236         /* convert mask to IPv6. This result will be strange */
1237         skipaddrV4toV6(mask_ip, &tmp);
1238         skIPUnionApplyMaskV6(&ipaddr->ip_ip, tmp.ip_ip.ipu_ipv6);
1239         return;
1240     }
1241     if (skipaddrGetAsV4(mask_ip, &mask_v4) == -1) {
1242         /* 'ipaddr' is IPv4 and 'mask_ip' is IPv6. convert 'ipaddr' to
1243          * v6; the result is going to be strange */
1244         skipaddrV4toV6(ipaddr, ipaddr);
1245         skIPUnionApplyMaskV6(&ipaddr->ip_ip, mask_ip->ip_ip.ipu_ipv6);
1246         return;
1247     }
1248     /* both addresses are IPv4 */
1249     skIPUnionApplyMaskV4(&ipaddr->ip_ip, mask_v4);
1250 }
1251 
1252 #endif /* SK_ENABLE_IPV6 */
1253 
1254 
1255 /* *************    IP WILDCARDS   ******************* */
1256 
1257 
1258 void
skIPWildcardClear(skIPWildcard_t * ipwild)1259 skIPWildcardClear(
1260     skIPWildcard_t     *ipwild)
1261 {
1262     assert(ipwild);
1263     memset(ipwild, 0, sizeof(skIPWildcard_t));
1264     memset(ipwild->m_min, 0xFF, sizeof(ipwild->m_min));
1265 }
1266 
1267 
1268 
1269 #if SK_ENABLE_IPV6
1270 int
skIPWildcardCheckIp(const skIPWildcard_t * ipwild,const skipaddr_t * ipaddr)1271 skIPWildcardCheckIp(
1272     const skIPWildcard_t   *ipwild,
1273     const skipaddr_t       *ipaddr)
1274 {
1275     uint32_t ip4;
1276 
1277     assert(ipwild);
1278     assert(ipaddr);
1279 
1280     if (skIPWildcardIsV6(ipwild)) {
1281         uint8_t ip6[16];
1282         skipaddrGetAsV6(ipaddr, ip6);
1283         return (_IPWILD_BLOCK_IS_SET(ipwild, 0, ((ip6[ 0] << 8) | ip6[ 1])) &&
1284                 _IPWILD_BLOCK_IS_SET(ipwild, 1, ((ip6[ 2] << 8) | ip6[ 3])) &&
1285                 _IPWILD_BLOCK_IS_SET(ipwild, 2, ((ip6[ 4] << 8) | ip6[ 5])) &&
1286                 _IPWILD_BLOCK_IS_SET(ipwild, 3, ((ip6[ 6] << 8) | ip6[ 7])) &&
1287                 _IPWILD_BLOCK_IS_SET(ipwild, 4, ((ip6[ 8] << 8) | ip6[ 9])) &&
1288                 _IPWILD_BLOCK_IS_SET(ipwild, 5, ((ip6[10] << 8) | ip6[11])) &&
1289                 _IPWILD_BLOCK_IS_SET(ipwild, 6, ((ip6[12] << 8) | ip6[13])) &&
1290                 _IPWILD_BLOCK_IS_SET(ipwild, 7, ((ip6[14] << 8) | ip6[15])));
1291     }
1292 
1293     if (skipaddrGetAsV4(ipaddr, &ip4)) {
1294         return 0;
1295     }
1296 
1297     return (_IPWILD_BLOCK_IS_SET((ipwild), 0, 0xFF & (ip4 >> 24)) &&
1298             _IPWILD_BLOCK_IS_SET((ipwild), 1, 0xFF & (ip4 >> 16)) &&
1299             _IPWILD_BLOCK_IS_SET((ipwild), 2, 0xFF & (ip4 >>  8)) &&
1300             _IPWILD_BLOCK_IS_SET((ipwild), 3, 0xFF & (ip4)));
1301 }
1302 
1303 
1304 /* Bind iterator to an ipwildcard, forcing IPv6 addresses */
1305 int
skIPWildcardIteratorBindV6(skIPWildcardIterator_t * out_iter,const skIPWildcard_t * ipwild)1306 skIPWildcardIteratorBindV6(
1307     skIPWildcardIterator_t *out_iter,
1308     const skIPWildcard_t   *ipwild)
1309 {
1310     if (skIPWildcardIteratorBind(out_iter, ipwild)) {
1311         return -1;
1312     }
1313     out_iter->force_ipv6 = 1;
1314     out_iter->force_ipv4 = 0;
1315     return 0;
1316 }
1317 
1318 
1319 /* Bind iterator to an ipwildcard, forcing IPv4 addresses */
1320 int
skIPWildcardIteratorBindV4(skIPWildcardIterator_t * out_iter,const skIPWildcard_t * ipwild)1321 skIPWildcardIteratorBindV4(
1322     skIPWildcardIterator_t *out_iter,
1323     const skIPWildcard_t   *ipwild)
1324 {
1325     assert(out_iter);
1326     if (NULL == ipwild) {
1327         return -1;
1328     }
1329 
1330     out_iter->ipwild = ipwild;
1331     out_iter->force_ipv6 = 0;
1332     /* only set force_ipv4 when wildcard is IPv6 */
1333     out_iter->force_ipv4 = skIPWildcardIsV6(ipwild);
1334     skIPWildcardIteratorReset(out_iter);
1335 
1336     return 0;
1337 }
1338 #endif /* SK_ENABLE_IPV6 */
1339 
1340 
1341 /* Bind iterator to an ipwildcard */
1342 int
skIPWildcardIteratorBind(skIPWildcardIterator_t * out_iter,const skIPWildcard_t * ipwild)1343 skIPWildcardIteratorBind(
1344     skIPWildcardIterator_t *out_iter,
1345     const skIPWildcard_t   *ipwild)
1346 {
1347     assert(out_iter);
1348     if (ipwild == NULL) {
1349         return -1;
1350     }
1351 
1352     out_iter->ipwild = ipwild;
1353     out_iter->force_ipv6 = 0;
1354     out_iter->force_ipv4 = 0;
1355     skIPWildcardIteratorReset(out_iter);
1356 
1357     return 0;
1358 }
1359 
1360 
1361 /* helper function for skIPWildcardIteratorNext() and
1362  * skIPWildcardIteratorNextCidr() */
1363 static skIteratorStatus_t
ipwildcardIterNext(skIPWildcardIterator_t * iter,skipaddr_t * ipaddr,uint32_t * prefix,int want_cidr)1364 ipwildcardIterNext(
1365     skIPWildcardIterator_t *iter,
1366     skipaddr_t             *ipaddr,
1367     uint32_t               *prefix,
1368     int                     want_cidr)
1369 {
1370     uint32_t cidr_adjust;
1371     uint32_t tmp;
1372     unsigned int check_ints;
1373     unsigned int idx;
1374     unsigned int i;
1375     unsigned int j;
1376 
1377     assert(iter);
1378     assert(ipaddr);
1379     assert(prefix);
1380 
1381     /* check the stopping condition */
1382     if (iter->no_more_entries) {
1383         return SK_ITERATOR_NO_MORE_ENTRIES;
1384     }
1385 
1386     /* the iterator is already set to the single IP to return or to
1387      * the first IP of the CIDR block to return; get that first IP,
1388      * and set prefix assuming a single IP */
1389 #if SK_ENABLE_IPV6
1390     if (skIPWildcardIsV6(iter->ipwild)) {
1391         if (iter->force_ipv4) {
1392             uint32_t ip4 = (iter->i_block[6] << 16) | iter->i_block[7];
1393             skipaddrSetV4(ipaddr, &ip4);
1394             *prefix = 32;
1395         } else {
1396             uint8_t ip6[16];
1397 
1398             ip6[ 0] = (uint8_t)(iter->i_block[0] >> 8);
1399             ip6[ 1] = (uint8_t)(iter->i_block[0] & 0xFF);
1400             ip6[ 2] = (uint8_t)(iter->i_block[1] >> 8);
1401             ip6[ 3] = (uint8_t)(iter->i_block[1] & 0xFF);
1402             ip6[ 4] = (uint8_t)(iter->i_block[2] >> 8);
1403             ip6[ 5] = (uint8_t)(iter->i_block[2] & 0xFF);
1404             ip6[ 6] = (uint8_t)(iter->i_block[3] >> 8);
1405             ip6[ 7] = (uint8_t)(iter->i_block[3] & 0xFF);
1406             ip6[ 8] = (uint8_t)(iter->i_block[4] >> 8);
1407             ip6[ 9] = (uint8_t)(iter->i_block[4] & 0xFF);
1408             ip6[10] = (uint8_t)(iter->i_block[5] >> 8);
1409             ip6[11] = (uint8_t)(iter->i_block[5] & 0xFF);
1410             ip6[12] = (uint8_t)(iter->i_block[6] >> 8);
1411             ip6[13] = (uint8_t)(iter->i_block[6] & 0xFF);
1412             ip6[14] = (uint8_t)(iter->i_block[7] >> 8);
1413             ip6[15] = (uint8_t)(iter->i_block[7] & 0xFF);
1414             skipaddrSetV6(ipaddr, ip6);
1415             *prefix = 128;
1416         }
1417     } else if (iter->force_ipv6) {
1418         uint32_t ip4 = ((iter->i_block[0] << 24) |
1419                         (iter->i_block[1] << 16) |
1420                         (iter->i_block[2] <<  8) |
1421                         (iter->i_block[3]));
1422         skipaddrSetV6FromUint32(ipaddr, &ip4);
1423         *prefix = 128;
1424     } else
1425 #endif
1426     {
1427         uint32_t ip4 = ((iter->i_block[0] << 24) |
1428                         (iter->i_block[1] << 16) |
1429                         (iter->i_block[2] <<  8) |
1430                         (iter->i_block[3]));
1431         skipaddrSetV4(ipaddr, &ip4);
1432         *prefix = 32;
1433     }
1434 
1435     /* skip the for() loop if not looking for a CIDR block */
1436     if (!want_cidr) {
1437         goto NEXT_IP;
1438     }
1439 
1440     /* determine the end of this CIDR block by counting the number of
1441      * consecutive high bits in the bitmap */
1442     i = iter->ipwild->num_blocks;
1443     while (i > 0) {
1444         --i;
1445         assert(i < (SK_ENABLE_IPV6 ? 8 : 4));
1446         /* 'idx' is array position of the uint32_t we are currently
1447          * looking at in the bitmap for this octet/hexadectet */
1448         idx = _BMAP_INDEX(iter->i_block[i]);
1449         assert(idx < (SK_ENABLE_IPV6 ? (65536/32) : (256/32)));
1450         /* this is the CIDR block adjustment to make due to this
1451          * octet/hexadectet only */
1452         cidr_adjust = 0;
1453         /* switch based on the number of additional bits we can
1454          * consider in the current uint32_t */
1455         switch (iter->i_block[i] & 0x1F) {
1456           case 0:
1457             /* can consider all */
1458             if (iter->ipwild->m_blocks[i][idx] == 0xFFFFFFFF) {
1459                 /* all bits in this uint32_t are high.  Check for a
1460                  * longer run of high bits by checking the value in
1461                  * adjacent uint32_t's. 'check_ints' is the number of
1462                  * values to check.  this calculation is based on the
1463                  * number of trailing 0's in the number of available
1464                  * uint32_t's. */
1465                 tmp = ((iter->i_block[i] >> 5)
1466                        | (1 << (2 * iter->ipwild->num_blocks - 5)));
1467                 if (tmp & 0x1) {
1468                     check_ints = 0;
1469                 } else {
1470                     check_ints = (1 << 1);
1471                     if ((tmp & 0xff) == 0) {
1472                         tmp >>= 8;
1473                         check_ints <<= 8;
1474                     }
1475                     if ((tmp & 0xf) == 0) {
1476                         tmp >>= 4;
1477                         check_ints <<= 4;
1478                     }
1479                     if ((tmp & 0x3) == 0) {
1480                         tmp >>= 2;
1481                         check_ints <<= 2;
1482                     }
1483                     check_ints >>= (tmp & 0x1);
1484                 }
1485                 /* move to next uint32_t; start counting from 1 since
1486                  * we already checked one uint32_t. */
1487                 ++idx;
1488                 for (j = 1; j < check_ints; ++j, ++idx) {
1489                     assert(idx < (SK_ENABLE_IPV6 ? (65536/32) : (256/32)));
1490                     if (iter->ipwild->m_blocks[i][idx] != 0xFFFFFFFF) {
1491                         break;
1492                     }
1493                 }
1494                 /* cidr_adjust is at least 5 plus an amount determined
1495                  * by the most significant bit in 'j' */
1496                 cidr_adjust = 5 + skIntegerLog2(j);
1497                 break;
1498             }
1499             /* FALLTHROUGH */
1500 
1501           case 16:
1502             /* we can consider at least 16 bits in this uint32_t */
1503             if (((iter->ipwild->m_blocks[i][idx]
1504                   >> (iter->i_block[i] & 0x1F)) & 0xFFFF) == 0xFFFF)
1505             {
1506                 cidr_adjust = 4;
1507                 break;
1508             }
1509             /* FALLTHROUGH */
1510 
1511           case 8: case 24:
1512             /* we can consider at least 8 bits in this uint32_t */
1513             if (((iter->ipwild->m_blocks[i][idx]
1514                   >> (iter->i_block[i] & 0x1F)) & 0xFF) == 0xFF)
1515             {
1516                 cidr_adjust = 3;
1517                 break;
1518             }
1519             /* FALLTHROUGH */
1520 
1521           case 4: case 12: case 20: case 28:
1522             if (((iter->ipwild->m_blocks[i][idx]
1523                   >> (iter->i_block[i] & 0x1F)) & 0xF) == 0xF)
1524             {
1525                 cidr_adjust = 2;
1526                 break;
1527             }
1528             /* FALLTHROUGH */
1529 
1530           case  2: case  6: case 10: case 14:
1531           case 18: case 22: case 26: case 30:
1532             if (((iter->ipwild->m_blocks[i][idx]
1533                   >> (iter->i_block[i] & 0x1F)) & 0x3) == 0x3)
1534             {
1535                 cidr_adjust = 1;
1536                 break;
1537             }
1538             /* FALLTHROUGH */
1539 
1540           default:
1541             break;
1542         }
1543 
1544         /* adjust the prefix value based on this octet/hexadectet */
1545         *prefix -= cidr_adjust;
1546         iter->i_block[i] += (1 << cidr_adjust) - 1;
1547         assert(iter->i_block[i] <= iter->ipwild->m_max[i]);
1548 
1549         /* do the consecutive bits run into the next
1550          * octet/hexadectet? */
1551         if (cidr_adjust < 2u * iter->ipwild->num_blocks) {
1552             /* no.  we've found the largest block */
1553             break;
1554         }
1555     }
1556 
1557   NEXT_IP:
1558     /* found the CIDR block to return this time.  move the iterator to
1559      * the start of the next IP or CIDR block for the next query */
1560     i = iter->ipwild->num_blocks;
1561     while (i > 0) {
1562         --i;
1563         /* is the i'th octet/hexadectet at its maximum? */
1564         if (iter->i_block[i] >= iter->ipwild->m_max[i]) {
1565             /* yes; reset the counter for this octet/hexadectet and
1566              * try the next most significant octet/hexadectet */
1567             iter->i_block[i] = iter->ipwild->m_min[i];
1568 
1569             if (iter->force_ipv4 && i <= 6) {
1570                 break;
1571             }
1572             continue;
1573         }
1574         /* else it is not at the max, and we can increment this
1575          * octet/hexadectet.  find the next high bit */
1576 
1577         /* assert that our stopping condition is valid */
1578         assert(_IPWILD_BLOCK_IS_SET(iter->ipwild, i, iter->ipwild->m_max[i]));
1579         ++iter->i_block[i];
1580         if (_IPWILD_BLOCK_IS_SET(iter->ipwild, i, iter->i_block[i])) {
1581             /* found it */
1582             return SK_ITERATOR_OK;
1583         }
1584 
1585         /* jump over multiple 0 bits. get current uint32_t */
1586         tmp = iter->ipwild->m_blocks[i][_BMAP_INDEX(iter->i_block[i])];
1587         if (iter->i_block[i] & 0x1F) {
1588             /* this uint32_t contains the CIDR block that is being
1589              * returned; need to shift off bits we have already
1590              * handled */
1591             tmp >>= (iter->i_block[i] & 0x1F);
1592             if (0 == tmp) {
1593                 /* no more high bits in this uint32_t */
1594                 iter->i_block[i] += 32 - (iter->i_block[i] & 0x1F);
1595                 tmp = iter->ipwild->m_blocks[i][_BMAP_INDEX(iter->i_block[i])];
1596             }
1597         }
1598         while (0 == tmp) {
1599             /* skip over uint32_t's that are 0 */
1600             iter->i_block[i] += 32;
1601             tmp = iter->ipwild->m_blocks[i][_BMAP_INDEX(iter->i_block[i])];
1602         }
1603 
1604         /* this uint32_t contains a high bit */
1605         if (0 == (tmp & 0x1)) {
1606             ++iter->i_block[i];
1607             if ((tmp & 0xFFFF) == 0) {
1608                 tmp >>= 16;
1609                 iter->i_block[i] += 16;
1610             }
1611             if ((tmp & 0xFF) == 0) {
1612                 tmp >>= 8;
1613                 iter->i_block[i] += 8;
1614             }
1615             if ((tmp & 0xF) == 0) {
1616                 tmp >>= 4;
1617                 iter->i_block[i] += 4;
1618             }
1619             if ((tmp & 0x3) == 0) {
1620                 tmp >>= 2;
1621                 iter->i_block[i] += 2;
1622             }
1623             iter->i_block[i] -= (tmp & 0x1);
1624         }
1625         assert(_IPWILD_BLOCK_IS_SET(iter->ipwild,i,iter->i_block[i]));
1626         return SK_ITERATOR_OK;
1627     }
1628 
1629     /* we're done. make the next call to Next() fail */
1630     iter->no_more_entries = 1;
1631 
1632     return SK_ITERATOR_OK;
1633 }
1634 
1635 
1636 /* Get next entry in tree */
1637 skIteratorStatus_t
skIPWildcardIteratorNext(skIPWildcardIterator_t * iter,skipaddr_t * ipaddr)1638 skIPWildcardIteratorNext(
1639     skIPWildcardIterator_t *iter,
1640     skipaddr_t             *ipaddr)
1641 {
1642     uint32_t prefix;
1643 
1644     return ipwildcardIterNext(iter, ipaddr, &prefix, 0);
1645 }
1646 
1647 
1648 /* get the next CIDR block in the wildcard */
1649 skIteratorStatus_t
skIPWildcardIteratorNextCidr(skIPWildcardIterator_t * iter,skipaddr_t * ipaddr,uint32_t * prefix)1650 skIPWildcardIteratorNextCidr(
1651     skIPWildcardIterator_t *iter,
1652     skipaddr_t             *ipaddr,
1653     uint32_t               *prefix)
1654 {
1655     return ipwildcardIterNext(iter, ipaddr, prefix, 1);
1656 }
1657 
1658 
1659 /* Reset iterator */
1660 void
skIPWildcardIteratorReset(skIPWildcardIterator_t * iter)1661 skIPWildcardIteratorReset(
1662     skIPWildcardIterator_t *iter)
1663 {
1664     int i;
1665 
1666     assert(iter);
1667 
1668 #if SK_ENABLE_IPV6
1669     if (iter->force_ipv4) {
1670         /* must ensure that wildcard contains 0:0:0:0:0:ffff:x:x */
1671         assert(skIPWildcardIsV6(iter->ipwild));
1672         for (i = 0; i < 5; ++i) {
1673             if (!_IPWILD_BLOCK_IS_SET(iter->ipwild, i, 0)) {
1674                 iter->no_more_entries = 1;
1675                 return;
1676             }
1677             assert(0 == iter->ipwild->m_min[i]);
1678             iter->i_block[i] = iter->ipwild->m_min[i];
1679         }
1680         if (!_IPWILD_BLOCK_IS_SET(iter->ipwild, 5, 0xFFFF)) {
1681             iter->no_more_entries = 1;
1682             return;
1683         }
1684         assert(UINT16_MAX == iter->ipwild->m_max[5]);
1685         iter->i_block[5] = iter->ipwild->m_max[5];
1686 
1687         iter->i_block[6] = iter->ipwild->m_min[6];
1688         iter->i_block[7] = iter->ipwild->m_min[7];
1689 
1690         iter->no_more_entries = 0;
1691         return;
1692     }
1693 #endif  /* SK_ENABLE_IPV6 */
1694 
1695     iter->no_more_entries = 0;
1696     for (i = 0; i < iter->ipwild->num_blocks; ++i) {
1697         iter->i_block[i] = iter->ipwild->m_min[i];
1698     }
1699 }
1700 
1701 
1702 /* ******************************************************************** */
1703 /* skcidr_t                                                             */
1704 /* ******************************************************************** */
1705 
1706 
1707 #if SK_ENABLE_IPV6
1708 /* check whether 'ipaddr' is in 'cidr' */
1709 int
skcidrCheckIP(const skcidr_t * cidr,const skipaddr_t * ipaddr)1710 skcidrCheckIP(
1711     const skcidr_t     *cidr,
1712     const skipaddr_t   *ipaddr)
1713 {
1714     uint8_t  ipv6[16];
1715     uint32_t ipv4;
1716 
1717     if (skcidrIsV6(cidr)) {
1718         skipaddrGetAsV6(ipaddr, ipv6);
1719 
1720         return (0 == memcmp(cidr->v6.ip, ipv6, cidr->v6.byte_length)
1721                 && ((0 == cidr->v6.mask)
1722                     || ((cidr->v6.mask & ipv6[cidr->v6.byte_length])
1723                         == cidr->v6.ip[cidr->v6.byte_length])));
1724     }
1725     if (0 == skipaddrGetAsV4(ipaddr, &ipv4)) {
1726         return ((ipv4 & cidr->v4.mask) == cidr->v4.ip);
1727     }
1728     return 0;
1729 }
1730 #endif  /* SK_ENABLE_IPV6 */
1731 
1732 /* Fill 'ipaddr' with the IP address in 'cidr' */
1733 void
skcidrGetIPAddr(const skcidr_t * cidr,skipaddr_t * ipaddr)1734 skcidrGetIPAddr(
1735     const skcidr_t     *cidr,
1736     skipaddr_t         *ipaddr)
1737 {
1738 #if SK_ENABLE_IPV6
1739     if (skcidrIsV6(cidr)) {
1740         skipaddrSetV6(ipaddr, cidr->v6.ip);
1741         return;
1742     }
1743 #endif
1744     skipaddrSetV4(ipaddr, &(cidr->v4.ip));
1745 }
1746 
1747 
1748 /* Fill 'cidr' using the 'ipaddr' and 'cidr_len' */
1749 int
skcidrSetFromIPAddr(skcidr_t * cidr,const skipaddr_t * ipaddr,uint32_t cidr_len)1750 skcidrSetFromIPAddr(
1751     skcidr_t           *cidr,
1752     const skipaddr_t   *ipaddr,
1753     uint32_t            cidr_len)
1754 {
1755 #if SK_ENABLE_IPV6
1756     if (skipaddrIsV6(ipaddr)) {
1757         uint8_t tmp_ip[16];
1758         skipaddrGetV6(ipaddr, tmp_ip);
1759         return skcidrSetV6(cidr, tmp_ip, cidr_len);
1760     }
1761 #endif
1762     return skcidrSetV4(cidr, skipaddrGetV4(ipaddr), cidr_len);
1763 }
1764 
1765 
1766 /* Fill 'cidr' using the 'ipv4' and 'cidr_len' */
1767 int
skcidrSetV4(skcidr_t * cidr,uint32_t ipv4,uint32_t cidr_len)1768 skcidrSetV4(
1769     skcidr_t           *cidr,
1770     uint32_t            ipv4,
1771     uint32_t            cidr_len)
1772 {
1773     if (cidr_len > 32) {
1774         return -1;
1775     }
1776 
1777     skcidrClear(cidr);
1778     cidr->v4.cidr_length = cidr_len;
1779     cidr->v4.mask = ((cidr_len == 32)
1780                      ? UINT32_MAX
1781                      : ~(UINT32_MAX >> cidr_len));
1782     cidr->v4.ip = ipv4 & cidr->v4.mask;
1783     return 0;
1784 }
1785 
1786 
1787 #if SK_ENABLE_IPV6
1788 /* Fill 'cidr' using the 'ipv6' and 'cidr_len' */
1789 int
skcidrSetV6(skcidr_t * cidr,const uint8_t * ipv6,uint32_t cidr_len)1790 skcidrSetV6(
1791     skcidr_t           *cidr,
1792     const uint8_t      *ipv6,
1793     uint32_t            cidr_len)
1794 {
1795     if (cidr_len > 128) {
1796         return -1;
1797     }
1798 
1799     skcidrClear(cidr);
1800     cidr->v6.is_ipv6 = 1;
1801     cidr->v6.cidr_length = cidr_len;
1802     cidr->v6.byte_length = cidr_len >> 3;
1803     cidr->v6.mask = 0xFF & ~(0xFF >> (cidr_len & 0x7));
1804     memcpy(cidr->v6.ip, ipv6, cidr->v6.byte_length);
1805     if (cidr->v6.mask) {
1806         cidr->v6.ip[cidr->v6.byte_length]
1807             = ipv6[cidr->v6.byte_length] & cidr->v6.mask;
1808     }
1809     return 0;
1810 }
1811 #endif  /* SK_ENABLE_IPV6 */
1812 
1813 
1814 /* ******************************************************************** */
1815 /* sockaddr                                                             */
1816 /* ******************************************************************** */
1817 
1818 
1819 /* Fill 'dest' of length 'len' with the address in 'src' */
1820 int
skipaddrToSockaddr(struct sockaddr * dest,size_t len,const skipaddr_t * src)1821 skipaddrToSockaddr(
1822     struct sockaddr    *dest,
1823     size_t              len,
1824     const skipaddr_t   *src)
1825 {
1826     assert(src);
1827     assert(dest);
1828 
1829 #if SK_ENABLE_IPV6
1830     if (skipaddrIsV6(src)) {
1831         struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)dest;
1832         if (len < sizeof(*v6)) {
1833             return -1;
1834         }
1835         memset(v6, 0, sizeof(*v6));
1836         v6->sin6_family = AF_INET6;
1837         skipaddrGetV6(src, v6->sin6_addr.s6_addr);
1838     } else
1839 #endif  /* SK_ENABLE_IPV6 */
1840     {
1841         struct sockaddr_in *v4 = (struct sockaddr_in *)dest;
1842         if (len < sizeof(*v4)) {
1843             return -1;
1844         }
1845         memset(v4, 0, sizeof(*v4));
1846         v4->sin_family = AF_INET;
1847         v4->sin_addr.s_addr = htonl(skipaddrGetV4(src));
1848     }
1849 
1850     return 0;
1851 }
1852 
1853 /* Fill 'dest' with address in 'src' */
1854 int
skipaddrFromSockaddr(skipaddr_t * dest,const struct sockaddr * src)1855 skipaddrFromSockaddr(
1856     skipaddr_t             *dest,
1857     const struct sockaddr  *src)
1858 {
1859     assert(dest);
1860     assert(src);
1861 
1862     switch (src->sa_family) {
1863       case AF_INET:
1864         {
1865             in_addr_t addr;
1866             const struct sockaddr_in *v4 = (const struct sockaddr_in *)src;
1867             addr = ntohl(v4->sin_addr.s_addr);
1868             skipaddrSetV4(dest, &addr);
1869         }
1870         break;
1871 #if SK_ENABLE_IPV6
1872       case AF_INET6:
1873         {
1874             const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)src;
1875             skipaddrSetV6(dest, v6->sin6_addr.s6_addr);
1876         }
1877         break;
1878 #endif
1879       default:
1880         return -1;
1881     }
1882 
1883     return 0;
1884 }
1885 
1886 
1887 int
skSockaddrCompare(const sk_sockaddr_t * a,const sk_sockaddr_t * b,unsigned int flags)1888 skSockaddrCompare(
1889     const sk_sockaddr_t    *a,
1890     const sk_sockaddr_t    *b,
1891     unsigned int            flags)
1892 {
1893     uint16_t pa, pb;
1894     sk_sockaddr_t temp;
1895 
1896     if (a == b) {
1897         return 0;
1898     }
1899     if (a == NULL) {
1900         return -1;
1901     }
1902     if (b == NULL) {
1903         return 1;
1904     }
1905     if (!(flags & SK_SOCKADDRCOMP_NOPORT)) {
1906         switch (a->sa.sa_family) {
1907           case AF_INET:
1908             pa = a->v4.sin_port;
1909             break;
1910           case AF_INET6:
1911             pa = a->v6.sin6_port;
1912             break;
1913           case AF_UNIX:
1914             pa = 0;
1915             break;
1916           default:
1917             skAbortBadCase(a->sa.sa_family);
1918         }
1919         switch (b->sa.sa_family) {
1920           case AF_INET:
1921             pb = b->v4.sin_port;
1922             break;
1923           case AF_INET6:
1924             pb = b->v6.sin6_port;
1925             break;
1926           case AF_UNIX:
1927             pb = 0;
1928             break;
1929           default:
1930             skAbortBadCase(b->sa.sa_family);
1931         }
1932         if (pa < pb) {
1933             return -1;
1934         }
1935         if (pa > pb) {
1936             return 1;
1937         }
1938     }
1939     if (!(flags & SK_SOCKADDRCOMP_NOT_V4_AS_V6)) {
1940         /* If necessary, convert V4 addresses to V6. */
1941         if (a->sa.sa_family == AF_INET6 && b->sa.sa_family == AF_INET) {
1942             temp.sa.sa_family = AF_INET6;
1943             memcpy(temp.v6.sin6_addr.s6_addr,
1944                    sk_ipv6_v4inv6, SK_IPV6_V4INV6_LEN);
1945             memcpy(temp.v6.sin6_addr.s6_addr + SK_IPV6_V4INV6_LEN,
1946                    &b->v4.sin_addr.s_addr, 4);
1947             b = &temp;
1948         } else if (a->sa.sa_family == AF_INET && b->sa.sa_family == AF_INET6) {
1949             temp.sa.sa_family = AF_INET6;
1950             memcpy(temp.v6.sin6_addr.s6_addr,
1951                    sk_ipv6_v4inv6, SK_IPV6_V4INV6_LEN);
1952             memcpy(temp.v6.sin6_addr.s6_addr + SK_IPV6_V4INV6_LEN,
1953                    &a->v4.sin_addr.s_addr, 4);
1954             a = &temp;
1955         }
1956     }
1957     if (a->sa.sa_family < b->sa.sa_family) {
1958         return -1;
1959     }
1960     if (a->sa.sa_family > b->sa.sa_family) {
1961         return 1;
1962     }
1963     if (flags & SK_SOCKADDRCOMP_NOADDR) {
1964         return 0;
1965     }
1966     switch (a->sa.sa_family) {
1967       case AF_INET:
1968         return memcmp(&a->v4.sin_addr.s_addr, &b->v4.sin_addr.s_addr,
1969                       sizeof(a->v4.sin_addr.s_addr));
1970       case AF_INET6:
1971         return memcmp(a->v6.sin6_addr.s6_addr, b->v6.sin6_addr.s6_addr,
1972                       sizeof(a->v6.sin6_addr.s6_addr));
1973       case AF_UNIX:
1974         return strncmp(a->un.sun_path, b->un.sun_path,
1975                        sizeof(a->un.sun_path));
1976       default:
1977         skAbortBadCase(a->sa.sa_family);
1978     }
1979 }
1980 
1981 ssize_t
skSockaddrString(char * buffer,size_t size,const sk_sockaddr_t * addr)1982 skSockaddrString(
1983     char                   *buffer,
1984     size_t                  size,
1985     const sk_sockaddr_t    *addr)
1986 {
1987     /* Must be large enough to hold UNIX domain socket path. */
1988     char sabuf[PATH_MAX];
1989     skipaddr_t ipaddr;
1990     uint16_t port;
1991     ssize_t rv;
1992 
1993     switch (addr->sa.sa_family) {
1994       case AF_INET6:
1995         if (0 == memcmp(addr->v6.sin6_addr.s6_addr, in6addr_any.s6_addr,
1996                         sizeof(addr->v6.sin6_addr.s6_addr)))
1997         {
1998             sabuf[0] = '*';
1999             sabuf[1] = '\0';
2000         } else {
2001 #if SK_ENABLE_IPV6
2002             skipaddrFromSockaddr(&ipaddr, &addr->sa);
2003             skipaddrString(sabuf, &ipaddr, SKIPADDR_CANONICAL);
2004 #elif defined(SK_HAVE_INET_NTOP)
2005             if (NULL == inet_ntop(AF_INET6, &addr->v6.sin6_addr,
2006                                   sabuf, sizeof(sabuf)))
2007             {
2008                 strcpy(sabuf, "<unknown-ipv6>");
2009             }
2010 #else  /* !SK_ENABLE_IPV6 && !defined(SK_HAVE_INET_NTOP) */
2011             strcpy(sabuf, "<unknown-ipv6>");
2012 #endif  /* SK_ENABLE_IPV6 */
2013         }
2014         port = ntohs(addr->v6.sin6_port);
2015         if (port) {
2016             rv = snprintf(buffer, size, ("[%s]:%" PRIu16), sabuf, port);
2017         } else {
2018             rv = snprintf(buffer, size, "%s", sabuf);
2019         }
2020         break;
2021       case AF_INET:
2022         if (addr->v4.sin_addr.s_addr == INADDR_ANY) {
2023             sabuf[0] = '*';
2024             sabuf[1] = '\0';
2025         } else {
2026             skipaddrFromSockaddr(&ipaddr, &addr->sa);
2027             skipaddrString(sabuf, &ipaddr, SKIPADDR_CANONICAL);
2028         }
2029         port = ntohs(addr->v4.sin_port);
2030         if (port) {
2031             rv = snprintf(buffer, size, ("%s:%" PRIu16), sabuf, port);
2032         } else {
2033             rv = snprintf(buffer, size, "%s", sabuf);
2034         }
2035         break;
2036       case AF_UNIX:
2037         rv = snprintf(buffer, size, "%s", addr->un.sun_path);
2038         break;
2039       default:
2040         skAbortBadCase(addr->sa.sa_family);
2041     }
2042 
2043     return rv;
2044 }
2045 
2046 int
skSockaddrArrayContains(const sk_sockaddr_array_t * array,const sk_sockaddr_t * addr,unsigned int flags)2047 skSockaddrArrayContains(
2048     const sk_sockaddr_array_t  *array,
2049     const sk_sockaddr_t        *addr,
2050     unsigned int                flags)
2051 {
2052     uint32_t i;
2053 
2054     if (array == NULL || addr == NULL) {
2055         return 0;
2056     }
2057     for (i = 0; i < skSockaddrArrayGetSize(array); i++) {
2058         if (skSockaddrCompare(skSockaddrArrayGet(array, i),
2059                               addr, flags) == 0)
2060         {
2061             return 1;
2062         }
2063     }
2064 
2065     return 0;
2066 }
2067 
2068 int
skSockaddrArrayEqual(const sk_sockaddr_array_t * a,const sk_sockaddr_array_t * b,unsigned int flags)2069 skSockaddrArrayEqual(
2070     const sk_sockaddr_array_t  *a,
2071     const sk_sockaddr_array_t  *b,
2072     unsigned int                flags)
2073 {
2074     uint32_t i;
2075 
2076     if (a == NULL) {
2077         return b == NULL;
2078     }
2079     if (b == NULL) {
2080         return 0;
2081     }
2082     if (skSockaddrArrayGetSize(a) != skSockaddrArrayGetSize(b)) {
2083         return 0;
2084     }
2085     for (i = 0; i < skSockaddrArrayGetSize(a); i++) {
2086         if (!skSockaddrArrayContains(b, skSockaddrArrayGet(a, i), flags)) {
2087             return 0;
2088         }
2089     }
2090     return 1;
2091 }
2092 
2093 int
skSockaddrArrayMatches(const sk_sockaddr_array_t * a,const sk_sockaddr_array_t * b,unsigned int flags)2094 skSockaddrArrayMatches(
2095     const sk_sockaddr_array_t  *a,
2096     const sk_sockaddr_array_t  *b,
2097     unsigned int                flags)
2098 {
2099     uint32_t i, j;
2100 
2101     if (a == NULL) {
2102         return b == NULL;
2103     }
2104     if (b == NULL) {
2105         return 0;
2106     }
2107     for (i = 0; i < skSockaddrArrayGetSize(a); ++i) {
2108         for (j = 0; j < skSockaddrArrayGetSize(b); ++j) {
2109             if (skSockaddrCompare(skSockaddrArrayGet(a, i),
2110                                   skSockaddrArrayGet(b, j),
2111                                   flags) == 0)
2112             {
2113                 return 1;
2114             }
2115         }
2116     }
2117     return 0;
2118 }
2119 
2120 
2121 /* Deprecated */
2122 size_t
skSockaddrLen(const sk_sockaddr_t * s)2123 skSockaddrLen(
2124     const sk_sockaddr_t    *s)
2125 {
2126     return skSockaddrGetLen(s);
2127 }
2128 
2129 /* Deprecated */
2130 int
skSockaddrPort(const sk_sockaddr_t * s)2131 skSockaddrPort(
2132     const sk_sockaddr_t    *s)
2133 {
2134     return skSockaddrGetPort(s);
2135 }
2136 
2137 /* Deprecated */
2138 const char *
skSockaddrArrayNameSafe(const sk_sockaddr_array_t * s)2139 skSockaddrArrayNameSafe(
2140     const sk_sockaddr_array_t  *s)
2141 {
2142     return skSockaddrArrayGetHostname(s);
2143 }
2144 
2145 /* Deprecated */
2146 const char *
skSockaddrArrayName(const sk_sockaddr_array_t * s)2147 skSockaddrArrayName(
2148     const sk_sockaddr_array_t  *s)
2149 {
2150     return s->name;
2151 }
2152 
2153 /* Deprecated */
2154 uint32_t
skSockaddrArraySize(const sk_sockaddr_array_t * s)2155 skSockaddrArraySize(
2156     const sk_sockaddr_array_t  *s)
2157 {
2158     return skSockaddrArrayGetSize(s);
2159 }
2160 
2161 
2162 /*
2163 ** Local Variables:
2164 ** mode:c
2165 ** indent-tabs-mode:nil
2166 ** c-basic-offset:4
2167 ** End:
2168 */
2169