~marcus-mc/+junk/ps3sdk

« back to all changes in this revision

Viewing changes to src/lwip/src/core/inet.c

  • Committer: Marcus Comstedt
  • Date: 2009-08-02 16:05:58 UTC
  • Revision ID: marcus@mc.pp.se-20090802160558-zazx8adsuo9s4gqp
Imported LWIP stuff from emoon's sources.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2001-2004 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
#include "lwip/sys.h"
 
50
 
 
51
/* These are some reference implementations of the checksum algorithm, with the
 
52
 * aim of being simple, correct and fully portable. Checksumming is the
 
53
 * first thing you would want to optimize for your platform. If you create
 
54
 * your own version, link it in and in your sys_arch.h put:
 
55
 * 
 
56
 * #define LWIP_CHKSUM <your_checksum_routine> 
 
57
*/
 
58
#ifndef LWIP_CHKSUM
 
59
#define LWIP_CHKSUM lwip_standard_chksum
 
60
 
 
61
#if 1 /* Version A */
 
62
/**
 
63
 * lwip checksum
 
64
 *
 
65
 * @param dataptr points to start of data to be summed at any boundary
 
66
 * @param len length of data to be summed
 
67
 * @return host order (!) lwip checksum (non-inverted Internet sum) 
 
68
 *
 
69
 * @note accumulator size limits summable length to 64k
 
70
 * @note host endianess is irrelevant (p3 RFC1071)
 
71
 */
 
72
static u16_t
 
73
lwip_standard_chksum(void *dataptr, u16_t len)
 
74
{
 
75
  u32_t acc;
 
76
  u16_t src;
 
77
  u8_t *octetptr;
 
78
 
 
79
  acc = 0;
 
80
  /* dataptr may be at odd or even addresses */
 
81
  octetptr = (u8_t*)dataptr;
 
82
  while (len > 1)
 
83
  {
 
84
    /* declare first octet as most significant
 
85
       thus assume network order, ignoring host order */
 
86
    src = (*octetptr) << 8;
 
87
    octetptr++;
 
88
    /* declare second octet as least significant */
 
89
    src |= (*octetptr);
 
90
    octetptr++;
 
91
    acc += src;
 
92
    len -= 2;
 
93
  }
 
94
  if (len > 0)
 
95
  {
 
96
    /* accumulate remaining octet */
 
97
    src = (*octetptr) << 8;
 
98
    acc += src;
 
99
  }
 
100
  /* add deferred carry bits */
 
101
  acc = (acc >> 16) + (acc & 0x0000ffffUL);
 
102
  if ((acc & 0xffff0000) != 0) {
 
103
    acc = (acc >> 16) + (acc & 0x0000ffffUL);
 
104
  }
 
105
  /* This maybe a little confusing: reorder sum using htons()
 
106
     instead of ntohs() since it has a little less call overhead.
 
107
     The caller must invert bits for Internet sum ! */
 
108
  return htons((u16_t)acc);
 
109
}
 
110
#endif
 
111
 
 
112
#if 0 /* Version B */
 
113
/*
 
114
 * Curt McDowell
 
115
 * Broadcom Corp.
 
116
 * csm@broadcom.com
 
117
 *
 
118
 * IP checksum two bytes at a time with support for
 
119
 * unaligned buffer.
 
120
 * Works for len up to and including 0x20000.
 
121
 * by Curt McDowell, Broadcom Corp. 12/08/2005
 
122
 *
 
123
 * @param dataptr points to start of data to be summed at any boundary
 
124
 * @param len length of data to be summed
 
125
 * @return host order (!) lwip checksum (non-inverted Internet sum) 
 
126
 */
 
127
 
 
128
static u16_t
 
129
lwip_standard_chksum(void *dataptr, int len)
 
130
{
 
131
  u8_t *pb = dataptr;
 
132
  u16_t *ps, t = 0;
 
133
  u32_t sum = 0;
 
134
  int odd = ((u32_t)pb & 1);
 
135
 
 
136
  /* Get aligned to u16_t */
 
137
  if (odd && len > 0) {
 
138
    ((u8_t *)&t)[1] = *pb++;
 
139
    len--;
 
140
  }
 
141
 
 
142
  /* Add the bulk of the data */
 
143
  ps = (u16_t *)pb;
 
144
  while (len > 1) {
 
145
    sum += *ps++;
 
146
    len -= 2;
 
147
  }
 
148
 
 
149
  /* Consume left-over byte, if any */
 
150
  if (len > 0)
 
151
    ((u8_t *)&t)[0] = *(u8_t *)ps;;
 
152
 
 
153
  /* Add end bytes */
 
154
  sum += t;
 
155
 
 
156
  /*  Fold 32-bit sum to 16 bits */
 
157
  while (sum >> 16)
 
158
    sum = (sum & 0xffff) + (sum >> 16);
 
159
 
 
160
  /* Swap if alignment was odd */
 
161
  if (odd)
 
162
    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
 
163
 
 
164
  return sum;
 
165
}
 
166
#endif
 
167
 
 
168
#if 0 /* Version C */
 
169
/**
 
170
 * An optimized checksum routine. Basically, it uses loop-unrolling on
 
171
 * the checksum loop, treating the head and tail bytes specially, whereas
 
172
 * the inner loop acts on 8 bytes at a time. 
 
173
 *
 
174
 * @arg start of buffer to be checksummed. May be an odd byte address.
 
175
 * @len number of bytes in the buffer to be checksummed.
 
176
 * @return host order (!) lwip checksum (non-inverted Internet sum) 
 
177
 * 
 
178
 * by Curt McDowell, Broadcom Corp. December 8th, 2005
 
179
 */
 
180
 
 
181
static u16_t
 
182
lwip_standard_chksum(void *dataptr, int len)
 
183
{
 
184
  u8_t *pb = dataptr;
 
185
  u16_t *ps, t = 0;
 
186
  u32_t *pl;
 
187
  u32_t sum = 0, tmp;
 
188
  /* starts at odd byte address? */
 
189
  int odd = ((u32_t)pb & 1);
 
190
 
 
191
  if (odd && len > 0) {
 
192
    ((u8_t *)&t)[1] = *pb++;
 
193
    len--;
 
194
  }
 
195
 
 
196
  ps = (u16_t *)pb;
 
197
 
 
198
  if (((u32_t)ps & 3) && len > 1) {
 
199
    sum += *ps++;
 
200
    len -= 2;
 
201
  }
 
202
 
 
203
  pl = (u32_t *)ps;
 
204
 
 
205
  while (len > 7)  {
 
206
    tmp = sum + *pl++;          /* ping */
 
207
    if (tmp < sum)
 
208
      tmp++;                    /* add back carry */
 
209
 
 
210
    sum = tmp + *pl++;          /* pong */
 
211
    if (sum < tmp)
 
212
      sum++;                    /* add back carry */
 
213
 
 
214
    len -= 8;
 
215
  }
 
216
 
 
217
  /* make room in upper bits */
 
218
  sum = (sum >> 16) + (sum & 0xffff);
 
219
 
 
220
  ps = (u16_t *)pl;
 
221
 
 
222
  /* 16-bit aligned word remaining? */
 
223
  while (len > 1) {
 
224
    sum += *ps++;
 
225
    len -= 2;
 
226
  }
 
227
 
 
228
  /* dangling tail byte remaining? */
 
229
  if (len > 0)                  /* include odd byte */
 
230
    ((u8_t *)&t)[0] = *(u8_t *)ps;
 
231
 
 
232
  sum += t;                     /* add end bytes */
 
233
 
 
234
  while (sum >> 16)             /* combine halves */
 
235
    sum = (sum >> 16) + (sum & 0xffff);
 
236
 
 
237
  if (odd)
 
238
    sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
 
239
 
 
240
  return sum;
 
241
}
 
242
#endif
 
243
 
 
244
#endif /* LWIP_CHKSUM */
 
245
 
 
246
/* inet_chksum_pseudo:
 
247
 *
 
248
 * Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
 
249
 * IP addresses are expected to be in network byte order.
 
250
 *
 
251
 * @param p chain of pbufs over that a checksum should be calculated (ip data part)
 
252
 * @param src source ip address (used for checksum of pseudo header)
 
253
 * @param dst destination ip address (used for checksum of pseudo header)
 
254
 * @param proto ip protocol (used for checksum of pseudo header)
 
255
 * @param proto_len length of the ip data part (used for checksum of pseudo header)
 
256
 * @return checksum (as u16_t) to be saved directly in the protocol header
 
257
 */
 
258
u16_t
 
259
inet_chksum_pseudo(struct pbuf *p,
 
260
       struct ip_addr *src, struct ip_addr *dest,
 
261
       u8_t proto, u16_t proto_len)
 
262
{
 
263
  u32_t acc;
 
264
  struct pbuf *q;
 
265
  u8_t swapped;
 
266
 
 
267
  acc = 0;
 
268
  swapped = 0;
 
269
  /* iterate through all pbuf in chain */
 
270
  for(q = p; q != NULL; q = q->next) {
 
271
    LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
 
272
      (void *)q, (void *)q->next));
 
273
    acc += LWIP_CHKSUM(q->payload, q->len);
 
274
    /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
 
275
    while (acc >> 16) {
 
276
      acc = (acc & 0xffffUL) + (acc >> 16);
 
277
    }
 
278
    if (q->len % 2 != 0) {
 
279
      swapped = 1 - swapped;
 
280
      acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
 
281
    }
 
282
    /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
 
283
  }
 
284
 
 
285
  if (swapped) {
 
286
    acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
 
287
  }
 
288
  acc += (src->addr & 0xffffUL);
 
289
  acc += ((src->addr >> 16) & 0xffffUL);
 
290
  acc += (dest->addr & 0xffffUL);
 
291
  acc += ((dest->addr >> 16) & 0xffffUL);
 
292
  acc += (u32_t)htons((u16_t)proto);
 
293
  acc += (u32_t)htons(proto_len);
 
294
 
 
295
  while (acc >> 16) {
 
296
    acc = (acc & 0xffffUL) + (acc >> 16);
 
297
  }
 
298
  LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
 
299
  return (u16_t)~(acc & 0xffffUL);
 
300
}
 
301
 
 
302
/* inet_chksum:
 
303
 *
 
304
 * Calculates the Internet checksum over a portion of memory. Used primarily for IP
 
305
 * and ICMP.
 
306
 *
 
307
 * @param dataptr start of the buffer to calculate the checksum (no alignment needed)
 
308
 * @param len length of the buffer to calculate the checksum
 
309
 * @return checksum (as u16_t) to be saved directly in the protocol header
 
310
 */
 
311
 
 
312
u16_t
 
313
inet_chksum(void *dataptr, u16_t len)
 
314
{
 
315
  u32_t acc;
 
316
 
 
317
  acc = LWIP_CHKSUM(dataptr, len);
 
318
  while (acc >> 16) {
 
319
    acc = (acc & 0xffff) + (acc >> 16);
 
320
  }
 
321
  return (u16_t)~(acc & 0xffff);
 
322
}
 
323
 
 
324
/**
 
325
 * Calculate a checksum over a chain of pbufs (without pseudo-header, much like
 
326
 * inet_chksum only pbufs are used).
 
327
 *
 
328
 * @param p pbuf chain over that the checksum should be calculated
 
329
 * @return checksum (as u16_t) to be saved directly in the protocol header
 
330
 */
 
331
u16_t
 
332
inet_chksum_pbuf(struct pbuf *p)
 
333
{
 
334
  u32_t acc;
 
335
  struct pbuf *q;
 
336
  u8_t swapped;
 
337
 
 
338
  acc = 0;
 
339
  swapped = 0;
 
340
  for(q = p; q != NULL; q = q->next) {
 
341
    acc += LWIP_CHKSUM(q->payload, q->len);
 
342
    while (acc >> 16) {
 
343
      acc = (acc & 0xffffUL) + (acc >> 16);
 
344
    }
 
345
    if (q->len % 2 != 0) {
 
346
      swapped = 1 - swapped;
 
347
      acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
 
348
    }
 
349
  }
 
350
 
 
351
  if (swapped) {
 
352
    acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
 
353
  }
 
354
  return (u16_t)~(acc & 0xffffUL);
 
355
}
 
356
 
 
357
/* Here for now until needed in other places in lwIP */
 
358
#ifndef isprint
 
359
#define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
 
360
#define isprint(c)           in_range(c, 0x20, 0x7f)
 
361
#define isdigit(c)           in_range(c, '0', '9')
 
362
#define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
 
363
#define islower(c)           in_range(c, 'a', 'z')
 
364
#define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
 
365
#endif    
 
366
    
 
367
/**
 
368
 * Ascii internet address interpretation routine.
 
369
 * The value returned is in network order.
 
370
 *
 
371
 * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
 
372
 * @return ip address in network order
 
373
 */
 
374
u32_t
 
375
inet_addr(const char *cp)
 
376
{
 
377
  struct in_addr val;
 
378
 
 
379
  if (inet_aton(cp, &val)) {
 
380
    return (val.s_addr);
 
381
  }
 
382
  return (INADDR_NONE);
 
383
}
 
384
 
 
385
/**
 
386
 * Check whether "cp" is a valid ascii representation
 
387
 * of an Internet address and convert to a binary address.
 
388
 * Returns 1 if the address is valid, 0 if not.
 
389
 * This replaces inet_addr, the return value from which
 
390
 * cannot distinguish between failure and a local broadcast address.
 
391
 *
 
392
 * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
 
393
 * @param addr pointer to which to save the ip address in network order
 
394
 * @return 1 if cp could be converted to addr, 0 on failure
 
395
 */
 
396
int
 
397
inet_aton(const char *cp, struct in_addr *addr)
 
398
{
 
399
  u32_t val;
 
400
  int base, n, c;
 
401
  u32_t parts[4];
 
402
  u32_t *pp = parts;
 
403
 
 
404
  c = *cp;
 
405
  for (;;) {
 
406
    /*
 
407
     * Collect number up to ``.''.
 
408
     * Values are specified as for C:
 
409
     * 0x=hex, 0=octal, 1-9=decimal.
 
410
     */
 
411
    if (!isdigit(c))
 
412
      return (0);
 
413
    val = 0;
 
414
    base = 10;
 
415
    if (c == '0') {
 
416
      c = *++cp;
 
417
      if (c == 'x' || c == 'X') {
 
418
        base = 16;
 
419
        c = *++cp;
 
420
      } else
 
421
        base = 8;
 
422
    }
 
423
    for (;;) {
 
424
      if (isdigit(c)) {
 
425
        val = (val * base) + (int)(c - '0');
 
426
        c = *++cp;
 
427
      } else if (base == 16 && isxdigit(c)) {
 
428
        val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
 
429
        c = *++cp;
 
430
      } else
 
431
        break;
 
432
    }
 
433
    if (c == '.') {
 
434
      /*
 
435
       * Internet format:
 
436
       *  a.b.c.d
 
437
       *  a.b.c   (with c treated as 16 bits)
 
438
       *  a.b (with b treated as 24 bits)
 
439
       */
 
440
      if (pp >= parts + 3)
 
441
        return (0);
 
442
      *pp++ = val;
 
443
      c = *++cp;
 
444
    } else
 
445
      break;
 
446
  }
 
447
  /*
 
448
   * Check for trailing characters.
 
449
   */
 
450
  if (c != '\0' && (!isprint(c) || !isspace(c)))
 
451
    return (0);
 
452
  /*
 
453
   * Concoct the address according to
 
454
   * the number of parts specified.
 
455
   */
 
456
  n = pp - parts + 1;
 
457
  switch (n) {
 
458
 
 
459
  case 0:
 
460
    return (0);       /* initial nondigit */
 
461
 
 
462
  case 1:             /* a -- 32 bits */
 
463
    break;
 
464
 
 
465
  case 2:             /* a.b -- 8.24 bits */
 
466
    if (val > 0xffffffUL)
 
467
      return (0);
 
468
    val |= parts[0] << 24;
 
469
    break;
 
470
 
 
471
  case 3:             /* a.b.c -- 8.8.16 bits */
 
472
    if (val > 0xffff)
 
473
      return (0);
 
474
    val |= (parts[0] << 24) | (parts[1] << 16);
 
475
    break;
 
476
 
 
477
  case 4:             /* a.b.c.d -- 8.8.8.8 bits */
 
478
    if (val > 0xff)
 
479
      return (0);
 
480
    val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
 
481
    break;
 
482
  }
 
483
  if (addr)
 
484
    addr->s_addr = htonl(val);
 
485
  return (1);
 
486
}
 
487
 
 
488
/**
 
489
 * Convert numeric IP address into decimal dotted ASCII representation.
 
490
 * returns ptr to static buffer; not reentrant!
 
491
 *
 
492
 * @paran addr ip address in network order to convert
 
493
 * @return pointer to a global static (!) buffer that holds the ASCII
 
494
 *         represenation of addr
 
495
 */
 
496
char *
 
497
inet_ntoa(struct in_addr addr)
 
498
{
 
499
  static char str[16];
 
500
  u32_t s_addr = addr.s_addr;
 
501
  char inv[3];
 
502
  char *rp;
 
503
  u8_t *ap;
 
504
  u8_t rem;
 
505
  u8_t n;
 
506
  u8_t i;
 
507
 
 
508
  rp = str;
 
509
  ap = (u8_t *)&s_addr;
 
510
  for(n = 0; n < 4; n++) {
 
511
    i = 0;
 
512
    do {
 
513
      rem = *ap % (u8_t)10;
 
514
      *ap /= (u8_t)10;
 
515
      inv[i++] = '0' + rem;
 
516
    } while(*ap);
 
517
    while(i--)
 
518
      *rp++ = inv[i];
 
519
    *rp++ = '.';
 
520
    ap++;
 
521
  }
 
522
  *--rp = 0;
 
523
  return str;
 
524
}
 
525
 
 
526
/**
 
527
 * These are reference implementations of the byte swapping functions.
 
528
 * Again with the aim of being simple, correct and fully portable.
 
529
 * Byte swapping is the second thing you would want to optimize. You will
 
530
 * need to port it to your architecture and in your cc.h:
 
531
 * 
 
532
 * #define LWIP_PLATFORM_BYTESWAP 1
 
533
 * #define LWIP_PLATFORM_HTONS(x) <your_htons>
 
534
 * #define LWIP_PLATFORM_HTONL(x) <your_htonl>
 
535
 *
 
536
 * Note ntohs() and ntohl() are merely references to the htonx counterparts.
 
537
 */
 
538
 
 
539
#ifndef BYTE_ORDER
 
540
#error BYTE_ORDER is not defined
 
541
#endif
 
542
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
 
543
 
 
544
/**
 
545
 * Convert an u16_t from host- to network byte order.
 
546
 *
 
547
 * @param n u16_t in host byte order
 
548
 * @return n in network byte order
 
549
 */
 
550
u16_t
 
551
htons(u16_t n)
 
552
{
 
553
  return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
 
554
}
 
555
 
 
556
/**
 
557
 * Convert an u16_t from network- to host byte order.
 
558
 *
 
559
 * @param n u16_t in network byte order
 
560
 * @return n in host byte order
 
561
 */
 
562
u16_t
 
563
ntohs(u16_t n)
 
564
{
 
565
  return htons(n);
 
566
}
 
567
 
 
568
/**
 
569
 * Convert an u32_t from host- to network byte order.
 
570
 *
 
571
 * @param n u32_t in host byte order
 
572
 * @return n in network byte order
 
573
 */
 
574
u32_t
 
575
htonl(u32_t n)
 
576
{
 
577
  return ((n & 0xff) << 24) |
 
578
    ((n & 0xff00) << 8) |
 
579
    ((n & 0xff0000UL) >> 8) |
 
580
    ((n & 0xff000000UL) >> 24);
 
581
}
 
582
 
 
583
/**
 
584
 * Convert an u32_t from network- to host byte order.
 
585
 *
 
586
 * @param n u32_t in network byte order
 
587
 * @return n in host byte order
 
588
 */
 
589
u32_t
 
590
ntohl(u32_t n)
 
591
{
 
592
  return htonl(n);
 
593
}
 
594
 
 
595
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */