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