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