Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
lwip_ip6_addr.c
00001 /** 00002 * @file 00003 * 00004 * IPv6 addresses. 00005 */ 00006 00007 /* 00008 * Copyright (c) 2010 Inico Technologies Ltd. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Ivan Delamer <delamer@inicotech.com> 00036 * 00037 * Functions for handling IPv6 addresses. 00038 * 00039 * Please coordinate changes and requests with Ivan Delamer 00040 * <delamer@inicotech.com> 00041 */ 00042 00043 #include "lwip/opt.h" 00044 00045 #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ 00046 00047 #include "lwip/ip_addr.h" 00048 #include "lwip/def.h" 00049 00050 /* used by IP6_ADDR_ANY(6) in ip6_addr.h */ 00051 const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); 00052 00053 #ifndef isprint 00054 #define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) 00055 #define isprint(c) in_range(c, 0x20, 0x7f) 00056 #define isdigit(c) in_range(c, '0', '9') 00057 #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) 00058 #define islower(c) in_range(c, 'a', 'z') 00059 #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 00060 #define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) 00061 #endif 00062 00063 /** 00064 * Check whether "cp" is a valid ascii representation 00065 * of an IPv6 address and convert to a binary address. 00066 * Returns 1 if the address is valid, 0 if not. 00067 * 00068 * @param cp IPv6 address in ascii representation (e.g. "FF01::1") 00069 * @param addr pointer to which to save the ip address in network order 00070 * @return 1 if cp could be converted to addr, 0 on failure 00071 */ 00072 int 00073 ip6addr_aton(const char *cp, ip6_addr_t *addr) 00074 { 00075 u32_t addr_index, zero_blocks, current_block_index, current_block_value; 00076 const char *s; 00077 00078 /* Count the number of colons, to count the number of blocks in a "::" sequence 00079 zero_blocks may be 1 even if there are no :: sequences */ 00080 zero_blocks = 8; 00081 for (s = cp; *s != 0; s++) { 00082 if (*s == ':') { 00083 zero_blocks--; 00084 } else if (!isxdigit(*s)) { 00085 break; 00086 } 00087 } 00088 00089 /* parse each block */ 00090 addr_index = 0; 00091 current_block_index = 0; 00092 current_block_value = 0; 00093 for (s = cp; *s != 0; s++) { 00094 if (*s == ':') { 00095 if (addr) { 00096 if (current_block_index & 0x1) { 00097 addr->addr[addr_index++] |= current_block_value; 00098 } 00099 else { 00100 addr->addr[addr_index] = current_block_value << 16; 00101 } 00102 } 00103 current_block_index++; 00104 current_block_value = 0; 00105 if (current_block_index > 7) { 00106 /* address too long! */ 00107 return 0; 00108 } 00109 if (s[1] == ':') { 00110 if (s[2] == ':') { 00111 /* invalid format: three successive colons */ 00112 return 0; 00113 } 00114 s++; 00115 /* "::" found, set zeros */ 00116 while (zero_blocks > 0) { 00117 zero_blocks--; 00118 if (current_block_index & 0x1) { 00119 addr_index++; 00120 } else { 00121 if (addr) { 00122 addr->addr[addr_index] = 0; 00123 } 00124 } 00125 current_block_index++; 00126 if (current_block_index > 7) { 00127 /* address too long! */ 00128 return 0; 00129 } 00130 } 00131 } 00132 } else if (isxdigit(*s)) { 00133 /* add current digit */ 00134 current_block_value = (current_block_value << 4) + 00135 (isdigit(*s) ? (u32_t)(*s - '0') : 00136 (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); 00137 } else { 00138 /* unexpected digit, space? CRLF? */ 00139 break; 00140 } 00141 } 00142 00143 if (addr) { 00144 if (current_block_index & 0x1) { 00145 addr->addr[addr_index++] |= current_block_value; 00146 } 00147 else { 00148 addr->addr[addr_index] = current_block_value << 16; 00149 } 00150 } 00151 00152 /* convert to network byte order. */ 00153 if (addr) { 00154 for (addr_index = 0; addr_index < 4; addr_index++) { 00155 addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); 00156 } 00157 } 00158 00159 if (current_block_index != 7) { 00160 return 0; 00161 } 00162 00163 return 1; 00164 } 00165 00166 /** 00167 * Convert numeric IPv6 address into ASCII representation. 00168 * returns ptr to static buffer; not reentrant! 00169 * 00170 * @param addr ip6 address in network order to convert 00171 * @return pointer to a global static (!) buffer that holds the ASCII 00172 * representation of addr 00173 */ 00174 char * 00175 ip6addr_ntoa(const ip6_addr_t *addr) 00176 { 00177 static char str[40]; 00178 return ip6addr_ntoa_r(addr, str, 40); 00179 } 00180 00181 /** 00182 * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. 00183 * 00184 * @param addr ip6 address in network order to convert 00185 * @param buf target buffer where the string is stored 00186 * @param buflen length of buf 00187 * @return either pointer to buf which now holds the ASCII 00188 * representation of addr or NULL if buf was too small 00189 */ 00190 char * 00191 ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) 00192 { 00193 u32_t current_block_index, current_block_value, next_block_value; 00194 s32_t i; 00195 u8_t zero_flag, empty_block_flag; 00196 00197 i = 0; 00198 empty_block_flag = 0; /* used to indicate a zero chain for "::' */ 00199 00200 for (current_block_index = 0; current_block_index < 8; current_block_index++) { 00201 /* get the current 16-bit block */ 00202 current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); 00203 if ((current_block_index & 0x1) == 0) { 00204 current_block_value = current_block_value >> 16; 00205 } 00206 current_block_value &= 0xffff; 00207 00208 /* Check for empty block. */ 00209 if (current_block_value == 0) { 00210 if (current_block_index == 7 && empty_block_flag == 1) { 00211 /* special case, we must render a ':' for the last block. */ 00212 buf[i++] = ':'; 00213 if (i >= buflen) { 00214 return NULL; 00215 } 00216 break; 00217 } 00218 if (empty_block_flag == 0) { 00219 /* generate empty block "::", but only if more than one contiguous zero block, 00220 * according to current formatting suggestions RFC 5952. */ 00221 next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); 00222 if ((current_block_index & 0x1) == 0x01) { 00223 next_block_value = next_block_value >> 16; 00224 } 00225 next_block_value &= 0xffff; 00226 if (next_block_value == 0) { 00227 empty_block_flag = 1; 00228 buf[i++] = ':'; 00229 if (i >= buflen) { 00230 return NULL; 00231 } 00232 continue; /* move on to next block. */ 00233 } 00234 } else if (empty_block_flag == 1) { 00235 /* move on to next block. */ 00236 continue; 00237 } 00238 } else if (empty_block_flag == 1) { 00239 /* Set this flag value so we don't produce multiple empty blocks. */ 00240 empty_block_flag = 2; 00241 } 00242 00243 if (current_block_index > 0) { 00244 buf[i++] = ':'; 00245 if (i >= buflen) { 00246 return NULL; 00247 } 00248 } 00249 00250 if ((current_block_value & 0xf000) == 0) { 00251 zero_flag = 1; 00252 } else { 00253 buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); 00254 zero_flag = 0; 00255 if (i >= buflen) { 00256 return NULL; 00257 } 00258 } 00259 00260 if (((current_block_value & 0xf00) == 0) && (zero_flag)) { 00261 /* do nothing */ 00262 } else { 00263 buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); 00264 zero_flag = 0; 00265 if (i >= buflen) { 00266 return NULL; 00267 } 00268 } 00269 00270 if (((current_block_value & 0xf0) == 0) && (zero_flag)) { 00271 /* do nothing */ 00272 } 00273 else { 00274 buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); 00275 zero_flag = 0; 00276 if (i >= buflen) { 00277 return NULL; 00278 } 00279 } 00280 00281 buf[i++] = xchar((current_block_value & 0xf)); 00282 if (i >= buflen) { 00283 return NULL; 00284 } 00285 } 00286 00287 buf[i] = 0; 00288 00289 return buf; 00290 } 00291 00292 #endif /* LWIP_IPV6 */
Generated on Fri Jul 22 2022 04:53:52 by
1.7.2
