ReactOS 0.4.16-dev-570-g1868985
ip6_addr.c
Go to the documentation of this file.
1
7/*
8 * Copyright (c) 2010 Inico Technologies Ltd.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31 * OF SUCH DAMAGE.
32 *
33 * This file is part of the lwIP TCP/IP stack.
34 *
35 * Author: Ivan Delamer <delamer@inicotech.com>
36 *
37 * Functions for handling IPv6 addresses.
38 *
39 * Please coordinate changes and requests with Ivan Delamer
40 * <delamer@inicotech.com>
41 */
42
43#include "lwip/opt.h"
44
45#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */
46
47#include "lwip/ip_addr.h"
48#include "lwip/def.h"
49#include "lwip/netif.h"
50
51#include <string.h>
52
53#if LWIP_IPV4
54#include "lwip/ip4_addr.h" /* for ip6addr_aton to handle IPv4-mapped addresses */
55#endif /* LWIP_IPV4 */
56
57/* used by IP6_ADDR_ANY(6) in ip6_addr.h */
58const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul);
59
60#define lwip_xchar(i) ((char)((i) < 10 ? '0' + (i) : 'A' + (i) - 10))
61
71int
72ip6addr_aton(const char *cp, ip6_addr_t *addr)
73{
74 u32_t addr_index, zero_blocks, current_block_index, current_block_value;
75 const char *s;
76#if LWIP_IPV4
77 int check_ipv4_mapped = 0;
78#endif /* LWIP_IPV4 */
79
80 /* Count the number of colons, to count the number of blocks in a "::" sequence
81 zero_blocks may be 1 even if there are no :: sequences */
82 zero_blocks = 8;
83 for (s = cp; *s != 0; s++) {
84 if (*s == ':') {
86#if LWIP_IPV4
87 } else if (*s == '.') {
88 if ((zero_blocks == 5) ||(zero_blocks == 2)) {
89 check_ipv4_mapped = 1;
90 /* last block could be the start of an IPv4 address */
92 } else {
93 /* invalid format */
94 return 0;
95 }
96 break;
97#endif /* LWIP_IPV4 */
98 } else if (!lwip_isxdigit(*s)) {
99 break;
100 }
101 }
102
103 /* parse each block */
104 addr_index = 0;
105 current_block_index = 0;
106 current_block_value = 0;
107 for (s = cp; *s != 0; s++) {
108 if (*s == ':') {
109 if (addr) {
110 if (current_block_index & 0x1) {
111 addr->addr[addr_index++] |= current_block_value;
112 }
113 else {
114 addr->addr[addr_index] = current_block_value << 16;
115 }
116 }
117 current_block_index++;
118#if LWIP_IPV4
119 if (check_ipv4_mapped) {
120 if (current_block_index == 6) {
121 ip4_addr_t ip4;
122 int ret = ip4addr_aton(s + 1, &ip4);
123 if (ret) {
124 if (addr) {
125 addr->addr[3] = lwip_htonl(ip4.addr);
126 current_block_index++;
127 goto fix_byte_order_and_return;
128 }
129 return 1;
130 }
131 }
132 }
133#endif /* LWIP_IPV4 */
134 current_block_value = 0;
135 if (current_block_index > 7) {
136 /* address too long! */
137 return 0;
138 }
139 if (s[1] == ':') {
140 if (s[2] == ':') {
141 /* invalid format: three successive colons */
142 return 0;
143 }
144 s++;
145 /* "::" found, set zeros */
146 while (zero_blocks > 0) {
147 zero_blocks--;
148 if (current_block_index & 0x1) {
149 addr_index++;
150 } else {
151 if (addr) {
152 addr->addr[addr_index] = 0;
153 }
154 }
155 current_block_index++;
156 if (current_block_index > 7) {
157 /* address too long! */
158 return 0;
159 }
160 }
161 }
162 } else if (lwip_isxdigit(*s)) {
163 /* add current digit */
164 current_block_value = (current_block_value << 4) +
165 (lwip_isdigit(*s) ? (u32_t)(*s - '0') :
166 (u32_t)(10 + (lwip_islower(*s) ? *s - 'a' : *s - 'A')));
167 } else {
168 /* unexpected digit, space? CRLF? */
169 break;
170 }
171 }
172
173 if (addr) {
174 if (current_block_index & 0x1) {
175 addr->addr[addr_index++] |= current_block_value;
176 }
177 else {
178 addr->addr[addr_index] = current_block_value << 16;
179 }
180#if LWIP_IPV4
181fix_byte_order_and_return:
182#endif
183 /* convert to network byte order. */
184 for (addr_index = 0; addr_index < 4; addr_index++) {
185 addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]);
186 }
187
188 ip6_addr_clear_zone(addr);
189#if LWIP_IPV6_SCOPES
190 if (*s == '%') {
191 const char *scopestr = s + 1;
192 if (*scopestr) {
193 struct netif *netif = netif_find(scopestr);
194 if (netif) {
195 ip6_addr_assign_zone(addr, IP6_UNKNOWN, netif);
196 }
197 }
198 }
199#endif
200 }
201
202 if (current_block_index != 7) {
203 return 0;
204 }
205
206 return 1;
207}
208
217char *
218ip6addr_ntoa(const ip6_addr_t *addr)
219{
220 static char str[40];
221 return ip6addr_ntoa_r(addr, str, 40);
222}
223
233char *
234ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen)
235{
236 u32_t current_block_index, current_block_value, next_block_value;
237 s32_t i;
238 u8_t zero_flag, empty_block_flag;
239
240#if LWIP_IPV4
241 if (ip6_addr_isipv4mappedipv6(addr)) {
242 /* This is an IPv4 mapped address */
243 ip4_addr_t addr4;
244 char *ret;
245#define IP4MAPPED_HEADER "::FFFF:"
246 char *buf_ip4 = buf + sizeof(IP4MAPPED_HEADER) - 1;
247 int buflen_ip4 = buflen - sizeof(IP4MAPPED_HEADER) + 1;
248 if (buflen < (int)sizeof(IP4MAPPED_HEADER)) {
249 return NULL;
250 }
251 memcpy(buf, IP4MAPPED_HEADER, sizeof(IP4MAPPED_HEADER));
252 addr4.addr = addr->addr[3];
253 ret = ip4addr_ntoa_r(&addr4, buf_ip4, buflen_ip4);
254 if (ret != buf_ip4) {
255 return NULL;
256 }
257 return buf;
258 }
259#endif /* LWIP_IPV4 */
260 i = 0;
261 empty_block_flag = 0; /* used to indicate a zero chain for "::' */
262
263 for (current_block_index = 0; current_block_index < 8; current_block_index++) {
264 /* get the current 16-bit block */
265 current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]);
266 if ((current_block_index & 0x1) == 0) {
267 current_block_value = current_block_value >> 16;
268 }
269 current_block_value &= 0xffff;
270
271 /* Check for empty block. */
272 if (current_block_value == 0) {
273 if (current_block_index == 7 && empty_block_flag == 1) {
274 /* special case, we must render a ':' for the last block. */
275 buf[i++] = ':';
276 if (i >= buflen) {
277 return NULL;
278 }
279 break;
280 }
281 if (empty_block_flag == 0) {
282 /* generate empty block "::", but only if more than one contiguous zero block,
283 * according to current formatting suggestions RFC 5952. */
284 next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]);
285 if ((current_block_index & 0x1) == 0x01) {
286 next_block_value = next_block_value >> 16;
287 }
288 next_block_value &= 0xffff;
289 if (next_block_value == 0) {
290 empty_block_flag = 1;
291 buf[i++] = ':';
292 if (i >= buflen) {
293 return NULL;
294 }
295 continue; /* move on to next block. */
296 }
297 } else if (empty_block_flag == 1) {
298 /* move on to next block. */
299 continue;
300 }
301 } else if (empty_block_flag == 1) {
302 /* Set this flag value so we don't produce multiple empty blocks. */
303 empty_block_flag = 2;
304 }
305
306 if (current_block_index > 0) {
307 buf[i++] = ':';
308 if (i >= buflen) {
309 return NULL;
310 }
311 }
312
313 if ((current_block_value & 0xf000) == 0) {
314 zero_flag = 1;
315 } else {
316 buf[i++] = lwip_xchar(((current_block_value & 0xf000) >> 12));
317 zero_flag = 0;
318 if (i >= buflen) {
319 return NULL;
320 }
321 }
322
323 if (((current_block_value & 0xf00) == 0) && (zero_flag)) {
324 /* do nothing */
325 } else {
326 buf[i++] = lwip_xchar(((current_block_value & 0xf00) >> 8));
327 zero_flag = 0;
328 if (i >= buflen) {
329 return NULL;
330 }
331 }
332
333 if (((current_block_value & 0xf0) == 0) && (zero_flag)) {
334 /* do nothing */
335 }
336 else {
337 buf[i++] = lwip_xchar(((current_block_value & 0xf0) >> 4));
338 zero_flag = 0;
339 if (i >= buflen) {
340 return NULL;
341 }
342 }
343
344 buf[i++] = lwip_xchar((current_block_value & 0xf));
345 if (i >= buflen) {
346 return NULL;
347 }
348 }
349
350 buf[i] = 0;
351
352 return buf;
353}
354
355#endif /* LWIP_IPV6 */
bool zero_blocks(PEXT2_FILESYS fs, ULONG blk, ULONG num, ULONG *ret_blk, ULONG *ret_count)
Definition: Mke2fs.c:122
#define lwip_htonl(x)
Definition: def.h:88
#define NULL
Definition: types.h:112
GLdouble s
Definition: gl.h:2039
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum const GLvoid * addr
Definition: glext.h:9621
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define lwip_isdigit(c)
Definition: arch.h:229
int32_t s32_t
Definition: arch.h:130
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define lwip_islower(c)
Definition: arch.h:231
#define lwip_isxdigit(c)
Definition: arch.h:230
struct netif * netif_find(const char *name)
Definition: netif.c:1755
#define IPADDR6_INIT(a, b, c, d)
Definition: ip_addr.h:345
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
POINT cp
Definition: magnifier.c:59
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
const WCHAR * str
Definition: netif.h:269
int ret