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

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