Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

icmp6.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
00003  * All rights reserved. 
00004  * 
00005  * Redistribution and use in source and binary forms, with or without modification, 
00006  * are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  * 3. The name of the author may not be used to endorse or promote products
00014  *    derived from this software without specific prior written permission. 
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
00017  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
00019  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
00021  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00024  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
00025  * OF SUCH DAMAGE.
00026  *
00027  * This file is part of the lwIP TCP/IP stack.
00028  * 
00029  * Author: Adam Dunkels <adam@sics.se>
00030  *
00031  */
00032 
00033 /* Some ICMP messages should be passed to the transport protocols. This
00034    is not implemented. */
00035 
00036 #include "lwip/opt.h"
00037 
00038 #include "lwip/icmp.h"
00039 #include "lwip/inet.h"
00040 #include "lwip/ip.h"
00041 #include "lwip/def.h"
00042 
00043 #include "lwip/stats.h"
00044 
00045 /*-----------------------------------------------------------------------------------*/
00046 void
00047 icmp_input(struct pbuf *p, struct netif *inp)
00048 {
00049   unsigned char type;
00050   struct icmp_echo_hdr *iecho;
00051   struct ip_hdr *iphdr;
00052   struct ip_addr tmpaddr;
00053   
00054  
00055 #ifdef ICMP_STATS
00056   ++lwip_stats.icmp.recv;
00057 #endif /* ICMP_STATS */
00058 
00059   type = ((char *)p->payload)[0];
00060 
00061   switch(type) {
00062   case ICMP6_ECHO:
00063     DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
00064 
00065     if(p->tot_len < sizeof(struct icmp_echo_hdr)) {
00066       DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
00067 
00068       pbuf_free(p);
00069 #ifdef ICMP_STATS
00070       ++lwip_stats.icmp.lenerr;
00071 #endif /* ICMP_STATS */
00072 
00073       return;      
00074     }
00075     iecho = p->payload;
00076     iphdr = (struct ip_hdr *)((char *)p->payload - IP_HLEN);
00077     if(inet_chksum_pbuf(p) != 0) {
00078       DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
00079 
00080 #ifdef ICMP_STATS
00081       ++lwip_stats.icmp.chkerr;
00082 #endif /* ICMP_STATS */
00083     /*      return;*/
00084     }
00085     DEBUGF(ICMP_DEBUG, ("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len));
00086     ip_addr_set(&tmpaddr, &(iphdr->src));
00087     ip_addr_set(&(iphdr->src), &(iphdr->dest));
00088     ip_addr_set(&(iphdr->dest), &tmpaddr);
00089     iecho->type = ICMP6_ER;
00090     /* adjust the checksum */
00091     if(iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
00092       iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
00093     } else {
00094       iecho->chksum += htons(ICMP6_ECHO << 8);
00095     }
00096     DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
00097 #ifdef ICMP_STATS
00098     ++lwip_stats.icmp.xmit;
00099 #endif /* ICMP_STATS */
00100 
00101     /*    DEBUGF("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len);*/
00102     ip_output_if(p, &(iphdr->src), IP_HDRINCL,
00103                  iphdr->hoplim, IP_PROTO_ICMP, inp);
00104     break; 
00105   default:
00106     DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type not supported.\n"));
00107 
00108 #ifdef ICMP_STATS
00109     ++lwip_stats.icmp.proterr;
00110     ++lwip_stats.icmp.drop;
00111 #endif /* ICMP_STATS */
00112   }
00113 
00114   pbuf_free(p);
00115 }
00116 /*-----------------------------------------------------------------------------------*/
00117 void
00118 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
00119 {
00120   struct pbuf *q;
00121   struct ip_hdr *iphdr;
00122   struct icmp_dur_hdr *idur;
00123   
00124   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
00125   /* ICMP header + IP header + 8 bytes of data */
00126 
00127   iphdr = p->payload;
00128   
00129   idur = q->payload;
00130   idur->type = (char)ICMP6_DUR;
00131   idur->icode = (char)t;
00132 
00133   memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
00134   
00135   /* calculate checksum */
00136   idur->chksum = 0;
00137   idur->chksum = inet_chksum(idur, q->len);
00138 #ifdef ICMP_STATS
00139   ++lwip_stats.icmp.xmit;
00140 #endif /* ICMP_STATS */
00141 
00142   ip_output(q, NULL,
00143             (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
00144   pbuf_free(q);
00145 }
00146 /*-----------------------------------------------------------------------------------*/
00147 void
00148 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
00149 {
00150   struct pbuf *q;
00151   struct ip_hdr *iphdr;
00152   struct icmp_te_hdr *tehdr;
00153 
00154   DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
00155   
00156   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
00157 
00158   iphdr = p->payload;
00159   
00160   tehdr = q->payload;
00161   tehdr->type = (char)ICMP6_TE;
00162   tehdr->icode = (char)t;
00163 
00164   /* copy fields from original packet */
00165   memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
00166   
00167   /* calculate checksum */
00168   tehdr->chksum = 0;
00169   tehdr->chksum = inet_chksum(tehdr, q->len);
00170 #ifdef ICMP_STATS
00171   ++lwip_stats.icmp.xmit;
00172 #endif /* ICMP_STATS */
00173   ip_output(q, NULL, 
00174             (struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
00175   pbuf_free(q);
00176 }
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 

Generated on Wed Jan 14 12:58:56 2004 for RTL-lwIP-0.4 by doxygen 1.3.4