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