00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
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
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
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
00118
00119 snmp_inc_icmpoutmsgs();
00120
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
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
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
00156 idur->chksum = 0;
00157 idur->chksum = inet_chksum(idur, q->len);
00158 #ifdef ICMP_STATS
00159 ++lwip_stats.icmp.xmit;
00160 #endif
00161
00162 snmp_inc_icmpoutmsgs();
00163
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
00189
00190 tehdr = q->payload;
00191 ICMPH_TYPE_SET(tehdr, ICMP_TE);
00192 ICMPH_CODE_SET(tehdr, t);
00193
00194
00195 memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
00196
00197
00198 tehdr->chksum = 0;
00199 tehdr->chksum = inet_chksum(tehdr, q->len);
00200 #ifdef ICMP_STATS
00201 ++lwip_stats.icmp.xmit;
00202 #endif
00203
00204 snmp_inc_icmpoutmsgs();
00205
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
00213
00214
00215
00216
00217
00218
00219