icmp.c
上传用户:yyhongfa
上传日期:2013-01-18
资源大小:267k
文件大小:6k
开发平台:

C/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. /* Some ICMP messages should be passed to the transport protocols. This
  33.    is not implemented. */
  34. #include "lwip/opt.h"
  35. #include "lwip/icmp.h"
  36. #include "lwip/inet.h"
  37. #include "lwip/ip.h"
  38. #include "lwip/def.h"
  39. #include "lwip/stats.h"
  40. #include "lwip/snmp.h"
  41. void
  42. icmp_input(struct pbuf *p, struct netif *inp)
  43. {
  44.   unsigned char type;
  45.   unsigned char code;
  46.   struct icmp_echo_hdr *iecho;
  47.   struct ip_hdr *iphdr;
  48.   struct ip_addr tmpaddr;
  49.   u16_t hlen;
  50.   ICMP_STATS_INC(icmp.recv);
  51.   snmp_inc_icmpinmsgs();
  52.   iphdr = p->payload;
  53.   hlen = IPH_HL(iphdr) * 4;
  54.   if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
  55.     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) receivedn", p->tot_len));
  56.     pbuf_free(p);
  57.     ICMP_STATS_INC(icmp.lenerr);
  58.     snmp_inc_icmpinerrors();
  59.     return;
  60.   }
  61.   type = *((u8_t *)p->payload);
  62.   code = *(((u8_t *)p->payload)+1);
  63.   switch (type) {
  64.   case ICMP_ECHO:
  65.     /* broadcast or multicast destination address? */
  66.     if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
  67.       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pingsn"));
  68.       ICMP_STATS_INC(icmp.err);
  69.       pbuf_free(p);
  70.       return;
  71.     }
  72.     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: pingn"));
  73.     if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
  74.       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo receivedn"));
  75.       pbuf_free(p);
  76.       ICMP_STATS_INC(icmp.lenerr);
  77.       snmp_inc_icmpinerrors();
  78.       return;
  79.     }
  80.     iecho = p->payload;
  81.     if (inet_chksum_pbuf(p) != 0) {
  82.       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echon"));
  83.       pbuf_free(p);
  84.       ICMP_STATS_INC(icmp.chkerr);
  85.       snmp_inc_icmpinerrors();
  86.       return;
  87.     }
  88.     tmpaddr.addr = iphdr->src.addr;
  89.     iphdr->src.addr = iphdr->dest.addr;
  90.     iphdr->dest.addr = tmpaddr.addr;
  91.     ICMPH_TYPE_SET(iecho, ICMP_ER);
  92.     /* adjust the checksum */
  93.     if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
  94.       iecho->chksum += htons(ICMP_ECHO << 8) + 1;
  95.     } else {
  96.       iecho->chksum += htons(ICMP_ECHO << 8);
  97.     }
  98.     ICMP_STATS_INC(icmp.xmit);
  99.     /* increase number of messages attempted to send */
  100.     snmp_inc_icmpoutmsgs();
  101.     /* increase number of echo replies attempted to send */
  102.     snmp_inc_icmpoutechoreps();
  103.     pbuf_header(p, hlen);
  104.     ip_output_if(p, &(iphdr->src), IP_HDRINCL,
  105.  IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
  106.     break;
  107.   default:
  108.   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.n", (int)type, (int)code));
  109.     ICMP_STATS_INC(icmp.proterr);
  110.     ICMP_STATS_INC(icmp.drop);
  111.   }
  112.   pbuf_free(p);
  113. }
  114. void
  115. icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
  116. {
  117.   struct pbuf *q;
  118.   struct ip_hdr *iphdr;
  119.   struct icmp_dur_hdr *idur;
  120.   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
  121.   /* ICMP header + IP header + 8 bytes of data */
  122.   iphdr = p->payload;
  123.   idur = q->payload;
  124.   ICMPH_TYPE_SET(idur, ICMP_DUR);
  125.   ICMPH_CODE_SET(idur, t);
  126.   memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
  127.   /* calculate checksum */
  128.   idur->chksum = 0;
  129.   idur->chksum = inet_chksum(idur, q->len);
  130.   ICMP_STATS_INC(icmp.xmit);
  131.   /* increase number of messages attempted to send */
  132.   snmp_inc_icmpoutmsgs();
  133.   /* increase number of destination unreachable messages attempted to send */
  134.   snmp_inc_icmpoutdestunreachs();
  135.   ip_output(q, NULL, &(iphdr->src),
  136.     ICMP_TTL, 0, IP_PROTO_ICMP);
  137.   pbuf_free(q);
  138. }
  139. #if IP_FORWARD
  140. void
  141. icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
  142. {
  143.   struct pbuf *q;
  144.   struct ip_hdr *iphdr;
  145.   struct icmp_te_hdr *tehdr;
  146.   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
  147.   iphdr = p->payload;
  148.   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
  149.   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
  150.   LWIP_DEBUGF(ICMP_DEBUG, (" to "));
  151.   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
  152.   LWIP_DEBUGF(ICMP_DEBUG, ("n"));
  153.   tehdr = q->payload;
  154.   ICMPH_TYPE_SET(tehdr, ICMP_TE);
  155.   ICMPH_CODE_SET(tehdr, t);
  156.   /* copy fields from original packet */
  157.   memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
  158.   /* calculate checksum */
  159.   tehdr->chksum = 0;
  160.   tehdr->chksum = inet_chksum(tehdr, q->len);
  161.   ICMP_STATS_INC(icmp.xmit);
  162.   /* increase number of messages attempted to send */
  163.   snmp_inc_icmpoutmsgs();
  164.   /* increase number of destination unreachable messages attempted to send */
  165.   snmp_inc_icmpouttimeexcds();
  166.   ip_output(q, NULL, &(iphdr->src),
  167.     ICMP_TTL, 0, IP_PROTO_ICMP);
  168.   pbuf_free(q);
  169. }
  170. #endif /* IP_FORWARD */