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