Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
mbed_official
Date:
Mon Mar 14 16:15:36 2016 +0000
Revision:
20:08f08bfc3f3d
Parent:
0:51ac1d130fd4
Synchronized with git revision fec574a5ed6db26aca1b13992ff271bf527d4a0d

Full URL: https://github.com/mbedmicro/mbed/commit/fec574a5ed6db26aca1b13992ff271bf527d4a0d/

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

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