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) {
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) 
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)
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)
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)
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)
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) 
526  | {
527  |   return addrptr->space;
528  | }
529  | 
530  | unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr) 
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) 
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) 
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) {
554  |   return IP_addr_b2_space( &(prefix->ip) );
555  | }
556  | 
557  | unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
558  |   return prefix->bits;
559  | }
560  | 
561  | unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
562  |   return IP_addr_b2v4_addr( &(prefix->ip) );
563  | }
564  | 
565  | /* range */
566  | 
567  | unsigned IP_rang_b2_space(ip_range_t *myrang) {
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) {
576  |   *address = IP_addr_b2v4_addr(addrptr);
577  | }
578  | 
579  | void IP_pref_b2v4(ip_prefix_t *prefptr, 
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, 
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,
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,
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,
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,
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, 
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,
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,
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,
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)
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,
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) 
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) 
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) 
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 )
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) 
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, 
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 ) 
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) 
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) 
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) {
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) {
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 ) 
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)
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)
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)
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 )
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)
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)
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 )
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)
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, 
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,
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 |