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