1/** 2 * @file 3 * Functions common to all TCP/IPv4 modules, such as the byte order functions. 4 * 5 */ 6 7/* 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 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: Adam Dunkels <adam@sics.se> 36 * 37 */ 38 39#include "lwip/opt.h" 40 41#include "lwip/inet.h" 42 43/* Here for now until needed in other places in lwIP */ 44#ifndef isprint 45#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) 46#define isprint(c) in_range(c, 0x20, 0x7f) 47#define isdigit(c) in_range(c, '0', '9') 48#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) 49#define islower(c) in_range(c, 'a', 'z') 50#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 51#endif 52 53/** 54 * Ascii internet address interpretation routine. 55 * The value returned is in network order. 56 * 57 * @param cp IP address in ascii represenation (e.g. "127.0.0.1") 58 * @return ip address in network order 59 */ 60u32_t inet_addr(const char *cp) 61{ 62 struct in_addr val; 63 64 if (inet_aton(cp, &val)) { 65 return (val.s_addr); 66 } 67 return (INADDR_NONE); 68} 69 70/** 71 * Check whether "cp" is a valid ascii representation 72 * of an Internet address and convert to a binary address. 73 * Returns 1 if the address is valid, 0 if not. 74 * This replaces inet_addr, the return value from which 75 * cannot distinguish between failure and a local broadcast address. 76 * 77 * @param cp IP address in ascii represenation (e.g. "127.0.0.1") 78 * @param addr pointer to which to save the ip address in network order 79 * @return 1 if cp could be converted to addr, 0 on failure 80 */ 81int inet_aton(const char *cp, struct in_addr *addr) 82{ 83 u32_t val; 84 u8_t base; 85 char c; 86 u32_t parts[4]; 87 u32_t *pp = parts; 88 89 c = *cp; 90 for (;;) { 91 /* 92 * Collect number up to ``.''. 93 * Values are specified as for C: 94 * 0x=hex, 0=octal, 1-9=decimal. 95 */ 96 if (!isdigit(c)) 97 return (0); 98 val = 0; 99 base = 10; 100 if (c == '0') { 101 c = *++cp; 102 if (c == 'x' || c == 'X') { 103 base = 16; 104 c = *++cp; 105 } else 106 base = 8; 107 } 108 for (;;) { 109 if (isdigit(c)) { 110 val = (val * base) + (int) (c - '0'); 111 c = *++cp; 112 } else if (base == 16 && isxdigit(c)) { 113 val = (val << 4) | (int) (c + 10 - (islower(c) ? 'a' : 'A')); 114 c = *++cp; 115 } else 116 break; 117 } 118 if (c == '.') { 119 /* 120 * Internet format: 121 * a.b.c.d 122 * a.b.c (with c treated as 16 bits) 123 * a.b (with b treated as 24 bits) 124 */ 125 if (pp >= parts + 3) 126 return (0); 127 *pp++ = val; 128 c = *++cp; 129 } else 130 break; 131 } 132 /* 133 * Check for trailing characters. 134 */ 135 if (c != '\0' && !isspace(c)) 136 return (0); 137 /* 138 * Concoct the address according to 139 * the number of parts specified. 140 */ 141 switch (pp - parts + 1) { 142 143 case 0: 144 return (0); /* initial nondigit */ 145 146 case 1: /* a -- 32 bits */ 147 break; 148 149 case 2: /* a.b -- 8.24 bits */ 150 if (val > 0xffffffUL) 151 return (0); 152 val |= parts[0] << 24; 153 break; 154 155 case 3: /* a.b.c -- 8.8.16 bits */ 156 if (val > 0xffff) 157 return (0); 158 val |= (parts[0] << 24) | (parts[1] << 16); 159 break; 160 161 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 162 if (val > 0xff) 163 return (0); 164 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 165 break; 166 } 167 if (addr) 168 addr->s_addr = htonl(val); 169 return (1); 170} 171 172/** 173 * Convert numeric IP address into decimal dotted ASCII representation. 174 * returns ptr to static buffer; not reentrant! 175 * 176 * @param addr ip address in network order to convert 177 * @return pointer to a global static (!) buffer that holds the ASCII 178 * represenation of addr 179 */ 180char *inet_ntoa(struct in_addr addr) 181{ 182 static char str[16]; 183 u32_t s_addr = addr.s_addr; 184 char inv[3]; 185 char *rp; 186 u8_t *ap; 187 u8_t rem; 188 u8_t n; 189 u8_t i; 190 191 rp = str; 192 ap = (u8_t *) & s_addr; 193 for (n = 0; n < 4; n++) { 194 i = 0; 195 do { 196 rem = *ap % (u8_t) 10; 197 *ap /= (u8_t) 10; 198 inv[i++] = '0' + rem; 199 } while (*ap); 200 while (i--) 201 *rp++ = inv[i]; 202 *rp++ = '.'; 203 ap++; 204 } 205 *--rp = 0; 206 return str; 207} 208 209/** 210 * These are reference implementations of the byte swapping functions. 211 * Again with the aim of being simple, correct and fully portable. 212 * Byte swapping is the second thing you would want to optimize. You will 213 * need to port it to your architecture and in your cc.h: 214 * 215 * #define LWIP_PLATFORM_BYTESWAP 1 216 * #define LWIP_PLATFORM_HTONS(x) <your_htons> 217 * #define LWIP_PLATFORM_HTONL(x) <your_htonl> 218 * 219 * Note ntohs() and ntohl() are merely references to the htonx counterparts. 220 */ 221 222#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) 223 224/** 225 * Convert an u16_t from host- to network byte order. 226 * 227 * @param n u16_t in host byte order 228 * @return n in network byte order 229 */ 230u16_t htons(u16_t n) 231{ 232 return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); 233} 234 235/** 236 * Convert an u16_t from network- to host byte order. 237 * 238 * @param n u16_t in network byte order 239 * @return n in host byte order 240 */ 241u16_t ntohs(u16_t n) 242{ 243 return htons(n); 244} 245 246/** 247 * Convert an u32_t from host- to network byte order. 248 * 249 * @param n u32_t in host byte order 250 * @return n in network byte order 251 */ 252u32_t htonl(u32_t n) 253{ 254 return ((n & 0xff) << 24) | 255 ((n & 0xff00) << 8) | 256 ((n & 0xff0000UL) >> 8) | ((n & 0xff000000UL) >> 24); 257} 258 259/** 260 * Convert an u32_t from network- to host byte order. 261 * 262 * @param n u32_t in network byte order 263 * @return n in host byte order 264 */ 265u32_t ntohl(u32_t n) 266{ 267 return htonl(n); 268} 269 270#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */ 271