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

icmp.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 #include "lwip/snmp.h"
00046 
00047 #define htons HTONS
00048 #define htonl HTONL
00049 
00050 /*-----------------------------------------------------------------------------------*/
00051 void
00052 icmp_input(struct pbuf *p, struct netif *inp)
00053 {
00054   unsigned char type;
00055   struct icmp_echo_hdr *iecho;
00056   struct ip_hdr *iphdr;
00057   struct ip_addr tmpaddr;
00058   u16_t hlen;
00059   
00060 #ifdef ICMP_STATS
00061   ++lwip_stats.icmp.recv;
00062 #endif /* ICMP_STATS */
00063   snmp_inc_icmpinmsgs();
00064 
00065   
00066   iphdr = p->payload;
00067   hlen = IPH_HL(iphdr) * 4;
00068   pbuf_header(p, -((s16_t)hlen));
00069 
00070   type = *((u8_t *)p->payload);
00071 
00072   switch(type) {
00073   case ICMP_ECHO:
00074     if(ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
00075        ip_addr_ismulticast(&iphdr->dest)) {
00076       DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
00077 #ifdef ICMP_STATS
00078       ++lwip_stats.icmp.err;
00079 #endif /* ICMP_STATS */
00080       pbuf_free(p);
00081       return;
00082     }
00083     DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
00084     DEBUGF(DEMO_DEBUG, ("Pong!\n"));
00085     if(p->tot_len < sizeof(struct icmp_echo_hdr)) {
00086       DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
00087       pbuf_free(p);
00088 #ifdef ICMP_STATS
00089       ++lwip_stats.icmp.lenerr;
00090 #endif /* ICMP_STATS */
00091       snmp_inc_icmpinerrors();
00092 
00093       return;      
00094     }
00095     iecho = p->payload;    
00096     if(inet_chksum_pbuf(p) != 0) {
00097       DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
00098       pbuf_free(p);
00099 #ifdef ICMP_STATS
00100       ++lwip_stats.icmp.chkerr;
00101 #endif /* ICMP_STATS */
00102       snmp_inc_icmpinerrors();
00103       return;
00104     }
00105     tmpaddr.addr = iphdr->src.addr;
00106     iphdr->src.addr = iphdr->dest.addr;
00107     iphdr->dest.addr = tmpaddr.addr;
00108     ICMPH_TYPE_SET(iecho, ICMP_ER);
00109     /* adjust the checksum */
00110     if(iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
00111       iecho->chksum += htons(ICMP_ECHO << 8) + 1;
00112     } else {
00113       iecho->chksum += htons(ICMP_ECHO << 8);
00114     }
00115 #ifdef ICMP_STATS
00116     ++lwip_stats.icmp.xmit;
00117 #endif /* ICMP_STATS */
00118     /* increase number of messages attempted to send */
00119     snmp_inc_icmpoutmsgs();
00120     /* increase number of echo replies attempted to send */
00121     snmp_inc_icmpoutechoreps();
00122 
00123     pbuf_header(p, hlen);
00124     ip_output_if(p, &(iphdr->src), IP_HDRINCL,
00125                  IPH_TTL(iphdr), IP_PROTO_ICMP, inp);
00126     break; 
00127   default:
00128     DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type not supported.\n"));
00129 #ifdef ICMP_STATS
00130     ++lwip_stats.icmp.proterr;
00131     ++lwip_stats.icmp.drop;
00132 #endif /* ICMP_STATS */
00133   }
00134   pbuf_free(p);
00135 }
00136 /*-----------------------------------------------------------------------------------*/
00137 void
00138 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
00139 {
00140   struct pbuf *q;
00141   struct ip_hdr *iphdr;
00142   struct icmp_dur_hdr *idur;
00143   
00144   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
00145   /* ICMP header + IP header + 8 bytes of data */
00146 
00147   iphdr = p->payload;
00148   
00149   idur = q->payload;
00150   ICMPH_TYPE_SET(idur, ICMP_DUR);
00151   ICMPH_CODE_SET(idur, t);
00152 
00153   memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
00154   
00155   /* calculate checksum */
00156   idur->chksum = 0;
00157   idur->chksum = inet_chksum(idur, q->len);
00158 #ifdef ICMP_STATS
00159   ++lwip_stats.icmp.xmit;
00160 #endif /* ICMP_STATS */
00161   /* increase number of messages attempted to send */
00162   snmp_inc_icmpoutmsgs();
00163   /* increase number of destination unreachable messages attempted to send */
00164   snmp_inc_icmpoutdestunreachs();
00165 
00166   ip_output(q, NULL, &(iphdr->src),
00167             ICMP_TTL, IP_PROTO_ICMP);
00168   pbuf_free(q);
00169 }
00170 /*-----------------------------------------------------------------------------------*/
00171 #if IP_FORWARD
00172 void
00173 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
00174 {
00175   struct pbuf *q;
00176   struct ip_hdr *iphdr;
00177   struct icmp_te_hdr *tehdr;
00178 
00179   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
00180 
00181   iphdr = p->payload;
00182 #if ICMP_DEBUG
00183   DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
00184   ip_addr_debug_print(&(iphdr->src));
00185   DEBUGF(ICMP_DEBUG, (" to "));
00186   ip_addr_debug_print(&(iphdr->dest));
00187   DEBUGF(ICMP_DEBUG, ("\n"));
00188 #endif /* ICMP_DEBNUG */
00189 
00190   tehdr = q->payload;
00191   ICMPH_TYPE_SET(tehdr, ICMP_TE);
00192   ICMPH_CODE_SET(tehdr, t);
00193 
00194   /* copy fields from original packet */
00195   memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
00196   
00197   /* calculate checksum */
00198   tehdr->chksum = 0;
00199   tehdr->chksum = inet_chksum(tehdr, q->len);
00200 #ifdef ICMP_STATS
00201   ++lwip_stats.icmp.xmit;
00202 #endif /* ICMP_STATS */
00203   /* increase number of messages attempted to send */
00204   snmp_inc_icmpoutmsgs();
00205   /* increase number of destination unreachable messages attempted to send */
00206   snmp_inc_icmpouttimeexcds();
00207   ip_output(q, NULL, &(iphdr->src),
00208             ICMP_TTL, IP_PROTO_ICMP);
00209   pbuf_free(q);
00210 }
00211 
00212 #endif /* IP_FORWARDING > 0 */
00213 
00214 
00215 
00216 
00217 
00218 
00219 

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