OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP/] [core/] [ipv4/] [ip.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/* @file
2
 *
3
 * This is the IP layer implementation for incoming and outgoing IP traffic.
4
 *
5
 * @see ip_frag.c
6
 *
7
 */
8
/*
9
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
10
 * All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without modification,
13
 * are permitted provided that the following conditions are met:
14
 *
15
 * 1. Redistributions of source code must retain the above copyright notice,
16
 *    this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright notice,
18
 *    this list of conditions and the following disclaimer in the documentation
19
 *    and/or other materials provided with the distribution.
20
 * 3. The name of the author may not be used to endorse or promote products
21
 *    derived from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
24
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
26
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
28
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32
 * OF SUCH DAMAGE.
33
 *
34
 * This file is part of the lwIP TCP/IP stack.
35
 *
36
 * Author: Adam Dunkels <adam@sics.se>
37
 *
38
 */
39
 
40
#include "lwip/opt.h"
41
 
42
#include "lwip/def.h"
43
#include "lwip/mem.h"
44
#include "lwip/ip.h"
45
#include "lwip/ip_frag.h"
46
#include "lwip/inet.h"
47
#include "lwip/netif.h"
48
#include "lwip/icmp.h"
49
#include "lwip/raw.h"
50
#include "lwip/udp.h"
51
#include "lwip/tcp.h"
52
 
53
#include "lwip/stats.h"
54
 
55
#include "arch/perf.h"
56
 
57
#include "lwip/snmp.h"
58
#if LWIP_DHCP
59
#  include "lwip/dhcp.h"
60
#endif /* LWIP_DHCP */
61
 
62
/**
63
 * Initializes the IP layer.
64
 */
65
 
66
void
67
ip_init(void)
68
{
69
#if IP_FRAG
70
  ip_frag_init();
71
#endif
72
}
73
 
74
/**
75
 * Finds the appropriate network interface for a given IP address. It
76
 * searches the list of network interfaces linearly. A match is found
77
 * if the masked IP address of the network interface equals the masked
78
 * IP address given to the function.
79
 */
80
 
81
struct netif *
82
ip_route(struct ip_addr *dest)
83
{
84
  struct netif *netif;
85
 
86
  /* iterate through netifs */
87
  for(netif = netif_list; netif != NULL; netif = netif->next) {
88
    /* network mask matches? */
89
    if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
90
      /* return netif on which to forward IP packet */
91
      return netif;
92
    }
93
  }
94
  /* no matching netif found, use default netif */
95
  return netif_default;
96
}
97
#if IP_FORWARD
98
 
99
/**
100
 * Forwards an IP packet. It finds an appropriate route for the
101
 * packet, decrements the TTL value of the packet, adjusts the
102
 * checksum and outputs the packet on the appropriate interface.
103
 */
104
 
105
static struct netif *
106
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
107
{
108
  struct netif *netif;
109
 
110
  PERF_START;
111
  /* Find network interface where to forward this IP packet to. */
112
  netif = ip_route((struct ip_addr *)&(iphdr->dest));
113
  if (netif == NULL) {
114
    LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
115
                      iphdr->dest.addr));
116
    snmp_inc_ipoutnoroutes();
117
    return (struct netif *)NULL;
118
  }
119
  /* Do not forward packets onto the same network interface on which
120
   * they arrived. */
121
  if (netif == inp) {
122
    LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
123
    snmp_inc_ipoutnoroutes();
124
    return (struct netif *)NULL;
125
  }
126
 
127
  /* decrement TTL */
128
  IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
129
  /* send ICMP if TTL == 0 */
130
  if (IPH_TTL(iphdr) == 0) {
131
    snmp_inc_ipinhdrerrors();
132
    /* Don't send ICMP messages in response to ICMP messages */
133
    if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
134
      icmp_time_exceeded(p, ICMP_TE_TTL);
135
    }
136
    return (struct netif *)NULL;
137
  }
138
 
139
  /* Incrementally update the IP checksum. */
140
  if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
141
    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
142
  } else {
143
    IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
144
  }
145
 
146
  LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
147
                    iphdr->dest.addr));
148
 
149
  IP_STATS_INC(ip.fw);
150
  IP_STATS_INC(ip.xmit);
151
  snmp_inc_ipforwdatagrams();
152
 
153
  PERF_STOP("ip_forward");
154
  /* transmit pbuf on chosen interface */
155
  netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
156
  return netif;
157
}
158
#endif /* IP_FORWARD */
159
 
160
/**
161
 * This function is called by the network interface device driver when
162
 * an IP packet is received. The function does the basic checks of the
163
 * IP header such as packet size being at least larger than the header
164
 * size etc. If the packet was not destined for us, the packet is
165
 * forwarded (using ip_forward). The IP checksum is always checked.
166
 *
167
 * Finally, the packet is sent to the upper layer protocol input function.
168
 *
169
 *
170
 *
171
 */
172
 
173
err_t
174
ip_input(struct pbuf *p, struct netif *inp) {
175
  struct ip_hdr *iphdr;
176
  struct netif *netif;
177
  u16_t iphdrlen;
178
 
179
  IP_STATS_INC(ip.recv);
180
  snmp_inc_ipinreceives();
181
 
182
  /* identify the IP header */
183
  iphdr = p->payload;
184
  if (IPH_V(iphdr) != 4) {
185
    LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
186
    ip_debug_print(p);
187
    pbuf_free(p);
188
    IP_STATS_INC(ip.err);
189
    IP_STATS_INC(ip.drop);
190
    snmp_inc_ipinhdrerrors();
191
    return ERR_OK;
192
  }
193
  /* obtain IP header length in number of 32-bit words */
194
  iphdrlen = IPH_HL(iphdr);
195
  /* calculate IP header length in bytes */
196
  iphdrlen *= 4;
197
 
198
  /* header length exceeds first pbuf length? */
199
  if (iphdrlen > p->len) {
200
    LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
201
      iphdrlen, p->len));
202
    /* free (drop) packet pbufs */
203
    pbuf_free(p);
204
    IP_STATS_INC(ip.lenerr);
205
    IP_STATS_INC(ip.drop);
206
    snmp_inc_ipindiscards();
207
    return ERR_OK;
208
  }
209
 
210
  /* verify checksum */
211
#if CHECKSUM_CHECK_IP
212
  if (inet_chksum(iphdr, iphdrlen) != 0) {
213
 
214
    LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
215
    ip_debug_print(p);
216
    pbuf_free(p);
217
    IP_STATS_INC(ip.chkerr);
218
    IP_STATS_INC(ip.drop);
219
    snmp_inc_ipinhdrerrors();
220
    return ERR_OK;
221
  }
222
#endif
223
 
224
  /* Trim pbuf. This should have been done at the netif layer,
225
   * but we'll do it anyway just to be sure that its done. */
226
  pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
227
 
228
  /* match packet against an interface, i.e. is this packet for us? */
229
  for (netif = netif_list; netif != NULL; netif = netif->next) {
230
 
231
    LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
232
      iphdr->dest.addr, netif->ip_addr.addr,
233
      iphdr->dest.addr & netif->netmask.addr,
234
      netif->ip_addr.addr & netif->netmask.addr,
235
      iphdr->dest.addr & ~(netif->netmask.addr)));
236
 
237
    /* interface is up and configured? */
238
    if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
239
    {
240
      /* unicast to this interface address? */
241
      if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
242
         /* or broadcast on this interface network address? */
243
         ip_addr_isbroadcast(&(iphdr->dest), netif)) {
244
        LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
245
          netif->name[0], netif->name[1]));
246
        /* break out of for loop */
247
        break;
248
      }
249
    }
250
  }
251
#if LWIP_DHCP
252
  /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
253
   * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
254
   * According to RFC 1542 section 3.1.1, referred by RFC 2131).
255
   */
256
  if (netif == NULL) {
257
    /* remote port is DHCP server? */
258
    if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
259
      LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
260
        ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
261
      if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
262
        LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
263
        netif = inp;
264
      }
265
    }
266
  }
267
#endif /* LWIP_DHCP */
268
  /* packet not for us? */
269
  if (netif == NULL) {
270
    /* packet not for us, route or discard */
271
    LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
272
#if IP_FORWARD
273
    /* non-broadcast packet? */
274
    if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
275
      /* try to forward IP packet on (other) interfaces */
276
      ip_forward(p, iphdr, inp);
277
    }
278
    else
279
#endif /* IP_FORWARD */
280
    {
281
      snmp_inc_ipinaddrerrors();
282
      snmp_inc_ipindiscards();
283
    }
284
    pbuf_free(p);
285
    return ERR_OK;
286
  }
287
  /* packet consists of multiple fragments? */
288
  if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
289
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
290
    LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
291
      ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
292
    /* reassemble the packet*/
293
    p = ip_reass(p);
294
    /* packet not fully reassembled yet? */
295
    if (p == NULL) {
296
      return ERR_OK;
297
    }
298
    iphdr = p->payload;
299
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
300
    pbuf_free(p);
301
    LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
302
      ntohs(IPH_OFFSET(iphdr))));
303
    IP_STATS_INC(ip.opterr);
304
    IP_STATS_INC(ip.drop);
305
    /* unsupported protocol feature */
306
    snmp_inc_ipinunknownprotos();
307
    return ERR_OK;
308
#endif /* IP_REASSEMBLY */
309
  }
310
 
311
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
312
  if (iphdrlen > IP_HLEN) {
313
    LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
314
    pbuf_free(p);
315
    IP_STATS_INC(ip.opterr);
316
    IP_STATS_INC(ip.drop);
317
    /* unsupported protocol feature */
318
    snmp_inc_ipinunknownprotos();
319
    return ERR_OK;
320
  }
321
#endif /* IP_OPTIONS == 0 */
322
 
323
  /* send to upper layers */
324
  LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
325
  ip_debug_print(p);
326
  LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
327
 
328
#if LWIP_RAW
329
  /* raw input did not eat the packet? */
330
  if (raw_input(p, inp) == 0) {
331
#endif /* LWIP_RAW */
332
 
333
  switch (IPH_PROTO(iphdr)) {
334
#if LWIP_UDP
335
  case IP_PROTO_UDP:
336
  case IP_PROTO_UDPLITE:
337
    snmp_inc_ipindelivers();
338
    udp_input(p, inp);
339
    break;
340
#endif /* LWIP_UDP */
341
#if LWIP_TCP
342
  case IP_PROTO_TCP:
343
    snmp_inc_ipindelivers();
344
    tcp_input(p, inp);
345
    break;
346
#endif /* LWIP_TCP */
347
  case IP_PROTO_ICMP:
348
    snmp_inc_ipindelivers();
349
    icmp_input(p, inp);
350
    break;
351
  default:
352
    /* send ICMP destination protocol unreachable unless is was a broadcast */
353
    if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
354
        !ip_addr_ismulticast(&(iphdr->dest))) {
355
      p->payload = iphdr;
356
      icmp_dest_unreach(p, ICMP_DUR_PROTO);
357
    }
358
    pbuf_free(p);
359
 
360
    LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
361
 
362
    IP_STATS_INC(ip.proterr);
363
    IP_STATS_INC(ip.drop);
364
    snmp_inc_ipinunknownprotos();
365
  }
366
#if LWIP_RAW
367
  } /* LWIP_RAW */
368
#endif
369
  return ERR_OK;
370
}
371
 
372
/**
373
 * Sends an IP packet on a network interface. This function constructs
374
 * the IP header and calculates the IP header checksum. If the source
375
 * IP address is NULL, the IP address of the outgoing network
376
 * interface is filled in as source address.
377
 *
378
 * @note ip_id: RFC791 "some host may be able to simply use
379
 *  unique identifiers independent of destination"
380
 */
381
 
382
err_t
383
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
384
             u8_t ttl, u8_t tos,
385
             u8_t proto, struct netif *netif)
386
{
387
  struct ip_hdr *iphdr;
388
  static u16_t ip_id = 0;
389
 
390
  snmp_inc_ipoutrequests();
391
 
392
  if (dest != IP_HDRINCL) {
393
    if (pbuf_header(p, IP_HLEN)) {
394
      LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
395
 
396
      IP_STATS_INC(ip.err);
397
      snmp_inc_ipoutdiscards();
398
      return ERR_BUF;
399
    }
400
 
401
    iphdr = p->payload;
402
 
403
    IPH_TTL_SET(iphdr, ttl);
404
    IPH_PROTO_SET(iphdr, proto);
405
 
406
    ip_addr_set(&(iphdr->dest), dest);
407
 
408
    IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
409
    IPH_LEN_SET(iphdr, htons(p->tot_len));
410
    IPH_OFFSET_SET(iphdr, htons(IP_DF));
411
    IPH_ID_SET(iphdr, htons(ip_id));
412
    ++ip_id;
413
 
414
    if (ip_addr_isany(src)) {
415
      ip_addr_set(&(iphdr->src), &(netif->ip_addr));
416
    } else {
417
      ip_addr_set(&(iphdr->src), src);
418
    }
419
 
420
    IPH_CHKSUM_SET(iphdr, 0);
421
#if CHECKSUM_GEN_IP
422
    IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
423
#endif
424
  } else {
425
    iphdr = p->payload;
426
    dest = &(iphdr->dest);
427
  }
428
 
429
#if IP_FRAG
430
  /* don't fragment if interface has mtu set to 0 [loopif] */
431
  if (netif->mtu && (p->tot_len > netif->mtu))
432
    return ip_frag(p,netif,dest);
433
#endif
434
 
435
  IP_STATS_INC(ip.xmit);
436
 
437
  LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
438
  ip_debug_print(p);
439
 
440
  LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
441
 
442
  return netif->output(netif, p, dest);
443
}
444
 
445
/**
446
 * Simple interface to ip_output_if. It finds the outgoing network
447
 * interface and calls upon ip_output_if to do the actual work.
448
 */
449
 
450
err_t
451
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
452
          u8_t ttl, u8_t tos, u8_t proto)
453
{
454
  struct netif *netif;
455
 
456
  if ((netif = ip_route(dest)) == NULL) {
457
    LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
458
 
459
    IP_STATS_INC(ip.rterr);
460
    snmp_inc_ipoutnoroutes();
461
    return ERR_RTE;
462
  }
463
 
464
  return ip_output_if(p, src, dest, ttl, tos, proto, netif);
465
}
466
 
467
#if IP_DEBUG
468
void
469
ip_debug_print(struct pbuf *p)
470
{
471
  struct ip_hdr *iphdr = p->payload;
472
  u8_t *payload;
473
 
474
  payload = (u8_t *)iphdr + IP_HLEN;
475
 
476
  LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
477
  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
478
  LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" |  0x%02"X16_F" |     %5"U16_F"     | (v, hl, tos, len)\n",
479
                    IPH_V(iphdr),
480
                    IPH_HL(iphdr),
481
                    IPH_TOS(iphdr),
482
                    ntohs(IPH_LEN(iphdr))));
483
  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
484
  LWIP_DEBUGF(IP_DEBUG, ("|    %5"U16_F"      |%"U16_F"%"U16_F"%"U16_F"|    %4"U16_F"   | (id, flags, offset)\n",
485
                    ntohs(IPH_ID(iphdr)),
486
                    ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
487
                    ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
488
                    ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
489
                    ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
490
  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
491
  LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |    0x%04"X16_F"     | (ttl, proto, chksum)\n",
492
                    IPH_TTL(iphdr),
493
                    IPH_PROTO(iphdr),
494
                    ntohs(IPH_CHKSUM(iphdr))));
495
  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
496
  LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (src)\n",
497
                    ip4_addr1(&iphdr->src),
498
                    ip4_addr2(&iphdr->src),
499
                    ip4_addr3(&iphdr->src),
500
                    ip4_addr4(&iphdr->src)));
501
  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
502
  LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (dest)\n",
503
                    ip4_addr1(&iphdr->dest),
504
                    ip4_addr2(&iphdr->dest),
505
                    ip4_addr3(&iphdr->dest),
506
                    ip4_addr4(&iphdr->dest)));
507
  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
508
}
509
#endif /* IP_DEBUG */
510
 
511
 
512
 
513
 
514
 
515
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.