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