xref: /titanic_44/usr/src/lib/libast/common/string/fmtip6.c (revision 8475e04352e630e4bd0f59a283286ee2475a14ce)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2008 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 
24 #if _PACKAGE_ast
25 #include <ast.h>
26 #endif
27 
28 #include <ip6.h>
29 
30 #if !_PACKAGE_ast
31 
32 /*
33  * return a pointer to n bytes from a circular re-use buffer
34  */
35 
36 static char*
37 fmtbuf(int n)
38 {
39 	char*		b;
40 
41 	static char	buf[1024];
42 	static char*	p = buf;
43 
44 	if ((&buf[sizeof(buf)] - p) < n)
45 		p = buf;
46 	b = p;
47 	p += n;
48 	return b;
49 }
50 
51 #endif
52 
53 /*
54  * copy p to s, then convert 0<=n<=999 to text
55  * next char in s returned
56  * caller ensures that s can take strlen(p)+3 bytes
57  */
58 
59 static char*
60 dec(char* s, char* p, int n)
61 {
62 	while (*s = *p++)
63 		s++;
64 	if (n >= 100)
65 		*s++ = '0' + ((n / 100) % 10);
66 	if (n >= 10)
67 		*s++ = '0' + ((n / 10) % 10);
68 	*s++ = '0' + (n % 10);
69 	return s;
70 }
71 
72 /*
73  * return pointer to normalized ipv6 address addr
74  * with optional prefix bits if 0 < bits <= 128
75  * return value in short-term circular buffer
76  */
77 
78 char*
79 fmtip6(unsigned char* addr, int bits)
80 {
81 	register unsigned char*	a = addr;
82 	register int		n = IP6ADDR;
83 	register int		i;
84 	register int		z;
85 	register int		k;
86 	register int		m;
87 	unsigned char		r[IP6ADDR];
88 	char*			b;
89 	char*			s;
90 
91 	static const char	dig[] = "0123456789ABCDEF";
92 
93 	s = b = fmtbuf(44);
94 	r[m = z = 0] = 0;
95 	if (a[0] == 0x20 && a[1] == 0x02 && (a[2] || a[3] || a[4] || a[5]))
96 	{
97 		z = 6;
98 		s = dec(s, "2002:", a[2]);
99 		s = dec(s, ".", a[3]);
100 		s = dec(s, ".", a[4]);
101 		s = dec(s, ".", a[5]);
102 	}
103 	for (i = z; i < n; i += 2)
104 	{
105 		for (k = i; i < n - 1 && !a[i] && !a[i + 1]; i += 2);
106 		if ((r[k] = i - k) > r[m] || r[k] == r[m] && i >= (n - 1))
107 			m = k;
108 	}
109 	if (!m)
110 		switch (r[m])
111 		{
112 		case 0:
113 			m = -1;
114 			break;
115 		case 14:
116 			if (!a[14] && a[15] <= 15)
117 				break;
118 			/*FALLTHROUGH*/
119 		case 12:
120 			s = dec(s, "::", a[12]);
121 			s = dec(s, ".", a[13]);
122 			s = dec(s, ".", a[14]);
123 			s = dec(s, ".", a[15]);
124 			n = 0;
125 			break;
126 		case 10:
127 			if (a[10] == 0xFF && a[11] == 0xFF)
128 			{
129 				s = dec(s, "::FFFF:", a[12]);
130 				s = dec(s, ".", a[13]);
131 				s = dec(s, ".", a[14]);
132 				s = dec(s, ".", a[15]);
133 				n = 0;
134 			}
135 			break;
136 		}
137 	for (i = z; i < n; i++)
138 	{
139 		if (i == m)
140 		{
141 			*s++ = ':';
142 			*s++ = ':';
143 			if ((i += r[m]) >= n)
144 				break;
145 			z = 0;
146 		}
147 		else if (i && !(i & 1))
148 		{
149 			if (z)
150 				z = 0;
151 			else
152 				*s++ = '0';
153 			*s++ = ':';
154 		}
155 		if ((k = (a[i] >> 4) & 0xf) || z)
156 		{
157 			z = 1;
158 			*s++ = dig[k];
159 		}
160 		if ((k = a[i] & 0xf) || z)
161 		{
162 			z = 1;
163 			*s++ = dig[k];
164 		}
165 	}
166 	if (bits > 0 && bits <= 128)
167 		s = dec(s, "/", bits);
168 	*s = 0;
169 	return b;
170 }
171