Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lwip_ip6_addr.c
Go to the documentation of this file.
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 Sun Jul 17 2022 08:25:24 by 1.7.2