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