modules/ip/ip.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. IP_sizebits
  2. ip_rang_validate
  3. IP_addr_t2b
  4. IP_pref_t2b
  5. IP_revd_t2b
  6. IP_rang_t2b
  7. IP_addr_b2_space
  8. IP_addr_b2v4_addr
  9. IP_addr_b2v6_hi
  10. IP_addr_b2v6_lo
  11. IP_pref_b2_space
  12. IP_pref_b2_len
  13. IP_pref_b2v4_addr
  14. IP_rang_b2_space
  15. IP_addr_b2v4
  16. IP_pref_b2v4
  17. IP_pref_b2v6
  18. IP_rang_b2v4
  19. IP_addr_v4_mk
  20. IP_addr_v6_mk
  21. IP_pref_v4_mk
  22. IP_rang_v4_mk
  23. IP_pref_a2v4
  24. IP_pref_a2v6
  25. IP_revd_a2v4
  26. IP_addr_a2v4
  27. IP_rang_a2v4
  28. IP_addr_f2b_v4
  29. IP_rang_f2b_v4
  30. IP_pref_f2b_v4
  31. IP_addr_f2b_v6
  32. IP_pref_f2b_v6
  33. IP_addr_s2b
  34. IP_addr_b2a
  35. IP_pref_b2a
  36. IP_rang_b2a
  37. IP_addr_bit_get
  38. IP_addr_bit_set
  39. IP_pref_bit_fix
  40. IP_addr_cmp
  41. IP_addr_in_pref
  42. IP_addr_in_rang
  43. IP_rang_span
  44. ad
  45. IP_rang_decomp
  46. IP_rang_encomp
  47. IP_pref_2_rang
  48. IP_rang_classful
  49. IP_smart_conv
  50. IP_smart_range

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

/* [<][>][^][v][top][bottom][index][help] */