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