modules/ip/ip.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- IP_sizebits
- ip_rang_validate
- IP_addr_t2b
- IP_pref_t2b
- IP_revd_t2b
- IP_rang_t2b
- IP_addr_b2_space
- IP_addr_b2v4_addr
- IP_addr_b2v6_hi
- IP_addr_b2v6_lo
- IP_pref_b2_space
- IP_pref_b2_len
- IP_pref_b2v4_addr
- IP_rang_b2_space
- IP_addr_b2v4
- IP_pref_b2v4
- IP_pref_b2v6
- IP_rang_b2v4
- IP_addr_v4_mk
- IP_addr_v6_mk
- IP_pref_v4_mk
- IP_rang_v4_mk
- IP_pref_a2v4
- IP_pref_a2v6
- IP_revd_a2v4
- IP_addr_a2v4
- IP_rang_a2v4
- IP_addr_f2b_v4
- IP_rang_f2b_v4
- IP_pref_f2b_v4
- IP_addr_f2b_v6
- IP_pref_f2b_v6
- IP_addr_s2b
- IP_addr_b2a
- IP_pref_b2a
- IP_rang_b2a
- IP_addr_bit_get
- IP_addr_bit_set
- IP_pref_bit_fix
- IP_addr_cmp
- IP_addr_in_pref
- IP_addr_in_rang
- IP_rang_span
- ad
- IP_rang_decomp
- IP_rang_encomp
- IP_pref_2_rang
- IP_rang_classful
- IP_smart_conv
- IP_smart_range
1 /***************************************
2 $Revision: 1.22 $
3
4 IP handling (ip). ip.c - conversions between ascii and binary forms
5 of IP addresses, prefixes and ranges.
6
7 various operations on binary forms.
8
9 Status: NOT REVUED, TESTED, COMPLETE
10
11 Design and implementation by: Marek Bukowy
12
13 ******************/ /******************
14 Copyright (c) 1999 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33
34 #define IP_IMPL
35 #include <iproutines.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <erroutines.h>
39
40 #include <ctype.h>
41 #include <memwrap.h>
42
43 #include <numconv.h>
44 #include <stubs.h>
45
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48
49 #include <inet6def.h>
50
51 /**************************************************************************/
52 /*+ return the max. length of bits per space
53
54 Yes, it *could* be a macro - but as a function it can detect
55 more programmer's errors. And will get inlined anyway.
56
57 +*/
58
59 int IP_sizebits(ip_space_t spc_id) {
/* [<][>][^][v][top][bottom][index][help] */
60 switch (spc_id) {
61 case IP_V4:
62 return 32;
63 case IP_V6:
64 return 128;
65 default:
66 /* die; */ /* error: bad IP version specified */
67 return -1;
68 }
69 }
70
71 static
72 er_ret_t
73 ip_rang_validate(ip_range_t *rangptr)
/* [<][>][^][v][top][bottom][index][help] */
74 {
75 if( rangptr->begin.space != rangptr->end.space ) {
76 /* die; */ /* incompatible IP spaces */
77 return IP_INVRAN;
78 }
79
80 /* XXX IPv6 missing */
81 if( rangptr->begin.space == IP_V4 ) {
82 if( rangptr->begin.words[0] > rangptr->end.words[0] ) {
83 return IP_INVRAN;
84 }
85 }
86
87 return IP_OK;
88 }
89 /**************************************************************************/
90 /*+
91 ascii IP address to binary.
92
93 In IP_EXPN mode IP will be "expanded"
94 (missing octets will be set to 0, MSB's will be set).
95 In IP_PLAIN mode the routine will complain if it sees less octets.
96
97 why not use the standard inet_blabla routine ?
98 it's because if some octets are missing, we make the address zero-padded
99 (unlike the inet_blabla, which puts zeros in the middle). We also want
100 to control the expansion with a flag.
101
102 +*/
103
104 er_ret_t
105 IP_addr_t2b(ip_addr_t *ipptr, char *addr, ip_exp_t expf)
/* [<][>][^][v][top][bottom][index][help] */
106 {
107 if( index(addr, ':') == NULL ) {
108 /* IPv4 */
109 char *dot=addr;
110 unsigned len, byte, result=0;
111 char cpy[4];
112 int last = 0, dotsfound=0;
113 int bytes=0;
114
115 if( expf != IP_PLAIN && expf != IP_EXPN ) {
116 return IP_INVARG;
117 }
118
119 do {
120 char *olddot = dot+1;
121 /* dot should point to the "end of this number", not necessarily a dot */
122
123 if ( (dot = index (addr, '.')) == NULL) {
124 /* after the ip it can contain lots of junk spaces */
125 while( *olddot != 0 && ! isspace(* (unsigned char *) olddot) ) {
126 olddot++;
127 }
128 dot = olddot;
129 last = 1;
130 }
131 else {
132 if( ++dotsfound > 3 ) {
133 /* handle syntax ERROR - too many dots found */
134 return IP_INVIP4;
135 }
136 }
137
138 if ((len = dot - addr) > 3) {
139 /* syntax ERROR - too many digits in an octet */
140 return IP_INVIP4;
141 }
142 strncpy( cpy, addr, len );
143 cpy[len]=0;
144
145 /* sscanf is waay too slow */
146
147 if( ut_dec_2_uns(cpy, &byte) < 0 ) {
148 /* handle syntax ERROR - invalid characters found */
149 return IP_INVIP4;
150 }
151
152
153 if( byte > 255 ) {
154 /* handle syntax ERROR - number between dots too high */
155 return IP_INVIP4;
156 }
157
158 result <<= 8;
159 result += byte;
160 bytes++;
161
162 addr = dot + 1;
163 } while (!last);
164
165 if( expf == IP_PLAIN ) {
166 if( bytes!=4 ) {
167 return IP_INVIP4;
168 }
169 }
170 else {
171 while( bytes<4 ) {
172 result <<= 8;
173 bytes++;
174 }
175 }
176
177 memset(ipptr, 0, sizeof(ip_addr_t));
178 ipptr->space = IP_V4;
179 ipptr->words[0] = result;
180 }
181 else {
182 /* IPv6 */
183 #define _IPV6_LENGTH 128
184 char addrcpy[_IPV6_LENGTH];
185 char *ch, *start;
186
187 strncpy(addrcpy, addr, _IPV6_LENGTH-1);
188 addrcpy[_IPV6_LENGTH-1] = 0;
189
190 /* get rid of superfluous whitespaces */
191 /* leading... */
192 for( ch = start = addrcpy ; *ch != 0; ch++ ) {
193 if( isspace( (int) *ch) ) {
194 start++;
195 }
196 else {
197 break;
198 }
199 }
200
201 /* and trailing */
202 while( *ch != 0 ) {
203 if( isspace( (int) *ch) ) {
204 *ch = 0;
205 break;
206 }
207 ch++;
208 }
209
210 if( inet_pton(AF_INET6, start, (ipptr->words)) == 0 ) {
211 return IP_NO6YET;
212 }
213
214 ipptr->space = IP_V6;
215
216 #undef _IPV6_LENGTH
217 }
218 return IP_OK;
219 }
220
221 /**************************************************************************/
222
223 /*+ converts a "IP/length" string into a binary prefix
224
225
226
227 +*/
228
229 er_ret_t
230 IP_pref_t2b(ip_prefix_t *prefptr, char *prefstr, ip_exp_t expf)
/* [<][>][^][v][top][bottom][index][help] */
231 {
232 char ip[256];
233 char *trash;
234 char *slash;
235 int len;
236 er_ret_t err;
237
238 if( expf != IP_PLAIN && expf != IP_EXPN ) {
239 return IP_INVARG;
240 }
241
242 if( (slash=index(prefstr, '/')) == NULL ) {
243 /* die; */ /* error: missing slash in prefix */
244 return IP_NOSLAS;
245 }
246 else {
247 /* copy the IP part to another string, ERROR if 256 chars not enough */
248
249 len = slash - prefstr;
250 if( len > 255 ) {
251 /* die; */ /* ERROR - ip address part of the string too long. */
252 return IP_ADTOLO;
253 }
254 strncpy(ip, prefstr, len);
255 ip[len]=0;
256
257 if( (err=IP_addr_t2b( &(prefptr->ip), ip, expf)) != IP_OK) {
258 /* die; */ /* set error flag: incorrect address format */
259 return err;
260 }
261
262 /* stop at first non-digit */
263 for(trash = slash+1;
264 isdigit(* (unsigned char*) trash); /* cast for stupid gcc */
265 trash++)
266 ;
267 len = trash - (slash+1) ;
268 if( len > 4 ) {
269 /* die; */ /* ERROR - prefix length part of the string too long. */
270 return IP_PRTOLO;
271 }
272 strncpy(ip, slash+1, len);
273 ip[len]=0;
274
275 if( ut_dec_2_uns(ip, &prefptr->bits) < 0
276 || prefptr->bits > IP_sizebits(prefptr->ip.space))
277 {
278 /* if( sscanf (slash+1, "%d", &(prefptr->bits)) < 1 ) {
279 die; */ /* handle syntax ERROR invalid characters found */
280 return IP_INVPRF;
281 }
282 }
283 /* sanitify the prefix - maybe some irrelevant bits are set */
284 /* never create broken binary prefixes. */
285
286 IP_pref_bit_fix(prefptr);
287
288 return IP_OK;
289 }
290
291 /**************************************************************************/
292
293 /*+ converts an inaddr/ip6int string into a binary prefix.
294 no distinction is made with respect to "expand" argument.
295 +*/
296 er_ret_t
297 IP_revd_t2b(ip_prefix_t *prefptr, char *prefstr, ip_exp_t expf)
/* [<][>][^][v][top][bottom][index][help] */
298 {
299 char ip[256], temp[256];
300 char *arpa;
301 int len, octets=0, goon=1;
302 char *dot;
303 er_ret_t err;
304
305 dieif( expf != IP_PLAIN && expf != IP_EXPN );
306
307 if( (arpa=strstr(prefstr, ".in-addr.arpa")) == NULL ) {
308
309 #if 0 /* XXX not yet implemented */
310 if( (arpa=strstr(prefstr, ".ip6.int")) != NULL ) {
311 /* ipv6 */
312 }
313 #endif
314
315 return IP_NOREVD;
316 }
317 else {
318 /* copy the IP part to another string, ERROR if 256 chars not enough */
319 len = arpa - prefstr;
320 if( len > 255 ) {
321 /* die; */ /* ERROR - ip address part of the string too long. */
322 return IP_ADTOLO;
323 }
324 strncpy(temp, prefstr, len);
325 temp[len]=0;
326
327 /* now : get the octets reversed one by one. */
328 ip[0]=0; /* init */
329 do {
330 if( (dot = strrchr( temp, '.' )) == NULL ) {
331 goon = 0;
332 dot = temp;
333 }
334
335 strcat(ip, dot + ( goon ) );
336 octets++;
337
338 /* add a dot, unless that was the last octet */
339 if( goon ) {
340 strcat(ip, ".");
341 }
342
343 *dot = 0;
344
345 } while( goon );
346
347 if( (err=IP_addr_t2b( &(prefptr->ip), ip, IP_EXPN)) != IP_OK) {
348 /* die; */ /* set error flag: incorrect address format */
349 return err;
350 }
351
352 prefptr->bits = octets * 8;
353 }
354 return IP_OK;
355 }
356
357 /**************************************************************************/
358
359 /*+ convert a range string into a binary range struct.
360 +*/
361 er_ret_t
362 IP_rang_t2b(ip_range_t *rangptr, char *rangstr, ip_exp_t expf)
/* [<][>][^][v][top][bottom][index][help] */
363 {
364 char *ips, *dash;
365 er_ret_t err;
366
367 if( expf != IP_PLAIN && expf != IP_EXPN ) {
368 return IP_INVARG;
369 }
370
371 if( (dash=index(rangstr, '-')) == NULL ) {
372 /* die; */ /* error: missing dash in range */
373 return IP_INVRAN;
374 }
375 else {
376 /* copy the first IP */
377 if( (err = wr_calloc( (void*) &ips,1,dash - rangstr + 1)) != UT_OK ) {
378 return err;
379 }
380
381 strncpy(ips, rangstr, dash - rangstr);
382
383 /* convert the first IP into a binary struct */
384 err=IP_addr_t2b( &(rangptr->begin), ips, expf);
385
386 /* check later */ /* set error flag: incorrect address format */
387
388 wr_free(ips);
389
390 if( err != IP_OK ) {
391 return err;
392 }
393
394 /* now find the other ip, skip the space */
395 ips=dash+1;
396 while( *ips == ' ' ) {
397 ips++;
398 }
399
400 /* convert the second IP into a binary struct */
401 if( (err=IP_addr_t2b( &(rangptr->end), ips, expf)) != IP_OK ) {
402 /* die; */ /* incorrect address format */
403 return err;
404 }
405
406
407
408 return ip_rang_validate(rangptr);
409 }
410 }
411
412
413 /**************************************************************************/
414 /* accessor functions */
415
416 /******** address **********/
417
418 unsigned IP_addr_b2_space(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
419 {
420 return addrptr->space;
421 }
422
423 unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
424 {
425 dieif( addrptr->space != IP_V4 );
426 return addrptr->words[0];
427 }
428 /* ipv4 */
429
430 ip_v6word_t IP_addr_b2v6_hi(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
431 {
432 dieif( addrptr->space != IP_V6 );
433 return ( (((ip_v6word_t) addrptr->words[0]) << 32)
434 + (((ip_v6word_t) addrptr->words[1]) ));
435 }
436
437 ip_v6word_t IP_addr_b2v6_lo(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
438 {
439 dieif( addrptr->space != IP_V6 );
440 return ( (((ip_v6word_t) addrptr->words[2]) << 32)
441 + (((ip_v6word_t) addrptr->words[3]) ));
442 }
443
444 /******** prefix **********/
445
446 unsigned IP_pref_b2_space(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
447 return IP_addr_b2_space( &(prefix->ip) );
448 }
449
450 unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
451 return prefix->bits;
452 }
453
454 unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
455 return IP_addr_b2v4_addr( &(prefix->ip) );
456 }
457
458 /* range */
459
460 unsigned IP_rang_b2_space(ip_range_t *myrang) {
/* [<][>][^][v][top][bottom][index][help] */
461 /* hardwire to IPV4 for now */
462 return IP_V4;
463 }
464
465 /*
466 * complex conversions (return void, set values through pointers *
467 */
468 void IP_addr_b2v4(ip_addr_t *addrptr, unsigned *address) {
/* [<][>][^][v][top][bottom][index][help] */
469 *address = IP_addr_b2v4_addr(addrptr);
470 }
471
472 void IP_pref_b2v4(ip_prefix_t *prefptr,
/* [<][>][^][v][top][bottom][index][help] */
473 unsigned int *prefix,
474 unsigned int *prefix_length)
475 {
476 *prefix = IP_addr_b2v4_addr( &(prefptr->ip));
477 *prefix_length = IP_pref_b2v4_len(prefptr);
478 }
479
480
481
482 void IP_pref_b2v6(ip_prefix_t *prefptr,
/* [<][>][^][v][top][bottom][index][help] */
483 ip_v6word_t *high,
484 ip_v6word_t *low,
485 unsigned int *prefix_length)
486 {
487 *high = IP_addr_b2v6_hi( &(prefptr->ip));
488 *low = IP_addr_b2v6_lo( &(prefptr->ip));
489 *prefix_length = IP_pref_b2v6_len(prefptr);
490 }
491
492
493 void IP_rang_b2v4(ip_range_t *myrang,
/* [<][>][^][v][top][bottom][index][help] */
494 unsigned *begin,
495 unsigned *end)
496 {
497 *begin = IP_addr_b2v4_addr( &(myrang->begin));
498 *end = IP_addr_b2v4_addr( &(myrang->end));
499 }
500
501
502
503 /******** construct from raw values **********/
504
505 /******** address **********/
506 er_ret_t IP_addr_v4_mk(ip_addr_t *addrptr,
/* [<][>][^][v][top][bottom][index][help] */
507 unsigned addrval) {
508 addrptr->space = IP_V4;
509 addrptr->words[0] = addrval;
510 addrptr->words[1] = addrptr->words[2] = addrptr->words[3] = 0;
511
512 /* no real possibility of checking the syntax */
513 return IP_OK;
514 }
515
516 er_ret_t IP_addr_v6_mk(ip_addr_t *addrptr,
/* [<][>][^][v][top][bottom][index][help] */
517 ip_v6word_t high,
518 ip_v6word_t low) {
519
520 ip_v6word_t ff = 0xffffffff;
521
522 addrptr->space = IP_V6;
523 (addrptr->words[0]) = (high >> 32) & ff;
524 (addrptr->words[1]) = high & ff ;
525 (addrptr->words[2]) = (low >> 32) & ff;
526 (addrptr->words[3]) = low & ff;
527
528 /* no real possibility of checking the syntax */
529 return IP_OK;
530 }
531
532 /******** prefix **********/
533 er_ret_t IP_pref_v4_mk(ip_prefix_t *prefix,
/* [<][>][^][v][top][bottom][index][help] */
534 unsigned prefval,
535 unsigned preflen)
536 {
537 if( preflen > 32 ) {
538 die;
539 }
540 IP_addr_v4_mk(&(prefix->ip), prefval);
541 prefix->bits = preflen;
542
543 IP_pref_bit_fix( prefix ); /* never produce inconsistent prefixes */
544
545 return IP_OK;
546 }
547
548 /******** range **********/
549 er_ret_t IP_rang_v4_mk(ip_range_t *rangptr,
/* [<][>][^][v][top][bottom][index][help] */
550 unsigned addrbegin,
551 unsigned addrend)
552 {
553 er_ret_t err;
554
555 if( (err=IP_addr_v4_mk( &(rangptr->begin), addrbegin)) == IP_OK ) {
556 err=IP_addr_v4_mk( &(rangptr->end), addrend);
557 }
558 return err;
559 }
560
561 /**************************************************************************/
562
563
564 /**************************************************************************/
565 /*+ a2v4 == functions to convert the ascii representation into binary,
566 * and then set the unsigned values at the pointers provided.
567 *
568 +*/
569
570 /* Convert route string into numbers */
571 /* ipv4 */
572 er_ret_t
573 IP_pref_a2v4(char *avalue, ip_prefix_t *pref,
/* [<][>][^][v][top][bottom][index][help] */
574 unsigned *prefix, unsigned *prefix_length)
575 {
576
577 er_ret_t ret;
578
579 if((ret = IP_pref_e2b(pref, avalue)) == IP_OK) {
580 IP_pref_b2v4(pref, prefix, prefix_length);
581 }
582 return(ret);
583 }
584
585 /* ipv6 */
586 er_ret_t
587 IP_pref_a2v6(char *avalue, ip_prefix_t *pref,
/* [<][>][^][v][top][bottom][index][help] */
588 ip_v6word_t *high, ip_v6word_t *low,
589 unsigned *prefix_length)
590 {
591 er_ret_t ret;
592
593 if((ret = IP_pref_e2b(pref, avalue)) == IP_OK) {
594 IP_pref_b2v6(pref, high, low, prefix_length);
595 }
596 return(ret);
597 }
598
599 /* Convert reverse domain string into numbers */
600 er_ret_t
601 IP_revd_a2v4(char *avalue, ip_prefix_t *pref,
/* [<][>][^][v][top][bottom][index][help] */
602 unsigned int *prefix, unsigned int *prefix_length)
603 {
604 er_ret_t ret;
605
606 if((ret = IP_revd_e2b(pref, avalue)) == IP_OK) {
607 IP_pref_b2v4(pref, prefix, prefix_length);
608 }
609 return(ret);
610 }
611
612 /* Convert ip addr string into numbers */
613 er_ret_t
614 IP_addr_a2v4(char *avalue,ip_addr_t *ipaddr, unsigned int *address)
/* [<][>][^][v][top][bottom][index][help] */
615 {
616 er_ret_t ret;
617
618 if((ret = IP_addr_e2b(ipaddr, avalue)) == IP_OK) {
619 IP_addr_b2v4(ipaddr, address);
620 }
621 return(ret);
622 }
623
624 /* Convert inetnum attribute into numbers */
625 er_ret_t
626 IP_rang_a2v4(char *rangstr, ip_range_t *myrang,
/* [<][>][^][v][top][bottom][index][help] */
627 unsigned int *begin_in, unsigned int *end_in)
628 {
629 er_ret_t ret;
630
631 if( (ret=IP_rang_e2b(myrang, rangstr)) == IP_OK ) {
632 #if 0 /* no IPv4 classful ranges anymore */
633 if( IP_addr_e2b( &(myrang->begin), rangstr ) == IP_OK )
634 if ((ret=IP_rang_classful( myrang , &(myrang->begin))) == IP_OK )
635 ;
636 #endif
637 IP_rang_b2v4(myrang, begin_in, end_in);
638 }
639
640 return (ret);
641 }
642
643
644 /* *********************************************************************
645 f2b - free numbers represented in ascii into a binary struct
646 ********************************************************************* */
647
648 er_ret_t
649 IP_addr_f2b_v4(ip_addr_t *addrptr, char *adrstr)
/* [<][>][^][v][top][bottom][index][help] */
650 {
651 unsigned address;
652
653 if( ut_dec_2_uns(adrstr, &address) < 0 ) {
654 return IP_INVARG;
655 }
656
657 return IP_addr_v4_mk(addrptr, address);
658 }
659
660 er_ret_t
661 IP_rang_f2b_v4(ip_range_t *rangptr, char *beginstr, char *endstr)
/* [<][>][^][v][top][bottom][index][help] */
662 {
663 if( IP_addr_f2b_v4( &(rangptr->begin), beginstr) != IP_OK
664 || IP_addr_f2b_v4( &(rangptr->end), endstr) != IP_OK) {
665 return IP_INVARG;
666 }
667 else {
668 return IP_OK;
669 }
670 }
671
672 er_ret_t
673 IP_pref_f2b_v4(ip_prefix_t *prefptr, char *prefixstr, char *lengthstr)
/* [<][>][^][v][top][bottom][index][help] */
674 {
675 if( IP_addr_f2b_v4( &(prefptr->ip), prefixstr) != IP_OK
676 || ut_dec_2_uns(lengthstr, &(prefptr->bits) ) < 0
677 || prefptr->bits > IP_sizebits(prefptr->ip.space)) {
678 return IP_INVARG;
679 }
680 IP_pref_bit_fix(prefptr); /* never create broken binary prefixes. */
681 return IP_OK;
682 }
683
684
685 er_ret_t
686 IP_addr_f2b_v6(ip_addr_t *addrptr, char *msbstr, char *lsbstr )
/* [<][>][^][v][top][bottom][index][help] */
687 {
688 ip_v6word_t high, low;
689
690 if( sscanf(msbstr, "%llu", &high) < 1 ||
691 sscanf(lsbstr, "%llu", &low) < 1 ) {
692 return IP_INVARG;
693 }
694
695 return IP_addr_v6_mk(addrptr, high, low);
696 }
697
698
699 er_ret_t
700 IP_pref_f2b_v6(ip_prefix_t *prefptr, char *msbstr, char *lsbstr, char *lengthstr)
/* [<][>][^][v][top][bottom][index][help] */
701 {
702 if( IP_addr_f2b_v6( &(prefptr->ip), msbstr, lsbstr ) != IP_OK
703 || ut_dec_2_uns(lengthstr, &(prefptr->bits) ) < 0
704 || prefptr->bits > IP_sizebits(prefptr->ip.space)) {
705 return IP_INVARG;
706 }
707 IP_pref_bit_fix(prefptr); /* never create broken binary prefixes. */
708 return IP_OK;
709 }
710
711
712 /**************************************************************************/
713 /*+ convert the socket's idea of address into a binary range struct.
714
715 space select the address type (and consequently struct type)
716 */
717
718 er_ret_t
719 IP_addr_s2b(ip_addr_t *addrptr,
/* [<][>][^][v][top][bottom][index][help] */
720 void *addr_in,
721 int addr_len)
722 {
723 if( addr_len == sizeof(struct sockaddr_in)
724 && ((struct sockaddr_in *)addr_in)->sin_family == AF_INET ) {
725 addrptr->space = IP_V4;
726 addrptr->words[0] =
727 ntohl( ((struct sockaddr_in*)addr_in)->sin_addr.s_addr);
728
729 /* set remaining limbs to zero */
730 addrptr->words[1] = addrptr->words[2] = addrptr->words[3] = 0;
731
732 }
733 else { /* unsupported family or invalid struct */
734 die;
735 }
736 return IP_OK;
737 }
738
739 /**************************************************************************/
740 /*+converts the IP binary address (binaddr) to a string (ascaddr)
741 of at most strmax characters. Independent of the result
742 (success or failure) it messes up the string.
743 +*/
744 er_ret_t
745 IP_addr_b2a( ip_addr_t *binaddr, char *ascaddr, int strmax )
/* [<][>][^][v][top][bottom][index][help] */
746 {
747
748 if(binaddr->space == IP_V4) {
749 if (snprintf(ascaddr, strmax, "%d.%d.%d.%d",
750 ((binaddr->words[0]) & ((unsigned)0xff<<24))>>24,
751 ((binaddr->words[0]) & (0xff<<16))>>16,
752 ((binaddr->words[0]) & (0xff<<8))>>8,
753 ((binaddr->words[0]) & (0xff<<0))>>0
754 ) >= strmax) {
755 /*die; */ /* string too short */
756 return IP_TOSHRT;
757 }
758 }
759 else {
760 /* IPv6 */
761
762 if( inet_ntop(AF_INET6, &(binaddr->words[0]), ascaddr, strmax)
763 == NULL ) {
764 return IP_TOSHRT;
765 }
766
767 /* not yet implemented. Sorry. */
768 /* die; */
769 /*return IP_NO6YET;*/
770 }
771 return IP_OK;
772 }
773
774 /**************************************************************************/
775
776 /*+ convert a binary prefix back into ascii string at most strmax chars long
777 +*/
778 er_ret_t
779 IP_pref_b2a(ip_prefix_t *prefptr, char *ascaddr, int strmax)
/* [<][>][^][v][top][bottom][index][help] */
780 {
781 int strl;
782 er_ret_t err;
783
784 if( (err=IP_addr_b2a (&(prefptr->ip), ascaddr, strmax)) != IP_OK) {
785 /*die; */ /* what the hell */
786 return err;
787 }
788 strl = strlen(ascaddr);
789 strmax -= strl;
790
791 /* now strmax holds the space that is left */
792
793 if( snprintf(ascaddr+strl, strmax, "/%d", prefptr->bits) >= strmax) {
794 /* die; */ /* error: string too short */
795 return IP_TOSHRT;
796 }
797 return IP_OK;
798 }
799
800
801
802 /**************************************************************************/
803 /*+ convert a binary range back into ascii string at most strmax chars long
804 +*/
805 er_ret_t
806 IP_rang_b2a(ip_range_t *rangptr, char *ascaddr, int strmax)
/* [<][>][^][v][top][bottom][index][help] */
807 {
808 int strl=0, strleft;
809 er_ret_t err;
810
811 strleft = strmax - strl;
812 if( (err=IP_addr_b2a (&(rangptr->begin), ascaddr, strleft)) != IP_OK) {
813 return err;
814 }
815 strl = strlen(ascaddr);
816
817 strleft = strmax - strl;
818 if( strleft < 5 ) {
819 return IP_TOSHRT;
820 }
821 strcat( ascaddr, " - " );
822 strl += 3;
823
824 strleft = strmax - strl;
825 if( (err=IP_addr_b2a (&(rangptr->end), ascaddr+strl, strleft)) != IP_OK) {
826 return err;
827 }
828
829 return IP_OK;
830 }
831
832 /**************************************************************************/
833 /*+ return the bitnum bit of the address,
834 COUNTING FROM THE TOP !!!!! ,
835 starting with 0 for the *most significant bit*.
836 +*/
837 int
838 IP_addr_bit_get(ip_addr_t *binaddr, int bitnum) {
/* [<][>][^][v][top][bottom][index][help] */
839 int bitval;
840 int w,c;
841
842 /* avoid unnecessary division */
843 if( binaddr->space == IP_V4 ) {
844 w = 0;
845 c = bitnum;
846 }
847 else {
848 w = bitnum / 32;
849 c = bitnum % 32;
850 }
851
852 bitval = (binaddr->words[w] & (0x80000000 >> (c)));
853
854 return (bitval != 0);
855
856 }
857
858 /**************************************************************************/
859 /*+ set the bitnum bit of the address to bitval,
860 COUNTING FROM THE TOP !!!!! ,
861 starting with 0 for the *most significant bit*.
862 +*/
863 void
864 IP_addr_bit_set(ip_addr_t *binaddr, int bitnum, int bitval) {
/* [<][>][^][v][top][bottom][index][help] */
865 int w,c;
866
867 /* avoid unnecessary division */
868 if( binaddr->space == IP_V4 ) {
869 w = 0;
870 c = bitnum;
871 }
872 else {
873 w = bitnum / 32;
874 c = bitnum % 32;
875 }
876
877 if ( bitval == 1 )
878
879 binaddr->words[w] |= (0x80000000 >> (c));
880 else
881 binaddr->words[w] &= ~(0x80000000 >> (c));
882 }
883 /**************************************************************************/
884
885 /*+ this fixes a prefix by setting insignificant bits to 0 +*/
886 void
887 IP_pref_bit_fix( ip_prefix_t *prefix )
/* [<][>][^][v][top][bottom][index][help] */
888 {
889
890 if( prefix->ip.space == IP_V4 ) {
891 ip_limb_t mask = 0xffffffff;
892
893 /* shorthand for ipv4 */
894
895 /* Shifting out by 32 bits does NOT turn all bits into 0... */
896 if( prefix->bits < 32 ) {
897 prefix->ip.words[0] &= ~(mask >> prefix->bits);
898 }
899 }
900 else {
901 int i;
902 for(i=prefix->bits; i < IP_sizebits(prefix->ip.space) ; i++) {
903 IP_addr_bit_set( & prefix->ip, i, 0);
904 }
905 }
906 }
907
908
909 /**************************************************************************/
910
911 /*+ compares two IP addresses up to the bit # len,
912 returns 0 if equal, 1 if ptra greater, -1 if ptrb greater.
913
914 It is the responsility of the caller to ensure that both addresses
915 are from the same IP space.
916
917 This is pretty slow; it is used in the searches of the radix tree,
918 so it might be good to optimise this.
919 +*/
920
921 int
922 IP_addr_cmp(ip_addr_t *ptra, ip_addr_t *ptrb, int len)
/* [<][>][^][v][top][bottom][index][help] */
923 {
924 int a,b,i;
925
926 for(i=0; i<len; i++) {
927 a=IP_addr_bit_get(ptra, i);
928 b=IP_addr_bit_get(ptrb, i);
929 if( a != b ) {
930 if( a > b ) return 1;
931 else return -1;
932 }
933 }
934 return 0;
935 }
936
937
938 /*+ checks if an IP address is contained within the prefix
939 returns 1 if it is, 0 otherwise
940
941 It is the responsility of the caller to ensure that both address
942 and prefix are from the same IP space.
943 +*/
944 int
945 IP_addr_in_pref(ip_addr_t *ptra, ip_prefix_t *prefix)
/* [<][>][^][v][top][bottom][index][help] */
946 {
947 return (IP_addr_cmp( ptra, & prefix->ip, prefix->bits) == 0);
948 }
949
950 /*+ checks if an IP address is contained within the range
951 returns 1 if it is, 0 otherwise
952
953 It is the responsility of the caller to ensure that both address
954 and range are from the same IP space.
955
956 works only for IPv4
957 +*/
958
959 int IP_addr_in_rang(ip_addr_t *ptra, ip_range_t *rangptr)
/* [<][>][^][v][top][bottom][index][help] */
960 {
961 /* if( rangptr->end.space == IP_V4 ) {
962 return ( rangptr->begin.words[0] <= ptra->words[0]
963 && rangptr->end.words[0] >= ptra->words[0] );
964 }
965 else {
966 */
967 return( IP_addr_cmp(ptra, &rangptr->begin,
968 IP_sizebits(rangptr->end.space)) >= 0 /* adr >= begin */
969 && IP_addr_cmp(ptra, &rangptr->end,
970 IP_sizebits(rangptr->end.space)) <= 0 /* adr <= end */
971 );
972 /* }*/
973 }
974
975 /**************************************************************************/
976
977 /*+ calculate the span of a range == size - 1 +*/
978
979 ip_rangesize_t
980 IP_rang_span( ip_range_t *rangptr )
/* [<][>][^][v][top][bottom][index][help] */
981 {
982 /* IPv4: */
983 dieif( rangptr->end.space != IP_V4 );
984
985 return rangptr->end.words[0] - rangptr->begin.words[0];
986 }
987
988
989 /**************************************************************************/
990
991 /*+
992 this is a shorthand notation to pull out the first word of the address.
993 it is defined for the scope od the following functions
994 +*/
995 #define ad(which) (rangptr->which)
/* [<][>][^][v][top][bottom][index][help] */
996
997 /**************************************************************************/
998 /*+ Decomposes a binary range into prefixes and appends them to the list.
999 Allocates prefix structures and list elements, they must be freed
1000 after use.
1001
1002 returns a bitmask of prefix lengths used.
1003 +*/
1004 unsigned
1005 IP_rang_decomp(ip_range_t *rangptr, GList **preflist)
/* [<][>][^][v][top][bottom][index][help] */
1006 {
1007 unsigned prefmask=0;
1008 register int slash=0;
1009 register unsigned c_dif, blk, ff;
1010 ip_range_t workrange;
1011 ip_addr_t workbegin;
1012 ip_addr_t workend;
1013 ip_prefix_t *prefptr;
1014
1015 dieif( rangptr->begin.space != IP_V4 );
1016
1017 if( ad(begin).words[0] > ad(end).words[0] ) { /* has gone too far */
1018 return 0;
1019 }
1020
1021 if( ad(begin).words[0] == ad(end).words[0] ) { /* an IP == a /32 (IPv4) */
1022 prefmask |= 1;
1023 if( wr_calloc( (void **)& prefptr, sizeof(ip_prefix_t), 1) != UT_OK) {
1024 die;
1025 }
1026 prefptr->ip = ad(begin);
1027 prefptr->bits = 32;
1028
1029 *preflist = g_list_append( *preflist, prefptr );
1030
1031 return prefmask;
1032 }
1033
1034 c_dif = ad(end).words[0] - ad(begin).words[0];
1035
1036 /* initialize work vars */
1037
1038 workbegin = ad(begin);
1039 workend = ad(end);
1040
1041 /* now find the biggest block fitting in this range */
1042 /* i.e. the first 2^n number smaller than c_dif */
1043
1044 /* the loop would not work for /0 (some stupid queries may have that) */
1045 /* so this must be checked for separately */
1046
1047 if( c_dif == 0xffffffff ) {
1048 /* they are already set to 0.0.0.0 - 255.255.255.255 */
1049 /* leave them alone. */
1050 blk = 0;
1051 slash = 0;
1052 }
1053 else {
1054
1055 c_dif += 1; /* was not done earlier to protect from overflow */
1056
1057 for(slash=1;
1058 slash<32 && ((blk=((unsigned)0x80000000>>(slash-1))) & c_dif) == 0;
1059 slash++) {}
1060
1061 /* clear all digits in a and b under the blk one. */
1062 ff=blk-1;
1063
1064 workbegin.words[0] = (workbegin.words[0] + ff) & ~ff;
1065
1066 workend.words[0] = (workend.words[0] + 1) & ~ff;
1067 }
1068
1069 if( workbegin.words[0] != workend.words[0] ) {
1070 prefmask |= blk;
1071 if( wr_malloc( (void **)& prefptr, sizeof(ip_prefix_t)) != UT_OK) {
1072 die;
1073 }
1074 prefptr->ip = workbegin;
1075 prefptr->bits = slash;
1076
1077 *preflist = g_list_append( *preflist, prefptr );
1078 }
1079
1080 if( ad(begin).words[0] != workbegin.words[0] ) {
1081 workrange.begin = ad(begin);
1082
1083 workbegin.words[0] -= 1;
1084 workrange.end = workbegin;
1085
1086 prefmask |= IP_rang_decomp( &workrange, preflist );
1087 }
1088
1089 /* here we must protect from decomposition of
1090 * 255.255.255.255 - 255.255.255.255 in case the range
1091 * 0.0.0.0 - 255.255.255.255 is considered. Hence the slash>0 condition.
1092 */
1093
1094 if( workend.words[0] <= ad(end).words[0] && slash > 0) {
1095 workrange.begin = workend;
1096 workrange.end = ad(end);
1097
1098 prefmask |= IP_rang_decomp( &workrange, preflist );
1099 }
1100
1101 return prefmask;
1102
1103 }
1104
1105
1106 /***************************************************************************/
1107
1108 /*+ Similar name, slightly different code, totally different functionality.
1109
1110 finds the smallest canonical block encompassing the whole given range,
1111 then MODIFIES the range pointed to by the argument
1112 so that it's equal to this block.
1113
1114 +*/
1115
1116 void IP_rang_encomp(ip_range_t *rangptr)
/* [<][>][^][v][top][bottom][index][help] */
1117 {
1118 int slash=0;
1119 unsigned c_dif, blk, ff, t_dif;
1120 ip_addr_t workbegin;
1121 ip_addr_t workend;
1122
1123 dieif( rangptr->begin.space != IP_V4 );
1124
1125 c_dif = ad(end).words[0] - ad(begin).words[0];
1126
1127 /* now find the biggest block fitting in this range */
1128 /* i.e. the first 2^n number smaller than c_dif */
1129
1130 /* the loop would not work for /0 (some stupid queries may have that) */
1131 /* so this must be checked for separately */
1132
1133 if( c_dif > 0x80000000 ) {
1134 slash = 0;
1135 ff = 0xffffffff;
1136 blk = 0;
1137
1138 workbegin = workend = ad(begin);
1139 workbegin.words[0] = 0;
1140 workend.words[0] = ff;
1141 }
1142 else {
1143
1144 do {
1145 c_dif += 1;
1146
1147 /* find the smallest block ENCOMPASSING c_dif. */
1148 /* this implies a loop from the bottom up */
1149
1150 for(slash=32;
1151 slash>1 && (blk=((unsigned)0x80000000>>(slash-1))) < c_dif;
1152 slash--) {}
1153
1154 ff=blk-1;
1155
1156 /* clear all digits in workbegin under the blk one. */
1157
1158 workbegin = ad(begin);
1159 workbegin.words[0] = workbegin.words[0] & ~ff;
1160
1161 /* see if it has not made the difference larger than blk, */
1162 /* retry if so */
1163
1164 t_dif = c_dif;
1165 c_dif = ad(end).words[0] - workbegin.words[0];
1166
1167 } while( c_dif >= t_dif );
1168
1169 /* set the endpoint to workbegin + blocksize - 1 */
1170 /* which amounts to + ff */
1171
1172 workend = ad(begin);
1173 workend.words[0] = workbegin.words[0] + ff;
1174 }
1175
1176
1177 /* set the range to new values */
1178
1179 rangptr->begin = workbegin;
1180 rangptr->end = workend;
1181 }
1182
1183 /***************************************************************************/
1184 /*+ sets a range equal to a prefix +*/
1185
1186 er_ret_t
1187 IP_pref_2_rang( ip_range_t *rangptr, ip_prefix_t *prefptr )
/* [<][>][^][v][top][bottom][index][help] */
1188 {
1189 ip_rangesize_t span;
1190 int shift;
1191 int i;
1192
1193 ad(begin) = ad(end) = prefptr->ip;
1194
1195 /* IPv6 is a bit more complicated, as four words are involved */
1196
1197 /* additional problem: shifting right by >=32 is equal to shifting by 0,
1198 so it does not change any bits */
1199 /* solution: don't touch those words */
1200
1201 for(i=0; i<4; i++) {
1202
1203 if( prefptr->bits < 32*(1+i) ) {
1204 shift = prefptr->bits < 32 + (i-1) * 32
1205 ? 0 : (prefptr->bits % 32) ;
1206 ad(end).words[i] |= (0xffffffffU >> shift);
1207 }
1208
1209 if( prefptr->ip.space == IP_V4) {
1210 break; /* do only first word for IPv4 */
1211 }
1212 }
1213 return IP_OK;
1214 }
1215
1216 #undef ad
1217
1218 /***************************************************************************/
1219
1220 /*+
1221 This is to parse a classfull address into a range.
1222
1223 Takes the address by pointer from addrptr and puts the result
1224 at rangptr.
1225
1226 Throws error if the address does not fall into any of the
1227 classfull categories
1228
1229 +*/
1230
1231 er_ret_t
1232 IP_rang_classful( ip_range_t *rangptr, ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
1233 {
1234 int i;
1235 unsigned b[4];
1236
1237 if( addrptr->space != IP_V4 ) {
1238 /* it's IPv6. There are no classful ranges or anything like that. */
1239 die;
1240 }
1241
1242 rangptr->begin = *addrptr;
1243 rangptr->end.space = IP_V4;
1244
1245 /* initisalise end to zero */
1246 for(i=0; i<IPLIMBNUM; i++) {
1247 rangptr->end.words[i] = 0;
1248 }
1249
1250 /* assume it's at least a valid IP. let's try different classes now */
1251
1252 /* we could have used a union here, but it would not work on */
1253 /* low endians. So byte by byte copying to and from an array. */
1254
1255 for(i=0; i<4; i++) {
1256 b[i] = ( rangptr->begin.words[0] & (0xFF << i*8) ) >> i*8;
1257 }
1258
1259 if( b[3] >= 1 && b[3] < 128
1260 && b[2] == 0 && b[1] == 0 && b[0] == 0 ) {
1261 b[2]=b[1]=b[0]=255;
1262 }
1263 else if( b[3] >= 128 && b[3] < 192
1264 && b[1] == 0 && b[0] == 0 ) {
1265 b[1]=b[0]=255;
1266 }
1267 else if( b[3] >= 192 && b[3] < 224
1268 && b[0] == 0 ) {
1269 b[0]=255;
1270 }
1271 else if( b[3] >= 224 && b[3] < 255 ) {
1272 /* just leave it, make it a /32, i.e. begin == end */
1273 /* EMPTY */;
1274 }
1275 else {
1276 /* Leave it and make it a /32 */
1277 /* This is AGAINST the rule! but we have some junk */
1278 /* so we have to compensate for it. */
1279 /* EMPTY */;
1280 }
1281
1282 /* copy the (now - modified) bytes into the end of range */
1283 for(i=0; i<4; i++) {
1284 rangptr->end.words[0] |= (b[i] << i*8);
1285 }
1286
1287 return IP_OK;
1288 }
1289
1290
1291 /***************************************************************************/
1292 /*+
1293 Trying to be smart :-) and convert a query search term into prefix(es),
1294 regardless of whether specified as IP address, prefix or range.
1295
1296 justcheck - if just checking the syntax (justcheck == 1),
1297 then the prefixes are freed before the function returns,
1298 otherwise it is the responsibility of the caller to free the list.
1299
1300 XXX must make sure all memory is freed if INVARG is returned
1301
1302 +*/
1303
1304 er_ret_t
1305 IP_smart_conv(char *key,
/* [<][>][^][v][top][bottom][index][help] */
1306 int justcheck,
1307 int encomp,
1308 GList **preflist,
1309 ip_exp_t expf,
1310 ip_keytype_t *keytype
1311 )
1312 {
1313 int free_it;
1314 er_ret_t call_err, err=IP_OK; /* let's be optimistic :-) */
1315 ip_prefix_t *querypref;
1316
1317 /* if just checking the syntax (justcheck == 1),
1318 then free_it = 1,
1319 else 0, but may be modified later (in range conversion)
1320 */
1321
1322 free_it = justcheck;
1323
1324 if( (call_err = wr_malloc( (void **) &querypref, sizeof(ip_prefix_t)))
1325 != UT_OK) {
1326 return call_err;
1327 }
1328
1329 if( IP_pref_t2b(querypref, key, expf) == IP_OK ) {
1330 *keytype = IPK_PREFIX;
1331
1332 if( justcheck == 0) {
1333 *preflist = g_list_append(*preflist, querypref);
1334 }
1335 }
1336 else {
1337 /* not a prefix. */
1338 /* Maybe an IP ? */
1339 if( IP_addr_t2b( &(querypref->ip), key, expf) == IP_OK ) {
1340
1341 *keytype = IPK_IP;
1342
1343 /*convert to a /32 or /128*/
1344 querypref->bits = IP_sizebits(querypref->ip.space);
1345
1346 if( justcheck == 0) {
1347 *preflist = g_list_append(*preflist, querypref);
1348 }
1349 }
1350 else {
1351 /* hm, maybe a range then ? */
1352 ip_range_t myrang;
1353
1354 /* won't use the querypref anymore, mark it for freeing later */
1355 free_it = 1;
1356
1357 if( IP_rang_t2b(&myrang, key, expf) == IP_OK ) {
1358 /* Wow. Great. */
1359
1360 *keytype = IPK_RANGE;
1361
1362 /* sometimes (exless match) we look for the first bigger(shorter) */
1363 /* prefix containing this range. */
1364
1365 if( encomp ) {
1366 IP_rang_encomp(&myrang);
1367 }
1368 /* OK, now we can let the engine happily find that there's just one */
1369 /* prefix in range */
1370
1371 if( justcheck == 0) {
1372 IP_rang_decomp(&myrang, preflist);
1373 }
1374 }
1375 else {
1376 *keytype = IPK_UNDEF;
1377 err = IP_INVARG; /* "conversion error" */
1378 }
1379 }
1380 }
1381
1382 if( free_it ) {
1383 wr_free(querypref);
1384 }
1385
1386 return err;
1387 }
1388
1389
1390 /* convert whatever comes into a range */
1391 er_ret_t
1392 IP_smart_range(char *key,
/* [<][>][^][v][top][bottom][index][help] */
1393 ip_range_t *rangptr,
1394 ip_exp_t expf,
1395 ip_keytype_t *keytype
1396 )
1397 {
1398 er_ret_t err=IP_OK;
1399 GList *preflist = NULL;
1400
1401 /* first : is it a range ? */
1402
1403 if( (err = IP_rang_t2b(rangptr, key, expf)) == IP_OK ) {
1404 *keytype = IPK_RANGE;
1405 }
1406 else {
1407 /* OK, this must be possible to convert it to prefix and from there
1408 to a range. */
1409 if( (err = IP_smart_conv(key, 0, 0, &preflist, expf, keytype))
1410 == IP_OK ) {
1411
1412 dieif( g_list_length(preflist) != 1 );
1413
1414 dieif(IP_pref_2_rang( rangptr, g_list_first(preflist)->data ) != IP_OK );
1415 }
1416 }
1417
1418 wr_clear_list( &preflist );
1419
1420 return err;
1421 }
1422