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