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