1 | /***************************************
2 | $Revision: 1.7 $
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
10 |
11 | Design and implementation by: Marek Bukowy
12 |
13 | ******************/ /******************
14 | Copyright (c) 1999 RIPE NCC
15 |
16 | All Rights Reserved
17 |
18 | Permission to use, copy, modify, and distribute this software and its
19 | documentation for any purpose and without fee is hereby granted,
20 | provided that the above copyright notice appear in all copies and that
21 | both that copyright notice and this permission notice appear in
22 | supporting documentation, and that the name of the author not be
23 | used in advertising or publicity pertaining to distribution of the
24 | software without specific, written prior permission.
25 |
26 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 | ***************************************/
33 |
34 | #include <iproutines.h>
35 | #include <string.h>
36 | #include <stdio.h>
37 | #include <erroutines.h>
38 |
39 | #include <ctype.h>
40 | #include <memwrap.h>
41 |
42 | #include <numconv.h>
43 | #include <stubs.h>
44 |
45 |
46 | /***************************************************************************/
47 | /*+ return the max. length of bits per space
48 |
49 | Yes, it *could* be a macro - but as a function it can detect
50 | more programmer's errors. And will get inlined anyway.
51 |
52 | +*/
53 |
54 | int IP_sizebits(ip_space_t spc_id) {
55 | switch (spc_id) {
56 | case IP_V4:
57 | return 32;
58 | case IP_V6:
59 | return 128;
60 | default:
61 | // die; /* error: bad IP version specified */
62 | return -1;
63 | }
64 | }
65 |
66 | /***************************************************************************/
67 | /*+
68 | ascii IP address to binary.
69 | In IP_EXPN mode IP will be treated as not-expanded.
70 | (missing octets will be set to 0, MSB will be set).
71 | In IP_PLAIN mode the routine will complain if it sees less octets.
72 | +*/
73 |
74 | er_ret_t
75 | IP_addr_t2b(ip_addr_t *ipptr, char *addr, ip_exp_t expf)
76 | {
77 | if( index(addr, ':') == NULL ) {
78 | /* IPv4 */
79 | char *dot;
80 | unsigned len, byte, result=0;
81 | char cpy[4];
82 | int last = 0, dotsfound=0;
83 | int bytes=0;
84 |
85 | if( expf != IP_PLAIN && expf != IP_EXPN ) {
86 | return IP_INVARG;
87 | }
88 |
89 | do {
90 | if ( (dot = index (addr, '.')) == NULL) {
91 | dot = index (addr, '\0');
92 | last = 1;
93 | }
94 | else {
95 | if( ++dotsfound > 3 ) {
96 | /* handle syntax ERROR - too many dots found */
97 | return IP_INVIP4;
98 | }
99 | }
100 |
101 | if ((len = dot - addr) > 4) {
102 | /* syntax ERROR - too many digits between dots*/
103 | return IP_INVIP4;
104 | }
105 | strncpy( cpy, addr, len );
106 | cpy[len]=0;
107 |
108 | /* sscanf is waay too slow */
109 |
110 | if( ut_dec_2_uns(cpy, &byte) < 0 ) {
111 | /* handle syntax ERROR - invalid characters found */
112 | return IP_INVIP4;
113 | }
114 |
115 |
116 | if( byte > 255 ) {
117 | /* handle syntax ERROR - number between dots too high */
118 | return IP_INVIP4;
119 | }
120 |
121 | result <<= 8;
122 | result += byte;
123 | bytes++;
124 |
125 | addr = dot + 1;
126 | } while (!last);
127 |
128 | if( expf == IP_PLAIN ) {
129 | if( bytes!=4 ) {
130 | return IP_INVIP4;
131 | }
132 | }
133 | else {
134 | while( bytes<4 ) {
135 | result <<= 8;
136 | bytes++;
137 | }
138 | }
139 |
140 | memset(ipptr, 0, sizeof(ip_addr_t));
141 | ipptr->space = IP_V4;
142 | ipptr->words[0] = result;
143 | }
144 | else {
145 | /* IPv6 */
146 | /* not yet implemented. Sorry. */
147 | // die;
148 | return IP_NO6YET;
149 | }
150 | return IP_OK;
151 | }
152 |
153 | /***************************************************************************/
154 |
155 | /*+ converts a "IP/length" string into a binary prefix
156 | +*/
157 | er_ret_t
158 | IP_pref_t2b(ip_prefix_t *prefptr, char *prefstr, ip_exp_t expf)
159 | {
160 | char ip[256];
161 | char *slash, *trash;
162 | int len;
163 | er_ret_t err;
164 |
165 | if( expf != IP_PLAIN && expf != IP_EXPN ) {
166 | return IP_INVARG;
167 | }
168 |
169 | if( (slash=index(prefstr, '/')) == NULL ) {
170 | // die; /* error: missing slash in prefix */
171 | return IP_NOSLAS;
172 | }
173 | else {
174 | /* copy the IP part to another string, ERROR if 256 chars is not nough */
175 |
176 | len = slash - prefstr;
177 | if( len > 255 ) {
178 | // die; /* ERROR - ip address part of the string too long. */
179 | return IP_ADTOLO;
180 | }
181 | strncpy(ip, prefstr, len);
182 | ip[len]=0;
183 |
184 | if( (err=IP_addr_t2b( &(prefptr->ip), ip, expf)) != IP_OK) {
185 | // die; /* set error flag: incorrect address format */
186 | return err;
187 | }
188 |
189 | // stop at first non-digit
190 | for(trash = slash+1; isdigit(*trash) ; trash++);
191 | len = trash - (slash+1) ;
192 | if( len > 4 ) {
193 | // die; /* ERROR - prefix length part of the string too long. */
194 | return IP_PRTOLO;
195 | }
196 | strncpy(ip, slash+1, len);
197 | ip[len]=0;
198 |
199 | if( ut_dec_2_uns(ip, &prefptr->bits) < 0 ) {
200 |
201 | // if( sscanf (slash+1, "%d", &(prefptr->bits)) < 1 ) {
202 | // die; /* handle syntax ERROR invalid characters found */
203 | return IP_INVPRF;
204 | }
205 | }
206 | // sanitify the prefix - maybe some irrelevant bits are set
207 | // never create broken binary prefixes.
208 |
209 | IP_pref_bit_fix(prefptr);
210 |
211 | return IP_OK;
212 | }
213 |
214 | /***************************************************************************/
215 |
216 | /*+ convert a range string into a binary range struct.
217 | +*/
218 | er_ret_t
219 | IP_rang_t2b(ip_range_t *rangptr, char *rangstr, ip_exp_t expf)
220 | {
221 | char *ips, *dash;
222 | er_ret_t err;
223 |
224 | if( expf != IP_PLAIN && expf != IP_EXPN ) {
225 | return IP_INVARG;
226 | }
227 |
228 | if( (dash=index(rangstr, '-')) == NULL ) {
229 | // die; /* error: missing dash in range */
230 | return IP_INVRAN;
231 | }
232 | else {
233 | /* copy the first IP */
234 | if( (err = wr_calloc( (void*) &ips,1,dash - rangstr + 1)) != UT_OK ) {
235 | return err;
236 | }
237 |
238 | strncpy(ips, rangstr, dash - rangstr);
239 |
240 | /* convert the first IP into a binary struct */
241 | err=IP_addr_t2b( &(rangptr->begin), ips, expf);
242 |
243 | // check later /* set error flag: incorrect address format */
244 |
245 | wr_free(ips);
246 |
247 | if( err != IP_OK ) {
248 | return err;
249 | }
250 |
251 | /* now find the other ip, skip the space */
252 | ips=dash+1;
253 | while( *ips == ' ' ) {
254 | ips++;
255 | }
256 |
257 | /* convert the second IP into a binary struct */
258 | if( (err=IP_addr_t2b( &(rangptr->end), ips, expf)) != IP_OK ) {
259 | // die; /* incorrect address format */
260 | return err;
261 | }
262 |
263 | if( rangptr->begin.space != rangptr->end.space ) {
264 | // die; /* incompatible IP spaces */
265 | return IP_INVRAN;
266 | }
267 |
268 | return IP_OK;
269 | }
270 | }
271 |
272 | /***************************************************************************/
273 |
274 |
275 |
276 | /*+converts the IP binary address (binaddr) to a string (ascaddr)
277 | of at most strmax characters. Independent of the result
278 | (success or failure) it messes up the string.
279 | +*/
280 | er_ret_t
281 | IP_addr_b2a( ip_addr_t *binaddr, char *ascaddr, int strmax )
282 | {
283 |
284 | if(binaddr->space == IP_V4) {
285 | if (snprintf(ascaddr, strmax, "%d.%d.%d.%d",
286 | ((binaddr->words[0]) & ((unsigned)0xff<<24))>>24,
287 | ((binaddr->words[0]) & (0xff<<16))>>16,
288 | ((binaddr->words[0]) & (0xff<<8))>>8,
289 | ((binaddr->words[0]) & (0xff<<0))>>0
290 | ) >= strmax) {
291 | //die; // string too short
292 | return IP_TOSHRT;
293 | }
294 |
295 | #if 0
296 | char buf[5];
297 | int mask;
298 |
299 | *ascaddr = '\0';
300 |
301 | // this is very inefficient - but maybe this is the way to go for IPv6
302 |
303 | for(mask=24; mask >= 0; mask -= 8) {
304 |
305 | sprintf(buf, "%d%s", ((binaddr->words[0]) & 0xff<<mask)>>mask,
306 | mask==0 ? "" : ".");
307 | if( (strlen(buf)+strlen(ascaddr)) >= strmax ) {
308 | // die; /* error: insufficient space */
309 | return IP_TOSHRT;
310 | }
311 | else {
312 | strcat(ascaddr, buf);
313 | }
314 | }
315 |
316 | #endif
317 |
318 | }
319 | else {
320 | /* IPv6 */
321 | /* not yet implemented. Sorry. */
322 | // die;
323 | return IP_NO6YET;
324 | }
325 | return IP_OK;
326 | }
327 |
328 | /***************************************************************************/
329 |
330 | /*+ convert a binary prefix back into ascii string at most strmax chars long
331 | +*/
332 | er_ret_t
333 | IP_pref_b2a(ip_prefix_t *prefptr, char *ascaddr, int strmax)
334 | {
335 | int strl;
336 | er_ret_t err;
337 |
338 | if( (err=IP_addr_b2a (&(prefptr->ip), ascaddr, strmax)) != IP_OK) {
339 | //die; /* what the hell */
340 | return err;
341 | }
342 | strl = strlen(ascaddr);
343 | strmax -= strl;
344 |
345 | /* now strmax holds the space that is left */
346 |
347 | if( snprintf(ascaddr+strl, strmax, "/%d", prefptr->bits) >= strmax) {
348 | // die; /* error: string too short */
349 | return IP_TOSHRT;
350 | }
351 | return IP_OK;
352 | }
353 |
354 |
355 |
356 | /***************************************************************************/
357 | /*+ convert a binary range back into ascii string at most strmax chars long
358 | +*/
359 | er_ret_t
360 | IP_rang_b2a(ip_range_t *rangptr, char *ascaddr, int strmax)
361 | {
362 | int strl=0, strleft;
363 | er_ret_t err;
364 |
365 | strleft = strmax - strl;
366 | if( (err=IP_addr_b2a (&(rangptr->begin), ascaddr, strleft)) != IP_OK) {
367 | return err;
368 | }
369 | strl = strlen(ascaddr);
370 |
371 | strleft = strmax - strl;
372 | if( strleft < 5 ) {
373 | return IP_TOSHRT;
374 | }
375 | strcat( ascaddr, " - " );
376 | strl += 3;
377 |
378 | strleft = strmax - strl;
379 | if( (err=IP_addr_b2a (&(rangptr->end), ascaddr+strl, strleft)) != IP_OK) {
380 | return err;
381 | }
382 |
383 | return IP_OK;
384 | }
385 |
386 | /***************************************************************************/
387 | /*+ return the bitnum bit of the address,
388 | COUNTING FROM THE TOP !!!!! ,
389 | starting with 0 for the *most significant bit*.
390 | +*/
391 | int
392 | IP_addr_bit_get(ip_addr_t *binaddr, int bitnum) {
393 | register int bitval;
394 |
395 | // IPv4 is easy...
396 | bitval = (binaddr->words[0] & (0x80000000 >> (bitnum)));
397 |
398 | return (bitval != 0);
399 |
400 | }
401 |
402 | /***************************************************************************/
403 | /*+ set the bitnum bit of the address to bitval,
404 | COUNTING FROM THE TOP !!!!! ,
405 | starting with 0 for the *most significant bit*.
406 | +*/
407 | void
408 | IP_addr_bit_set(ip_addr_t *binaddr, int bitnum, int bitval) {
409 |
410 | // IPv4 is easy...
411 | if ( bitval == 1 )
412 | binaddr->words[0] |= (0x80000000 >> (bitnum));
413 | else
414 | binaddr->words[0] &= ~(0x80000000 >> (bitnum));
415 | }
416 | /***************************************************************************/
417 |
418 | /*+ this fixes a prefix by setting insignificant bits to 0 +*/
419 | void
420 | IP_pref_bit_fix( ip_prefix_t *prefix )
421 | {
422 |
423 | unsigned mask=0xffffffff;
424 |
425 | // shorthand for ipv4
426 |
427 | // Shifting out by 32 bits does NOT turn all bits into 0...
428 | if( prefix->bits < 32 ) {
429 | prefix->ip.words[0] &= ~(mask >> prefix->bits);
430 | }
431 |
432 | #if 0
433 | int i;
434 | for(i=prefix->bits; i < IP_sizebits(prefix->ip.space) ; i++) {
435 | IP_addr_bit_set( & prefix->ip, i, 0);
436 | }
437 | #endif
438 |
439 |
440 | }
441 |
442 | /***************************************************************************/
443 |
444 |
445 | /*+
446 | This is a hook function for use with g_list_foreach, to print a list
447 | of prefixes
448 | +*/
449 |
450 | void ip_print_prefix(void *dataptr, void *junk) {
451 | char ascpref[IP_PREFSTR_MAX];
452 | ip_prefix_t *binpref=dataptr;
453 |
454 | IP_pref_b2a( binpref, ascpref, IP_PREFSTR_MAX );
455 | printf ("prefix: %s\n", ascpref);
456 | }
457 |
458 |
459 | /***************************************************************************/
460 |
461 | /*+ compares two IP addresses up to the bit # len,
462 | returns 0 if equal, 1 if ptra greater, -1 if ptrb greater.
463 |
464 | It is the responsility of the caller to ensure that both addresses
465 | are from the same IP space.
466 | +*/
467 |
468 | int
469 | IP_addr_cmp(ip_addr_t *ptra, ip_addr_t *ptrb, int len)
470 | {
471 | int a,b,i;
472 |
473 | for(i=0; i<len; i++) {
474 | a=IP_addr_bit_get(ptra, i);
475 | b=IP_addr_bit_get(ptrb, i);
476 | if( a != b ) {
477 | if( a > b ) return 1;
478 | else return -1;
479 | }
480 | }
481 | return 0;
482 | }
483 |
484 |
485 |
486 |
487 |
488 | /***************************************************************************/
489 |
490 | /*+
491 | this is a shorthand notation to pull out the first word of the address.
492 | it is defined for the scope od the following functions
493 | +*/
494 | #define ad(which) (rangptr->which)
495 |
496 | /***************************************************************************/
497 | /*+ calculate the span of a range == size - 1 +*/
498 |
499 | ip_rangesize_t
500 | IP_rang_span( ip_range_t *rangptr )
501 | {
502 | // IPv4:
503 | return ad(end).words[0] - ad(begin).words[0];
504 | }
505 |
506 | /***************************************************************************/
507 |
508 | /*+ Decomposes a binary range into prefixes and appends them to the list.
509 | Allocates prefix structures and list elements, they must be freed after use.
510 |
511 | returns a bitmask of prefix lengths used.
512 | +*/
513 |
514 | unsigned
515 | IP_rang_decomp(ip_range_t *rangptr, GList **preflist)
516 | {
517 | unsigned prefmask=0;
518 | register int slash=0;
519 | register unsigned c_dif, blk, ff;
520 | ip_range_t workrange;
521 | ip_addr_t workbegin;
522 | ip_addr_t workend;
523 | ip_prefix_t *prefptr;
524 |
525 | if( ad(begin).words[0] > ad(end).words[0] ) { // has gone too far
526 | return 0;
527 | }
528 |
529 | if( ad(begin).words[0] == ad(end).words[0] ) { // one IP, i.e. /32 for IPv4
530 | prefmask |= 1;
531 | if( wr_calloc( (void **)& prefptr, sizeof(ip_prefix_t), 1) != UT_OK) {
532 | die;
533 | }
534 | prefptr->ip = ad(begin);
535 | prefptr->bits = 32;
536 |
537 | *preflist = g_list_append( *preflist, prefptr );
538 |
539 | return prefmask;
540 | }
541 |
542 | c_dif = ad(end).words[0] - ad(begin).words[0];
543 |
544 | // initialize work vars
545 |
546 | workbegin = ad(begin);
547 | workend = ad(end);
548 |
549 | // now find the biggest block fitting in this range
550 | // i.e. the first 2^n number smaller than c_dif
551 |
552 | // the loop would not work for /0 (some stupid queries may have that)
553 | // so this must be checked for separately
554 |
555 | if( c_dif == 0xffffffff ) {
556 | // they are already set to 0.0.0.0 - 255.255.255.255
557 | // leave them alone.
558 | blk = 0;
559 | slash = 0;
560 | }
561 | else {
562 |
563 | c_dif += 1; // was not done earlier to protect from overflow
564 |
565 | for(slash=1;
566 | slash<32 && ((blk=((unsigned)0x80000000>>(slash-1))) & c_dif) == 0;
567 | slash++) {}
568 |
569 | // clear all digits in a and b under the blk one.
570 | ff=blk-1;
571 |
572 | workbegin.words[0] = (workbegin.words[0] + ff) & ~ff;
573 |
574 | workend.words[0] = (workend.words[0] + 1) & ~ff;
575 | }
576 |
577 | if( workbegin.words[0] != workend.words[0] ) {
578 | prefmask |= blk;
579 | if( wr_malloc( (void **)& prefptr, sizeof(ip_prefix_t)) != UT_OK) {
580 | die;
581 | }
582 | prefptr->ip = workbegin;
583 | prefptr->bits = slash;
584 |
585 | *preflist = g_list_append( *preflist, prefptr );
586 | }
587 |
588 | if( ad(begin).words[0] != workbegin.words[0] ) {
589 | workrange.begin = ad(begin);
590 |
591 | workbegin.words[0] -= 1;
592 | workrange.end = workbegin;
593 |
594 | prefmask |= IP_rang_decomp( &workrange, preflist );
595 | }
596 |
597 | // here we must protect from decomposition of
598 | // 255.255.255.255 - 255.255.255.255 in case the range
599 | // 0.0.0.0 - 255.255.255.255 is considered. Hence the slash>0 condition.
600 |
601 | if( workend.words[0] <= ad(end).words[0] && slash > 0) {
602 | workrange.begin = workend;
603 | workrange.end = ad(end);
604 |
605 | prefmask |= IP_rang_decomp( &workrange, preflist );
606 | }
607 |
608 | return prefmask;
609 | }
610 |
611 |
612 | /***************************************************************************/
613 |
614 | /*+ Similar name, slightly different code, totally different functionality.
615 |
616 | finds the smallest canonical block encompassing the whole given range,
617 | then MODIFIES the range pointed to by the argument
618 | so that it's equal to this block.
619 |
620 | returns a bitmask of prefix length used.
621 | +*/
622 |
623 | unsigned
624 | IP_rang_encomp(ip_range_t *rangptr)
625 | {
626 | unsigned prefmask=0;
627 | int slash=0;
628 | unsigned c_dif, blk, ff, t_dif;
629 | ip_range_t workrange;
630 | ip_addr_t workbegin;
631 | ip_addr_t workend;
632 |
633 | c_dif = ad(end).words[0] - ad(begin).words[0];
634 |
635 | // now find the biggest block fitting in this range
636 | // i.e. the first 2^n number smaller than c_dif
637 |
638 | // the loop would not work for /0 (some stupid queries may have that)
639 | // so this must be checked for separately
640 |
641 | if( c_dif > 0x80000000 ) {
642 | slash = 0;
643 | ff = 0xffffffff;
644 | blk = 0;
645 |
646 | workbegin = workend = ad(begin);
647 | workbegin.words[0] = 0;
648 | workend.words[0] = ff;
649 | }
650 | else {
651 |
652 | do {
653 | c_dif += 1;
654 |
655 | // find the smallest block ENCOMPASSING c_dif.
656 | // this implies a loop from the bottom up
657 |
658 | for(slash=32;
659 | slash>1 && (blk=((unsigned)0x80000000>>(slash-1))) < c_dif;
660 | slash--) {}
661 |
662 | ff=blk-1;
663 |
664 | // clear all digits in workbegin under the blk one.
665 |
666 | workbegin = ad(begin);
667 | workbegin.words[0] = workbegin.words[0] & ~ff;
668 |
669 | // see if it has not made the difference larger than blk,
670 | // retry if so
671 |
672 | t_dif = c_dif;
673 | c_dif = ad(end).words[0] - workbegin.words[0];
674 |
675 | } while( c_dif >= t_dif );
676 |
677 | // set the endpoint to workbegin + blocksize - 1
678 | // which amounts to + ff
679 |
680 | workend = ad(begin);
681 | workend.words[0] = workbegin.words[0] + ff;
682 | }
683 |
684 |
685 | // set the range to new values
686 |
687 | rangptr->begin = workbegin;
688 | rangptr->end = workend;
689 | }
690 |
691 | /***************************************************************************/
692 | /*+ sets a range equal to a prefix +*/
693 |
694 | er_ret_t
695 | IP_pref_2_rang( ip_range_t *rangptr, ip_prefix_t *prefptr )
696 | {
697 | ip_rangesize_t span;
698 |
699 | ad(begin) = ad(end) = prefptr->ip;
700 |
701 | if( prefptr->bits > 0 ) {
702 | span = (1 << (32 - prefptr->bits)) - 1 ;
703 | }
704 | else {
705 | span = 0xffffffff;
706 | }
707 |
708 | ad(end).words[0] += span;
709 |
710 | return IP_OK;
711 | }
712 |
713 | #undef ad
714 |
715 | /***************************************************************************/
716 |
717 | /*+
718 | This is to parse a classfull address into a range.
719 |
720 | Takes the address by pointer from addrptr and puts the result
721 | at rangptr.
722 |
723 | Throws error if the address does not fall into any of the
724 | classfull categories
725 |
726 | +*/
727 |
728 | er_ret_t
729 | IP_rang_classful( ip_range_t *rangptr, ip_addr_t *addrptr)
730 | {
731 | int i;
732 | unsigned b[4];
733 |
734 | if( addrptr->space != IP_V4 ) {
735 | // it's IPv6. There are no classful ranges or anything like that.
736 | // we accept only explicit ranges
737 |
738 | die;
739 | }
740 |
741 | rangptr->begin = *addrptr;
742 | rangptr->end.space = IP_V4;
743 | for(i=0; i<4; i++) {
744 | rangptr->end.words[i] = 0;
745 | }
746 |
747 | /* assume it's at least a valid IP. let's try different classes now */
748 |
749 | // we could have used a union here, but it would not work on
750 | // low endians. So byte by byte copying to and from an array.
751 |
752 | for(i=0; i<4; i++) {
753 | b[i] = ( rangptr->begin.words[0] & (0xFF << i*8) ) >> i*8;
754 | }
755 |
756 | if( b[3] >= 1 && b[3] < 128
757 | && b[2] == 0 && b[1] == 0 && b[0] == 0 ) {
758 | b[2]=b[1]=b[0]=255;
759 | }
760 | else if( b[3] >= 128 && b[3] < 192
761 | && b[1] == 0 && b[0] == 0 ) {
762 | b[1]=b[0]=255;
763 | }
764 | else if( b[3] >= 192 && b[3] < 224
765 | && b[0] == 0 ) {
766 | b[0]=255;
767 | }
768 | else if( b[3] >= 224 && b[3] < 255 ) {
769 | // just leave it, make it a /32, i.e. begin == end
770 | }
771 | else {
772 | // Leave it and make it a /32
773 | // This is AGAINST the rule! but we have some junk
774 | // so we have to compensate for it.
775 | }
776 |
777 | // copy the (now - modified) bytes into the end of range
778 | for(i=0; i<4; i++) {
779 | rangptr->end.words[0] |= (b[i] << i*8);
780 | }
781 |
782 | return IP_OK;
783 | }
784 |
785 |
786 | /***************************************************************************/
787 | /*+
788 | Trying to be smart :-) and convert a query search term into prefix(es),
789 | regardless of whether specified as IP address, prefix or range.
790 |
791 | justcheck - if just checking the syntax (justcheck == 1),
792 | then the prefixes are freed before the function returns,
793 | otherwise it is the responsibility of the caller to free the list.
794 |
795 | +*/
796 |
797 | er_ret_t
798 | IP_smart_conv(char *key,
799 | int justcheck,
800 | int encomp,
801 | GList **preflist,
802 | ip_exp_t expf)
803 | {
804 | int free_it;
805 | er_ret_t call_err, err=IP_OK; // let's be optimistic :-)
806 | ip_prefix_t *querypref;
807 |
808 | /* if just checking the syntax (justcheck == 1),
809 | then free_it = 1,
810 | else 0, but may be modified later (in range conversion)
811 | */
812 |
813 | free_it = justcheck;
814 |
815 | if( (call_err = wr_malloc( (void **) &querypref, sizeof(ip_prefix_t)))
816 | != UT_OK) {
817 | return call_err;
818 | }
819 |
820 | if( IP_pref_t2b(querypref, key, expf) == IP_OK ) {
821 | if( justcheck == 0) {
822 | *preflist = g_list_append(*preflist, querypref);
823 | }
824 | }
825 | else {
826 | // not a prefix.
827 | // Maybe an IP ?
828 | if( IP_addr_t2b( &(querypref->ip), key, expf) == IP_OK ) {
829 |
830 | //convert to a /32
831 | querypref->bits = 32;
832 |
833 | if( justcheck == 0) {
834 | *preflist = g_list_append(*preflist, querypref);
835 | }
836 | }
837 | else {
838 | // hm, maybe a range then ?
839 | ip_range_t myrang;
840 |
841 | // won't use the querypref anymore, mark it for freeing later
842 | free_it = 1;
843 |
844 | if( IP_rang_t2b(&myrang, key, expf) == IP_OK ) {
845 | // Wow. Great.
846 |
847 | // sometimes (exless match) we look for the first bigger(shorter)
848 | // prefix containing this range.
849 |
850 | if( encomp ) {
851 | IP_rang_encomp(&myrang);
852 | }
853 | // OK, now we can let the engine happily find that it's just one
854 | // range
855 |
856 | if( justcheck == 0) {
857 | IP_rang_decomp(&myrang, preflist);
858 | }
859 | }
860 | else {
861 | err = IP_INVARG; // "conversion error"
862 | }
863 | }
864 | }
865 |
866 | if( free_it ) {
867 | wr_free(querypref);
868 | }
869 |
870 | return err;
871 | }
872 |
873 |
874 | #ifdef MODULE_TEST
875 | #include "ip_test.c"
876 | #endif