1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 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
36static char*
37fmtbuf(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
59static char*
60dec(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
78char*
79fmtip6(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			{
145				z = 1;
146				break;
147			}
148			z = 0;
149		}
150		else if (i && !(i & 1))
151		{
152			if (z)
153				z = 0;
154			else
155				*s++ = '0';
156			*s++ = ':';
157		}
158		if ((k = (a[i] >> 4) & 0xf) || z)
159		{
160			z = 1;
161			*s++ = dig[k];
162		}
163		if ((k = a[i] & 0xf) || z)
164		{
165			z = 1;
166			*s++ = dig[k];
167		}
168	}
169	if (!z && *(s - 1) == ':')
170		*s++ = '0';
171	if (bits > 0 && bits <= 128)
172		s = dec(s, "/", bits);
173	*s = 0;
174	return b;
175}
176