My fork of the HTTPServer (working)
Core/lwIP/core/ipv4/icmp.c@1:284f2df30cf9, 2012-11-20 (annotated)
- Committer:
- screamer
- Date:
- Tue Nov 20 12:18:53 2012 +0000
- Revision:
- 1:284f2df30cf9
- Parent:
- 0:7a64fbb4069d
local changes
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
screamer | 0:7a64fbb4069d | 1 | /** |
screamer | 0:7a64fbb4069d | 2 | * @file |
screamer | 0:7a64fbb4069d | 3 | * ICMP - Internet Control Message Protocol |
screamer | 0:7a64fbb4069d | 4 | * |
screamer | 0:7a64fbb4069d | 5 | */ |
screamer | 0:7a64fbb4069d | 6 | |
screamer | 0:7a64fbb4069d | 7 | /* |
screamer | 0:7a64fbb4069d | 8 | * Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
screamer | 0:7a64fbb4069d | 9 | * All rights reserved. |
screamer | 0:7a64fbb4069d | 10 | * |
screamer | 0:7a64fbb4069d | 11 | * Redistribution and use in source and binary forms, with or without modification, |
screamer | 0:7a64fbb4069d | 12 | * are permitted provided that the following conditions are met: |
screamer | 0:7a64fbb4069d | 13 | * |
screamer | 0:7a64fbb4069d | 14 | * 1. Redistributions of source code must retain the above copyright notice, |
screamer | 0:7a64fbb4069d | 15 | * this list of conditions and the following disclaimer. |
screamer | 0:7a64fbb4069d | 16 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
screamer | 0:7a64fbb4069d | 17 | * this list of conditions and the following disclaimer in the documentation |
screamer | 0:7a64fbb4069d | 18 | * and/or other materials provided with the distribution. |
screamer | 0:7a64fbb4069d | 19 | * 3. The name of the author may not be used to endorse or promote products |
screamer | 0:7a64fbb4069d | 20 | * derived from this software without specific prior written permission. |
screamer | 0:7a64fbb4069d | 21 | * |
screamer | 0:7a64fbb4069d | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
screamer | 0:7a64fbb4069d | 23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
screamer | 0:7a64fbb4069d | 24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
screamer | 0:7a64fbb4069d | 25 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
screamer | 0:7a64fbb4069d | 26 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
screamer | 0:7a64fbb4069d | 27 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
screamer | 0:7a64fbb4069d | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
screamer | 0:7a64fbb4069d | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
screamer | 0:7a64fbb4069d | 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
screamer | 0:7a64fbb4069d | 31 | * OF SUCH DAMAGE. |
screamer | 0:7a64fbb4069d | 32 | * |
screamer | 0:7a64fbb4069d | 33 | * This file is part of the lwIP TCP/IP stack. |
screamer | 0:7a64fbb4069d | 34 | * |
screamer | 0:7a64fbb4069d | 35 | * Author: Adam Dunkels <adam@sics.se> |
screamer | 0:7a64fbb4069d | 36 | * |
screamer | 0:7a64fbb4069d | 37 | */ |
screamer | 0:7a64fbb4069d | 38 | |
screamer | 0:7a64fbb4069d | 39 | /* Some ICMP messages should be passed to the transport protocols. This |
screamer | 0:7a64fbb4069d | 40 | is not implemented. */ |
screamer | 0:7a64fbb4069d | 41 | |
screamer | 0:7a64fbb4069d | 42 | #include "lwip/opt.h" |
screamer | 0:7a64fbb4069d | 43 | |
screamer | 0:7a64fbb4069d | 44 | #if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ |
screamer | 0:7a64fbb4069d | 45 | |
screamer | 0:7a64fbb4069d | 46 | #include "lwip/icmp.h" |
screamer | 0:7a64fbb4069d | 47 | #include "lwip/inet.h" |
screamer | 0:7a64fbb4069d | 48 | #include "lwip/inet_chksum.h" |
screamer | 0:7a64fbb4069d | 49 | #include "lwip/ip.h" |
screamer | 0:7a64fbb4069d | 50 | #include "lwip/def.h" |
screamer | 0:7a64fbb4069d | 51 | #include "lwip/stats.h" |
screamer | 0:7a64fbb4069d | 52 | #include "lwip/snmp.h" |
screamer | 0:7a64fbb4069d | 53 | |
screamer | 0:7a64fbb4069d | 54 | #include <string.h> |
screamer | 0:7a64fbb4069d | 55 | |
screamer | 0:7a64fbb4069d | 56 | /* The amount of data from the original packet to return in a dest-unreachable */ |
screamer | 0:7a64fbb4069d | 57 | #define ICMP_DEST_UNREACH_DATASIZE 8 |
screamer | 0:7a64fbb4069d | 58 | |
screamer | 0:7a64fbb4069d | 59 | /** |
screamer | 0:7a64fbb4069d | 60 | * Processes ICMP input packets, called from ip_input(). |
screamer | 0:7a64fbb4069d | 61 | * |
screamer | 0:7a64fbb4069d | 62 | * Currently only processes icmp echo requests and sends |
screamer | 0:7a64fbb4069d | 63 | * out the echo response. |
screamer | 0:7a64fbb4069d | 64 | * |
screamer | 0:7a64fbb4069d | 65 | * @param p the icmp echo request packet, p->payload pointing to the ip header |
screamer | 0:7a64fbb4069d | 66 | * @param inp the netif on which this packet was received |
screamer | 0:7a64fbb4069d | 67 | */ |
screamer | 0:7a64fbb4069d | 68 | void |
screamer | 0:7a64fbb4069d | 69 | icmp_input(struct pbuf *p, struct netif *inp) |
screamer | 0:7a64fbb4069d | 70 | { |
screamer | 0:7a64fbb4069d | 71 | u8_t type; |
screamer | 0:7a64fbb4069d | 72 | #ifdef LWIP_DEBUG |
screamer | 0:7a64fbb4069d | 73 | u8_t code; |
screamer | 0:7a64fbb4069d | 74 | #endif /* LWIP_DEBUG */ |
screamer | 0:7a64fbb4069d | 75 | struct icmp_echo_hdr *iecho; |
screamer | 0:7a64fbb4069d | 76 | struct ip_hdr *iphdr; |
screamer | 0:7a64fbb4069d | 77 | struct ip_addr tmpaddr; |
screamer | 0:7a64fbb4069d | 78 | s16_t hlen; |
screamer | 0:7a64fbb4069d | 79 | |
screamer | 0:7a64fbb4069d | 80 | ICMP_STATS_INC(icmp.recv); |
screamer | 0:7a64fbb4069d | 81 | snmp_inc_icmpinmsgs(); |
screamer | 0:7a64fbb4069d | 82 | |
screamer | 0:7a64fbb4069d | 83 | |
screamer | 0:7a64fbb4069d | 84 | iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) |
screamer | 0:7a64fbb4069d | 85 | hlen = IPH_HL(iphdr) * 4; |
screamer | 0:7a64fbb4069d | 86 | if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) { |
screamer | 0:7a64fbb4069d | 87 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); |
screamer | 0:7a64fbb4069d | 88 | goto lenerr; |
screamer | 0:7a64fbb4069d | 89 | } |
screamer | 0:7a64fbb4069d | 90 | |
screamer | 0:7a64fbb4069d | 91 | type = *((u8_t *)p->payload); |
screamer | 0:7a64fbb4069d | 92 | #ifdef LWIP_DEBUG |
screamer | 0:7a64fbb4069d | 93 | code = *(((u8_t *)p->payload)+1); |
screamer | 0:7a64fbb4069d | 94 | #endif /* LWIP_DEBUG */ |
screamer | 0:7a64fbb4069d | 95 | switch (type) { |
screamer | 0:7a64fbb4069d | 96 | case ICMP_ECHO: |
screamer | 0:7a64fbb4069d | 97 | #if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING |
screamer | 0:7a64fbb4069d | 98 | { |
screamer | 0:7a64fbb4069d | 99 | int accepted = 1; |
screamer | 0:7a64fbb4069d | 100 | #if !LWIP_MULTICAST_PING |
screamer | 0:7a64fbb4069d | 101 | /* multicast destination address? */ |
screamer | 0:7a64fbb4069d | 102 | if (ip_addr_ismulticast(&(iphdr->dest))) { |
screamer | 0:7a64fbb4069d | 103 | accepted = 0; |
screamer | 0:7a64fbb4069d | 104 | } |
screamer | 0:7a64fbb4069d | 105 | #endif /* LWIP_MULTICAST_PING */ |
screamer | 0:7a64fbb4069d | 106 | #if !LWIP_BROADCAST_PING |
screamer | 0:7a64fbb4069d | 107 | /* broadcast destination address? */ |
screamer | 0:7a64fbb4069d | 108 | if (ip_addr_isbroadcast(&(iphdr->dest), inp)) { |
screamer | 0:7a64fbb4069d | 109 | accepted = 0; |
screamer | 0:7a64fbb4069d | 110 | } |
screamer | 0:7a64fbb4069d | 111 | #endif /* LWIP_BROADCAST_PING */ |
screamer | 0:7a64fbb4069d | 112 | /* broadcast or multicast destination address not acceptd? */ |
screamer | 0:7a64fbb4069d | 113 | if (!accepted) { |
screamer | 0:7a64fbb4069d | 114 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n")); |
screamer | 0:7a64fbb4069d | 115 | ICMP_STATS_INC(icmp.err); |
screamer | 0:7a64fbb4069d | 116 | pbuf_free(p); |
screamer | 0:7a64fbb4069d | 117 | return; |
screamer | 0:7a64fbb4069d | 118 | } |
screamer | 0:7a64fbb4069d | 119 | } |
screamer | 0:7a64fbb4069d | 120 | #endif /* !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ |
screamer | 0:7a64fbb4069d | 121 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); |
screamer | 0:7a64fbb4069d | 122 | if (p->tot_len < sizeof(struct icmp_echo_hdr)) { |
screamer | 0:7a64fbb4069d | 123 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); |
screamer | 0:7a64fbb4069d | 124 | goto lenerr; |
screamer | 0:7a64fbb4069d | 125 | } |
screamer | 0:7a64fbb4069d | 126 | if (inet_chksum_pbuf(p) != 0) { |
screamer | 0:7a64fbb4069d | 127 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); |
screamer | 0:7a64fbb4069d | 128 | pbuf_free(p); |
screamer | 0:7a64fbb4069d | 129 | ICMP_STATS_INC(icmp.chkerr); |
screamer | 0:7a64fbb4069d | 130 | snmp_inc_icmpinerrors(); |
screamer | 0:7a64fbb4069d | 131 | return; |
screamer | 0:7a64fbb4069d | 132 | } |
screamer | 0:7a64fbb4069d | 133 | if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) { |
screamer | 0:7a64fbb4069d | 134 | /* p is not big enough to contain link headers |
screamer | 0:7a64fbb4069d | 135 | * allocate a new one and copy p into it |
screamer | 0:7a64fbb4069d | 136 | */ |
screamer | 0:7a64fbb4069d | 137 | struct pbuf *r; |
screamer | 0:7a64fbb4069d | 138 | /* switch p->payload to ip header */ |
screamer | 0:7a64fbb4069d | 139 | if (pbuf_header(p, hlen)) { |
screamer | 0:7a64fbb4069d | 140 | LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0); |
screamer | 0:7a64fbb4069d | 141 | goto memerr; |
screamer | 0:7a64fbb4069d | 142 | } |
screamer | 0:7a64fbb4069d | 143 | /* allocate new packet buffer with space for link headers */ |
screamer | 0:7a64fbb4069d | 144 | r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); |
screamer | 0:7a64fbb4069d | 145 | if (r == NULL) { |
screamer | 0:7a64fbb4069d | 146 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); |
screamer | 0:7a64fbb4069d | 147 | goto memerr; |
screamer | 0:7a64fbb4069d | 148 | } |
screamer | 0:7a64fbb4069d | 149 | LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", |
screamer | 0:7a64fbb4069d | 150 | (r->len >= hlen + sizeof(struct icmp_echo_hdr))); |
screamer | 0:7a64fbb4069d | 151 | /* copy the whole packet including ip header */ |
screamer | 0:7a64fbb4069d | 152 | if (pbuf_copy(r, p) != ERR_OK) { |
screamer | 0:7a64fbb4069d | 153 | LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0); |
screamer | 0:7a64fbb4069d | 154 | goto memerr; |
screamer | 0:7a64fbb4069d | 155 | } |
screamer | 0:7a64fbb4069d | 156 | iphdr = (struct ip_hdr *)(r->payload); // static_cast<struct ip_hdr *>(x) |
screamer | 0:7a64fbb4069d | 157 | /* switch r->payload back to icmp header */ |
screamer | 0:7a64fbb4069d | 158 | if (pbuf_header(r, -hlen)) { |
screamer | 0:7a64fbb4069d | 159 | LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); |
screamer | 0:7a64fbb4069d | 160 | goto memerr; |
screamer | 0:7a64fbb4069d | 161 | } |
screamer | 0:7a64fbb4069d | 162 | /* free the original p */ |
screamer | 0:7a64fbb4069d | 163 | pbuf_free(p); |
screamer | 0:7a64fbb4069d | 164 | /* we now have an identical copy of p that has room for link headers */ |
screamer | 0:7a64fbb4069d | 165 | p = r; |
screamer | 0:7a64fbb4069d | 166 | } else { |
screamer | 0:7a64fbb4069d | 167 | /* restore p->payload to point to icmp header */ |
screamer | 0:7a64fbb4069d | 168 | if (pbuf_header(p, -(s16_t)(PBUF_IP_HLEN + PBUF_LINK_HLEN))) { |
screamer | 0:7a64fbb4069d | 169 | LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); |
screamer | 0:7a64fbb4069d | 170 | goto memerr; |
screamer | 0:7a64fbb4069d | 171 | } |
screamer | 0:7a64fbb4069d | 172 | } |
screamer | 0:7a64fbb4069d | 173 | /* At this point, all checks are OK. */ |
screamer | 0:7a64fbb4069d | 174 | /* We generate an answer by switching the dest and src ip addresses, |
screamer | 0:7a64fbb4069d | 175 | * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ |
screamer | 0:7a64fbb4069d | 176 | iecho = (struct icmp_echo_hdr *)(p->payload); // static_cast<struct icmp_echo_hdr *>(x) |
screamer | 0:7a64fbb4069d | 177 | tmpaddr.addr = iphdr->src.addr; |
screamer | 0:7a64fbb4069d | 178 | iphdr->src.addr = iphdr->dest.addr; |
screamer | 0:7a64fbb4069d | 179 | iphdr->dest.addr = tmpaddr.addr; |
screamer | 0:7a64fbb4069d | 180 | ICMPH_TYPE_SET(iecho, ICMP_ER); |
screamer | 0:7a64fbb4069d | 181 | /* adjust the checksum */ |
screamer | 0:7a64fbb4069d | 182 | if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) { |
screamer | 0:7a64fbb4069d | 183 | iecho->chksum += htons(ICMP_ECHO << 8) + 1; |
screamer | 0:7a64fbb4069d | 184 | } else { |
screamer | 0:7a64fbb4069d | 185 | iecho->chksum += htons(ICMP_ECHO << 8); |
screamer | 0:7a64fbb4069d | 186 | } |
screamer | 0:7a64fbb4069d | 187 | |
screamer | 0:7a64fbb4069d | 188 | /* Set the correct TTL and recalculate the header checksum. */ |
screamer | 0:7a64fbb4069d | 189 | IPH_TTL_SET(iphdr, ICMP_TTL); |
screamer | 0:7a64fbb4069d | 190 | IPH_CHKSUM_SET(iphdr, 0); |
screamer | 0:7a64fbb4069d | 191 | #if CHECKSUM_GEN_IP |
screamer | 0:7a64fbb4069d | 192 | IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); |
screamer | 0:7a64fbb4069d | 193 | #endif /* CHECKSUM_GEN_IP */ |
screamer | 0:7a64fbb4069d | 194 | |
screamer | 0:7a64fbb4069d | 195 | ICMP_STATS_INC(icmp.xmit); |
screamer | 0:7a64fbb4069d | 196 | /* increase number of messages attempted to send */ |
screamer | 0:7a64fbb4069d | 197 | snmp_inc_icmpoutmsgs(); |
screamer | 0:7a64fbb4069d | 198 | /* increase number of echo replies attempted to send */ |
screamer | 0:7a64fbb4069d | 199 | snmp_inc_icmpoutechoreps(); |
screamer | 0:7a64fbb4069d | 200 | |
screamer | 0:7a64fbb4069d | 201 | if(pbuf_header(p, hlen)) { |
screamer | 0:7a64fbb4069d | 202 | LWIP_ASSERT("Can't move over header in packet", 0); |
screamer | 0:7a64fbb4069d | 203 | } else { |
screamer | 0:7a64fbb4069d | 204 | err_t ret; |
screamer | 0:7a64fbb4069d | 205 | struct ip_addr iphdrsrc; // XXX: __packed hack |
screamer | 0:7a64fbb4069d | 206 | iphdrsrc.addr = iphdr->src.addr; |
screamer | 0:7a64fbb4069d | 207 | ret = ip_output_if(p, &(iphdrsrc), IP_HDRINCL, |
screamer | 0:7a64fbb4069d | 208 | ICMP_TTL, 0, IP_PROTO_ICMP, inp); |
screamer | 0:7a64fbb4069d | 209 | if (ret != ERR_OK) { |
screamer | 0:7a64fbb4069d | 210 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret)); |
screamer | 0:7a64fbb4069d | 211 | } |
screamer | 0:7a64fbb4069d | 212 | } |
screamer | 0:7a64fbb4069d | 213 | break; |
screamer | 0:7a64fbb4069d | 214 | default: |
screamer | 0:7a64fbb4069d | 215 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", |
screamer | 0:7a64fbb4069d | 216 | (s16_t)type, (s16_t)code)); |
screamer | 0:7a64fbb4069d | 217 | ICMP_STATS_INC(icmp.proterr); |
screamer | 0:7a64fbb4069d | 218 | ICMP_STATS_INC(icmp.drop); |
screamer | 0:7a64fbb4069d | 219 | } |
screamer | 0:7a64fbb4069d | 220 | pbuf_free(p); |
screamer | 0:7a64fbb4069d | 221 | return; |
screamer | 0:7a64fbb4069d | 222 | lenerr: |
screamer | 0:7a64fbb4069d | 223 | pbuf_free(p); |
screamer | 0:7a64fbb4069d | 224 | ICMP_STATS_INC(icmp.lenerr); |
screamer | 0:7a64fbb4069d | 225 | snmp_inc_icmpinerrors(); |
screamer | 0:7a64fbb4069d | 226 | return; |
screamer | 0:7a64fbb4069d | 227 | memerr: |
screamer | 0:7a64fbb4069d | 228 | pbuf_free(p); |
screamer | 0:7a64fbb4069d | 229 | ICMP_STATS_INC(icmp.err); |
screamer | 0:7a64fbb4069d | 230 | snmp_inc_icmpinerrors(); |
screamer | 0:7a64fbb4069d | 231 | return; |
screamer | 0:7a64fbb4069d | 232 | } |
screamer | 0:7a64fbb4069d | 233 | |
screamer | 0:7a64fbb4069d | 234 | /** |
screamer | 0:7a64fbb4069d | 235 | * Send an icmp 'destination unreachable' packet, called from ip_input() if |
screamer | 0:7a64fbb4069d | 236 | * the transport layer protocol is unknown and from udp_input() if the local |
screamer | 0:7a64fbb4069d | 237 | * port is not bound. |
screamer | 0:7a64fbb4069d | 238 | * |
screamer | 0:7a64fbb4069d | 239 | * @param p the input packet for which the 'unreachable' should be sent, |
screamer | 0:7a64fbb4069d | 240 | * p->payload pointing to the IP header |
screamer | 0:7a64fbb4069d | 241 | * @param t type of the 'unreachable' packet |
screamer | 0:7a64fbb4069d | 242 | */ |
screamer | 0:7a64fbb4069d | 243 | void |
screamer | 0:7a64fbb4069d | 244 | icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) |
screamer | 0:7a64fbb4069d | 245 | { |
screamer | 0:7a64fbb4069d | 246 | struct pbuf *q; |
screamer | 0:7a64fbb4069d | 247 | struct ip_hdr *iphdr; |
screamer | 0:7a64fbb4069d | 248 | struct icmp_dur_hdr *idur; |
screamer | 0:7a64fbb4069d | 249 | |
screamer | 0:7a64fbb4069d | 250 | /* ICMP header + IP header + 8 bytes of data */ |
screamer | 0:7a64fbb4069d | 251 | q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, |
screamer | 0:7a64fbb4069d | 252 | PBUF_RAM); |
screamer | 0:7a64fbb4069d | 253 | if (q == NULL) { |
screamer | 0:7a64fbb4069d | 254 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n")); |
screamer | 0:7a64fbb4069d | 255 | return; |
screamer | 0:7a64fbb4069d | 256 | } |
screamer | 0:7a64fbb4069d | 257 | LWIP_ASSERT("check that first pbuf can hold icmp message", |
screamer | 0:7a64fbb4069d | 258 | (q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); |
screamer | 0:7a64fbb4069d | 259 | |
screamer | 0:7a64fbb4069d | 260 | iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) |
screamer | 0:7a64fbb4069d | 261 | |
screamer | 0:7a64fbb4069d | 262 | idur = (struct icmp_dur_hdr *)(q->payload); // static_cast<struct icmp_dur_hdr *>(x) |
screamer | 0:7a64fbb4069d | 263 | ICMPH_TYPE_SET(idur, ICMP_DUR); |
screamer | 0:7a64fbb4069d | 264 | ICMPH_CODE_SET(idur, t); |
screamer | 0:7a64fbb4069d | 265 | |
screamer | 0:7a64fbb4069d | 266 | SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), p->payload, |
screamer | 0:7a64fbb4069d | 267 | IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); |
screamer | 0:7a64fbb4069d | 268 | |
screamer | 0:7a64fbb4069d | 269 | /* calculate checksum */ |
screamer | 0:7a64fbb4069d | 270 | idur->chksum = 0; |
screamer | 0:7a64fbb4069d | 271 | idur->chksum = inet_chksum(idur, q->len); |
screamer | 0:7a64fbb4069d | 272 | ICMP_STATS_INC(icmp.xmit); |
screamer | 0:7a64fbb4069d | 273 | /* increase number of messages attempted to send */ |
screamer | 0:7a64fbb4069d | 274 | snmp_inc_icmpoutmsgs(); |
screamer | 0:7a64fbb4069d | 275 | /* increase number of destination unreachable messages attempted to send */ |
screamer | 0:7a64fbb4069d | 276 | snmp_inc_icmpoutdestunreachs(); |
screamer | 0:7a64fbb4069d | 277 | |
screamer | 0:7a64fbb4069d | 278 | struct ip_addr iphdrsrc; |
screamer | 0:7a64fbb4069d | 279 | iphdrsrc.addr = iphdr->src.addr; |
screamer | 0:7a64fbb4069d | 280 | ip_output(q, NULL, &(iphdrsrc), ICMP_TTL, 0, IP_PROTO_ICMP); |
screamer | 0:7a64fbb4069d | 281 | pbuf_free(q); |
screamer | 0:7a64fbb4069d | 282 | } |
screamer | 0:7a64fbb4069d | 283 | |
screamer | 0:7a64fbb4069d | 284 | #if IP_FORWARD || IP_REASSEMBLY |
screamer | 0:7a64fbb4069d | 285 | /** |
screamer | 0:7a64fbb4069d | 286 | * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. |
screamer | 0:7a64fbb4069d | 287 | * |
screamer | 0:7a64fbb4069d | 288 | * @param p the input packet for which the 'time exceeded' should be sent, |
screamer | 0:7a64fbb4069d | 289 | * p->payload pointing to the IP header |
screamer | 0:7a64fbb4069d | 290 | * @param t type of the 'time exceeded' packet |
screamer | 0:7a64fbb4069d | 291 | */ |
screamer | 0:7a64fbb4069d | 292 | void |
screamer | 0:7a64fbb4069d | 293 | icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) |
screamer | 0:7a64fbb4069d | 294 | { |
screamer | 0:7a64fbb4069d | 295 | struct pbuf *q; |
screamer | 0:7a64fbb4069d | 296 | struct ip_hdr *iphdr; |
screamer | 0:7a64fbb4069d | 297 | struct icmp_te_hdr *tehdr; |
screamer | 0:7a64fbb4069d | 298 | |
screamer | 0:7a64fbb4069d | 299 | /* ICMP header + IP header + 8 bytes of data */ |
screamer | 0:7a64fbb4069d | 300 | q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, |
screamer | 0:7a64fbb4069d | 301 | PBUF_RAM); |
screamer | 0:7a64fbb4069d | 302 | if (q == NULL) { |
screamer | 0:7a64fbb4069d | 303 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); |
screamer | 0:7a64fbb4069d | 304 | return; |
screamer | 0:7a64fbb4069d | 305 | } |
screamer | 0:7a64fbb4069d | 306 | LWIP_ASSERT("check that first pbuf can hold icmp message", |
screamer | 0:7a64fbb4069d | 307 | (q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); |
screamer | 0:7a64fbb4069d | 308 | |
screamer | 0:7a64fbb4069d | 309 | iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) |
screamer | 0:7a64fbb4069d | 310 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); |
screamer | 0:7a64fbb4069d | 311 | ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src)); |
screamer | 0:7a64fbb4069d | 312 | LWIP_DEBUGF(ICMP_DEBUG, (" to ")); |
screamer | 0:7a64fbb4069d | 313 | ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest)); |
screamer | 0:7a64fbb4069d | 314 | LWIP_DEBUGF(ICMP_DEBUG, ("\n")); |
screamer | 0:7a64fbb4069d | 315 | |
screamer | 0:7a64fbb4069d | 316 | tehdr = (struct icmp_te_hdr *)(q->payload); // static_cast<struct icmp_te_hdr *>(x) |
screamer | 0:7a64fbb4069d | 317 | ICMPH_TYPE_SET(tehdr, ICMP_TE); |
screamer | 0:7a64fbb4069d | 318 | ICMPH_CODE_SET(tehdr, t); |
screamer | 0:7a64fbb4069d | 319 | |
screamer | 0:7a64fbb4069d | 320 | /* copy fields from original packet */ |
screamer | 0:7a64fbb4069d | 321 | SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), (u8_t *)p->payload, |
screamer | 0:7a64fbb4069d | 322 | IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); |
screamer | 0:7a64fbb4069d | 323 | |
screamer | 0:7a64fbb4069d | 324 | /* calculate checksum */ |
screamer | 0:7a64fbb4069d | 325 | tehdr->chksum = 0; |
screamer | 0:7a64fbb4069d | 326 | tehdr->chksum = inet_chksum(tehdr, q->len); |
screamer | 0:7a64fbb4069d | 327 | ICMP_STATS_INC(icmp.xmit); |
screamer | 0:7a64fbb4069d | 328 | /* increase number of messages attempted to send */ |
screamer | 0:7a64fbb4069d | 329 | snmp_inc_icmpoutmsgs(); |
screamer | 0:7a64fbb4069d | 330 | /* increase number of destination unreachable messages attempted to send */ |
screamer | 0:7a64fbb4069d | 331 | snmp_inc_icmpouttimeexcds(); |
screamer | 0:7a64fbb4069d | 332 | struct ip_addr iphdrsrc; |
screamer | 0:7a64fbb4069d | 333 | iphdrsrc.addr = iphdr->src.addr; |
screamer | 0:7a64fbb4069d | 334 | ip_output(q, NULL, &iphdrsrc, ICMP_TTL, 0, IP_PROTO_ICMP); |
screamer | 0:7a64fbb4069d | 335 | pbuf_free(q); |
screamer | 0:7a64fbb4069d | 336 | } |
screamer | 0:7a64fbb4069d | 337 | |
screamer | 0:7a64fbb4069d | 338 | #endif /* IP_FORWARD */ |
screamer | 0:7a64fbb4069d | 339 | |
screamer | 0:7a64fbb4069d | 340 | #endif /* LWIP_ICMP */ |