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