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