/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- IP_sizebits
- ip_rang_validate
- IP_addr_t2b
- IP_pref_t2b
- IP_revd_t2b
- IP_rang_t2b
- IP_addr_b2_space
- IP_addr_b2v4_addr
- IP_addr_b2v6_hi
- IP_addr_b2v6_lo
- IP_pref_b2_space
- IP_pref_b2_len
- IP_pref_b2v4_addr
- IP_rang_b2_space
- IP_addr_b2v4
- IP_pref_b2v4
- IP_pref_b2v6
- IP_rang_b2v4
- IP_addr_v4_mk
- IP_addr_v6_mk
- IP_pref_v4_mk
- IP_rang_v4_mk
- IP_pref_a2v4
- IP_pref_a2v6
- IP_revd_a2v4
- IP_addr_a2v4
- IP_rang_a2v4
- IP_addr_f2b_v4
- IP_rang_f2b_v4
- IP_pref_f2b_v4
- IP_addr_f2b_v6
- IP_pref_f2b_v6
- IP_addr_s2b
- IP_addr_b2a
- IP_pref_b2a
- IP_rang_b2a
- IP_addr_bit_get
- IP_addr_bit_set
- IP_pref_bit_fix
- IP_addr_cmp
- IP_addr_in_pref
- IP_addr_in_rang
- IP_rang_span
- IP_rang_decomp
- IP_rang_encomp
- IP_pref_2_rang
- IP_rang_classful
- IP_smart_conv
- IP_smart_range
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) {
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
526 {
527 return addrptr->space;
528 }
529
530 unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
554 return IP_addr_b2_space( &(prefix->ip) );
555 }
556
557 unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
558 return prefix->bits;
559 }
560
561 unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
562 return IP_addr_b2v4_addr( &(prefix->ip) );
563 }
564
565 /* range */
566
567 unsigned IP_rang_b2_space(ip_range_t *myrang) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
576 *address = IP_addr_b2v4_addr(addrptr);
577 }
578
579 void IP_pref_b2v4(ip_prefix_t *prefptr,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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