]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - src/core/inet.c
Merged from DEVEL into main tree.
[pes-rpp/rpp-lwip.git] / src / core / inet.c
1 /*
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32
33
34 /* inet.c
35  *
36  * Functions common to all TCP/IP modules, such as the Internet checksum and the
37  * byte order functions.
38  *
39  */
40
41
42 #include "lwip/opt.h"
43
44 #include "lwip/arch.h"
45
46 #include "lwip/def.h"
47 #include "lwip/inet.h"
48
49
50
51 static u16_t
52 lwip_chksum(void *dataptr, int len)
53 {
54   u32_t acc;
55
56   LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
57   for(acc = 0; len > 1; len -= 2) {
58       /*    acc = acc + *((u16_t *)dataptr)++;*/
59     acc += *(u16_t *)dataptr;
60     dataptr = (void *)((u16_t *)dataptr + 1);
61   }
62
63   /* add up any odd byte */
64   if (len == 1) {
65     acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
66     LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
67   } else {
68     LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
69   }
70   acc = (acc >> 16) + (acc & 0xffffUL);
71
72   if ((acc & 0xffff0000) != 0) {
73     acc = (acc >> 16) + (acc & 0xffffUL);
74   }
75
76   return (u16_t)acc;
77 }
78
79 /* inet_chksum_pseudo:
80  *
81  * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
82  */
83
84 u16_t
85 inet_chksum_pseudo(struct pbuf *p,
86        struct ip_addr *src, struct ip_addr *dest,
87        u8_t proto, u16_t proto_len)
88 {
89   u32_t acc;
90   struct pbuf *q;
91   u8_t swapped;
92
93   acc = 0;
94   swapped = 0;
95   /* iterate through all pbuf in chain */
96   for(q = p; q != NULL; q = q->next) {
97     LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
98       (void *)q, (void *)q->next));
99     acc += lwip_chksum(q->payload, q->len);
100     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
101     while (acc >> 16) {
102       acc = (acc & 0xffffUL) + (acc >> 16);
103     }
104     if (q->len % 2 != 0) {
105       swapped = 1 - swapped;
106       acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
107     }
108     /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));*/
109   }
110
111   if (swapped) {
112     acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
113   }
114   acc += (src->addr & 0xffffUL);
115   acc += ((src->addr >> 16) & 0xffffUL);
116   acc += (dest->addr & 0xffffUL);
117   acc += ((dest->addr >> 16) & 0xffffUL);
118   acc += (u32_t)htons((u16_t)proto);
119   acc += (u32_t)htons(proto_len);
120
121   while (acc >> 16) {
122     acc = (acc & 0xffffUL) + (acc >> 16);
123   }
124   LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
125   return ~(acc & 0xffffUL);
126 }
127
128 /* inet_chksum:
129  *
130  * Calculates the Internet checksum over a portion of memory. Used primarely for IP
131  * and ICMP.
132  */
133
134 u16_t
135 inet_chksum(void *dataptr, u16_t len)
136 {
137   u32_t acc;
138
139   acc = lwip_chksum(dataptr, len);
140   while (acc >> 16) {
141     acc = (acc & 0xffff) + (acc >> 16);
142   }
143   return ~(acc & 0xffff);
144 }
145
146 u16_t
147 inet_chksum_pbuf(struct pbuf *p)
148 {
149   u32_t acc;
150   struct pbuf *q;
151   u8_t swapped;
152
153   acc = 0;
154   swapped = 0;
155   for(q = p; q != NULL; q = q->next) {
156     acc += lwip_chksum(q->payload, q->len);
157     while (acc >> 16) {
158       acc = (acc & 0xffffUL) + (acc >> 16);
159     }
160     if (q->len % 2 != 0) {
161       swapped = 1 - swapped;
162       acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
163     }
164   }
165
166   if (swapped) {
167     acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
168   }
169   return ~(acc & 0xffffUL);
170 }
171
172 /* Here for now until needed in other places in lwIP */
173 #ifndef isascii
174 #define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
175 #define isascii(c)           in_range(c, 0x20, 0x7f)
176 #define isdigit(c)           in_range(c, '0', '9')
177 #define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
178 #define islower(c)           in_range(c, 'a', 'z')
179 #define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
180 #endif          
181                 
182
183  /*
184   * Ascii internet address interpretation routine.
185   * The value returned is in network order.
186   */
187
188  /*  */
189  /* inet_addr */
190  u32_t inet_addr(const char *cp)
191  {
192      struct in_addr val;
193
194      if (inet_aton(cp, &val)) {
195          return (val.s_addr);
196      }
197      return (INADDR_NONE);
198  }
199
200  /*
201   * Check whether "cp" is a valid ascii representation
202   * of an Internet address and convert to a binary address.
203   * Returns 1 if the address is valid, 0 if not.
204   * This replaces inet_addr, the return value from which
205   * cannot distinguish between failure and a local broadcast address.
206   */
207  /*  */
208  /* inet_aton */
209  int inet_aton(const char *cp, struct in_addr *addr)
210  {
211      u32_t val;
212      int base, n;
213      char c;
214      u32_t parts[4];
215      u32_t* pp = parts;
216
217      c = *cp;
218      for (;;) {
219          /*
220           * Collect number up to ``.''.
221           * Values are specified as for C:
222           * 0x=hex, 0=octal, isdigit=decimal.
223           */
224          if (!isdigit(c))
225              return (0);
226          val = 0; base = 10;
227          if (c == '0') {
228              c = *++cp;
229              if (c == 'x' || c == 'X')
230                  base = 16, c = *++cp;
231              else
232                  base = 8;
233          }
234          for (;;) {
235              if (isascii(c) && isdigit(c)) {
236                  val = (val * base) + (c - '0');
237                  c = *++cp;
238              } else if (base == 16 && isascii(c) && isxdigit(c)) {
239                  val = (val << 4) |
240                      (c + 10 - (islower(c) ? 'a' : 'A'));
241                  c = *++cp;
242              } else
243              break;
244          }
245          if (c == '.') {
246              /*
247               * Internet format:
248               *  a.b.c.d
249               *  a.b.c   (with c treated as 16 bits)
250               *  a.b (with b treated as 24 bits)
251               */
252              if (pp >= parts + 3)
253                  return (0);
254              *pp++ = val;
255              c = *++cp;
256          } else
257              break;
258      }
259      /*
260       * Check for trailing characters.
261       */
262      if (c != '\0' && (!isascii(c) || !isspace(c)))
263          return (0);
264      /*
265       * Concoct the address according to
266       * the number of parts specified.
267       */
268      n = pp - parts + 1;
269      switch (n) {
270
271      case 0:
272          return (0);     /* initial nondigit */
273
274      case 1:             /* a -- 32 bits */
275          break;
276
277      case 2:             /* a.b -- 8.24 bits */
278          if (val > 0xffffff)
279              return (0);
280          val |= parts[0] << 24;
281          break;
282
283      case 3:             /* a.b.c -- 8.8.16 bits */
284          if (val > 0xffff)
285              return (0);
286          val |= (parts[0] << 24) | (parts[1] << 16);
287          break;
288
289      case 4:             /* a.b.c.d -- 8.8.8.8 bits */
290          if (val > 0xff)
291              return (0);
292          val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
293          break;
294      }
295      if (addr)
296          addr->s_addr = htonl(val);
297      return (1);
298  }
299
300 /* Convert numeric IP address into decimal dotted ASCII representation.
301  * returns ptr to static buffer; not reentrant!
302  */
303 u8_t *inet_ntoa(u32_t addr)
304 {
305   static u8_t str[16];
306   u8_t inv[3];
307   u8_t *rp;
308   u8_t *ap;
309   u8_t rem;
310   u8_t n;
311   u8_t i;
312
313   rp = str;
314   ap = (u8_t *)&addr;
315   for(n = 0; n < 4; n++) {
316     i = 0;
317     do {
318       rem = *ap % (u8_t)10;
319       *ap /= (u8_t)10;
320       inv[i++] = '0' + rem;
321     } while(*ap);
322     while(i--)
323       *rp++ = inv[i];
324     *rp++ = '.';
325     ap++;
326   }
327   *--rp = 0;
328   return str;
329 }
330
331
332 #ifndef BYTE_ORDER
333 #error BYTE_ORDER is not defined
334 #endif
335 #if BYTE_ORDER == LITTLE_ENDIAN
336
337 u16_t
338 htons(u16_t n)
339 {
340   return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
341 }
342
343 u16_t
344 ntohs(u16_t n)
345 {
346   return htons(n);
347 }
348
349 u32_t
350 htonl(u32_t n)
351 {
352   return ((n & 0xff) << 24) |
353     ((n & 0xff00) << 8) |
354     ((n & 0xff0000) >> 8) |
355     ((n & 0xff000000) >> 24);
356 }
357
358 u32_t
359 ntohl(u32_t n)
360 {
361   return htonl(n);
362 }
363
364 #endif /* BYTE_ORDER == LITTLE_ENDIAN */