1 /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
2 
3 /**
4  * @file
5  * Functions common to all TCP/IPv4 modules, such as the byte order functions.
6  *
7  */
8 
9 /*
10  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * This file is part of the lwIP TCP/IP stack.
36  *
37  * Author: Adam Dunkels <adam@sics.se>
38  *
39  */
40 
41 #include "lwip/opt.h"
42 
43 #include "lwip/inet.h"
44 
45 /* Here for now until needed in other places in lwIP */
46 #ifndef isprint
47 #define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
48 #define isprint(c)           in_range(c, 0x20, 0x7f)
49 #define isdigit(c)           in_range(c, '0', '9')
50 #define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
51 #define islower(c)           in_range(c, 'a', 'z')
52 #define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
53 #endif
54 
55 /**
56  * Ascii internet address interpretation routine.
57  * The value returned is in network order.
58  *
59  * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
60  * @return ip address in network order
61  */
62 u32_t
inet_addr(const char * cp)63 inet_addr(const char *cp)
64 {
65   struct in_addr val;
66 
67   if (inet_aton(cp, &val)) {
68     return (val.s_addr);
69   }
70   return (INADDR_NONE);
71 }
72 
73 /**
74  * Check whether "cp" is a valid ascii representation
75  * of an Internet address and convert to a binary address.
76  * Returns 1 if the address is valid, 0 if not.
77  * This replaces inet_addr, the return value from which
78  * cannot distinguish between failure and a local broadcast address.
79  *
80  * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
81  * @param addr pointer to which to save the ip address in network order
82  * @return 1 if cp could be converted to addr, 0 on failure
83  */
84 int
inet_aton(const char * cp,struct in_addr * addr)85 inet_aton(const char *cp, struct in_addr *addr)
86 {
87   u32_t val;
88   u8_t base;
89   char c;
90   u32_t parts[4];
91   u32_t *pp = parts;
92 
93   c = *cp;
94   for (;;) {
95     /*
96      * Collect number up to ``.''.
97      * Values are specified as for C:
98      * 0x=hex, 0=octal, 1-9=decimal.
99      */
100     if (!isdigit(c))
101       return (0);
102     val = 0;
103     base = 10;
104     if (c == '0') {
105       c = *++cp;
106       if (c == 'x' || c == 'X') {
107         base = 16;
108         c = *++cp;
109       } else
110         base = 8;
111     }
112     for (;;) {
113       if (isdigit(c)) {
114         val = (val * base) + (int)(c - '0');
115         c = *++cp;
116       } else if (base == 16 && isxdigit(c)) {
117         val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
118         c = *++cp;
119       } else
120         break;
121     }
122     if (c == '.') {
123       /*
124        * Internet format:
125        *  a.b.c.d
126        *  a.b.c   (with c treated as 16 bits)
127        *  a.b (with b treated as 24 bits)
128        */
129       if (pp >= parts + 3)
130         return (0);
131       *pp++ = val;
132       c = *++cp;
133     } else
134       break;
135   }
136   /*
137    * Check for trailing characters.
138    */
139   if (c != '\0' && !isspace(c))
140     return (0);
141   /*
142    * Concoct the address according to
143    * the number of parts specified.
144    */
145   switch (pp - parts + 1) {
146 
147   case 0:
148     return (0);       /* initial nondigit */
149 
150   case 1:             /* a -- 32 bits */
151     break;
152 
153   case 2:             /* a.b -- 8.24 bits */
154     if (val > 0xffffffUL)
155       return (0);
156     val |= parts[0] << 24;
157     break;
158 
159   case 3:             /* a.b.c -- 8.8.16 bits */
160     if (val > 0xffff)
161       return (0);
162     val |= (parts[0] << 24) | (parts[1] << 16);
163     break;
164 
165   case 4:             /* a.b.c.d -- 8.8.8.8 bits */
166     if (val > 0xff)
167       return (0);
168     val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
169     break;
170   }
171   if (addr)
172     addr->s_addr = htonl(val);
173   return (1);
174 }
175 
176 /**
177  * Convert numeric IP address into decimal dotted ASCII representation.
178  * returns ptr to static buffer; not reentrant!
179  *
180  * @param addr ip address in network order to convert
181  * @return pointer to a global static (!) buffer that holds the ASCII
182  *         represenation of addr
183  */
184 char *
inet_ntoa(struct in_addr addr)185 inet_ntoa(struct in_addr addr)
186 {
187   static char str[16];
188   u32_t s_addr = addr.s_addr;
189   char inv[3];
190   char *rp;
191   u8_t *ap;
192   u8_t rem;
193   u8_t n;
194   u8_t i;
195 
196   rp = str;
197   ap = (u8_t *)&s_addr;
198   for(n = 0; n < 4; n++) {
199     i = 0;
200     do {
201       rem = *ap % (u8_t)10;
202       *ap /= (u8_t)10;
203       inv[i++] = '0' + rem;
204     } while(*ap);
205     while(i--)
206       *rp++ = inv[i];
207     *rp++ = '.';
208     ap++;
209   }
210   *--rp = 0;
211   return str;
212 }
213 
214 /**
215  * These are reference implementations of the byte swapping functions.
216  * Again with the aim of being simple, correct and fully portable.
217  * Byte swapping is the second thing you would want to optimize. You will
218  * need to port it to your architecture and in your cc.h:
219  *
220  * #define LWIP_PLATFORM_BYTESWAP 1
221  * #define LWIP_PLATFORM_HTONS(x) <your_htons>
222  * #define LWIP_PLATFORM_HTONL(x) <your_htonl>
223  *
224  * Note ntohs() and ntohl() are merely references to the htonx counterparts.
225  */
226 
227 #if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
228 
229 /**
230  * Convert an u16_t from host- to network byte order.
231  *
232  * @param n u16_t in host byte order
233  * @return n in network byte order
234  */
235 u16_t
htons(u16_t n)236 htons(u16_t n)
237 {
238   return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
239 }
240 
241 /**
242  * Convert an u16_t from network- to host byte order.
243  *
244  * @param n u16_t in network byte order
245  * @return n in host byte order
246  */
247 u16_t
ntohs(u16_t n)248 ntohs(u16_t n)
249 {
250   return htons(n);
251 }
252 
253 /**
254  * Convert an u32_t from host- to network byte order.
255  *
256  * @param n u32_t in host byte order
257  * @return n in network byte order
258  */
259 u32_t
htonl(u32_t n)260 htonl(u32_t n)
261 {
262   return ((n & 0xff) << 24) |
263     ((n & 0xff00) << 8) |
264     ((n & 0xff0000UL) >> 8) |
265     ((n & 0xff000000UL) >> 24);
266 }
267 
268 /**
269  * Convert an u32_t from network- to host byte order.
270  *
271  * @param n u32_t in network byte order
272  * @return n in host byte order
273  */
274 u32_t
ntohl(u32_t n)275 ntohl(u32_t n)
276 {
277   return htonl(n);
278 }
279 
280 #endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
281