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