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

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