xref: /titanic_51/usr/src/lib/libast/common/string/strtoip6.c (revision dc4bf86d3869090fa08d98d7030728be986fd289)
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 #else
27 #include <stdint.h>
28 #endif
29 
30 #include <ctype.h>
31 #include <ip6.h>
32 
33 /*
34  * convert string to ipv6 network byte order ip address
35  * with optional prefix bits
36  * pointer to first unused char placed in *e, even on error
37  * return 0:ok <0:error
38  */
39 
40 #define COL		16
41 #define DOT		17
42 #define END		18
43 #define PFX		19
44 
45 int
46 strtoip6(register const char* s, char** e, unsigned char* addr, unsigned char* bits)
47 {
48 	register unsigned char*	b = addr;
49 	register unsigned char*	x = b + IP6ADDR;
50 	register unsigned char*	z;
51 	register int		c;
52 	register uint32_t	a;
53 
54 	static unsigned char	lex[256];
55 
56 	if (!lex[0])
57 	{
58 		for (c = 0; c < sizeof(lex); ++c)
59 			lex[c] = END;
60 		lex['0'] = 0;
61 		lex['1'] = 1;
62 		lex['2'] = 2;
63 		lex['3'] = 3;
64 		lex['4'] = 4;
65 		lex['5'] = 5;
66 		lex['6'] = 6;
67 		lex['7'] = 7;
68 		lex['8'] = 8;
69 		lex['9'] = 9;
70 		lex['A'] = lex['a'] = 10;
71 		lex['B'] = lex['b'] = 11;
72 		lex['C'] = lex['c'] = 12;
73 		lex['D'] = lex['d'] = 13;
74 		lex['E'] = lex['e'] = 14;
75 		lex['F'] = lex['f'] = 15;
76 		lex[':'] = COL;
77 		lex['.'] = DOT;
78 		lex['/'] = PFX;
79 	}
80 	while (isspace(*s))
81 		s++;
82 	z = 0;
83 	a = 0;
84 	if (*s)
85 		for (;;)
86 		{
87 			switch (c = lex[*((unsigned char*)s++)])
88 			{
89 			case END:
90 			case PFX:
91 				if ((x - b) < 2)
92 					break;
93 				*b++ = a>>8;
94 				*b++ = a;
95 				break;
96 			case COL:
97 				if ((x - b) < 2)
98 					break;
99 				*b++ = a>>8;
100 				*b++ = a;
101 				a = 0;
102 				if (*s == ':')
103 				{
104 					if (z)
105 					{
106 						s--;
107 						break;
108 					}
109 					z = b;
110 					if ((c = lex[*((unsigned char*)++s)]) >= 16)
111 					{
112 						s++;
113 						break;
114 					}
115 				}
116 				continue;
117 			case DOT:
118 				if (b >= x)
119 				{
120 					s--;
121 					break;
122 				}
123 				*b++ = ((a >> 8) & 0xf) * 100 + ((a >> 4) & 0xf) * 10 + (a & 0xf);
124 				a = 0;
125 				for (;;)
126 				{
127 					switch (c = lex[*((unsigned char*)s++)])
128 					{
129 					case COL:
130 					case END:
131 					case PFX:
132 						if (b < x)
133 							*b++ = a;
134 						a = 0;
135 						break;
136 					case DOT:
137 						if (b >= x)
138 							break;
139 						*b++ = a;
140 						a = 0;
141 						continue;
142 					default:
143 						a = (a * 10) + c;
144 						continue;
145 					}
146 					break;
147 				}
148 				if (c == COL)
149 				{
150 					if (*s == ':')
151 					{
152 						if (z)
153 						{
154 							s--;
155 							break;
156 						}
157 						z = b;
158 						if ((c = lex[*((unsigned char*)++s)]) >= 16)
159 						{
160 							s++;
161 							break;
162 						}
163 					}
164 					if ((b - addr) == 6 && addr[0] == 0x20 && addr[1] == 0x02)
165 						continue;
166 				}
167 				break;
168 			default:
169 				a = (a << 4) | c;
170 				continue;
171 			}
172 			break;
173 		}
174 	if (b == addr)
175 		c = END + 1;
176 	else
177 	{
178 		if (z)
179 		{
180 			while (b > z)
181 				*--x = *--b;
182 			while (x > z)
183 				*--x = 0;
184 		}
185 		else
186 			while (b < x)
187 				*b++ = 0;
188 		if (bits)
189 		{
190 			a = 0;
191 			if (c == PFX)
192 				while ((c = lex[*((unsigned char*)s++)]) < 10)
193 					a = a * 10 + c;
194 			*bits = a;
195 		}
196 	}
197 	if (e)
198 		*e = (char*)(s - 1);
199 	return c == END ? 0 : -1;
200 }
201