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.25 $
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 range check 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 *domstr, ip_exp_t expf)
/* [<][>][^][v][top][bottom][index][help] */
298 {
299 #define CPYLEN 264
300 char ip[256], temp[256];
301 char prefstr[CPYLEN+1];
302 char *arpa;
303 char *ch;
304 int len, octets=0, goon=1;
305 char *dot;
306 er_ret_t err;
307
308 dieif( expf != IP_PLAIN && expf != IP_EXPN );
309
310 /* The input may not be in lowercase, but must be processed as well.
311 The simplest solution: make a copy and change it to lowercase. */
312
313 strncpy( prefstr, domstr, CPYLEN );
314 prefstr[CPYLEN] = '\0';
315
316 for(ch = prefstr; *ch != '\0'; ch++) {
317 *ch = tolower(*ch);
318 }
319
320 if( (arpa=strstr(prefstr, ".in-addr.arpa")) == NULL ) {
321
322 #if 0 /* XXX ip6.int version not yet implemented */
323 if( (arpa=strstr(prefstr, ".ip6.int")) != NULL ) {
324 /* ipv6 */
325 }
326 #endif
327
328 return IP_NOREVD;
329 }
330 else {
331 /* copy the IP part to another string, ERROR if 256 chars not enough */
332 len = arpa - prefstr;
333 if( len > 255 ) {
334 /* die; */ /* ERROR - ip address part of the string too long. */
335 return IP_ADTOLO;
336 }
337 strncpy(temp, prefstr, len);
338 temp[len]=0;
339
340 /* now : get the octets reversed one by one. */
341 ip[0]=0; /* init */
342 do {
343 if( (dot = strrchr( temp, '.' )) == NULL ) {
344 goon = 0;
345 dot = temp;
346 }
347
348 strcat(ip, dot + ( goon ) );
349 octets++;
350
351 /* add a dot, unless that was the last octet */
352 if( goon ) {
353 strcat(ip, ".");
354 }
355
356 *dot = 0;
357
358 } while( goon );
359
360 if( (err=IP_addr_t2b( &(prefptr->ip), ip, IP_EXPN)) != IP_OK) {
361 /* die; */ /* set error flag: incorrect address format */
362 return err;
363 }
364
365 prefptr->bits = octets * 8;
366 }
367 return IP_OK;
368 }
369
370 /**************************************************************************/
371
372 /*+ convert a range string into a binary range struct.
373 +*/
374 er_ret_t
375 IP_rang_t2b(ip_range_t *rangptr, char *rangstr, ip_exp_t expf)
/* [<][>][^][v][top][bottom][index][help] */
376 {
377 char *ips, *dash;
378 er_ret_t err;
379
380 if( expf != IP_PLAIN && expf != IP_EXPN ) {
381 return IP_INVARG;
382 }
383
384 if( (dash=index(rangstr, '-')) == NULL ) {
385 /* die; */ /* error: missing dash in range */
386 return IP_INVRAN;
387 }
388 else {
389 /* copy the first IP */
390 if( (err = wr_calloc( (void*) &ips,1,dash - rangstr + 1)) != UT_OK ) {
391 return err;
392 }
393
394 strncpy(ips, rangstr, dash - rangstr);
395
396 /* convert the first IP into a binary struct */
397 err=IP_addr_t2b( &(rangptr->begin), ips, expf);
398
399 /* check later */ /* set error flag: incorrect address format */
400
401 wr_free(ips);
402
403 if( err != IP_OK ) {
404 return err;
405 }
406
407 /* now find the other ip, skip the space */
408 ips=dash+1;
409 while( *ips == ' ' ) {
410 ips++;
411 }
412
413 /* convert the second IP into a binary struct */
414 if( (err=IP_addr_t2b( &(rangptr->end), ips, expf)) != IP_OK ) {
415 /* die; */ /* incorrect address format */
416 return err;
417 }
418
419
420
421 return ip_rang_validate(rangptr);
422 }
423 }
424
425
426 /**************************************************************************/
427 /* accessor functions */
428
429 /******** address **********/
430
431 unsigned IP_addr_b2_space(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
432 {
433 return addrptr->space;
434 }
435
436 unsigned IP_addr_b2v4_addr(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
437 {
438 dieif( addrptr->space != IP_V4 );
439 return addrptr->words[0];
440 }
441 /* ipv4 */
442
443 ip_v6word_t IP_addr_b2v6_hi(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
444 {
445 dieif( addrptr->space != IP_V6 );
446 return ( (((ip_v6word_t) addrptr->words[0]) << 32)
447 + (((ip_v6word_t) addrptr->words[1]) ));
448 }
449
450 ip_v6word_t IP_addr_b2v6_lo(ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
451 {
452 dieif( addrptr->space != IP_V6 );
453 return ( (((ip_v6word_t) addrptr->words[2]) << 32)
454 + (((ip_v6word_t) addrptr->words[3]) ));
455 }
456
457 /******** prefix **********/
458
459 unsigned IP_pref_b2_space(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
460 return IP_addr_b2_space( &(prefix->ip) );
461 }
462
463 unsigned IP_pref_b2_len(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
464 return prefix->bits;
465 }
466
467 unsigned IP_pref_b2v4_addr(ip_prefix_t *prefix) {
/* [<][>][^][v][top][bottom][index][help] */
468 return IP_addr_b2v4_addr( &(prefix->ip) );
469 }
470
471 /* range */
472
473 unsigned IP_rang_b2_space(ip_range_t *myrang) {
/* [<][>][^][v][top][bottom][index][help] */
474 /* hardwire to IPV4 for now */
475 return IP_V4;
476 }
477
478 /*
479 * complex conversions (return void, set values through pointers *
480 */
481 void IP_addr_b2v4(ip_addr_t *addrptr, unsigned *address) {
/* [<][>][^][v][top][bottom][index][help] */
482 *address = IP_addr_b2v4_addr(addrptr);
483 }
484
485 void IP_pref_b2v4(ip_prefix_t *prefptr,
/* [<][>][^][v][top][bottom][index][help] */
486 unsigned int *prefix,
487 unsigned int *prefix_length)
488 {
489 *prefix = IP_addr_b2v4_addr( &(prefptr->ip));
490 *prefix_length = IP_pref_b2v4_len(prefptr);
491 }
492
493
494
495 void IP_pref_b2v6(ip_prefix_t *prefptr,
/* [<][>][^][v][top][bottom][index][help] */
496 ip_v6word_t *high,
497 ip_v6word_t *low,
498 unsigned int *prefix_length)
499 {
500 *high = IP_addr_b2v6_hi( &(prefptr->ip));
501 *low = IP_addr_b2v6_lo( &(prefptr->ip));
502 *prefix_length = IP_pref_b2v6_len(prefptr);
503 }
504
505
506 void IP_rang_b2v4(ip_range_t *myrang,
/* [<][>][^][v][top][bottom][index][help] */
507 unsigned *begin,
508 unsigned *end)
509 {
510 *begin = IP_addr_b2v4_addr( &(myrang->begin));
511 *end = IP_addr_b2v4_addr( &(myrang->end));
512 }
513
514
515
516 /******** construct from raw values **********/
517
518 /******** address **********/
519 er_ret_t IP_addr_v4_mk(ip_addr_t *addrptr,
/* [<][>][^][v][top][bottom][index][help] */
520 unsigned addrval) {
521 addrptr->space = IP_V4;
522 addrptr->words[0] = addrval;
523 addrptr->words[1] = addrptr->words[2] = addrptr->words[3] = 0;
524
525 /* no real possibility of checking the syntax */
526 return IP_OK;
527 }
528
529 er_ret_t IP_addr_v6_mk(ip_addr_t *addrptr,
/* [<][>][^][v][top][bottom][index][help] */
530 ip_v6word_t high,
531 ip_v6word_t low) {
532
533 ip_v6word_t ff = 0xffffffff;
534
535 addrptr->space = IP_V6;
536 (addrptr->words[0]) = (high >> 32) & ff;
537 (addrptr->words[1]) = high & ff ;
538 (addrptr->words[2]) = (low >> 32) & ff;
539 (addrptr->words[3]) = low & ff;
540
541 /* no real possibility of checking the syntax */
542 return IP_OK;
543 }
544
545 /******** prefix **********/
546 er_ret_t IP_pref_v4_mk(ip_prefix_t *prefix,
/* [<][>][^][v][top][bottom][index][help] */
547 unsigned prefval,
548 unsigned preflen)
549 {
550 if( preflen > 32 ) {
551 die;
552 }
553 IP_addr_v4_mk(&(prefix->ip), prefval);
554 prefix->bits = preflen;
555
556 IP_pref_bit_fix( prefix ); /* never produce inconsistent prefixes */
557
558 return IP_OK;
559 }
560
561 /******** range **********/
562 er_ret_t IP_rang_v4_mk(ip_range_t *rangptr,
/* [<][>][^][v][top][bottom][index][help] */
563 unsigned addrbegin,
564 unsigned addrend)
565 {
566 er_ret_t err;
567
568 if( (err=IP_addr_v4_mk( &(rangptr->begin), addrbegin)) == IP_OK ) {
569 err=IP_addr_v4_mk( &(rangptr->end), addrend);
570 }
571 return err;
572 }
573
574 /**************************************************************************/
575
576
577 /**************************************************************************/
578 /*+ a2v4 == functions to convert the ascii representation into binary,
579 * and then set the unsigned values at the pointers provided.
580 *
581 +*/
582
583 /* Convert route string into numbers */
584 /* ipv4 */
585 er_ret_t
586 IP_pref_a2v4(char *avalue, ip_prefix_t *pref,
/* [<][>][^][v][top][bottom][index][help] */
587 unsigned *prefix, unsigned *prefix_length)
588 {
589
590 er_ret_t ret;
591
592 if((ret = IP_pref_e2b(pref, avalue)) == IP_OK) {
593 IP_pref_b2v4(pref, prefix, prefix_length);
594 }
595 return(ret);
596 }
597
598 /* ipv6 */
599 er_ret_t
600 IP_pref_a2v6(char *avalue, ip_prefix_t *pref,
/* [<][>][^][v][top][bottom][index][help] */
601 ip_v6word_t *high, ip_v6word_t *low,
602 unsigned *prefix_length)
603 {
604 er_ret_t ret;
605
606 if((ret = IP_pref_e2b(pref, avalue)) == IP_OK) {
607 IP_pref_b2v6(pref, high, low, prefix_length);
608 }
609 return(ret);
610 }
611
612 /* Convert reverse domain string into numbers */
613 er_ret_t
614 IP_revd_a2v4(char *avalue, ip_prefix_t *pref,
/* [<][>][^][v][top][bottom][index][help] */
615 unsigned int *prefix, unsigned int *prefix_length)
616 {
617 er_ret_t ret;
618
619 if((ret = IP_revd_e2b(pref, avalue)) == IP_OK) {
620 IP_pref_b2v4(pref, prefix, prefix_length);
621 }
622 return(ret);
623 }
624
625 /* Convert ip addr string into numbers */
626 er_ret_t
627 IP_addr_a2v4(char *avalue,ip_addr_t *ipaddr, unsigned int *address)
/* [<][>][^][v][top][bottom][index][help] */
628 {
629 er_ret_t ret;
630
631 if((ret = IP_addr_e2b(ipaddr, avalue)) == IP_OK) {
632 IP_addr_b2v4(ipaddr, address);
633 }
634 return(ret);
635 }
636
637 /* Convert inetnum attribute into numbers */
638 er_ret_t
639 IP_rang_a2v4(char *rangstr, ip_range_t *myrang,
/* [<][>][^][v][top][bottom][index][help] */
640 unsigned int *begin_in, unsigned int *end_in)
641 {
642 er_ret_t ret;
643
644 if( (ret=IP_rang_e2b(myrang, rangstr)) == IP_OK ) {
645 #if 0 /* no IPv4 classful ranges anymore */
646 if( IP_addr_e2b( &(myrang->begin), rangstr ) == IP_OK )
647 if ((ret=IP_rang_classful( myrang , &(myrang->begin))) == IP_OK )
648 ;
649 #endif
650 IP_rang_b2v4(myrang, begin_in, end_in);
651 }
652
653 return (ret);
654 }
655
656
657 /* *********************************************************************
658 f2b - free numbers represented in ascii into a binary struct
659 ********************************************************************* */
660
661 er_ret_t
662 IP_addr_f2b_v4(ip_addr_t *addrptr, char *adrstr)
/* [<][>][^][v][top][bottom][index][help] */
663 {
664 unsigned address;
665
666 if( ut_dec_2_uns(adrstr, &address) < 0 ) {
667 return IP_INVARG;
668 }
669
670 return IP_addr_v4_mk(addrptr, address);
671 }
672
673 er_ret_t
674 IP_rang_f2b_v4(ip_range_t *rangptr, char *beginstr, char *endstr)
/* [<][>][^][v][top][bottom][index][help] */
675 {
676 if( IP_addr_f2b_v4( &(rangptr->begin), beginstr) != IP_OK
677 || IP_addr_f2b_v4( &(rangptr->end), endstr) != IP_OK) {
678 return IP_INVARG;
679 }
680 else {
681 return IP_OK;
682 }
683 }
684
685 er_ret_t
686 IP_pref_f2b_v4(ip_prefix_t *prefptr, char *prefixstr, char *lengthstr)
/* [<][>][^][v][top][bottom][index][help] */
687 {
688 if( IP_addr_f2b_v4( &(prefptr->ip), prefixstr) != IP_OK
689 || ut_dec_2_uns(lengthstr, &(prefptr->bits) ) < 0
690 || prefptr->bits > IP_sizebits(prefptr->ip.space)) {
691 return IP_INVARG;
692 }
693 IP_pref_bit_fix(prefptr); /* never create broken binary prefixes. */
694 return IP_OK;
695 }
696
697
698 er_ret_t
699 IP_addr_f2b_v6(ip_addr_t *addrptr, char *msbstr, char *lsbstr )
/* [<][>][^][v][top][bottom][index][help] */
700 {
701 ip_v6word_t high, low;
702
703 if( sscanf(msbstr, "%llu", &high) < 1 ||
704 sscanf(lsbstr, "%llu", &low) < 1 ) {
705 return IP_INVARG;
706 }
707
708 return IP_addr_v6_mk(addrptr, high, low);
709 }
710
711
712 er_ret_t
713 IP_pref_f2b_v6(ip_prefix_t *prefptr, char *msbstr, char *lsbstr, char *lengthstr)
/* [<][>][^][v][top][bottom][index][help] */
714 {
715 if( IP_addr_f2b_v6( &(prefptr->ip), msbstr, lsbstr ) != IP_OK
716 || ut_dec_2_uns(lengthstr, &(prefptr->bits) ) < 0
717 || prefptr->bits > IP_sizebits(prefptr->ip.space)) {
718 return IP_INVARG;
719 }
720 IP_pref_bit_fix(prefptr); /* never create broken binary prefixes. */
721 return IP_OK;
722 }
723
724
725 /**************************************************************************/
726 /*+ convert the socket's idea of address into a binary range struct.
727
728 space select the address type (and consequently struct type)
729 */
730
731 er_ret_t
732 IP_addr_s2b(ip_addr_t *addrptr,
/* [<][>][^][v][top][bottom][index][help] */
733 void *addr_in,
734 int addr_len)
735 {
736 if( addr_len == sizeof(struct sockaddr_in)
737 && ((struct sockaddr_in *)addr_in)->sin_family == AF_INET ) {
738 addrptr->space = IP_V4;
739 addrptr->words[0] =
740 ntohl( ((struct sockaddr_in*)addr_in)->sin_addr.s_addr);
741
742 /* set remaining limbs to zero */
743 addrptr->words[1] = addrptr->words[2] = addrptr->words[3] = 0;
744
745 }
746 else { /* unsupported family or invalid struct */
747 die;
748 }
749 return IP_OK;
750 }
751
752 /**************************************************************************/
753 /*+converts the IP binary address (binaddr) to a string (ascaddr)
754 of at most strmax characters. Independent of the result
755 (success or failure) it messes up the string.
756 +*/
757 er_ret_t
758 IP_addr_b2a( ip_addr_t *binaddr, char *ascaddr, int strmax )
/* [<][>][^][v][top][bottom][index][help] */
759 {
760
761 if(binaddr->space == IP_V4) {
762 if (snprintf(ascaddr, strmax, "%d.%d.%d.%d",
763 ((binaddr->words[0]) & ((unsigned)0xff<<24))>>24,
764 ((binaddr->words[0]) & (0xff<<16))>>16,
765 ((binaddr->words[0]) & (0xff<<8))>>8,
766 ((binaddr->words[0]) & (0xff<<0))>>0
767 ) >= strmax) {
768 /*die; */ /* string too short */
769 return IP_TOSHRT;
770 }
771 }
772 else {
773 /* IPv6 */
774
775 if( inet_ntop(AF_INET6, &(binaddr->words[0]), ascaddr, strmax)
776 == NULL ) {
777 return IP_TOSHRT;
778 }
779
780 /* not yet implemented. Sorry. */
781 /* die; */
782 /*return IP_NO6YET;*/
783 }
784 return IP_OK;
785 }
786
787 /**************************************************************************/
788
789 /*+ convert a binary prefix back into ascii string at most strmax chars long
790 +*/
791 er_ret_t
792 IP_pref_b2a(ip_prefix_t *prefptr, char *ascaddr, int strmax)
/* [<][>][^][v][top][bottom][index][help] */
793 {
794 int strl;
795 er_ret_t err;
796
797 if( (err=IP_addr_b2a (&(prefptr->ip), ascaddr, strmax)) != IP_OK) {
798 /*die; */ /* what the hell */
799 return err;
800 }
801 strl = strlen(ascaddr);
802 strmax -= strl;
803
804 /* now strmax holds the space that is left */
805
806 if( snprintf(ascaddr+strl, strmax, "/%d", prefptr->bits) >= strmax) {
807 /* die; */ /* error: string too short */
808 return IP_TOSHRT;
809 }
810 return IP_OK;
811 }
812
813
814
815 /**************************************************************************/
816 /*+ convert a binary range back into ascii string at most strmax chars long
817 +*/
818 er_ret_t
819 IP_rang_b2a(ip_range_t *rangptr, char *ascaddr, int strmax)
/* [<][>][^][v][top][bottom][index][help] */
820 {
821 int strl=0, strleft;
822 er_ret_t err;
823
824 strleft = strmax - strl;
825 if( (err=IP_addr_b2a (&(rangptr->begin), ascaddr, strleft)) != IP_OK) {
826 return err;
827 }
828 strl = strlen(ascaddr);
829
830 strleft = strmax - strl;
831 if( strleft < 5 ) {
832 return IP_TOSHRT;
833 }
834 strcat( ascaddr, " - " );
835 strl += 3;
836
837 strleft = strmax - strl;
838 if( (err=IP_addr_b2a (&(rangptr->end), ascaddr+strl, strleft)) != IP_OK) {
839 return err;
840 }
841
842 return IP_OK;
843 }
844
845 /**************************************************************************/
846 /*+ return the bitnum bit of the address,
847 COUNTING FROM THE TOP !!!!! ,
848 starting with 0 for the *most significant bit*.
849 +*/
850 int
851 IP_addr_bit_get(ip_addr_t *binaddr, int bitnum) {
/* [<][>][^][v][top][bottom][index][help] */
852 int bitval;
853 int w,c;
854
855 /* avoid unnecessary division */
856 if( binaddr->space == IP_V4 ) {
857 w = 0;
858 c = bitnum;
859 }
860 else {
861 w = bitnum / 32;
862 c = bitnum % 32;
863 }
864
865 bitval = (binaddr->words[w] & (0x80000000 >> (c)));
866
867 return (bitval != 0);
868
869 }
870
871 /**************************************************************************/
872 /*+ set the bitnum bit of the address to bitval,
873 COUNTING FROM THE TOP !!!!! ,
874 starting with 0 for the *most significant bit*.
875 +*/
876 void
877 IP_addr_bit_set(ip_addr_t *binaddr, int bitnum, int bitval) {
/* [<][>][^][v][top][bottom][index][help] */
878 int w,c;
879
880 /* avoid unnecessary division */
881 if( binaddr->space == IP_V4 ) {
882 w = 0;
883 c = bitnum;
884 }
885 else {
886 w = bitnum / 32;
887 c = bitnum % 32;
888 }
889
890 if ( bitval == 1 )
891
892 binaddr->words[w] |= (0x80000000 >> (c));
893 else
894 binaddr->words[w] &= ~(0x80000000 >> (c));
895 }
896 /**************************************************************************/
897
898 /*+ this fixes a prefix by setting insignificant bits to 0 +*/
899 void
900 IP_pref_bit_fix( ip_prefix_t *prefix )
/* [<][>][^][v][top][bottom][index][help] */
901 {
902
903 if( prefix->ip.space == IP_V4 ) {
904 ip_limb_t mask = 0xffffffff;
905
906 /* shorthand for ipv4 */
907
908 /* Shifting out by 32 bits does NOT turn all bits into 0... */
909 if( prefix->bits < 32 ) {
910 prefix->ip.words[0] &= ~(mask >> prefix->bits);
911 }
912 }
913 else {
914 int i;
915 for(i=prefix->bits; i < IP_sizebits(prefix->ip.space) ; i++) {
916 IP_addr_bit_set( & prefix->ip, i, 0);
917 }
918 }
919 }
920
921
922 /**************************************************************************/
923
924 /*+ compares two IP addresses up to the bit # len,
925 returns 0 if equal, 1 if ptra greater, -1 if ptrb greater.
926
927 It is the responsility of the caller to ensure that both addresses
928 are from the same IP space.
929
930 This is pretty slow; it is used in the searches of the radix tree,
931 so it might be good to optimise this.
932 +*/
933
934 int
935 IP_addr_cmp(ip_addr_t *ptra, ip_addr_t *ptrb, int len)
/* [<][>][^][v][top][bottom][index][help] */
936 {
937 int a,b,i;
938
939 for(i=0; i<len; i++) {
940 a=IP_addr_bit_get(ptra, i);
941 b=IP_addr_bit_get(ptrb, i);
942 if( a != b ) {
943 if( a > b ) return 1;
944 else return -1;
945 }
946 }
947 return 0;
948 }
949
950
951 /*+ checks if an IP address is contained within the prefix
952 returns 1 if it is, 0 otherwise
953
954 It is the responsility of the caller to ensure that both address
955 and prefix are from the same IP space.
956 +*/
957 int
958 IP_addr_in_pref(ip_addr_t *ptra, ip_prefix_t *prefix)
/* [<][>][^][v][top][bottom][index][help] */
959 {
960 return (IP_addr_cmp( ptra, & prefix->ip, prefix->bits) == 0);
961 }
962
963 /*+ checks if an IP address is contained within the range
964 returns 1 if it is, 0 otherwise
965
966 It is the responsility of the caller to ensure that both address
967 and range are from the same IP space.
968
969 works only for IPv4
970 +*/
971
972 int IP_addr_in_rang(ip_addr_t *ptra, ip_range_t *rangptr)
/* [<][>][^][v][top][bottom][index][help] */
973 {
974 /* if( rangptr->end.space == IP_V4 ) {
975 return ( rangptr->begin.words[0] <= ptra->words[0]
976 && rangptr->end.words[0] >= ptra->words[0] );
977 }
978 else {
979 */
980 return( IP_addr_cmp(ptra, &rangptr->begin,
981 IP_sizebits(rangptr->end.space)) >= 0 /* adr >= begin */
982 && IP_addr_cmp(ptra, &rangptr->end,
983 IP_sizebits(rangptr->end.space)) <= 0 /* adr <= end */
984 );
985 /* }*/
986 }
987
988 /**************************************************************************/
989
990 /*+ calculate the span of a range == size - 1 +*/
991
992 ip_rangesize_t
993 IP_rang_span( ip_range_t *rangptr )
/* [<][>][^][v][top][bottom][index][help] */
994 {
995 /* IPv4: */
996 dieif( rangptr->end.space != IP_V4 );
997
998 return rangptr->end.words[0] - rangptr->begin.words[0];
999 }
1000
1001
1002 /**************************************************************************/
1003
1004 /*+
1005 this is a shorthand notation to pull out the first word of the address.
1006 it is defined for the scope od the following functions
1007 +*/
1008 #define ad(which) (rangptr->which)
/* [<][>][^][v][top][bottom][index][help] */
1009
1010 /**************************************************************************/
1011 /*+ Decomposes a binary range into prefixes and appends them to the list.
1012 Allocates prefix structures and list elements, they must be freed
1013 after use.
1014
1015 returns a bitmask of prefix lengths used.
1016 +*/
1017 unsigned
1018 IP_rang_decomp(ip_range_t *rangptr, GList **preflist)
/* [<][>][^][v][top][bottom][index][help] */
1019 {
1020 unsigned prefmask=0;
1021 register int slash=0;
1022 register unsigned c_dif, blk, ff;
1023 ip_range_t workrange;
1024 ip_addr_t workbegin;
1025 ip_addr_t workend;
1026 ip_prefix_t *prefptr;
1027
1028 dieif( rangptr->begin.space != IP_V4 );
1029
1030 if( ad(begin).words[0] > ad(end).words[0] ) { /* has gone too far */
1031 return 0;
1032 }
1033
1034 if( ad(begin).words[0] == ad(end).words[0] ) { /* an IP == a /32 (IPv4) */
1035 prefmask |= 1;
1036 if( wr_calloc( (void **)& prefptr, sizeof(ip_prefix_t), 1) != UT_OK) {
1037 die;
1038 }
1039 prefptr->ip = ad(begin);
1040 prefptr->bits = 32;
1041
1042 *preflist = g_list_append( *preflist, prefptr );
1043
1044 return prefmask;
1045 }
1046
1047 c_dif = ad(end).words[0] - ad(begin).words[0];
1048
1049 /* initialize work vars */
1050
1051 workbegin = ad(begin);
1052 workend = ad(end);
1053
1054 /* now find the biggest block fitting in this range */
1055 /* i.e. the first 2^n number smaller than c_dif */
1056
1057 /* the loop would not work for /0 (some stupid queries may have that) */
1058 /* so this must be checked for separately */
1059
1060 if( c_dif == 0xffffffff ) {
1061 /* they are already set to 0.0.0.0 - 255.255.255.255 */
1062 /* leave them alone. */
1063 blk = 0;
1064 slash = 0;
1065 }
1066 else {
1067
1068 c_dif += 1; /* was not done earlier to protect from overflow */
1069
1070 for(slash=1;
1071 slash<32 && ((blk=((unsigned)0x80000000>>(slash-1))) & c_dif) == 0;
1072 slash++) {}
1073
1074 /* clear all digits in a and b under the blk one. */
1075 ff=blk-1;
1076
1077 workbegin.words[0] = (workbegin.words[0] + ff) & ~ff;
1078
1079 workend.words[0] = (workend.words[0] + 1) & ~ff;
1080 }
1081
1082 if( workbegin.words[0] != workend.words[0] ) {
1083 prefmask |= blk;
1084 if( wr_malloc( (void **)& prefptr, sizeof(ip_prefix_t)) != UT_OK) {
1085 die;
1086 }
1087 prefptr->ip = workbegin;
1088 prefptr->bits = slash;
1089
1090 *preflist = g_list_append( *preflist, prefptr );
1091 }
1092
1093 if( ad(begin).words[0] != workbegin.words[0] ) {
1094 workrange.begin = ad(begin);
1095
1096 workbegin.words[0] -= 1;
1097 workrange.end = workbegin;
1098
1099 prefmask |= IP_rang_decomp( &workrange, preflist );
1100 }
1101
1102 /* here we must protect from decomposition of
1103 * 255.255.255.255 - 255.255.255.255 in case the range
1104 * 0.0.0.0 - 255.255.255.255 is considered. Hence the slash>0 condition.
1105 */
1106
1107 if( workend.words[0] <= ad(end).words[0] && slash > 0) {
1108 workrange.begin = workend;
1109 workrange.end = ad(end);
1110
1111 prefmask |= IP_rang_decomp( &workrange, preflist );
1112 }
1113
1114 return prefmask;
1115
1116 }
1117
1118
1119 /***************************************************************************/
1120
1121 /*+ Similar name, slightly different code, totally different functionality.
1122
1123 finds the smallest canonical block encompassing the whole given range,
1124 then MODIFIES the range pointed to by the argument
1125 so that it's equal to this block.
1126
1127 +*/
1128
1129 void IP_rang_encomp(ip_range_t *rangptr)
/* [<][>][^][v][top][bottom][index][help] */
1130 {
1131 int slash=0;
1132 unsigned c_dif, blk, ff, t_dif;
1133 ip_addr_t workbegin;
1134 ip_addr_t workend;
1135
1136 dieif( rangptr->begin.space != IP_V4 );
1137
1138 c_dif = ad(end).words[0] - ad(begin).words[0];
1139
1140 /* now find the biggest block fitting in this range */
1141 /* i.e. the first 2^n number smaller than c_dif */
1142
1143 /* the loop would not work for /0 (some stupid queries may have that) */
1144 /* so this must be checked for separately */
1145
1146 if( c_dif > 0x80000000 ) {
1147 slash = 0;
1148 ff = 0xffffffff;
1149 blk = 0;
1150
1151 workbegin = workend = ad(begin);
1152 workbegin.words[0] = 0;
1153 workend.words[0] = ff;
1154 }
1155 else {
1156
1157 do {
1158 c_dif += 1;
1159
1160 /* find the smallest block ENCOMPASSING c_dif. */
1161 /* this implies a loop from the bottom up */
1162
1163 for(slash=32;
1164 slash>1 && (blk=((unsigned)0x80000000>>(slash-1))) < c_dif;
1165 slash--) {}
1166
1167 ff=blk-1;
1168
1169 /* clear all digits in workbegin under the blk one. */
1170
1171 workbegin = ad(begin);
1172 workbegin.words[0] = workbegin.words[0] & ~ff;
1173
1174 /* see if it has not made the difference larger than blk, */
1175 /* retry if so */
1176
1177 t_dif = c_dif;
1178 c_dif = ad(end).words[0] - workbegin.words[0];
1179
1180 } while( c_dif >= t_dif );
1181
1182 /* set the endpoint to workbegin + blocksize - 1 */
1183 /* which amounts to + ff */
1184
1185 workend = ad(begin);
1186 workend.words[0] = workbegin.words[0] + ff;
1187 }
1188
1189
1190 /* set the range to new values */
1191
1192 rangptr->begin = workbegin;
1193 rangptr->end = workend;
1194 }
1195
1196 /***************************************************************************/
1197 /*+ sets a range equal to a prefix +*/
1198
1199 er_ret_t
1200 IP_pref_2_rang( ip_range_t *rangptr, ip_prefix_t *prefptr )
/* [<][>][^][v][top][bottom][index][help] */
1201 {
1202 int shift;
1203 int i;
1204
1205 ad(begin) = ad(end) = prefptr->ip;
1206
1207 /* IPv6 is a bit more complicated, as four words are involved */
1208
1209 /* additional problem: shifting right by >=32 is equal to shifting by 0,
1210 so it does not change any bits */
1211 /* solution: don't touch those words */
1212
1213 for(i=0; i<4; i++) {
1214
1215 if( prefptr->bits < 32*(1+i) ) {
1216 shift = prefptr->bits < 32 + (i-1) * 32
1217 ? 0 : (prefptr->bits % 32) ;
1218 ad(end).words[i] |= (0xffffffffU >> shift);
1219 }
1220
1221 if( prefptr->ip.space == IP_V4) {
1222 break; /* do only first word for IPv4 */
1223 }
1224 }
1225 return IP_OK;
1226 }
1227
1228 #undef ad
1229
1230 /***************************************************************************/
1231
1232 /*+
1233 This is to parse a classfull address into a range.
1234
1235 Takes the address by pointer from addrptr and puts the result
1236 at rangptr.
1237
1238 Throws error if the address does not fall into any of the
1239 classfull categories
1240
1241 +*/
1242
1243 er_ret_t
1244 IP_rang_classful( ip_range_t *rangptr, ip_addr_t *addrptr)
/* [<][>][^][v][top][bottom][index][help] */
1245 {
1246 int i;
1247 unsigned b[4];
1248
1249 if( addrptr->space != IP_V4 ) {
1250 /* it's IPv6. There are no classful ranges or anything like that. */
1251 die;
1252 }
1253
1254 rangptr->begin = *addrptr;
1255 rangptr->end.space = IP_V4;
1256
1257 /* initisalise end to zero */
1258 for(i=0; i<IPLIMBNUM; i++) {
1259 rangptr->end.words[i] = 0;
1260 }
1261
1262 /* assume it's at least a valid IP. let's try different classes now */
1263
1264 /* we could have used a union here, but it would not work on */
1265 /* low endians. So byte by byte copying to and from an array. */
1266
1267 for(i=0; i<4; i++) {
1268 b[i] = ( rangptr->begin.words[0] & (0xFF << i*8) ) >> i*8;
1269 }
1270
1271 if( b[3] >= 1 && b[3] < 128
1272 && b[2] == 0 && b[1] == 0 && b[0] == 0 ) {
1273 b[2]=b[1]=b[0]=255;
1274 }
1275 else if( b[3] >= 128 && b[3] < 192
1276 && b[1] == 0 && b[0] == 0 ) {
1277 b[1]=b[0]=255;
1278 }
1279 else if( b[3] >= 192 && b[3] < 224
1280 && b[0] == 0 ) {
1281 b[0]=255;
1282 }
1283 else if( b[3] >= 224 && b[3] < 255 ) {
1284 /* just leave it, make it a /32, i.e. begin == end */
1285 /* EMPTY */;
1286 }
1287 else {
1288 /* Leave it and make it a /32 */
1289 /* This is AGAINST the rule! but we have some junk */
1290 /* so we have to compensate for it. */
1291 /* EMPTY */;
1292 }
1293
1294 /* copy the (now - modified) bytes into the end of range */
1295 for(i=0; i<4; i++) {
1296 rangptr->end.words[0] |= (b[i] << i*8);
1297 }
1298
1299 return IP_OK;
1300 }
1301
1302
1303 /***************************************************************************/
1304 /*+
1305 Trying to be smart :-) and convert a query search term into prefix(es),
1306 regardless of whether specified as IP address, prefix or range.
1307
1308 justcheck - if just checking the syntax (justcheck == 1),
1309 then the prefixes are freed before the function returns,
1310 otherwise it is the responsibility of the caller to free the list.
1311
1312 +*/
1313
1314 er_ret_t
1315 IP_smart_conv(char *key,
/* [<][>][^][v][top][bottom][index][help] */
1316 int justcheck,
1317 int encomp,
1318 GList **preflist,
1319 ip_exp_t expf,
1320 ip_keytype_t *keytype
1321 )
1322 {
1323 int free_it;
1324 er_ret_t call_err, err=IP_OK; /* let's be optimistic :-) */
1325 ip_prefix_t *querypref;
1326
1327 /* if just checking the syntax (justcheck == 1),
1328 then free_it = 1,
1329 else 0, but may be modified later (in range conversion)
1330 */
1331
1332 free_it = justcheck;
1333
1334 if( (call_err = wr_malloc( (void **) &querypref, sizeof(ip_prefix_t)))
1335 != UT_OK) {
1336 return call_err;
1337 }
1338
1339 if( IP_pref_t2b(querypref, key, expf) == IP_OK ) {
1340 *keytype = IPK_PREFIX;
1341
1342 if( justcheck == 0) {
1343 *preflist = g_list_append(*preflist, querypref);
1344 }
1345 }
1346 else {
1347 /* not a prefix. */
1348 /* Maybe an IP ? */
1349 if( IP_addr_t2b( &(querypref->ip), key, expf) == IP_OK ) {
1350
1351 *keytype = IPK_IP;
1352
1353 /*convert to a /32 or /128*/
1354 querypref->bits = IP_sizebits(querypref->ip.space);
1355
1356 if( justcheck == 0) {
1357 *preflist = g_list_append(*preflist, querypref);
1358 }
1359 }
1360 else {
1361 /* hm, maybe a range then ? */
1362 ip_range_t myrang;
1363
1364 /* won't use the querypref anymore, mark it for freeing later */
1365 free_it = 1;
1366
1367 if( IP_rang_t2b(&myrang, key, expf) == IP_OK ) {
1368 /* Wow. Great. */
1369
1370 *keytype = IPK_RANGE;
1371
1372 /* sometimes (exless match) we look for the first bigger(shorter) */
1373 /* prefix containing this range. */
1374
1375 if( encomp ) {
1376 IP_rang_encomp(&myrang);
1377 }
1378 /* OK, now we can let the engine happily find that there's just one */
1379 /* prefix in range */
1380
1381 if( justcheck == 0) {
1382 IP_rang_decomp(&myrang, preflist);
1383 }
1384 }
1385 else {
1386 *keytype = IPK_UNDEF;
1387 err = IP_INVARG; /* "conversion error" */
1388 }
1389 }
1390 }
1391
1392 if( free_it ) {
1393 wr_free(querypref);
1394 }
1395
1396 return err;
1397 }
1398
1399
1400 /* convert whatever comes into a range */
1401 er_ret_t
1402 IP_smart_range(char *key,
/* [<][>][^][v][top][bottom][index][help] */
1403 ip_range_t *rangptr,
1404 ip_exp_t expf,
1405 ip_keytype_t *keytype
1406 )
1407 {
1408 er_ret_t err=IP_OK;
1409 GList *preflist = NULL;
1410
1411 /* first : is it a range ? */
1412
1413 if( (err = IP_rang_t2b(rangptr, key, expf)) == IP_OK ) {
1414 *keytype = IPK_RANGE;
1415 }
1416 else {
1417 /* OK, this must be possible to convert it to prefix and from there
1418 to a range. */
1419 if( (err = IP_smart_conv(key, 0, 0, &preflist, expf, keytype))
1420 == IP_OK ) {
1421
1422 dieif( g_list_length(preflist) != 1 );
1423
1424 dieif(IP_pref_2_rang( rangptr, g_list_first(preflist)->data ) != IP_OK );
1425 }
1426 }
1427
1428 wr_clear_list( &preflist );
1429
1430 return err;
1431 }
1432