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