Source File ip/ip.c

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