1 /*****************************************************************
2 ** @(#) ip6.c
3 *****************************************************************/
4 # include <stdio.h>
5 # include <assert.h>
6 # include <string.h>
7 # include <ctype.h>
8 # include <stdlib.h>
9
10 # include "debug.h"
11
12 #define extern
13 # include "ip6.h"
14 #undef extern
15
16 #define isipv6char(c) ((c) == ':' || isxdigit(c))
17
18 static const char *ip6addrfmt = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
19 static const char *ip6hostfmtpart = ":%04x";
20 static const char *ip6subfmtpart = "%04x:";
21
22 static char *ip62string (char *str, size_t size, const ip6_t *ipv6, int norm);
23
24 #if 0
25 /*****************************************************************
26 ** count the number of leading 0 bits in "val"
27 *****************************************************************/
28 static int nbits0 (unsigned short val)
29 {
30 int nbits;
31
32 if ( val == 0 )
33 return 16;
34
35 nbits = 0;
36 while ( (val & 0x8000) == 0 )
37 {
38 nbits++;
39 val <<= 1;
40 }
41
42 return nbits;
43 }
44 #endif
45
46 /*****************************************************************
47 **
48 ** ip62string print the ipv6 address "normalized" or "abbreviated"
49 ** into the string "str"
50 ** if "str" is NULL, then an internal static buffer will be used
51 ** and a pointer to this buffer will be returned.
52 ** Otherwise the return value is a pointer to "str".
53 **
54 *****************************************************************/
ip62string(char * str,size_t size,const ip6_t * ipv6,int norm)55 static char *ip62string (char *str, size_t size, const ip6_t *ipv6, int norm)
56 {
57 static char v6addr[IPV6_STR_SIZE + 1];
58 int len;
59
60 assert ( ipv6 != NULL );
61
62 if ( str == NULL )
63 {
64 str = v6addr;
65 size = sizeof (v6addr);
66 }
67 str[0] = '\0';
68
69 if ( !ip6isset (ipv6) )
70 return str;
71
72 if ( norm || ipv6->sbit == 0 ) /* prefix or host ip */
73 {
74 // snprintf (str, size, "%x:%x:%x:%x:%x:%x:%x:%x",
75 //len = snprintf (str, size, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
76 len = snprintf (str, size, ip6addrfmt,
77 ipv6->addr[0], ipv6->addr[1], ipv6->addr[2],
78 ipv6->addr[3], ipv6->addr[4], ipv6->addr[5],
79 ipv6->addr[6], ipv6->addr[7]);
80 if ( ipv6->ebit != 128 )
81 snprintf (str+len, size-len, "/%u", ipv6->ebit);
82 }
83 else if ( ipv6->ebit == 128 ) /* interface id */
84 {
85 int i;
86
87 len = snprintf (str, size, ":");
88 i = ipv6->sbit / 16;
89 //fprintf (stderr, "i = %d len = %d\n", i, len);
90 while ( i < 8 )
91 len += snprintf (str+len, size-len, ip6hostfmtpart /*":%04x"*/, ipv6->addr[i++]);
92 }
93 else /* subnet id */
94 {
95 int i, j;
96
97 len = snprintf (str, size, ":");
98 i = ipv6->sbit / 16;
99 j = ipv6->ebit / 16;
100 //fprintf (stderr, "i = %d j = %d\n", i, j);
101 while ( i < j )
102 len += snprintf (str+len, size-len, ip6subfmtpart /*"%04x:"*/, ipv6->addr[i++]);
103 }
104
105 return str;
106 }
107
108 /*****************************************************************
109 ** ip6isset (ip)
110 *****************************************************************/
ip6isset(const ip6_t * ipv6)111 int ip6isset (const ip6_t *ipv6)
112 {
113 return (ipv6 && ipv6->isset);
114 }
115
116 /*****************************************************************
117 ** ip6setfmt (int upper)
118 *****************************************************************/
ip6setfmt(int upper)119 void ip6setfmt (int upper)
120 {
121 if ( upper )
122 {
123 ip6addrfmt = "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X";
124 ip6hostfmtpart = ":%04X";
125 ip6subfmtpart = "%04X:";
126 }
127 else
128 {
129 ip6addrfmt = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
130 ip6hostfmtpart = ":%04x";
131 ip6subfmtpart = "%04x:";
132 }
133 }
134
135
136 /*****************************************************************
137 ** ip6put ()
138 *****************************************************************/
ip6put(FILE * fp,ip6_t * ip)139 int ip6put (FILE *fp, ip6_t *ip)
140 {
141 char str[IPV6_STR_SIZE];
142
143 assert ( fp != NULL );
144 assert ( ip != NULL );
145
146 ip6tostr (str, sizeof str, ip);
147
148 return fprintf (fp, "%s", str);
149 }
150
151 /*****************************************************************
152 **
153 ** ip6tostring print the ipv6 address "normalized" into the
154 ** string "str"
155 **
156 ** The output is always a full blown ipv6 address with or
157 ** w/o a prefix (sbit < 128)
158 **
159 *****************************************************************/
ip6tostring(char * str,size_t size,const ip6_t * ipv6)160 char *ip6tostring (char *str, size_t size, const ip6_t *ipv6)
161 {
162 return ip62string (str, size, ipv6, 1);
163 }
164
165 /*****************************************************************
166 **
167 ** ip6tostring print the ipv6 address "abbreviated" into the
168 ** string "str"
169 ** The Output depends on the value of the s/ebits
170 **
171 ** sbit & ebit output
172 ** 0 128 ~~~~:~~~~:~~~~:~~~~:~~~~:~~~~:~~~~:~~~~
173 ** 0 x ~~~~:~~~~:~~~~:~~~~::/x
174 ** x 128 ::~~~~:~~~~:~~~~:~~~~
175 ** >48 64 :~~~~:
176 **
177 *****************************************************************/
ip6tostr(char * str,size_t size,const ip6_t * ipv6)178 char *ip6tostr (char *str, size_t size, const ip6_t *ipv6)
179 {
180 return ip62string (str, size, ipv6, 0);
181 }
182
183
184 /*****************************************************************
185 **
186 ** ip6fromstr() read an ipv6 address from str
187 **
188 ** this could be a full blown ipv6 address including a prefixlen
189 ** or a hostid starting with "::" or a subnetid ":~~~~:"
190 **
191 ** return the number of chars read in str or a negative value
192 ** on failure
193 **
194 *****************************************************************/
ip6fromstr(ip6_t * ip,const char * str)195 int ip6fromstr (ip6_t *ip, const char *str)
196 {
197 int i;
198 int sbit;
199 int ebit;
200 int dc;
201 int colon;
202 unsigned int addr[8];
203 const char *p;
204 const char *eos;
205
206 assert ( ip != NULL );
207 assert ( str != NULL );
208
209 for ( i = 0; i < 8; i++ )
210 addr[i] = 0;
211
212 ip->isset = 0;
213 dc = colon = 0;
214 for ( p = str; *p && isipv6char (*p); p++ )
215 if ( *p == ':' )
216 {
217 colon++; /* count colons */
218 if ( p[1] == ':' ) /* is this a double colon ? */
219 {
220 if ( dc ) /* more than one "::" ? */
221 return -1;
222 dc = colon; /* mark it */
223 }
224 }
225
226 dbg_val2 ("c=%d dc=%d \n", colon, dc);
227 eos = p;
228 if ( *str == ':' ) /* ipv6 string starts with a colon */
229 {
230 if ( dc == 1 ) /* strings starts with a double colon ? */
231 {
232 ; // hostid
233 sbit = 64;
234 ebit = 128;
235 }
236 else
237 {
238 ; // subnet
239 sbit = 48;
240 ebit = 64;
241 }
242 }
243 else if ( colon == 7 || (colon < 7 && dc) ) /* error checking */
244 {
245 int mask;
246
247 sbit = 0;
248
249 /* looking for mask */
250 mask = 128;
251 if ( (p = strchr (p, '/')) != NULL )
252 {
253 p++; /* skip '/' */
254 if ( sscanf (p, "%u", &mask) != 1 || mask < 0 || mask > 128 )
255 mask = 128;
256 while ( *p && isdigit (*p) )
257 p++;
258 eos = p;
259 }
260 ebit = mask;
261 }
262 else
263 return -2;
264
265 dbg_val4 ("c=%d dc=%d sbit=%d ebit=%d\n", colon, dc, sbit, ebit);
266 i = 0;
267 p = str;
268 if ( *p == ':' )
269 {
270 colon--;
271 if ( dc == 1 ) /* double colon at the beginning ? */
272 {
273 i = 8 - colon;
274 p++;
275 }
276 else if ( dc == 0 && colon == 1 ) /* :1234: subnet */
277 i = 3; /* put it between 48 and 64 bits */
278 p++;
279 }
280
281
282 while ( *p && isipv6char (*p) )
283 {
284 assert ( i >= 0 && i < 8 );
285
286 dbg_val4 ("c=%d dc=%d i=%d p=%s ", colon, dc, i, p);
287 if ( sscanf (p, "%4x", &addr[i]) != 1 )
288 return -3;
289 dbg_val (" %04x\n", addr[i]);
290
291 while ( isxdigit (*p) )
292 p++;
293
294 if ( *p == ':' )
295 {
296 if ( *++p == ':' ) /* double colon ? */
297 {
298 p++;
299 i = (8 - colon) + dc;
300 }
301 else
302 i++;
303 }
304
305 }
306
307 /* fill up the ip6_t struct */
308 for ( i = 0; i < 8; i++ )
309 ip->addr[i] = addr[i];
310
311 ip->sbit = sbit;
312 ip->ebit = ebit;
313 ip->isset = 1;
314
315 return eos - str;
316 }
317
ip6fromint(ip6_t * ipv6,int a,int b,int c,int d,int e,int f,int g,int h,int mask)318 int ip6fromint (ip6_t *ipv6, int a, int b, int c, int d, int e, int f, int g, int h, int mask)
319 {
320 assert ( ipv6 != NULL );
321
322 ipv6->addr[0] = a;
323 ipv6->addr[1] = b;
324 ipv6->addr[2] = c;
325 ipv6->addr[3] = d;
326 ipv6->addr[4] = e;
327 ipv6->addr[5] = f;
328 ipv6->addr[6] = g;
329 ipv6->addr[7] = h;
330
331 ipv6->sbit = 0;
332 if ( mask < 0 ) /* negative mask values are counted from right */
333 {
334 mask *= 1;
335 if ( mask < 128 )
336 ipv6->sbit = mask;
337 mask = 128; /* endbit is always 128 */
338 }
339
340 if ( mask > 128 )
341 mask = 128;
342 ipv6->ebit = mask;
343 ipv6->isset = 1;
344
345 return 1;
346 }
347
ip6getsbit(const ip6_t * ipv6)348 int ip6getsbit (const ip6_t *ipv6)
349 {
350 assert ( ipv6 );
351 assert ( ipv6->isset );
352
353 return ipv6->sbit;
354 }
355
ip6getebit(const ip6_t * ipv6)356 int ip6getebit (const ip6_t *ipv6)
357 {
358 assert ( ipv6 );
359 assert ( ipv6->isset );
360
361 return ipv6->ebit;
362 }
363
364 /*****************************************************************
365 ** return the prefix mask if sbit == 0;
366 ** Otherwise the diff between s and ebit is returned as a
367 ** negativ value
368 *****************************************************************/
ip6getmask(const ip6_t * ipv6)369 int ip6getmask (const ip6_t *ipv6)
370 {
371 assert ( ipv6 );
372 assert ( ipv6->isset );
373
374 return ipv6->ebit -ipv6->sbit;
375 }
376
ip6setmask(ip6_t * ipv6,int mask)377 int ip6setmask (ip6_t *ipv6, int mask)
378 {
379 assert ( ipv6 );
380 assert ( ipv6->isset );
381
382 ip6setsbit (ipv6, 0);
383 ip6setebit (ipv6, mask);
384
385 return mask;
386 }
387
ip6setsbit(ip6_t * ipv6,int sbit)388 int ip6setsbit (ip6_t *ipv6, int sbit)
389 {
390 assert ( ipv6 );
391 assert ( ipv6->isset );
392
393 sbit = max (0, sbit);
394 sbit = min (sbit, 128);
395 //sbit = min (sbit, ipv6->ebit);
396
397 return ipv6->sbit = sbit;
398 }
399
ip6setebit(ip6_t * ipv6,int ebit)400 int ip6setebit (ip6_t *ipv6, int ebit)
401 {
402 assert ( ipv6 );
403 assert ( ipv6->isset );
404
405 ebit = max (0, ebit);
406 ebit = min (ebit, 128);
407 //ebit = max (ipv6->sbit+1, ebit);
408
409 return ipv6->ebit = ebit;
410 }
411
412
ip6getshort(const ip6_t * ipv6,int nr)413 int ip6getshort (const ip6_t *ipv6, int nr)
414 {
415 assert ( ipv6 );
416 assert ( nr >= 0 && nr < 8 );
417 assert ( ipv6->isset );
418
419 return 0xFFFF & ipv6->addr[nr];
420 }
421
ip6getbyte(const ip6_t * ipv6,int nr)422 int ip6getbyte (const ip6_t *ipv6, int nr)
423 {
424 unsigned short s;
425 unsigned short shiftbits;
426
427 assert ( ipv6 );
428 assert ( nr >= 0 && nr < 16 );
429 assert ( ipv6->isset );
430
431 s = ipv6->addr[nr/2];
432 shiftbits = (1 - nr%2) * 8;
433
434 return 0xFF & (s >> shiftbits);
435 }
436
ip6getnibble(const ip6_t * ipv6,int nr)437 int ip6getnibble (const ip6_t *ipv6, int nr)
438 {
439 unsigned short s;
440 unsigned short shiftbits;
441
442 assert ( ipv6 );
443 assert ( nr >= 0 && nr < 32 );
444 assert ( ipv6->isset );
445
446 s = ipv6->addr[nr/4];
447 shiftbits = (3 - nr%4) * 4;
448
449 return 0xF & (s >> shiftbits);
450 }
451
ip6getbit(const ip6_t * ipv6,int nr)452 int ip6getbit (const ip6_t *ipv6, int nr)
453 {
454 unsigned short s;
455 unsigned short shiftbits;
456
457 assert ( ipv6 );
458 assert ( nr >= 0 && nr < 128 );
459 assert ( ipv6->isset );
460
461 s = ipv6->addr[nr/16];
462 shiftbits = (15 - nr%16);
463
464 return 0x1 & (s >> shiftbits);
465 }
466
ip6setshort(ip6_t * ipv6,int nr,int val)467 int ip6setshort (ip6_t *ipv6, int nr, int val)
468 {
469 assert ( ipv6 );
470 assert ( nr >= 0 && nr < 8 );
471 assert ( ipv6->isset );
472
473 return ipv6->addr[nr] = (0xFFFF & val);
474 }
475
ip6setbyte(ip6_t * ipv6,int bytenr,int val)476 int ip6setbyte (ip6_t *ipv6, int bytenr, int val)
477 {
478 unsigned short snr;
479 unsigned short mask;
480 int shift;
481
482 assert ( ipv6 );
483 assert ( bytenr >= 0 && bytenr < 16 );
484 assert ( ipv6->isset );
485
486 snr = bytenr / 2;
487
488 shift = (1 - bytenr%2) * 8;
489 mask = ~(0xFF << shift);
490
491 return ipv6->addr[snr] = (ipv6->addr[snr] & mask) | ((0xFF & val) << shift);
492 }
493
ip6setnibble(ip6_t * ipv6,int nibnr,int val)494 int ip6setnibble (ip6_t *ipv6, int nibnr, int val)
495 {
496 unsigned short snr;
497 unsigned short mask;
498 unsigned short shift;
499
500 assert ( ipv6 );
501 assert ( nibnr >= 0 && nibnr < 32 );
502 assert ( ipv6->isset );
503
504 snr = nibnr / 4;
505
506 shift = (3 - nibnr%4) * 4;
507 mask = ~(0xF << shift);
508
509 return ipv6->addr[snr] = (ipv6->addr[snr] & mask) | ((0xF & val) << shift);
510 }
511
ip6setbit(ip6_t * ipv6,int bitnr,int val)512 int ip6setbit (ip6_t *ipv6, int bitnr, int val)
513 {
514 unsigned short snr;
515 unsigned short mask;
516 unsigned short shift;
517
518 assert ( ipv6 );
519 assert ( bitnr >= 0 && bitnr < 128 );
520 assert ( ipv6->isset );
521
522 snr = bitnr / 16;
523 shift = (15 - bitnr%16);
524 mask = ~(0x1 << shift);
525
526 return ipv6->addr[snr] = (ipv6->addr[snr] & mask) | ((0x1 & val) << shift);
527 }
528
529 /*****************************************************************
530 ** ip6getulbit() get the universl/local bit of the host identifier
531 *****************************************************************/
ip6getulbit(const ip6_t * ipv6)532 int ip6getulbit (const ip6_t *ipv6)
533 {
534 assert ( ipv6 );
535
536 if ( !ip6isset (ipv6) )
537 return -1;
538
539 return ip6getbit (ipv6, 64+7);
540 }
541
542
543 /*****************************************************************
544 ** ip6copy (dip, sip)
545 ** copy source ip6 to destination ip6
546 ** if dip is null allocate a destination ip6_t object dynamically
547 ** if sip is null clear (unset) the destination object
548 ** return a pointer to dip or the dynamic allocated memory
549 *****************************************************************/
ip6copy(ip6_t * dipv6,const ip6_t * sipv6)550 ip6_t *ip6copy (ip6_t *dipv6, const ip6_t *sipv6)
551 {
552 if ( dipv6 == NULL )
553 if ( (dipv6 = calloc (1, sizeof (ip6_t))) == NULL )
554 return NULL;
555
556 if ( sipv6 == NULL )
557 {
558 memset (dipv6, 0, sizeof (ip6_t));
559 return dipv6;
560 }
561
562 #if 1
563 memcpy (dipv6, sipv6, sizeof (ip6_t));
564 #else
565 for ( i = 0; i < 8; i++ )
566 dipv6->addr[i] = sipv6->addr[i];
567 dipv6->sbit = sipv6->sbit;
568 dipv6->ebit = sipv6->ebit;
569 dipv6->isset = sipv6->isset;
570 #endif
571
572 return dipv6;
573 }
574
575 /*****************************************************************
576 ** ip6cmp ()
577 ** compare two ip6 address objects
578 ** returns a negative value if ipa is less than ipb
579 ** a value of 0 if both are equal, or a value greater
580 ** than 0 if ipa is greater than ipb
581 *****************************************************************/
ip6cmp(const ip6_t * ipa,const ip6_t * ipb)582 int ip6cmp (const ip6_t *ipa, const ip6_t *ipb)
583 {
584 int i;
585
586 assert ( ipa );
587 assert ( ipb );
588
589 if ( !ip6isset (ipa) ) return -1;
590 if ( !ip6isset (ipb) ) return 1;
591
592 i = 0;
593 while ( i < 8 && ipa->addr[i] == ipb->addr[i] )
594 i++;
595
596 if ( i < 8 )
597 return ipa->addr[i] - ipb->addr[i];
598
599 return ipa->ebit - ipb->ebit;
600 }
601
602 /*****************************************************************
603 ** ip6match (ip, prefix)
604 ** test if ip address matches prefix
605 ** Returns the prefix len if "ip" matches "prefix", 0 otherwise.
606 ** A negativ value is returned on error
607 *****************************************************************/
ip6match(const ip6_t * ip,const ip6_t * prefix)608 int ip6match (const ip6_t *ip, const ip6_t *prefix)
609 {
610 int i;
611 int ebit;
612
613 assert ( ip );
614 assert ( prefix );
615
616 if ( !ip6isset (ip) || !ip6isset (prefix) )
617 return -1;
618
619 if ( ip->sbit || prefix->sbit ) /* both must start at bit 0 */
620 return -1;
621
622 if ( ip->ebit < prefix->ebit ) /* ip is shorter than prefix ? */
623 return 0;
624
625 ebit = prefix->ebit / 16;
626 for ( i = 0; i < ebit; i++ )
627 if ( ip->addr[i] != prefix->addr[i] )
628 return 0;
629
630 ebit = prefix->ebit;
631 for ( i *= 16; i < ebit; i++ )
632 if ( ip6getbit (ip, i) != ip6getbit (prefix, i) )
633 return 0;
634
635 return i;
636 }
637
638 /*****************************************************************
639 ** ip6chop ()
640 ** Chop "ip" to a size of "ebit"
641 ** (set all bits greater "ebits" of "ip" to zero)
642 *****************************************************************/
ip6chop(ip6_t * ip,int ebit)643 ip6_t *ip6chop (ip6_t *ip, int ebit)
644 {
645 int i;
646 int bend;
647
648 if ( ip == NULL || !ip6isset (ip) )
649 return NULL;
650
651 i = ebit;
652 bend = ebit % 16;
653 while ( bend-- > 0 )
654 ip6setbit (ip, i++, 0);
655
656 i = ebit / 16;
657 while ( ++i < 8 )
658 ip->addr[i] = 0;
659
660 ip->ebit = ebit;
661
662 return ip;
663 }
664
665 /*****************************************************************
666 **
667 ** ip6append ()
668 **
669 ** append ipb, which is an subnet or hostid object, at ipa,
670 ** which is a prefix ip6 address object.
671 **
672 ** returns the new prefix len or a negative value on failure
673 **
674 *****************************************************************/
ip6append(ip6_t * ipa,const ip6_t * ipb)675 int ip6append (ip6_t *ipa, const ip6_t *ipb)
676 {
677 int i;
678 int bend;
679
680 assert ( ipa );
681 assert ( ipb );
682
683 if ( !ipb->isset )
684 return -1;
685
686 if ( ipa->ebit != ipb->sbit ) /* b must be on a's boundary */
687 return -2;
688
689 i = ipa->ebit;
690 bend = ipb->ebit;
691 while ( i < bend )
692 {
693 ip6setbit (ipa, i, ip6getbit (ipb, i));
694 i++;
695 }
696
697 i = ipa->ebit / 16;
698 bend = ipb->ebit / 16;
699 while ( ++i < bend )
700 ipa->addr[i] = ipb->addr[i];
701 ipa->ebit = ipb->ebit;
702
703 return ipa->ebit;
704 }
705
ip6revdns(char * dst,size_t len,const ip6_t * ipv6,int mask)706 char *ip6revdns (char *dst, size_t len, const ip6_t *ipv6, int mask)
707 {
708 int i;
709 char *p;
710
711 assert ( mask % 4 == 0 );
712
713 p = dst;
714 /* we are looking for nibbles */
715 i = mask / 4;
716 while ( i-- > 0 )
717 p += snprintf (p, len - (p-dst), "%01x.", ip6getnibble (ipv6, i));
718 snprintf (p, len - (p-dst), "ip6.arpa.");
719
720 return dst;
721 }
722
723 #ifdef TEST
main(int argc,char * argv[])724 int main (int argc, char *argv[])
725 {
726 int i;
727 int ret;
728 ip6_t ip;
729 ip6_t net;
730 ip6_t *newip;
731 char str[255+1];
732 char v6host[19+1];
733 static const char *strings[] = {
734 "1:2:3:4:5:6:7:8" ,
735 "::5:6:7:8" ,
736 "::53" ,
737 "1:2:3:4::" ,
738 "2a01:0002:30:400:0::/64" ,
739 "1:2::7:8" ,
740 "1::7:8" ,
741 "1:2:3:4:5::8" ,
742 ":23:",
743 NULL
744 };
745 static const char *badstrings[] = {
746 "1:2:3:4::5:6:7:8" ,
747 "1:2::4::6:7:8" ,
748 "1:::8" ,
749 ":::8" ,
750 NULL
751 };
752
753 ip6fromint (&ip, 0x2001, 0xdb8, 0x0123, 0x4567, 0x89ab, 0xcdef, 0x1, 0x2, 64);
754 ip6tostr (str, sizeof (str), &ip);
755 printf ("ip6tostr: \"%s\" sbit=%d ebit=%d\n", str, ip6getsbit (&ip), ip6getebit (&ip));
756
757 printf ("getshort\t");
758 for ( i = 0; i < 8; i++ )
759 printf ("%04x%c", ip6getshort (&ip, i), i < 7 ? ':' : '\n');
760 printf ("getbyte \t");
761 for ( i = 0; i < 16; i++ )
762 {
763 printf ("%02x", ip6getbyte (&ip, i++));
764 printf ("%02x", ip6getbyte (&ip, i));
765 printf ("%c", i < 15 ? ':' : '\n');
766 }
767
768 printf ("getnibble\t");
769 i = 0;
770 while ( i < 32 )
771 {
772 printf ("%01x", ip6getnibble (&ip, i++));
773 printf ("%01x", ip6getnibble (&ip, i++));
774 printf ("%01x", ip6getnibble (&ip, i++));
775 printf ("%01x", ip6getnibble (&ip, i++));
776 printf ("%c", i < 31 ? ':' : '\n');
777 }
778 printf ("Prefix(getbit)\t");
779 for ( i = 0; i < ip6getebit (&ip); i++ )
780 {
781 printf ("%u", ip6getbit (&ip, i));
782 if ( (i+1) % 16 == 0 )
783 printf (":");
784 else if ( (i+1) % 4 == 0 )
785 printf ("^");
786 }
787 printf ("\n");
788 printf ("HostId(getbit)\t");
789 for ( i = 64; i < 128; i++ )
790 {
791 printf ("%u", ip6getbit (&ip, i));
792 if ( (i+1) % 16 == 0 )
793 printf (":");
794 else if ( (i+1) % 4 == 0 )
795 printf ("^");
796 }
797 printf ("\n");
798
799 for ( i = 0; strings[i] != NULL; i++ )
800 {
801 printf ("\n");
802 printf ("parsing %s\n", strings[i]);
803 if ( (ret = ip6fromstr (&ip, strings[i])) < 0 )
804 fprintf (stderr, "Bad string %d\n", ret);
805 else
806 {
807 ip6tostr (str, sizeof (str), &ip);
808 printf ("%s sbit/ebit=%d/%d", str, ip6getsbit (&ip), ip6getebit(&ip));
809 printf ("\t len=%d\n", ret);
810 }
811 printf ("\t%s", ip6revdns (str, sizeof(str), &ip, 64));
812 printf ("\n");
813 }
814 for ( i = 0; badstrings[i] != NULL; i++ )
815 {
816 printf ("\n");
817 printf ("bad string parsing %s\n", badstrings[i]);
818 if ( (ret = ip6fromstr (&ip, badstrings[i])) < 0 )
819 fprintf (stderr, "Bad string %d which is ok!", ret);
820 else
821 fprintf (stderr, "Good string which is not ok!");
822 printf ("\n");
823 }
824
825 /* how to setup an IPv6 address out of a prefix, a subnetid and a hostid */
826 {
827 int plen;
828 ip6_t prefix;
829 ip6_t subnet;
830 ip6_t hostid;
831 ip6_t *ip;
832
833 ip6setfmt (1);
834
835 ip6fromstr (&prefix, "2001:db8:1:1230::/60");
836 ip6fromstr (&subnet, ":ad:");
837 ip6fromstr (&hostid, "::53");
838
839 plen = ip6getebit (&prefix);
840 ip6setsbit (&subnet, plen);
841
842 printf ("\n");
843 ip6tostr (str, sizeof (str), &prefix);
844 printf ("Prefix %s\tsbit/ebit=%d/%d\n", str, ip6getsbit (&prefix), ip6getebit(&prefix));
845 ip6tostr (str, sizeof (str), &subnet);
846 printf ("Prefix %s\tsbit/ebit=%d/%d\n", str, ip6getsbit (&subnet), ip6getebit(&subnet));
847 ip6tostr (str, sizeof (str), &hostid);
848 printf ("Prefix %s\tsbit/ebit=%d/%d\n", str, ip6getsbit (&hostid), ip6getebit(&hostid));
849
850 ip = ip6copy (NULL, &prefix);
851
852 ip6setfmt (0);
853 ip6append (ip, &subnet);
854 ip6append (ip, &hostid);
855 ip6tostring (str, sizeof (str), ip);
856 printf ("Address %s\n", str);
857 ip6tostr (str, sizeof (str), &prefix);
858 printf ("Prefix %s\n", str);
859 printf ("Address match %d\n", ip6match (ip, &prefix));
860
861 ip6chop (ip, 60);
862 ip6tostr (str, sizeof (str), ip);
863 printf ("\nSubnet only %s\n", str);
864
865 if ( ip6cmp (ip, &prefix) == 0 )
866 printf ("original prefix and new ip address are identical\n");
867 else
868 printf ("original prefix and new ip address are different\n");
869 }
870
871 return 1;
872 }
873 #endif
874