## modules/ip/ip.c

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

## DEFINITIONS

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. IP_rang_decomp
45. IP_rang_encomp
46. IP_pref_2_rang
47. IP_rang_classful
48. IP_smart_conv
49. IP_smart_range

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

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