Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / core / ipv6 / icmp6.c
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 /* Some ICMP messages should be passed to the transport protocols. This
34    is not implemented. */
35
36 #include "lwip/opt.h"
37
38 #if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
39
40 #include "lwip/icmp.h"
41 #include "lwip/inet.h"
42 #include "lwip/ip.h"
43 #include "lwip/def.h"
44 #include "lwip/stats.h"
45
46 void
47 icmp_input(struct pbuf *p, struct netif *inp)
48 {
49   u8_t type;
50   struct icmp_echo_hdr *iecho;
51   struct ip_hdr *iphdr;
52   struct ip_addr tmpaddr;
53
54   ICMP_STATS_INC(icmp.recv);
55
56   /* TODO: check length before accessing payload! */
57
58   type = ((u8_t *)p->payload)[0];
59
60   switch (type) {
61   case ICMP6_ECHO:
62     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
63
64     if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
65       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
66
67       pbuf_free(p);
68       ICMP_STATS_INC(icmp.lenerr);
69       return;
70     }
71     iecho = p->payload;
72     iphdr = (struct ip_hdr *)((u8_t *)p->payload - IP_HLEN);
73     if (inet_chksum_pbuf(p) != 0) {
74       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
75       ICMP_STATS_INC(icmp.chkerr);
76     /*      return;*/
77     }
78     LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %"S16_F" p->tot_len %"S16_F"\n", p->len, p->tot_len));
79     ip_addr_set(&tmpaddr, &(iphdr->src));
80     ip_addr_set(&(iphdr->src), &(iphdr->dest));
81     ip_addr_set(&(iphdr->dest), &tmpaddr);
82     iecho->type = ICMP6_ER;
83     /* adjust the checksum */
84     if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
85       iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
86     } else {
87       iecho->chksum += htons(ICMP6_ECHO << 8);
88     }
89     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%"X16_F")\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
90     ICMP_STATS_INC(icmp.xmit);
91
92     /*    LWIP_DEBUGF("icmp: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len);*/
93     ip_output_if (p, &(iphdr->src), IP_HDRINCL,
94      iphdr->hoplim, IP_PROTO_ICMP, inp);
95     break;
96   default:
97     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" not supported.\n", (s16_t)type));
98     ICMP_STATS_INC(icmp.proterr);
99     ICMP_STATS_INC(icmp.drop);
100   }
101
102   pbuf_free(p);
103 }
104
105 void
106 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
107 {
108   struct pbuf *q;
109   struct ip_hdr *iphdr;
110   struct icmp_dur_hdr *idur;
111
112   /* @todo: can this be PBUF_LINK instead of PBUF_IP? */
113   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
114   /* ICMP header + IP header + 8 bytes of data */
115   if (q == NULL) {
116     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
117     pbuf_free(p);
118     return;
119   }
120   LWIP_ASSERT("check that first pbuf can hold icmp message",
121              (q->len >= (8 + IP_HLEN + 8)));
122
123   iphdr = p->payload;
124
125   idur = q->payload;
126   idur->type = (u8_t)ICMP6_DUR;
127   idur->icode = (u8_t)t;
128
129   SMEMCPY((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
130
131   /* calculate checksum */
132   idur->chksum = 0;
133   idur->chksum = inet_chksum(idur, q->len);
134   ICMP_STATS_INC(icmp.xmit);
135
136   ip_output(q, NULL,
137       (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
138   pbuf_free(q);
139 }
140
141 void
142 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
143 {
144   struct pbuf *q;
145   struct ip_hdr *iphdr;
146   struct icmp_te_hdr *tehdr;
147
148   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
149
150   /* @todo: can this be PBUF_LINK instead of PBUF_IP? */
151   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
152   /* ICMP header + IP header + 8 bytes of data */
153   if (q == NULL) {
154     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
155     pbuf_free(p);
156     return;
157   }
158   LWIP_ASSERT("check that first pbuf can hold icmp message",
159              (q->len >= (8 + IP_HLEN + 8)));
160
161   iphdr = p->payload;
162
163   tehdr = q->payload;
164   tehdr->type = (u8_t)ICMP6_TE;
165   tehdr->icode = (u8_t)t;
166
167   /* copy fields from original packet */
168   SMEMCPY((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
169
170   /* calculate checksum */
171   tehdr->chksum = 0;
172   tehdr->chksum = inet_chksum(tehdr, q->len);
173   ICMP_STATS_INC(icmp.xmit);
174   ip_output(q, NULL,
175       (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
176   pbuf_free(q);
177 }
178
179 #endif /* LWIP_ICMP */