Source File modules/ip/ip.c

    1    | /***************************************
    2    |   $Revision: 1.22 $
    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   | static
    72   | er_ret_t
    73   | ip_rang_validate(ip_range_t *rangptr)
    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)
    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)
    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)
    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)
    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)
    419  | {
    420  |   return addrptr->space;
    421  | }
    422  |
    423  | unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr)
    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)
    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)
    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) {
    447  |   return IP_addr_b2_space( &(prefix->ip) );
    448  | }
    449  |
    450  | unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
    451  |   return prefix->bits;
    452  | }
    453  |
    454  | unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
    455  |   return IP_addr_b2v4_addr( &(prefix->ip) );
    456  | }
    457  |
    458  | /* range */
    459  |
    460  | unsigned IP_rang_b2_space(ip_range_t *myrang) {
    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) {
    469  |   *address = IP_addr_b2v4_addr(addrptr);
    470  | }
    471  |
    472  | void IP_pref_b2v4(ip_prefix_t *prefptr,
    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,
    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,
    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,
    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,
    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,
    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,
    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,
    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,
    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,
    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)
    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,
    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)
    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)
    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)
    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 )
    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)
    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,
    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 )
    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)
    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)
    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) {
    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) {
    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 )
    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)
    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)
    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)
    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 )
    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)
    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)
    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)
    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 )
    1188 | {
    1189 |   ip_rangesize_t span;
    1190 |   int shift;
    1191 |   int i;
    1192 |
    1193 |   ad(begin) = ad(end) = prefptr->ip;
    1194 |
    1195 |   /* IPv6 is a bit more complicated, as four words are involved */
    1196 |
    1197 |   /* additional problem: shifting right by >=32 is equal to shifting by 0,
    1198 |      so it does not change any bits */
    1199 |   /* solution: don't touch those words */
    1200 |
    1201 |   for(i=0; i<4; i++) {
    1202 |
    1203 |     if( prefptr->bits < 32*(1+i) ) {
    1204 |       shift = prefptr->bits < 32 + (i-1) * 32
    1205 | 	? 0 : (prefptr->bits % 32) ;
    1206 |       ad(end).words[i] |= (0xffffffffU >> shift);
    1207 |     }
    1208 |
    1209 |     if( prefptr->ip.space == IP_V4) {
    1210 |       break; /* do only first word for IPv4 */
    1211 |     }
    1212 |   }
    1213 |   return IP_OK;
    1214 | }
    1215 |
    1216 | #undef ad
    1217 |
    1218 | /***************************************************************************/
    1219 |
    1220 | /*+
    1221 |    This is to parse a classfull address into a range.
    1222 |
    1223 |    Takes the address by pointer from addrptr and puts the result
    1224 |    at rangptr.
    1225 |
    1226 |    Throws error if the address does not fall into any of the
    1227 |    classfull categories
    1228 |
    1229 | +*/
    1230 |
    1231 | er_ret_t
    1232 | IP_rang_classful( ip_range_t *rangptr, ip_addr_t *addrptr)
    1233 | {
    1234 | int i;
    1235 | unsigned b[4];
    1236 |
    1237 |   if( addrptr->space != IP_V4 ) {
    1238 |     /* it's IPv6. There are no classful ranges or anything like that. */
    1239 |     die;
    1240 |   }
    1241 |
    1242 |   rangptr->begin = *addrptr;
    1243 |   rangptr->end.space = IP_V4;
    1244 |
    1245 |   /* initisalise end to zero */
    1246 |   for(i=0; i<IPLIMBNUM; i++) {
    1247 |     rangptr->end.words[i] = 0;
    1248 |   }
    1249 |
    1250 |   /* assume it's at least a valid IP. let's try different classes now */
    1251 |
    1252 |   /* we could have used a union here, but it would not work on */
    1253 |   /* low endians. So byte by byte copying to and from an array. */
    1254 |
    1255 |   for(i=0; i<4; i++) {
    1256 |     b[i] = ( rangptr->begin.words[0] & (0xFF << i*8) ) >> i*8;
    1257 |   }
    1258 |
    1259 |   if( b[3] >= 1 && b[3] < 128
    1260 |       && b[2] == 0 && b[1] == 0 && b[0] == 0 ) {
    1261 |     b[2]=b[1]=b[0]=255;
    1262 |   }
    1263 |   else if( b[3] >= 128 && b[3] < 192
    1264 | 	   && b[1] == 0 && b[0] == 0 ) {
    1265 |     b[1]=b[0]=255;
    1266 |   }
    1267 |   else if( b[3] >= 192 && b[3] < 224
    1268 | 	   &&  b[0] == 0 ) {
    1269 |     b[0]=255;
    1270 |   }
    1271 |   else if( b[3] >= 224 && b[3] < 255 ) {
    1272 |     /* just leave it, make it a /32, i.e. begin == end */
    1273 |     /* EMPTY */;
    1274 |   }
    1275 |   else {
    1276 |     /* Leave it and make it a /32 */
    1277 |     /* This is AGAINST the rule! but we have some junk  */
    1278 |     /* so we have to compensate for it. */
    1279 |     /* EMPTY */;
    1280 |   }
    1281 |
    1282 |   /* copy the (now - modified) bytes into the end of range */
    1283 |   for(i=0; i<4; i++) {
    1284 |     rangptr->end.words[0] |= (b[i] << i*8);
    1285 |   }
    1286 |
    1287 |   return IP_OK;
    1288 | }
    1289 |
    1290 |
    1291 | /***************************************************************************/
    1292 | /*+
    1293 |   Trying to be smart :-) and convert a query search term into prefix(es),
    1294 |   regardless of whether specified as IP address, prefix or range.
    1295 |
    1296 |   justcheck - if just checking the syntax (justcheck == 1),
    1297 |      then the prefixes are freed before the function returns,
    1298 |      otherwise it is the responsibility of the caller to free the list.
    1299 |
    1300 |      XXX must make sure all memory is freed if INVARG is returned
    1301 |
    1302 | +*/
    1303 |
    1304 | er_ret_t
    1305 | IP_smart_conv(char *key,
    1306 | 	      int justcheck,
    1307 | 	      int encomp,
    1308 | 	      GList **preflist,
    1309 | 	      ip_exp_t expf,
    1310 | 	      ip_keytype_t *keytype
    1311 | 	      )
    1312 | {
    1313 |   int free_it;
    1314 |   er_ret_t call_err, err=IP_OK;      /* let's be optimistic :-) */
    1315 |   ip_prefix_t *querypref;
    1316 |
    1317 |   /* if just checking the syntax (justcheck == 1),
    1318 |      then free_it = 1,
    1319 |      else 0, but may be modified later (in range conversion)
    1320 |   */
    1321 |
    1322 |   free_it = justcheck;
    1323 |
    1324 |   if( (call_err = wr_malloc( (void **) &querypref, sizeof(ip_prefix_t)))
    1325 |       != UT_OK) {
    1326 |     return call_err;
    1327 |   }
    1328 |
    1329 |   if( IP_pref_t2b(querypref, key, expf) == IP_OK ) {
    1330 |     *keytype = IPK_PREFIX;
    1331 |
    1332 |     if( justcheck == 0) {
    1333 |       *preflist = g_list_append(*preflist, querypref);
    1334 |     }
    1335 |   }
    1336 |   else {
    1337 |     /* not a prefix.  */
    1338 |     /* Maybe an IP ? */
    1339 |     if( IP_addr_t2b( &(querypref->ip), key, expf) == IP_OK ) {
    1340 |
    1341 |       *keytype = IPK_IP;
    1342 |
    1343 |       /*convert to a /32 or /128*/
    1344 |       querypref->bits =  IP_sizebits(querypref->ip.space);
    1345 |
    1346 |       if( justcheck == 0) {
    1347 | 	*preflist = g_list_append(*preflist, querypref);
    1348 |       }
    1349 |     }
    1350 |     else {
    1351 |       /* hm, maybe a range then ? */
    1352 |       ip_range_t myrang;
    1353 |
    1354 |       /* won't use the querypref anymore, mark it for freeing later */
    1355 |       free_it = 1;
    1356 |
    1357 |       if( IP_rang_t2b(&myrang, key, expf) == IP_OK ) {
    1358 | 	/* Wow. Great.  */
    1359 |
    1360 | 	*keytype = IPK_RANGE;
    1361 |
    1362 | 	/* sometimes (exless match) we look for the first bigger(shorter)  */
    1363 | 	/* prefix containing this range. */
    1364 |
    1365 | 	if( encomp ) {
    1366 | 	  IP_rang_encomp(&myrang);
    1367 | 	}
    1368 | 	/* OK, now we can let the engine happily find that there's just one */
    1369 | 	/* prefix in range */
    1370 |
    1371 | 	if( justcheck == 0) {
    1372 | 	  IP_rang_decomp(&myrang, preflist);
    1373 | 	}
    1374 |       }
    1375 |       else {
    1376 | 	*keytype = IPK_UNDEF;
    1377 | 	err = IP_INVARG; /* "conversion error" */
    1378 |       }
    1379 |     }
    1380 |   }
    1381 |
    1382 |   if( free_it ) {
    1383 |     wr_free(querypref);
    1384 |   }
    1385 |
    1386 |   return err;
    1387 | }
    1388 |
    1389 |
    1390 | /* convert whatever comes into a range */
    1391 | er_ret_t
    1392 | IP_smart_range(char *key,
    1393 | 	       ip_range_t *rangptr,
    1394 | 	       ip_exp_t expf,
    1395 | 	       ip_keytype_t *keytype
    1396 | 	       )
    1397 | {
    1398 |   er_ret_t  err=IP_OK;
    1399 |   GList    *preflist = NULL;
    1400 |
    1401 |   /* first : is it a range ? */
    1402 |
    1403 |   if( (err = IP_rang_t2b(rangptr, key, expf)) == IP_OK ) {
    1404 |       *keytype = IPK_RANGE;
    1405 |   }
    1406 |   else {
    1407 |       /* OK, this must be possible to convert it to prefix and from there
    1408 | 	 to a range. */
    1409 |       if( (err = IP_smart_conv(key, 0, 0, &preflist, expf, keytype))
    1410 | 	  == IP_OK ) {
    1411 |
    1412 | 	  dieif( g_list_length(preflist) != 1 );
    1413 |
    1414 | 	  dieif(IP_pref_2_rang( rangptr, g_list_first(preflist)->data ) != IP_OK );
    1415 |       }
    1416 |   }
    1417 |
    1418 |   wr_clear_list( &preflist );
    1419 |
    1420 |   return err;
    1421 | }
    1422 |