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