modules/ip/ip.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- IP_sizebits
- ip_rang_validate
- IP_addr_t2b
- IP_pref_t2b
- IP_revd_t2b
- IP_rang_t2b
- IP_addr_b2_space
- IP_addr_b2v4_addr
- IP_addr_b2v6_hi
- IP_addr_b2v6_lo
- IP_pref_b2_space
- IP_pref_b2_len
- IP_pref_b2v4_addr
- IP_rang_b2_space
- IP_addr_b2v4
- IP_pref_b2v4
- IP_pref_b2v6
- IP_rang_b2v4
- IP_addr_v4_mk
- IP_addr_v6_mk
- IP_pref_v4_mk
- IP_rang_v4_mk
- IP_pref_a2v4
- IP_pref_a2v6
- IP_revd_a2v4
- IP_addr_a2v4
- IP_rang_a2v4
- IP_addr_f2b_v4
- IP_rang_f2b_v4
- IP_pref_f2b_v4
- IP_addr_f2b_v6
- IP_pref_f2b_v6
- IP_addr_s2b
- IP_addr_b2a
- IP_pref_b2a
- IP_rang_b2a
- IP_addr_bit_get
- IP_addr_bit_set
- IP_pref_bit_fix
- IP_addr_cmp
- IP_addr_in_pref
- IP_addr_in_rang
- IP_rang_span
- ad
- IP_rang_decomp
- IP_rang_encomp
- IP_pref_2_rang
- IP_rang_classful
- IP_smart_conv
- IP_smart_range
1 /***************************************
2 $Revision: 1.23 $
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) {
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
419 {
420 return addrptr->space;
421 }
422
423 unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
447 return IP_addr_b2_space( &(prefix->ip) );
448 }
449
450 unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
451 return prefix->bits;
452 }
453
454 unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
455 return IP_addr_b2v4_addr( &(prefix->ip) );
456 }
457
458 /* range */
459
460 unsigned IP_rang_b2_space(ip_range_t *myrang) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
469 *address = IP_addr_b2v4_addr(addrptr);
470 }
471
472 void IP_pref_b2v4(ip_prefix_t *prefptr,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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,
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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)
/* [<][>][^][v][top][bottom][index][help] */
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 )
/* [<][>][^][v][top][bottom][index][help] */
1188 {
1189 int shift;
1190 int i;
1191
1192 ad(begin) = ad(end) = prefptr->ip;
1193
1194 /* IPv6 is a bit more complicated, as four words are involved */
1195
1196 /* additional problem: shifting right by >=32 is equal to shifting by 0,
1197 so it does not change any bits */
1198 /* solution: don't touch those words */
1199
1200 for(i=0; i<4; i++) {
1201
1202 if( prefptr->bits < 32*(1+i) ) {
1203 shift = prefptr->bits < 32 + (i-1) * 32
1204 ? 0 : (prefptr->bits % 32) ;
1205 ad(end).words[i] |= (0xffffffffU >> shift);
1206 }
1207
1208 if( prefptr->ip.space == IP_V4) {
1209 break; /* do only first word for IPv4 */
1210 }
1211 }
1212 return IP_OK;
1213 }
1214
1215 #undef ad
1216
1217 /***************************************************************************/
1218
1219 /*+
1220 This is to parse a classfull address into a range.
1221
1222 Takes the address by pointer from addrptr and puts the result
1223 at rangptr.
1224
1225 Throws error if the address does not fall into any of the
1226 classfull categories
1227
1228 +*/
1229
1230 er_ret_t
1231 IP_rang_classful( ip_range_t *rangptr, ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
1232 {
1233 int i;
1234 unsigned b[4];
1235
1236 if( addrptr->space != IP_V4 ) {
1237 /* it's IPv6. There are no classful ranges or anything like that. */
1238 die;
1239 }
1240
1241 rangptr->begin = *addrptr;
1242 rangptr->end.space = IP_V4;
1243
1244 /* initisalise end to zero */
1245 for(i=0; i<IPLIMBNUM; i++) {
1246 rangptr->end.words[i] = 0;
1247 }
1248
1249 /* assume it's at least a valid IP. let's try different classes now */
1250
1251 /* we could have used a union here, but it would not work on */
1252 /* low endians. So byte by byte copying to and from an array. */
1253
1254 for(i=0; i<4; i++) {
1255 b[i] = ( rangptr->begin.words[0] & (0xFF << i*8) ) >> i*8;
1256 }
1257
1258 if( b[3] >= 1 && b[3] < 128
1259 && b[2] == 0 && b[1] == 0 && b[0] == 0 ) {
1260 b[2]=b[1]=b[0]=255;
1261 }
1262 else if( b[3] >= 128 && b[3] < 192
1263 && b[1] == 0 && b[0] == 0 ) {
1264 b[1]=b[0]=255;
1265 }
1266 else if( b[3] >= 192 && b[3] < 224
1267 && b[0] == 0 ) {
1268 b[0]=255;
1269 }
1270 else if( b[3] >= 224 && b[3] < 255 ) {
1271 /* just leave it, make it a /32, i.e. begin == end */
1272 /* EMPTY */;
1273 }
1274 else {
1275 /* Leave it and make it a /32 */
1276 /* This is AGAINST the rule! but we have some junk */
1277 /* so we have to compensate for it. */
1278 /* EMPTY */;
1279 }
1280
1281 /* copy the (now - modified) bytes into the end of range */
1282 for(i=0; i<4; i++) {
1283 rangptr->end.words[0] |= (b[i] << i*8);
1284 }
1285
1286 return IP_OK;
1287 }
1288
1289
1290 /***************************************************************************/
1291 /*+
1292 Trying to be smart :-) and convert a query search term into prefix(es),
1293 regardless of whether specified as IP address, prefix or range.
1294
1295 justcheck - if just checking the syntax (justcheck == 1),
1296 then the prefixes are freed before the function returns,
1297 otherwise it is the responsibility of the caller to free the list.
1298
1299 XXX must make sure all memory is freed if INVARG is returned
1300
1301 +*/
1302
1303 er_ret_t
1304 IP_smart_conv(char *key,
/* [<][>][^][v][top][bottom][index][help] */
1305 int justcheck,
1306 int encomp,
1307 GList **preflist,
1308 ip_exp_t expf,
1309 ip_keytype_t *keytype
1310 )
1311 {
1312 int free_it;
1313 er_ret_t call_err, err=IP_OK; /* let's be optimistic :-) */
1314 ip_prefix_t *querypref;
1315
1316 /* if just checking the syntax (justcheck == 1),
1317 then free_it = 1,
1318 else 0, but may be modified later (in range conversion)
1319 */
1320
1321 free_it = justcheck;
1322
1323 if( (call_err = wr_malloc( (void **) &querypref, sizeof(ip_prefix_t)))
1324 != UT_OK) {
1325 return call_err;
1326 }
1327
1328 if( IP_pref_t2b(querypref, key, expf) == IP_OK ) {
1329 *keytype = IPK_PREFIX;
1330
1331 if( justcheck == 0) {
1332 *preflist = g_list_append(*preflist, querypref);
1333 }
1334 }
1335 else {
1336 /* not a prefix. */
1337 /* Maybe an IP ? */
1338 if( IP_addr_t2b( &(querypref->ip), key, expf) == IP_OK ) {
1339
1340 *keytype = IPK_IP;
1341
1342 /*convert to a /32 or /128*/
1343 querypref->bits = IP_sizebits(querypref->ip.space);
1344
1345 if( justcheck == 0) {
1346 *preflist = g_list_append(*preflist, querypref);
1347 }
1348 }
1349 else {
1350 /* hm, maybe a range then ? */
1351 ip_range_t myrang;
1352
1353 /* won't use the querypref anymore, mark it for freeing later */
1354 free_it = 1;
1355
1356 if( IP_rang_t2b(&myrang, key, expf) == IP_OK ) {
1357 /* Wow. Great. */
1358
1359 *keytype = IPK_RANGE;
1360
1361 /* sometimes (exless match) we look for the first bigger(shorter) */
1362 /* prefix containing this range. */
1363
1364 if( encomp ) {
1365 IP_rang_encomp(&myrang);
1366 }
1367 /* OK, now we can let the engine happily find that there's just one */
1368 /* prefix in range */
1369
1370 if( justcheck == 0) {
1371 IP_rang_decomp(&myrang, preflist);
1372 }
1373 }
1374 else {
1375 *keytype = IPK_UNDEF;
1376 err = IP_INVARG; /* "conversion error" */
1377 }
1378 }
1379 }
1380
1381 if( free_it ) {
1382 wr_free(querypref);
1383 }
1384
1385 return err;
1386 }
1387
1388
1389 /* convert whatever comes into a range */
1390 er_ret_t
1391 IP_smart_range(char *key,
/* [<][>][^][v][top][bottom][index][help] */
1392 ip_range_t *rangptr,
1393 ip_exp_t expf,
1394 ip_keytype_t *keytype
1395 )
1396 {
1397 er_ret_t err=IP_OK;
1398 GList *preflist = NULL;
1399
1400 /* first : is it a range ? */
1401
1402 if( (err = IP_rang_t2b(rangptr, key, expf)) == IP_OK ) {
1403 *keytype = IPK_RANGE;
1404 }
1405 else {
1406 /* OK, this must be possible to convert it to prefix and from there
1407 to a range. */
1408 if( (err = IP_smart_conv(key, 0, 0, &preflist, expf, keytype))
1409 == IP_OK ) {
1410
1411 dieif( g_list_length(preflist) != 1 );
1412
1413 dieif(IP_pref_2_rang( rangptr, g_list_first(preflist)->data ) != IP_OK );
1414 }
1415 }
1416
1417 wr_clear_list( &preflist );
1418
1419 return err;
1420 }
1421