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