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) {
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) 
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)
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)
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)
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)
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) 
507  | {
508  |   return addrptr->space;
509  | }
510  | 
511  | unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr) 
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) 
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) 
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) {
535  |   return IP_addr_b2_space( &(prefix->ip) );
536  | }
537  | 
538  | unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
539  |   return prefix->bits;
540  | }
541  | 
542  | unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
543  |   return IP_addr_b2v4_addr( &(prefix->ip) );
544  | }
545  | 
546  | /* range */
547  | 
548  | unsigned IP_rang_b2_space(ip_range_t *myrang) {
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) {
557  |   *address = IP_addr_b2v4_addr(addrptr);
558  | }
559  | 
560  | void IP_pref_b2v4(ip_prefix_t *prefptr, 
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, 
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,
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,
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,
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,
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, 
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,
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,
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,
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)
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,
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) 
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) 
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) 
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 )
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) 
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, 
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 ) 
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) 
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) 
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) {
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) {
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 ) 
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)
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)
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)
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 )
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)
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)
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)
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 )
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)
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, 
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,
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 |