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