1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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*
fmtbuf(int n)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*
dec(char * s,char * p,int n)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*
fmtip6(unsigned char * addr,int bits)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 {
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