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 lwip by
ip_addr.c
00001 /** 00002 * @file 00003 * This is the IPv4 address tools implementation. 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 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: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 #include "lwip/opt.h" 00040 #include "lwip/ip_addr.h" 00041 #include "lwip/netif.h" 00042 00043 /* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ 00044 const ip_addr_t ip_addr_any = { IPADDR_ANY }; 00045 const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; 00046 00047 /** 00048 * Determine if an address is a broadcast address on a network interface 00049 * 00050 * @param addr address to be checked 00051 * @param netif the network interface against which the address is checked 00052 * @return returns non-zero if the address is a broadcast address 00053 */ 00054 u8_t 00055 ip4_addr_isbroadcast(u32_t addr, const struct netif *netif) 00056 { 00057 ip_addr_t ipaddr; 00058 ip4_addr_set_u32(&ipaddr, addr); 00059 00060 /* all ones (broadcast) or all zeroes (old skool broadcast) */ 00061 if ((~addr == IPADDR_ANY) || 00062 (addr == IPADDR_ANY)) { 00063 return 1; 00064 /* no broadcast support on this network interface? */ 00065 } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { 00066 /* the given address cannot be a broadcast address 00067 * nor can we check against any broadcast addresses */ 00068 return 0; 00069 /* address matches network interface address exactly? => no broadcast */ 00070 } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) { 00071 return 0; 00072 /* on the same (sub) network... */ 00073 } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask)) 00074 /* ...and host identifier bits are all ones? =>... */ 00075 && ((addr & ~ip4_addr_get_u32(&netif->netmask)) == 00076 (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) { 00077 /* => network broadcast address */ 00078 return 1; 00079 } else { 00080 return 0; 00081 } 00082 } 00083 00084 /** Checks if a netmask is valid (starting with ones, then only zeros) 00085 * 00086 * @param netmask the IPv4 netmask to check (in network byte order!) 00087 * @return 1 if the netmask is valid, 0 if it is not 00088 */ 00089 u8_t 00090 ip4_addr_netmask_valid(u32_t netmask) 00091 { 00092 u32_t mask; 00093 u32_t nm_hostorder = lwip_htonl(netmask); 00094 00095 /* first, check for the first zero */ 00096 for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { 00097 if ((nm_hostorder & mask) == 0) { 00098 break; 00099 } 00100 } 00101 /* then check that there is no one */ 00102 for (; mask != 0; mask >>= 1) { 00103 if ((nm_hostorder & mask) != 0) { 00104 /* there is a one after the first zero -> invalid */ 00105 return 0; 00106 } 00107 } 00108 /* no one after the first zero -> valid */ 00109 return 1; 00110 } 00111 00112 /* Here for now until needed in other places in lwIP */ 00113 #ifndef isprint 00114 #define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) 00115 #define isprint(c) in_range(c, 0x20, 0x7f) 00116 #define isdigit(c) in_range(c, '0', '9') 00117 #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) 00118 #define islower(c) in_range(c, 'a', 'z') 00119 #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 00120 #endif 00121 00122 /** 00123 * Ascii internet address interpretation routine. 00124 * The value returned is in network order. 00125 * 00126 * @param cp IP address in ascii represenation (e.g. "127.0.0.1") 00127 * @return ip address in network order 00128 */ 00129 u32_t 00130 ipaddr_addr(const char *cp) 00131 { 00132 ip_addr_t val; 00133 00134 if (ipaddr_aton(cp, &val)) { 00135 return ip4_addr_get_u32(&val); 00136 } 00137 return (IPADDR_NONE); 00138 } 00139 00140 /** 00141 * Check whether "cp" is a valid ascii representation 00142 * of an Internet address and convert to a binary address. 00143 * Returns 1 if the address is valid, 0 if not. 00144 * This replaces inet_addr, the return value from which 00145 * cannot distinguish between failure and a local broadcast address. 00146 * 00147 * @param cp IP address in ascii represenation (e.g. "127.0.0.1") 00148 * @param addr pointer to which to save the ip address in network order 00149 * @return 1 if cp could be converted to addr, 0 on failure 00150 */ 00151 int 00152 ipaddr_aton(const char *cp, ip_addr_t *addr) 00153 { 00154 u32_t val; 00155 u8_t base; 00156 char c; 00157 u32_t parts[4]; 00158 u32_t *pp = parts; 00159 00160 c = *cp; 00161 for (;;) { 00162 /* 00163 * Collect number up to ``.''. 00164 * Values are specified as for C: 00165 * 0x=hex, 0=octal, 1-9=decimal. 00166 */ 00167 if (!isdigit(c)) 00168 return (0); 00169 val = 0; 00170 base = 10; 00171 if (c == '0') { 00172 c = *++cp; 00173 if (c == 'x' || c == 'X') { 00174 base = 16; 00175 c = *++cp; 00176 } else 00177 base = 8; 00178 } 00179 for (;;) { 00180 if (isdigit(c)) { 00181 val = (val * base) + (int)(c - '0'); 00182 c = *++cp; 00183 } else if (base == 16 && isxdigit(c)) { 00184 val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); 00185 c = *++cp; 00186 } else 00187 break; 00188 } 00189 if (c == '.') { 00190 /* 00191 * Internet format: 00192 * a.b.c.d 00193 * a.b.c (with c treated as 16 bits) 00194 * a.b (with b treated as 24 bits) 00195 */ 00196 if (pp >= parts + 3) { 00197 return (0); 00198 } 00199 *pp++ = val; 00200 c = *++cp; 00201 } else 00202 break; 00203 } 00204 /* 00205 * Check for trailing characters. 00206 */ 00207 if (c != '\0' && !isspace(c)) { 00208 return (0); 00209 } 00210 /* 00211 * Concoct the address according to 00212 * the number of parts specified. 00213 */ 00214 switch (pp - parts + 1) { 00215 00216 case 0: 00217 return (0); /* initial nondigit */ 00218 00219 case 1: /* a -- 32 bits */ 00220 break; 00221 00222 case 2: /* a.b -- 8.24 bits */ 00223 if (val > 0xffffffUL) { 00224 return (0); 00225 } 00226 val |= parts[0] << 24; 00227 break; 00228 00229 case 3: /* a.b.c -- 8.8.16 bits */ 00230 if (val > 0xffff) { 00231 return (0); 00232 } 00233 val |= (parts[0] << 24) | (parts[1] << 16); 00234 break; 00235 00236 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 00237 if (val > 0xff) { 00238 return (0); 00239 } 00240 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 00241 break; 00242 default: 00243 LWIP_ASSERT("unhandled", 0); 00244 break; 00245 } 00246 if (addr) { 00247 ip4_addr_set_u32(addr, htonl(val)); 00248 } 00249 return (1); 00250 } 00251 00252 /** 00253 * Convert numeric IP address into decimal dotted ASCII representation. 00254 * returns ptr to static buffer; not reentrant! 00255 * 00256 * @param addr ip address in network order to convert 00257 * @return pointer to a global static (!) buffer that holds the ASCII 00258 * represenation of addr 00259 */ 00260 char * 00261 ipaddr_ntoa(const ip_addr_t *addr) 00262 { 00263 static char str[16]; 00264 return ipaddr_ntoa_r(addr, str, 16); 00265 } 00266 00267 /** 00268 * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. 00269 * 00270 * @param addr ip address in network order to convert 00271 * @param buf target buffer where the string is stored 00272 * @param buflen length of buf 00273 * @return either pointer to buf which now holds the ASCII 00274 * representation of addr or NULL if buf was too small 00275 */ 00276 char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen) 00277 { 00278 u32_t s_addr; 00279 char inv[3]; 00280 char *rp; 00281 u8_t *ap; 00282 u8_t rem; 00283 u8_t n; 00284 u8_t i; 00285 int len = 0; 00286 00287 s_addr = ip4_addr_get_u32(addr); 00288 00289 rp = buf; 00290 ap = (u8_t *)&s_addr; 00291 for(n = 0; n < 4; n++) { 00292 i = 0; 00293 do { 00294 rem = *ap % (u8_t)10; 00295 *ap /= (u8_t)10; 00296 inv[i++] = '0' + rem; 00297 } while(*ap); 00298 while(i--) { 00299 if (len++ >= buflen) { 00300 return NULL; 00301 } 00302 *rp++ = inv[i]; 00303 } 00304 if (len++ >= buflen) { 00305 return NULL; 00306 } 00307 *rp++ = '.'; 00308 ap++; 00309 } 00310 *--rp = 0; 00311 return buf; 00312 }
Generated on Tue Jul 12 2022 11:29:37 by
