## modules/ip/ip.c

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

## FUNCTIONS

This source file includes following functions.

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

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

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