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:
11:4b3f6f8b92d2
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 * This is the IPv4 layer implementation for incoming and outgoing IP traffic.
mbed_official 0:51ac1d130fd4 4 *
mbed_official 0:51ac1d130fd4 5 * @see ip_frag.c
mbed_official 0:51ac1d130fd4 6 *
mbed_official 0:51ac1d130fd4 7 */
mbed_official 0:51ac1d130fd4 8
mbed_official 0:51ac1d130fd4 9 /*
mbed_official 0:51ac1d130fd4 10 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
mbed_official 0:51ac1d130fd4 11 * All rights reserved.
mbed_official 0:51ac1d130fd4 12 *
mbed_official 0:51ac1d130fd4 13 * Redistribution and use in source and binary forms, with or without modification,
mbed_official 0:51ac1d130fd4 14 * are permitted provided that the following conditions are met:
mbed_official 0:51ac1d130fd4 15 *
mbed_official 0:51ac1d130fd4 16 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 0:51ac1d130fd4 17 * this list of conditions and the following disclaimer.
mbed_official 0:51ac1d130fd4 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 0:51ac1d130fd4 19 * this list of conditions and the following disclaimer in the documentation
mbed_official 0:51ac1d130fd4 20 * and/or other materials provided with the distribution.
mbed_official 0:51ac1d130fd4 21 * 3. The name of the author may not be used to endorse or promote products
mbed_official 0:51ac1d130fd4 22 * derived from this software without specific prior written permission.
mbed_official 0:51ac1d130fd4 23 *
mbed_official 0:51ac1d130fd4 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
mbed_official 0:51ac1d130fd4 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 0:51ac1d130fd4 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
mbed_official 0:51ac1d130fd4 27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
mbed_official 0:51ac1d130fd4 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
mbed_official 0:51ac1d130fd4 29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
mbed_official 0:51ac1d130fd4 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
mbed_official 0:51ac1d130fd4 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
mbed_official 0:51ac1d130fd4 32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
mbed_official 0:51ac1d130fd4 33 * OF SUCH DAMAGE.
mbed_official 0:51ac1d130fd4 34 *
mbed_official 0:51ac1d130fd4 35 * This file is part of the lwIP TCP/IP stack.
mbed_official 0:51ac1d130fd4 36 *
mbed_official 0:51ac1d130fd4 37 * Author: Adam Dunkels <adam@sics.se>
mbed_official 0:51ac1d130fd4 38 *
mbed_official 0:51ac1d130fd4 39 */
mbed_official 0:51ac1d130fd4 40
mbed_official 0:51ac1d130fd4 41 #include "lwip/opt.h"
mbed_official 0:51ac1d130fd4 42 #include "lwip/ip.h"
mbed_official 0:51ac1d130fd4 43 #include "lwip/def.h"
mbed_official 0:51ac1d130fd4 44 #include "lwip/mem.h"
mbed_official 0:51ac1d130fd4 45 #include "lwip/ip_frag.h"
mbed_official 0:51ac1d130fd4 46 #include "lwip/inet_chksum.h"
mbed_official 0:51ac1d130fd4 47 #include "lwip/netif.h"
mbed_official 0:51ac1d130fd4 48 #include "lwip/icmp.h"
mbed_official 0:51ac1d130fd4 49 #include "lwip/igmp.h"
mbed_official 0:51ac1d130fd4 50 #include "lwip/raw.h"
mbed_official 0:51ac1d130fd4 51 #include "lwip/udp.h"
mbed_official 0:51ac1d130fd4 52 #include "lwip/tcp_impl.h"
mbed_official 0:51ac1d130fd4 53 #include "lwip/snmp.h"
mbed_official 0:51ac1d130fd4 54 #include "lwip/dhcp.h"
mbed_official 0:51ac1d130fd4 55 #include "lwip/autoip.h"
mbed_official 0:51ac1d130fd4 56 #include "lwip/stats.h"
mbed_official 0:51ac1d130fd4 57 #include "arch/perf.h"
mbed_official 0:51ac1d130fd4 58
mbed_official 0:51ac1d130fd4 59 #include <string.h>
mbed_official 0:51ac1d130fd4 60
mbed_official 0:51ac1d130fd4 61 /** Set this to 0 in the rare case of wanting to call an extra function to
mbed_official 0:51ac1d130fd4 62 * generate the IP checksum (in contrast to calculating it on-the-fly). */
mbed_official 0:51ac1d130fd4 63 #ifndef LWIP_INLINE_IP_CHKSUM
mbed_official 0:51ac1d130fd4 64 #define LWIP_INLINE_IP_CHKSUM 1
mbed_official 0:51ac1d130fd4 65 #endif
mbed_official 0:51ac1d130fd4 66 #if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
mbed_official 0:51ac1d130fd4 67 #define CHECKSUM_GEN_IP_INLINE 1
mbed_official 0:51ac1d130fd4 68 #else
mbed_official 0:51ac1d130fd4 69 #define CHECKSUM_GEN_IP_INLINE 0
mbed_official 0:51ac1d130fd4 70 #endif
mbed_official 0:51ac1d130fd4 71
mbed_official 0:51ac1d130fd4 72 #if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
mbed_official 0:51ac1d130fd4 73 #define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
mbed_official 0:51ac1d130fd4 74
mbed_official 0:51ac1d130fd4 75 /** Some defines for DHCP to let link-layer-addressed packets through while the
mbed_official 0:51ac1d130fd4 76 * netif is down.
mbed_official 0:51ac1d130fd4 77 * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT
mbed_official 0:51ac1d130fd4 78 * to return 1 if the port is accepted and 0 if the port is not accepted.
mbed_official 0:51ac1d130fd4 79 */
mbed_official 0:51ac1d130fd4 80 #if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
mbed_official 0:51ac1d130fd4 81 /* accept DHCP client port and custom port */
mbed_official 0:51ac1d130fd4 82 #define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
mbed_official 0:51ac1d130fd4 83 || (LWIP_IP_ACCEPT_UDP_PORT(port)))
mbed_official 0:51ac1d130fd4 84 #elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
mbed_official 0:51ac1d130fd4 85 /* accept custom port only */
mbed_official 0:51ac1d130fd4 86 #define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(dst_port))
mbed_official 0:51ac1d130fd4 87 #else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
mbed_official 0:51ac1d130fd4 88 /* accept DHCP client port only */
mbed_official 0:51ac1d130fd4 89 #define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
mbed_official 0:51ac1d130fd4 90 #endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
mbed_official 0:51ac1d130fd4 91
mbed_official 0:51ac1d130fd4 92 #else /* LWIP_DHCP */
mbed_official 0:51ac1d130fd4 93 #define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
mbed_official 0:51ac1d130fd4 94 #endif /* LWIP_DHCP */
mbed_official 0:51ac1d130fd4 95
mbed_official 0:51ac1d130fd4 96 /**
mbed_official 0:51ac1d130fd4 97 * The interface that provided the packet for the current callback
mbed_official 0:51ac1d130fd4 98 * invocation.
mbed_official 0:51ac1d130fd4 99 */
mbed_official 0:51ac1d130fd4 100 struct netif *current_netif;
mbed_official 0:51ac1d130fd4 101
mbed_official 0:51ac1d130fd4 102 /**
mbed_official 0:51ac1d130fd4 103 * Header of the input packet currently being processed.
mbed_official 0:51ac1d130fd4 104 */
mbed_official 0:51ac1d130fd4 105 const struct ip_hdr *current_header;
mbed_official 0:51ac1d130fd4 106 /** Source IP address of current_header */
mbed_official 0:51ac1d130fd4 107 ip_addr_t current_iphdr_src;
mbed_official 0:51ac1d130fd4 108 /** Destination IP address of current_header */
mbed_official 0:51ac1d130fd4 109 ip_addr_t current_iphdr_dest;
mbed_official 0:51ac1d130fd4 110
mbed_official 0:51ac1d130fd4 111 /** The IP header ID of the next outgoing IP packet */
mbed_official 0:51ac1d130fd4 112 static u16_t ip_id;
mbed_official 0:51ac1d130fd4 113
mbed_official 0:51ac1d130fd4 114 /**
mbed_official 0:51ac1d130fd4 115 * Finds the appropriate network interface for a given IP address. It
mbed_official 0:51ac1d130fd4 116 * searches the list of network interfaces linearly. A match is found
mbed_official 0:51ac1d130fd4 117 * if the masked IP address of the network interface equals the masked
mbed_official 0:51ac1d130fd4 118 * IP address given to the function.
mbed_official 0:51ac1d130fd4 119 *
mbed_official 0:51ac1d130fd4 120 * @param dest the destination IP address for which to find the route
mbed_official 0:51ac1d130fd4 121 * @return the netif on which to send to reach dest
mbed_official 0:51ac1d130fd4 122 */
mbed_official 0:51ac1d130fd4 123 struct netif *
mbed_official 0:51ac1d130fd4 124 ip_route(ip_addr_t *dest)
mbed_official 0:51ac1d130fd4 125 {
mbed_official 0:51ac1d130fd4 126 struct netif *netif;
mbed_official 0:51ac1d130fd4 127
mbed_official 0:51ac1d130fd4 128 /* iterate through netifs */
mbed_official 0:51ac1d130fd4 129 for(netif = netif_list; netif != NULL; netif = netif->next) {
mbed_official 0:51ac1d130fd4 130 /* network mask matches? */
mbed_official 0:51ac1d130fd4 131 if (netif_is_up(netif)) {
mbed_official 0:51ac1d130fd4 132 if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
mbed_official 0:51ac1d130fd4 133 /* return netif on which to forward IP packet */
mbed_official 0:51ac1d130fd4 134 return netif;
mbed_official 0:51ac1d130fd4 135 }
mbed_official 0:51ac1d130fd4 136 }
mbed_official 0:51ac1d130fd4 137 }
mbed_official 0:51ac1d130fd4 138 if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
mbed_official 0:51ac1d130fd4 139 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
mbed_official 0:51ac1d130fd4 140 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
mbed_official 0:51ac1d130fd4 141 IP_STATS_INC(ip.rterr);
mbed_official 0:51ac1d130fd4 142 snmp_inc_ipoutnoroutes();
mbed_official 0:51ac1d130fd4 143 return NULL;
mbed_official 0:51ac1d130fd4 144 }
mbed_official 0:51ac1d130fd4 145 /* no matching netif found, use default netif */
mbed_official 0:51ac1d130fd4 146 return netif_default;
mbed_official 0:51ac1d130fd4 147 }
mbed_official 0:51ac1d130fd4 148
mbed_official 0:51ac1d130fd4 149 #if IP_FORWARD
mbed_official 0:51ac1d130fd4 150 /**
mbed_official 0:51ac1d130fd4 151 * Forwards an IP packet. It finds an appropriate route for the
mbed_official 0:51ac1d130fd4 152 * packet, decrements the TTL value of the packet, adjusts the
mbed_official 0:51ac1d130fd4 153 * checksum and outputs the packet on the appropriate interface.
mbed_official 0:51ac1d130fd4 154 *
mbed_official 0:51ac1d130fd4 155 * @param p the packet to forward (p->payload points to IP header)
mbed_official 0:51ac1d130fd4 156 * @param iphdr the IP header of the input packet
mbed_official 0:51ac1d130fd4 157 * @param inp the netif on which this packet was received
mbed_official 0:51ac1d130fd4 158 */
mbed_official 0:51ac1d130fd4 159 static void
mbed_official 0:51ac1d130fd4 160 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
mbed_official 0:51ac1d130fd4 161 {
mbed_official 0:51ac1d130fd4 162 struct netif *netif;
mbed_official 0:51ac1d130fd4 163
mbed_official 0:51ac1d130fd4 164 PERF_START;
mbed_official 0:51ac1d130fd4 165
mbed_official 0:51ac1d130fd4 166 /* RFC3927 2.7: do not forward link-local addresses */
mbed_official 0:51ac1d130fd4 167 if (ip_addr_islinklocal(&current_iphdr_dest)) {
mbed_official 0:51ac1d130fd4 168 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
mbed_official 0:51ac1d130fd4 169 ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
mbed_official 0:51ac1d130fd4 170 ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
mbed_official 0:51ac1d130fd4 171 goto return_noroute;
mbed_official 0:51ac1d130fd4 172 }
mbed_official 0:51ac1d130fd4 173
mbed_official 0:51ac1d130fd4 174 /* Find network interface where to forward this IP packet to. */
mbed_official 0:51ac1d130fd4 175 netif = ip_route(&current_iphdr_dest);
mbed_official 0:51ac1d130fd4 176 if (netif == NULL) {
mbed_official 0:51ac1d130fd4 177 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
mbed_official 0:51ac1d130fd4 178 ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
mbed_official 0:51ac1d130fd4 179 ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
mbed_official 0:51ac1d130fd4 180 goto return_noroute;
mbed_official 0:51ac1d130fd4 181 }
mbed_official 0:51ac1d130fd4 182 /* Do not forward packets onto the same network interface on which
mbed_official 0:51ac1d130fd4 183 * they arrived. */
mbed_official 0:51ac1d130fd4 184 if (netif == inp) {
mbed_official 0:51ac1d130fd4 185 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
mbed_official 0:51ac1d130fd4 186 goto return_noroute;
mbed_official 0:51ac1d130fd4 187 }
mbed_official 0:51ac1d130fd4 188
mbed_official 0:51ac1d130fd4 189 /* decrement TTL */
mbed_official 0:51ac1d130fd4 190 IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
mbed_official 0:51ac1d130fd4 191 /* send ICMP if TTL == 0 */
mbed_official 0:51ac1d130fd4 192 if (IPH_TTL(iphdr) == 0) {
mbed_official 0:51ac1d130fd4 193 snmp_inc_ipinhdrerrors();
mbed_official 0:51ac1d130fd4 194 #if LWIP_ICMP
mbed_official 0:51ac1d130fd4 195 /* Don't send ICMP messages in response to ICMP messages */
mbed_official 0:51ac1d130fd4 196 if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
mbed_official 0:51ac1d130fd4 197 icmp_time_exceeded(p, ICMP_TE_TTL);
mbed_official 0:51ac1d130fd4 198 }
mbed_official 0:51ac1d130fd4 199 #endif /* LWIP_ICMP */
mbed_official 0:51ac1d130fd4 200 return;
mbed_official 0:51ac1d130fd4 201 }
mbed_official 0:51ac1d130fd4 202
mbed_official 0:51ac1d130fd4 203 /* Incrementally update the IP checksum. */
mbed_official 0:51ac1d130fd4 204 if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
mbed_official 0:51ac1d130fd4 205 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
mbed_official 0:51ac1d130fd4 206 } else {
mbed_official 0:51ac1d130fd4 207 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
mbed_official 0:51ac1d130fd4 208 }
mbed_official 0:51ac1d130fd4 209
mbed_official 0:51ac1d130fd4 210 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
mbed_official 0:51ac1d130fd4 211 ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
mbed_official 0:51ac1d130fd4 212 ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
mbed_official 0:51ac1d130fd4 213
mbed_official 0:51ac1d130fd4 214 IP_STATS_INC(ip.fw);
mbed_official 0:51ac1d130fd4 215 IP_STATS_INC(ip.xmit);
mbed_official 0:51ac1d130fd4 216 snmp_inc_ipforwdatagrams();
mbed_official 0:51ac1d130fd4 217
mbed_official 0:51ac1d130fd4 218 PERF_STOP("ip_forward");
mbed_official 0:51ac1d130fd4 219 /* transmit pbuf on chosen interface */
mbed_official 0:51ac1d130fd4 220 netif->output(netif, p, &current_iphdr_dest);
mbed_official 0:51ac1d130fd4 221 return;
mbed_official 0:51ac1d130fd4 222 return_noroute:
mbed_official 0:51ac1d130fd4 223 snmp_inc_ipoutnoroutes();
mbed_official 0:51ac1d130fd4 224 }
mbed_official 0:51ac1d130fd4 225 #endif /* IP_FORWARD */
mbed_official 0:51ac1d130fd4 226
mbed_official 0:51ac1d130fd4 227 /**
mbed_official 0:51ac1d130fd4 228 * This function is called by the network interface device driver when
mbed_official 0:51ac1d130fd4 229 * an IP packet is received. The function does the basic checks of the
mbed_official 0:51ac1d130fd4 230 * IP header such as packet size being at least larger than the header
mbed_official 0:51ac1d130fd4 231 * size etc. If the packet was not destined for us, the packet is
mbed_official 0:51ac1d130fd4 232 * forwarded (using ip_forward). The IP checksum is always checked.
mbed_official 0:51ac1d130fd4 233 *
mbed_official 0:51ac1d130fd4 234 * Finally, the packet is sent to the upper layer protocol input function.
mbed_official 0:51ac1d130fd4 235 *
mbed_official 0:51ac1d130fd4 236 * @param p the received IP packet (p->payload points to IP header)
mbed_official 0:51ac1d130fd4 237 * @param inp the netif on which this packet was received
mbed_official 0:51ac1d130fd4 238 * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
mbed_official 0:51ac1d130fd4 239 * processed, but currently always returns ERR_OK)
mbed_official 0:51ac1d130fd4 240 */
mbed_official 0:51ac1d130fd4 241 err_t
mbed_official 0:51ac1d130fd4 242 ip_input(struct pbuf *p, struct netif *inp)
mbed_official 0:51ac1d130fd4 243 {
mbed_official 0:51ac1d130fd4 244 struct ip_hdr *iphdr;
mbed_official 0:51ac1d130fd4 245 struct netif *netif;
mbed_official 0:51ac1d130fd4 246 u16_t iphdr_hlen;
mbed_official 0:51ac1d130fd4 247 u16_t iphdr_len;
mbed_official 0:51ac1d130fd4 248 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
mbed_official 0:51ac1d130fd4 249 int check_ip_src=1;
mbed_official 0:51ac1d130fd4 250 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
mbed_official 0:51ac1d130fd4 251
mbed_official 0:51ac1d130fd4 252 IP_STATS_INC(ip.recv);
mbed_official 0:51ac1d130fd4 253 snmp_inc_ipinreceives();
mbed_official 0:51ac1d130fd4 254
mbed_official 0:51ac1d130fd4 255 /* identify the IP header */
mbed_official 0:51ac1d130fd4 256 iphdr = (struct ip_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 257 if (IPH_V(iphdr) != 4) {
mbed_official 0:51ac1d130fd4 258 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
mbed_official 0:51ac1d130fd4 259 ip_debug_print(p);
mbed_official 0:51ac1d130fd4 260 pbuf_free(p);
mbed_official 0:51ac1d130fd4 261 IP_STATS_INC(ip.err);
mbed_official 0:51ac1d130fd4 262 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 263 snmp_inc_ipinhdrerrors();
mbed_official 0:51ac1d130fd4 264 return ERR_OK;
mbed_official 0:51ac1d130fd4 265 }
mbed_official 0:51ac1d130fd4 266
mbed_official 0:51ac1d130fd4 267 /* obtain IP header length in number of 32-bit words */
mbed_official 0:51ac1d130fd4 268 iphdr_hlen = IPH_HL(iphdr);
mbed_official 0:51ac1d130fd4 269 /* calculate IP header length in bytes */
mbed_official 0:51ac1d130fd4 270 iphdr_hlen *= 4;
mbed_official 0:51ac1d130fd4 271 /* obtain ip length in bytes */
mbed_official 0:51ac1d130fd4 272 iphdr_len = ntohs(IPH_LEN(iphdr));
mbed_official 0:51ac1d130fd4 273
mbed_official 0:51ac1d130fd4 274 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
mbed_official 0:51ac1d130fd4 275 if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
mbed_official 0:51ac1d130fd4 276 if (iphdr_hlen > p->len) {
mbed_official 0:51ac1d130fd4 277 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
mbed_official 0:51ac1d130fd4 278 ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
mbed_official 0:51ac1d130fd4 279 iphdr_hlen, p->len));
mbed_official 0:51ac1d130fd4 280 }
mbed_official 0:51ac1d130fd4 281 if (iphdr_len > p->tot_len) {
mbed_official 0:51ac1d130fd4 282 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
mbed_official 0:51ac1d130fd4 283 ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
mbed_official 0:51ac1d130fd4 284 iphdr_len, p->tot_len));
mbed_official 0:51ac1d130fd4 285 }
mbed_official 0:51ac1d130fd4 286 /* free (drop) packet pbufs */
mbed_official 0:51ac1d130fd4 287 pbuf_free(p);
mbed_official 0:51ac1d130fd4 288 IP_STATS_INC(ip.lenerr);
mbed_official 0:51ac1d130fd4 289 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 290 snmp_inc_ipindiscards();
mbed_official 0:51ac1d130fd4 291 return ERR_OK;
mbed_official 0:51ac1d130fd4 292 }
mbed_official 0:51ac1d130fd4 293
mbed_official 0:51ac1d130fd4 294 /* verify checksum */
mbed_official 0:51ac1d130fd4 295 #if CHECKSUM_CHECK_IP
mbed_official 0:51ac1d130fd4 296 if (inet_chksum(iphdr, iphdr_hlen) != 0) {
mbed_official 0:51ac1d130fd4 297
mbed_official 0:51ac1d130fd4 298 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
mbed_official 0:51ac1d130fd4 299 ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
mbed_official 0:51ac1d130fd4 300 ip_debug_print(p);
mbed_official 0:51ac1d130fd4 301 pbuf_free(p);
mbed_official 0:51ac1d130fd4 302 IP_STATS_INC(ip.chkerr);
mbed_official 0:51ac1d130fd4 303 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 304 snmp_inc_ipinhdrerrors();
mbed_official 0:51ac1d130fd4 305 return ERR_OK;
mbed_official 0:51ac1d130fd4 306 }
mbed_official 0:51ac1d130fd4 307 #endif
mbed_official 0:51ac1d130fd4 308
mbed_official 0:51ac1d130fd4 309 /* Trim pbuf. This should have been done at the netif layer,
mbed_official 0:51ac1d130fd4 310 * but we'll do it anyway just to be sure that its done. */
mbed_official 0:51ac1d130fd4 311 pbuf_realloc(p, iphdr_len);
mbed_official 0:51ac1d130fd4 312
mbed_official 0:51ac1d130fd4 313 /* copy IP addresses to aligned ip_addr_t */
mbed_official 0:51ac1d130fd4 314 ip_addr_copy(current_iphdr_dest, iphdr->dest);
mbed_official 0:51ac1d130fd4 315 ip_addr_copy(current_iphdr_src, iphdr->src);
mbed_official 0:51ac1d130fd4 316
mbed_official 0:51ac1d130fd4 317 /* match packet against an interface, i.e. is this packet for us? */
mbed_official 0:51ac1d130fd4 318 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 319 if (ip_addr_ismulticast(&current_iphdr_dest)) {
mbed_official 0:51ac1d130fd4 320 if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
mbed_official 0:51ac1d130fd4 321 netif = inp;
mbed_official 0:51ac1d130fd4 322 } else {
mbed_official 0:51ac1d130fd4 323 netif = NULL;
mbed_official 0:51ac1d130fd4 324 }
mbed_official 0:51ac1d130fd4 325 } else
mbed_official 0:51ac1d130fd4 326 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 327 {
mbed_official 0:51ac1d130fd4 328 /* start trying with inp. if that's not acceptable, start walking the
mbed_official 0:51ac1d130fd4 329 list of configured netifs.
mbed_official 0:51ac1d130fd4 330 'first' is used as a boolean to mark whether we started walking the list */
mbed_official 0:51ac1d130fd4 331 int first = 1;
mbed_official 0:51ac1d130fd4 332 netif = inp;
mbed_official 0:51ac1d130fd4 333 do {
mbed_official 0:51ac1d130fd4 334 LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
mbed_official 0:51ac1d130fd4 335 ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr),
mbed_official 0:51ac1d130fd4 336 ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask),
mbed_official 0:51ac1d130fd4 337 ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask),
mbed_official 0:51ac1d130fd4 338 ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask)));
mbed_official 0:51ac1d130fd4 339
mbed_official 0:51ac1d130fd4 340 /* interface is up and configured? */
mbed_official 0:51ac1d130fd4 341 if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
mbed_official 0:51ac1d130fd4 342 /* unicast to this interface address? */
mbed_official 0:51ac1d130fd4 343 if (ip_addr_cmp(&current_iphdr_dest, &(netif->ip_addr)) ||
mbed_official 0:51ac1d130fd4 344 /* or broadcast on this interface network address? */
mbed_official 0:51ac1d130fd4 345 ip_addr_isbroadcast(&current_iphdr_dest, netif)) {
mbed_official 0:51ac1d130fd4 346 LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
mbed_official 0:51ac1d130fd4 347 netif->name[0], netif->name[1]));
mbed_official 0:51ac1d130fd4 348 /* break out of for loop */
mbed_official 0:51ac1d130fd4 349 break;
mbed_official 0:51ac1d130fd4 350 }
mbed_official 0:51ac1d130fd4 351 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 352 /* connections to link-local addresses must persist after changing
mbed_official 0:51ac1d130fd4 353 the netif's address (RFC3927 ch. 1.9) */
mbed_official 0:51ac1d130fd4 354 if ((netif->autoip != NULL) &&
mbed_official 0:51ac1d130fd4 355 ip_addr_cmp(&current_iphdr_dest, &(netif->autoip->llipaddr))) {
mbed_official 0:51ac1d130fd4 356 LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
mbed_official 0:51ac1d130fd4 357 netif->name[0], netif->name[1]));
mbed_official 0:51ac1d130fd4 358 /* break out of for loop */
mbed_official 0:51ac1d130fd4 359 break;
mbed_official 0:51ac1d130fd4 360 }
mbed_official 0:51ac1d130fd4 361 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 362 }
mbed_official 0:51ac1d130fd4 363 if (first) {
mbed_official 0:51ac1d130fd4 364 first = 0;
mbed_official 0:51ac1d130fd4 365 netif = netif_list;
mbed_official 0:51ac1d130fd4 366 } else {
mbed_official 0:51ac1d130fd4 367 netif = netif->next;
mbed_official 0:51ac1d130fd4 368 }
mbed_official 0:51ac1d130fd4 369 if (netif == inp) {
mbed_official 0:51ac1d130fd4 370 netif = netif->next;
mbed_official 0:51ac1d130fd4 371 }
mbed_official 0:51ac1d130fd4 372 } while(netif != NULL);
mbed_official 0:51ac1d130fd4 373 }
mbed_official 0:51ac1d130fd4 374
mbed_official 0:51ac1d130fd4 375 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
mbed_official 0:51ac1d130fd4 376 /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
mbed_official 0:51ac1d130fd4 377 * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
mbed_official 0:51ac1d130fd4 378 * According to RFC 1542 section 3.1.1, referred by RFC 2131).
mbed_official 0:51ac1d130fd4 379 *
mbed_official 0:51ac1d130fd4 380 * If you want to accept private broadcast communication while a netif is down,
mbed_official 0:51ac1d130fd4 381 * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
mbed_official 0:51ac1d130fd4 382 *
mbed_official 0:51ac1d130fd4 383 * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
mbed_official 0:51ac1d130fd4 384 */
mbed_official 0:51ac1d130fd4 385 if (netif == NULL) {
mbed_official 0:51ac1d130fd4 386 /* remote port is DHCP server? */
mbed_official 0:51ac1d130fd4 387 if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
mbed_official 0:51ac1d130fd4 388 struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
mbed_official 0:51ac1d130fd4 389 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
mbed_official 0:51ac1d130fd4 390 ntohs(udphdr->dest)));
mbed_official 0:51ac1d130fd4 391 if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
mbed_official 0:51ac1d130fd4 392 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
mbed_official 0:51ac1d130fd4 393 netif = inp;
mbed_official 0:51ac1d130fd4 394 check_ip_src = 0;
mbed_official 0:51ac1d130fd4 395 }
mbed_official 0:51ac1d130fd4 396 }
mbed_official 0:51ac1d130fd4 397 }
mbed_official 0:51ac1d130fd4 398 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
mbed_official 0:51ac1d130fd4 399
mbed_official 0:51ac1d130fd4 400 /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
mbed_official 0:51ac1d130fd4 401 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
mbed_official 0:51ac1d130fd4 402 /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
bogdanm 11:4b3f6f8b92d2 403 if (check_ip_src && current_iphdr_src.addr != IPADDR_ANY)
mbed_official 0:51ac1d130fd4 404 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
mbed_official 0:51ac1d130fd4 405 { if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
mbed_official 0:51ac1d130fd4 406 (ip_addr_ismulticast(&current_iphdr_src))) {
mbed_official 0:51ac1d130fd4 407 /* packet source is not valid */
mbed_official 0:51ac1d130fd4 408 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
mbed_official 0:51ac1d130fd4 409 /* free (drop) packet pbufs */
mbed_official 0:51ac1d130fd4 410 pbuf_free(p);
mbed_official 0:51ac1d130fd4 411 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 412 snmp_inc_ipinaddrerrors();
mbed_official 0:51ac1d130fd4 413 snmp_inc_ipindiscards();
mbed_official 0:51ac1d130fd4 414 return ERR_OK;
mbed_official 0:51ac1d130fd4 415 }
mbed_official 0:51ac1d130fd4 416 }
mbed_official 0:51ac1d130fd4 417
mbed_official 0:51ac1d130fd4 418 /* packet not for us? */
mbed_official 0:51ac1d130fd4 419 if (netif == NULL) {
mbed_official 0:51ac1d130fd4 420 /* packet not for us, route or discard */
mbed_official 0:51ac1d130fd4 421 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
mbed_official 0:51ac1d130fd4 422 #if IP_FORWARD
mbed_official 0:51ac1d130fd4 423 /* non-broadcast packet? */
mbed_official 0:51ac1d130fd4 424 if (!ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
mbed_official 0:51ac1d130fd4 425 /* try to forward IP packet on (other) interfaces */
mbed_official 0:51ac1d130fd4 426 ip_forward(p, iphdr, inp);
mbed_official 0:51ac1d130fd4 427 } else
mbed_official 0:51ac1d130fd4 428 #endif /* IP_FORWARD */
mbed_official 0:51ac1d130fd4 429 {
mbed_official 0:51ac1d130fd4 430 snmp_inc_ipinaddrerrors();
mbed_official 0:51ac1d130fd4 431 snmp_inc_ipindiscards();
mbed_official 0:51ac1d130fd4 432 }
mbed_official 0:51ac1d130fd4 433 pbuf_free(p);
mbed_official 0:51ac1d130fd4 434 return ERR_OK;
mbed_official 0:51ac1d130fd4 435 }
mbed_official 0:51ac1d130fd4 436 /* packet consists of multiple fragments? */
mbed_official 0:51ac1d130fd4 437 if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
mbed_official 0:51ac1d130fd4 438 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
mbed_official 0:51ac1d130fd4 439 LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
mbed_official 0:51ac1d130fd4 440 ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
mbed_official 0:51ac1d130fd4 441 /* reassemble the packet*/
mbed_official 0:51ac1d130fd4 442 p = ip_reass(p);
mbed_official 0:51ac1d130fd4 443 /* packet not fully reassembled yet? */
mbed_official 0:51ac1d130fd4 444 if (p == NULL) {
mbed_official 0:51ac1d130fd4 445 return ERR_OK;
mbed_official 0:51ac1d130fd4 446 }
mbed_official 0:51ac1d130fd4 447 iphdr = (struct ip_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 448 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
mbed_official 0:51ac1d130fd4 449 pbuf_free(p);
mbed_official 0:51ac1d130fd4 450 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
mbed_official 0:51ac1d130fd4 451 ntohs(IPH_OFFSET(iphdr))));
mbed_official 0:51ac1d130fd4 452 IP_STATS_INC(ip.opterr);
mbed_official 0:51ac1d130fd4 453 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 454 /* unsupported protocol feature */
mbed_official 0:51ac1d130fd4 455 snmp_inc_ipinunknownprotos();
mbed_official 0:51ac1d130fd4 456 return ERR_OK;
mbed_official 0:51ac1d130fd4 457 #endif /* IP_REASSEMBLY */
mbed_official 0:51ac1d130fd4 458 }
mbed_official 0:51ac1d130fd4 459
mbed_official 0:51ac1d130fd4 460 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
mbed_official 0:51ac1d130fd4 461
mbed_official 0:51ac1d130fd4 462 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 463 /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
mbed_official 0:51ac1d130fd4 464 if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
mbed_official 0:51ac1d130fd4 465 #else
mbed_official 0:51ac1d130fd4 466 if (iphdr_hlen > IP_HLEN) {
mbed_official 0:51ac1d130fd4 467 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 468 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
mbed_official 0:51ac1d130fd4 469 pbuf_free(p);
mbed_official 0:51ac1d130fd4 470 IP_STATS_INC(ip.opterr);
mbed_official 0:51ac1d130fd4 471 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 472 /* unsupported protocol feature */
mbed_official 0:51ac1d130fd4 473 snmp_inc_ipinunknownprotos();
mbed_official 0:51ac1d130fd4 474 return ERR_OK;
mbed_official 0:51ac1d130fd4 475 }
mbed_official 0:51ac1d130fd4 476 #endif /* IP_OPTIONS_ALLOWED == 0 */
mbed_official 0:51ac1d130fd4 477
mbed_official 0:51ac1d130fd4 478 /* send to upper layers */
mbed_official 0:51ac1d130fd4 479 LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
mbed_official 0:51ac1d130fd4 480 ip_debug_print(p);
mbed_official 0:51ac1d130fd4 481 LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
mbed_official 0:51ac1d130fd4 482
mbed_official 0:51ac1d130fd4 483 current_netif = inp;
mbed_official 0:51ac1d130fd4 484 current_header = iphdr;
mbed_official 0:51ac1d130fd4 485
mbed_official 0:51ac1d130fd4 486 #if LWIP_RAW
mbed_official 0:51ac1d130fd4 487 /* raw input did not eat the packet? */
mbed_official 0:51ac1d130fd4 488 if (raw_input(p, inp) == 0)
mbed_official 0:51ac1d130fd4 489 #endif /* LWIP_RAW */
mbed_official 0:51ac1d130fd4 490 {
mbed_official 0:51ac1d130fd4 491
mbed_official 0:51ac1d130fd4 492 switch (IPH_PROTO(iphdr)) {
mbed_official 0:51ac1d130fd4 493 #if LWIP_UDP
mbed_official 0:51ac1d130fd4 494 case IP_PROTO_UDP:
mbed_official 0:51ac1d130fd4 495 #if LWIP_UDPLITE
mbed_official 0:51ac1d130fd4 496 case IP_PROTO_UDPLITE:
mbed_official 0:51ac1d130fd4 497 #endif /* LWIP_UDPLITE */
mbed_official 0:51ac1d130fd4 498 snmp_inc_ipindelivers();
mbed_official 0:51ac1d130fd4 499 udp_input(p, inp);
mbed_official 0:51ac1d130fd4 500 break;
mbed_official 0:51ac1d130fd4 501 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 502 #if LWIP_TCP
mbed_official 0:51ac1d130fd4 503 case IP_PROTO_TCP:
mbed_official 0:51ac1d130fd4 504 snmp_inc_ipindelivers();
mbed_official 0:51ac1d130fd4 505 tcp_input(p, inp);
mbed_official 0:51ac1d130fd4 506 break;
mbed_official 0:51ac1d130fd4 507 #endif /* LWIP_TCP */
mbed_official 0:51ac1d130fd4 508 #if LWIP_ICMP
mbed_official 0:51ac1d130fd4 509 case IP_PROTO_ICMP:
mbed_official 0:51ac1d130fd4 510 snmp_inc_ipindelivers();
mbed_official 0:51ac1d130fd4 511 icmp_input(p, inp);
mbed_official 0:51ac1d130fd4 512 break;
mbed_official 0:51ac1d130fd4 513 #endif /* LWIP_ICMP */
mbed_official 0:51ac1d130fd4 514 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 515 case IP_PROTO_IGMP:
mbed_official 0:51ac1d130fd4 516 igmp_input(p, inp, &current_iphdr_dest);
mbed_official 0:51ac1d130fd4 517 break;
mbed_official 0:51ac1d130fd4 518 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 519 default:
mbed_official 0:51ac1d130fd4 520 #if LWIP_ICMP
mbed_official 0:51ac1d130fd4 521 /* send ICMP destination protocol unreachable unless is was a broadcast */
mbed_official 0:51ac1d130fd4 522 if (!ip_addr_isbroadcast(&current_iphdr_dest, inp) &&
mbed_official 0:51ac1d130fd4 523 !ip_addr_ismulticast(&current_iphdr_dest)) {
mbed_official 0:51ac1d130fd4 524 p->payload = iphdr;
mbed_official 0:51ac1d130fd4 525 icmp_dest_unreach(p, ICMP_DUR_PROTO);
mbed_official 0:51ac1d130fd4 526 }
mbed_official 0:51ac1d130fd4 527 #endif /* LWIP_ICMP */
mbed_official 0:51ac1d130fd4 528 pbuf_free(p);
mbed_official 0:51ac1d130fd4 529
mbed_official 0:51ac1d130fd4 530 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
mbed_official 0:51ac1d130fd4 531
mbed_official 0:51ac1d130fd4 532 IP_STATS_INC(ip.proterr);
mbed_official 0:51ac1d130fd4 533 IP_STATS_INC(ip.drop);
mbed_official 0:51ac1d130fd4 534 snmp_inc_ipinunknownprotos();
mbed_official 0:51ac1d130fd4 535 }
mbed_official 0:51ac1d130fd4 536 }
mbed_official 0:51ac1d130fd4 537
mbed_official 0:51ac1d130fd4 538 current_netif = NULL;
mbed_official 0:51ac1d130fd4 539 current_header = NULL;
mbed_official 0:51ac1d130fd4 540 ip_addr_set_any(&current_iphdr_src);
mbed_official 0:51ac1d130fd4 541 ip_addr_set_any(&current_iphdr_dest);
mbed_official 0:51ac1d130fd4 542
mbed_official 0:51ac1d130fd4 543 return ERR_OK;
mbed_official 0:51ac1d130fd4 544 }
mbed_official 0:51ac1d130fd4 545
mbed_official 0:51ac1d130fd4 546 /**
mbed_official 0:51ac1d130fd4 547 * Sends an IP packet on a network interface. This function constructs
mbed_official 0:51ac1d130fd4 548 * the IP header and calculates the IP header checksum. If the source
mbed_official 0:51ac1d130fd4 549 * IP address is NULL, the IP address of the outgoing network
mbed_official 0:51ac1d130fd4 550 * interface is filled in as source address.
mbed_official 0:51ac1d130fd4 551 * If the destination IP address is IP_HDRINCL, p is assumed to already
mbed_official 0:51ac1d130fd4 552 * include an IP header and p->payload points to it instead of the data.
mbed_official 0:51ac1d130fd4 553 *
mbed_official 0:51ac1d130fd4 554 * @param p the packet to send (p->payload points to the data, e.g. next
mbed_official 0:51ac1d130fd4 555 protocol header; if dest == IP_HDRINCL, p already includes an IP
mbed_official 0:51ac1d130fd4 556 header and p->payload points to that IP header)
mbed_official 0:51ac1d130fd4 557 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
mbed_official 0:51ac1d130fd4 558 * IP address of the netif used to send is used as source address)
mbed_official 0:51ac1d130fd4 559 * @param dest the destination IP address to send the packet to
mbed_official 0:51ac1d130fd4 560 * @param ttl the TTL value to be set in the IP header
mbed_official 0:51ac1d130fd4 561 * @param tos the TOS value to be set in the IP header
mbed_official 0:51ac1d130fd4 562 * @param proto the PROTOCOL to be set in the IP header
mbed_official 0:51ac1d130fd4 563 * @param netif the netif on which to send this packet
mbed_official 0:51ac1d130fd4 564 * @return ERR_OK if the packet was sent OK
mbed_official 0:51ac1d130fd4 565 * ERR_BUF if p doesn't have enough space for IP/LINK headers
mbed_official 0:51ac1d130fd4 566 * returns errors returned by netif->output
mbed_official 0:51ac1d130fd4 567 *
mbed_official 0:51ac1d130fd4 568 * @note ip_id: RFC791 "some host may be able to simply use
mbed_official 0:51ac1d130fd4 569 * unique identifiers independent of destination"
mbed_official 0:51ac1d130fd4 570 */
mbed_official 0:51ac1d130fd4 571 err_t
mbed_official 0:51ac1d130fd4 572 ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
mbed_official 0:51ac1d130fd4 573 u8_t ttl, u8_t tos,
mbed_official 0:51ac1d130fd4 574 u8_t proto, struct netif *netif)
mbed_official 0:51ac1d130fd4 575 {
mbed_official 0:51ac1d130fd4 576 #if IP_OPTIONS_SEND
mbed_official 0:51ac1d130fd4 577 return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
mbed_official 0:51ac1d130fd4 578 }
mbed_official 0:51ac1d130fd4 579
mbed_official 0:51ac1d130fd4 580 /**
mbed_official 0:51ac1d130fd4 581 * Same as ip_output_if() but with the possibility to include IP options:
mbed_official 0:51ac1d130fd4 582 *
mbed_official 0:51ac1d130fd4 583 * @ param ip_options pointer to the IP options, copied into the IP header
mbed_official 0:51ac1d130fd4 584 * @ param optlen length of ip_options
mbed_official 0:51ac1d130fd4 585 */
mbed_official 0:51ac1d130fd4 586 err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
mbed_official 0:51ac1d130fd4 587 u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
mbed_official 0:51ac1d130fd4 588 u16_t optlen)
mbed_official 0:51ac1d130fd4 589 {
mbed_official 0:51ac1d130fd4 590 #endif /* IP_OPTIONS_SEND */
mbed_official 0:51ac1d130fd4 591 struct ip_hdr *iphdr;
mbed_official 0:51ac1d130fd4 592 ip_addr_t dest_addr;
mbed_official 0:51ac1d130fd4 593 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 594 u32_t chk_sum = 0;
mbed_official 0:51ac1d130fd4 595 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 596
mbed_official 0:51ac1d130fd4 597 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
mbed_official 0:51ac1d130fd4 598 gets altered as the packet is passed down the stack */
mbed_official 0:51ac1d130fd4 599 LWIP_ASSERT("p->ref == 1", p->ref == 1);
mbed_official 0:51ac1d130fd4 600
mbed_official 0:51ac1d130fd4 601 snmp_inc_ipoutrequests();
mbed_official 0:51ac1d130fd4 602
mbed_official 0:51ac1d130fd4 603 /* Should the IP header be generated or is it already included in p? */
mbed_official 0:51ac1d130fd4 604 if (dest != IP_HDRINCL) {
mbed_official 0:51ac1d130fd4 605 u16_t ip_hlen = IP_HLEN;
mbed_official 0:51ac1d130fd4 606 #if IP_OPTIONS_SEND
mbed_official 0:51ac1d130fd4 607 u16_t optlen_aligned = 0;
mbed_official 0:51ac1d130fd4 608 if (optlen != 0) {
mbed_official 0:51ac1d130fd4 609 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 610 int i;
mbed_official 0:51ac1d130fd4 611 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 612 /* round up to a multiple of 4 */
mbed_official 0:51ac1d130fd4 613 optlen_aligned = ((optlen + 3) & ~3);
mbed_official 0:51ac1d130fd4 614 ip_hlen += optlen_aligned;
mbed_official 0:51ac1d130fd4 615 /* First write in the IP options */
mbed_official 0:51ac1d130fd4 616 if (pbuf_header(p, optlen_aligned)) {
mbed_official 0:51ac1d130fd4 617 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
mbed_official 0:51ac1d130fd4 618 IP_STATS_INC(ip.err);
mbed_official 0:51ac1d130fd4 619 snmp_inc_ipoutdiscards();
mbed_official 0:51ac1d130fd4 620 return ERR_BUF;
mbed_official 0:51ac1d130fd4 621 }
mbed_official 0:51ac1d130fd4 622 MEMCPY(p->payload, ip_options, optlen);
mbed_official 0:51ac1d130fd4 623 if (optlen < optlen_aligned) {
mbed_official 0:51ac1d130fd4 624 /* zero the remaining bytes */
mbed_official 0:51ac1d130fd4 625 memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
mbed_official 0:51ac1d130fd4 626 }
mbed_official 0:51ac1d130fd4 627 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 628 for (i = 0; i < optlen_aligned/2; i++) {
mbed_official 0:51ac1d130fd4 629 chk_sum += ((u16_t*)p->payload)[i];
mbed_official 0:51ac1d130fd4 630 }
mbed_official 0:51ac1d130fd4 631 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 632 }
mbed_official 0:51ac1d130fd4 633 #endif /* IP_OPTIONS_SEND */
mbed_official 0:51ac1d130fd4 634 /* generate IP header */
mbed_official 0:51ac1d130fd4 635 if (pbuf_header(p, IP_HLEN)) {
mbed_official 0:51ac1d130fd4 636 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
mbed_official 0:51ac1d130fd4 637
mbed_official 0:51ac1d130fd4 638 IP_STATS_INC(ip.err);
mbed_official 0:51ac1d130fd4 639 snmp_inc_ipoutdiscards();
mbed_official 0:51ac1d130fd4 640 return ERR_BUF;
mbed_official 0:51ac1d130fd4 641 }
mbed_official 0:51ac1d130fd4 642
mbed_official 0:51ac1d130fd4 643 iphdr = (struct ip_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 644 LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
mbed_official 0:51ac1d130fd4 645 (p->len >= sizeof(struct ip_hdr)));
mbed_official 0:51ac1d130fd4 646
mbed_official 0:51ac1d130fd4 647 IPH_TTL_SET(iphdr, ttl);
mbed_official 0:51ac1d130fd4 648 IPH_PROTO_SET(iphdr, proto);
mbed_official 0:51ac1d130fd4 649 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 650 chk_sum += LWIP_MAKE_U16(proto, ttl);
mbed_official 0:51ac1d130fd4 651 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 652
mbed_official 0:51ac1d130fd4 653 /* dest cannot be NULL here */
mbed_official 0:51ac1d130fd4 654 ip_addr_copy(iphdr->dest, *dest);
mbed_official 0:51ac1d130fd4 655 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 656 chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
mbed_official 0:51ac1d130fd4 657 chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
mbed_official 0:51ac1d130fd4 658 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 659
mbed_official 0:51ac1d130fd4 660 IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
mbed_official 0:51ac1d130fd4 661 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 662 chk_sum += iphdr->_v_hl_tos;
mbed_official 0:51ac1d130fd4 663 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 664 IPH_LEN_SET(iphdr, htons(p->tot_len));
mbed_official 0:51ac1d130fd4 665 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 666 chk_sum += iphdr->_len;
mbed_official 0:51ac1d130fd4 667 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 668 IPH_OFFSET_SET(iphdr, 0);
mbed_official 0:51ac1d130fd4 669 IPH_ID_SET(iphdr, htons(ip_id));
mbed_official 0:51ac1d130fd4 670 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 671 chk_sum += iphdr->_id;
mbed_official 0:51ac1d130fd4 672 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 673 ++ip_id;
mbed_official 0:51ac1d130fd4 674
mbed_official 0:51ac1d130fd4 675 if (ip_addr_isany(src)) {
mbed_official 0:51ac1d130fd4 676 ip_addr_copy(iphdr->src, netif->ip_addr);
mbed_official 0:51ac1d130fd4 677 } else {
mbed_official 0:51ac1d130fd4 678 /* src cannot be NULL here */
mbed_official 0:51ac1d130fd4 679 ip_addr_copy(iphdr->src, *src);
mbed_official 0:51ac1d130fd4 680 }
mbed_official 0:51ac1d130fd4 681
mbed_official 0:51ac1d130fd4 682 #if CHECKSUM_GEN_IP_INLINE
mbed_official 0:51ac1d130fd4 683 chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
mbed_official 0:51ac1d130fd4 684 chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
mbed_official 0:51ac1d130fd4 685 chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
mbed_official 0:51ac1d130fd4 686 chk_sum = (chk_sum >> 16) + chk_sum;
mbed_official 0:51ac1d130fd4 687 chk_sum = ~chk_sum;
mbed_official 0:51ac1d130fd4 688 iphdr->_chksum = chk_sum; /* network order */
mbed_official 0:51ac1d130fd4 689 #else /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 690 IPH_CHKSUM_SET(iphdr, 0);
mbed_official 0:51ac1d130fd4 691 #if CHECKSUM_GEN_IP
mbed_official 0:51ac1d130fd4 692 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
mbed_official 0:51ac1d130fd4 693 #endif
mbed_official 0:51ac1d130fd4 694 #endif /* CHECKSUM_GEN_IP_INLINE */
mbed_official 0:51ac1d130fd4 695 } else {
mbed_official 0:51ac1d130fd4 696 /* IP header already included in p */
mbed_official 0:51ac1d130fd4 697 iphdr = (struct ip_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 698 ip_addr_copy(dest_addr, iphdr->dest);
mbed_official 0:51ac1d130fd4 699 dest = &dest_addr;
mbed_official 0:51ac1d130fd4 700 }
mbed_official 0:51ac1d130fd4 701
mbed_official 0:51ac1d130fd4 702 IP_STATS_INC(ip.xmit);
mbed_official 0:51ac1d130fd4 703
mbed_official 0:51ac1d130fd4 704 LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
mbed_official 0:51ac1d130fd4 705 ip_debug_print(p);
mbed_official 0:51ac1d130fd4 706
mbed_official 0:51ac1d130fd4 707 #if ENABLE_LOOPBACK
mbed_official 0:51ac1d130fd4 708 if (ip_addr_cmp(dest, &netif->ip_addr)) {
mbed_official 0:51ac1d130fd4 709 /* Packet to self, enqueue it for loopback */
mbed_official 0:51ac1d130fd4 710 LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
mbed_official 0:51ac1d130fd4 711 return netif_loop_output(netif, p, dest);
mbed_official 0:51ac1d130fd4 712 }
mbed_official 0:51ac1d130fd4 713 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 714 if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
mbed_official 0:51ac1d130fd4 715 netif_loop_output(netif, p, dest);
mbed_official 0:51ac1d130fd4 716 }
mbed_official 0:51ac1d130fd4 717 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 718 #endif /* ENABLE_LOOPBACK */
mbed_official 0:51ac1d130fd4 719 #if IP_FRAG
mbed_official 0:51ac1d130fd4 720 /* don't fragment if interface has mtu set to 0 [loopif] */
mbed_official 0:51ac1d130fd4 721 if (netif->mtu && (p->tot_len > netif->mtu)) {
mbed_official 0:51ac1d130fd4 722 return ip_frag(p, netif, dest);
mbed_official 0:51ac1d130fd4 723 }
mbed_official 0:51ac1d130fd4 724 #endif /* IP_FRAG */
mbed_official 0:51ac1d130fd4 725
mbed_official 0:51ac1d130fd4 726 LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
mbed_official 0:51ac1d130fd4 727 return netif->output(netif, p, dest);
mbed_official 0:51ac1d130fd4 728 }
mbed_official 0:51ac1d130fd4 729
mbed_official 0:51ac1d130fd4 730 /**
mbed_official 0:51ac1d130fd4 731 * Simple interface to ip_output_if. It finds the outgoing network
mbed_official 0:51ac1d130fd4 732 * interface and calls upon ip_output_if to do the actual work.
mbed_official 0:51ac1d130fd4 733 *
mbed_official 0:51ac1d130fd4 734 * @param p the packet to send (p->payload points to the data, e.g. next
mbed_official 0:51ac1d130fd4 735 protocol header; if dest == IP_HDRINCL, p already includes an IP
mbed_official 0:51ac1d130fd4 736 header and p->payload points to that IP header)
mbed_official 0:51ac1d130fd4 737 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
mbed_official 0:51ac1d130fd4 738 * IP address of the netif used to send is used as source address)
mbed_official 0:51ac1d130fd4 739 * @param dest the destination IP address to send the packet to
mbed_official 0:51ac1d130fd4 740 * @param ttl the TTL value to be set in the IP header
mbed_official 0:51ac1d130fd4 741 * @param tos the TOS value to be set in the IP header
mbed_official 0:51ac1d130fd4 742 * @param proto the PROTOCOL to be set in the IP header
mbed_official 0:51ac1d130fd4 743 *
mbed_official 0:51ac1d130fd4 744 * @return ERR_RTE if no route is found
mbed_official 0:51ac1d130fd4 745 * see ip_output_if() for more return values
mbed_official 0:51ac1d130fd4 746 */
mbed_official 0:51ac1d130fd4 747 err_t
mbed_official 0:51ac1d130fd4 748 ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
mbed_official 0:51ac1d130fd4 749 u8_t ttl, u8_t tos, u8_t proto)
mbed_official 0:51ac1d130fd4 750 {
mbed_official 0:51ac1d130fd4 751 struct netif *netif;
mbed_official 0:51ac1d130fd4 752
mbed_official 0:51ac1d130fd4 753 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
mbed_official 0:51ac1d130fd4 754 gets altered as the packet is passed down the stack */
mbed_official 0:51ac1d130fd4 755 LWIP_ASSERT("p->ref == 1", p->ref == 1);
mbed_official 0:51ac1d130fd4 756
mbed_official 0:51ac1d130fd4 757 if ((netif = ip_route(dest)) == NULL) {
mbed_official 0:51ac1d130fd4 758 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
mbed_official 0:51ac1d130fd4 759 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
mbed_official 0:51ac1d130fd4 760 IP_STATS_INC(ip.rterr);
mbed_official 0:51ac1d130fd4 761 return ERR_RTE;
mbed_official 0:51ac1d130fd4 762 }
mbed_official 0:51ac1d130fd4 763
mbed_official 0:51ac1d130fd4 764 return ip_output_if(p, src, dest, ttl, tos, proto, netif);
mbed_official 0:51ac1d130fd4 765 }
mbed_official 0:51ac1d130fd4 766
mbed_official 0:51ac1d130fd4 767 #if LWIP_NETIF_HWADDRHINT
mbed_official 0:51ac1d130fd4 768 /** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
mbed_official 0:51ac1d130fd4 769 * before calling ip_output_if.
mbed_official 0:51ac1d130fd4 770 *
mbed_official 0:51ac1d130fd4 771 * @param p the packet to send (p->payload points to the data, e.g. next
mbed_official 0:51ac1d130fd4 772 protocol header; if dest == IP_HDRINCL, p already includes an IP
mbed_official 0:51ac1d130fd4 773 header and p->payload points to that IP header)
mbed_official 0:51ac1d130fd4 774 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
mbed_official 0:51ac1d130fd4 775 * IP address of the netif used to send is used as source address)
mbed_official 0:51ac1d130fd4 776 * @param dest the destination IP address to send the packet to
mbed_official 0:51ac1d130fd4 777 * @param ttl the TTL value to be set in the IP header
mbed_official 0:51ac1d130fd4 778 * @param tos the TOS value to be set in the IP header
mbed_official 0:51ac1d130fd4 779 * @param proto the PROTOCOL to be set in the IP header
mbed_official 0:51ac1d130fd4 780 * @param addr_hint address hint pointer set to netif->addr_hint before
mbed_official 0:51ac1d130fd4 781 * calling ip_output_if()
mbed_official 0:51ac1d130fd4 782 *
mbed_official 0:51ac1d130fd4 783 * @return ERR_RTE if no route is found
mbed_official 0:51ac1d130fd4 784 * see ip_output_if() for more return values
mbed_official 0:51ac1d130fd4 785 */
mbed_official 0:51ac1d130fd4 786 err_t
mbed_official 0:51ac1d130fd4 787 ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
mbed_official 0:51ac1d130fd4 788 u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
mbed_official 0:51ac1d130fd4 789 {
mbed_official 0:51ac1d130fd4 790 struct netif *netif;
mbed_official 0:51ac1d130fd4 791 err_t err;
mbed_official 0:51ac1d130fd4 792
mbed_official 0:51ac1d130fd4 793 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
mbed_official 0:51ac1d130fd4 794 gets altered as the packet is passed down the stack */
mbed_official 0:51ac1d130fd4 795 LWIP_ASSERT("p->ref == 1", p->ref == 1);
mbed_official 0:51ac1d130fd4 796
mbed_official 0:51ac1d130fd4 797 if ((netif = ip_route(dest)) == NULL) {
mbed_official 0:51ac1d130fd4 798 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
mbed_official 0:51ac1d130fd4 799 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
mbed_official 0:51ac1d130fd4 800 IP_STATS_INC(ip.rterr);
mbed_official 0:51ac1d130fd4 801 return ERR_RTE;
mbed_official 0:51ac1d130fd4 802 }
mbed_official 0:51ac1d130fd4 803
mbed_official 0:51ac1d130fd4 804 netif->addr_hint = addr_hint;
mbed_official 0:51ac1d130fd4 805 err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
mbed_official 0:51ac1d130fd4 806 netif->addr_hint = NULL;
mbed_official 0:51ac1d130fd4 807
mbed_official 0:51ac1d130fd4 808 return err;
mbed_official 0:51ac1d130fd4 809 }
mbed_official 0:51ac1d130fd4 810 #endif /* LWIP_NETIF_HWADDRHINT*/
mbed_official 0:51ac1d130fd4 811
mbed_official 0:51ac1d130fd4 812 #if IP_DEBUG
mbed_official 0:51ac1d130fd4 813 /* Print an IP header by using LWIP_DEBUGF
mbed_official 0:51ac1d130fd4 814 * @param p an IP packet, p->payload pointing to the IP header
mbed_official 0:51ac1d130fd4 815 */
mbed_official 0:51ac1d130fd4 816 void
mbed_official 0:51ac1d130fd4 817 ip_debug_print(struct pbuf *p)
mbed_official 0:51ac1d130fd4 818 {
mbed_official 0:51ac1d130fd4 819 struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 820 u8_t *payload;
mbed_official 0:51ac1d130fd4 821
mbed_official 0:51ac1d130fd4 822 payload = (u8_t *)iphdr + IP_HLEN;
mbed_official 0:51ac1d130fd4 823
mbed_official 0:51ac1d130fd4 824 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
mbed_official 0:51ac1d130fd4 825 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 826 LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
mbed_official 0:51ac1d130fd4 827 IPH_V(iphdr),
mbed_official 0:51ac1d130fd4 828 IPH_HL(iphdr),
mbed_official 0:51ac1d130fd4 829 IPH_TOS(iphdr),
mbed_official 0:51ac1d130fd4 830 ntohs(IPH_LEN(iphdr))));
mbed_official 0:51ac1d130fd4 831 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 832 LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
mbed_official 0:51ac1d130fd4 833 ntohs(IPH_ID(iphdr)),
mbed_official 0:51ac1d130fd4 834 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
mbed_official 0:51ac1d130fd4 835 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
mbed_official 0:51ac1d130fd4 836 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
mbed_official 0:51ac1d130fd4 837 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
mbed_official 0:51ac1d130fd4 838 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 839 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
mbed_official 0:51ac1d130fd4 840 IPH_TTL(iphdr),
mbed_official 0:51ac1d130fd4 841 IPH_PROTO(iphdr),
mbed_official 0:51ac1d130fd4 842 ntohs(IPH_CHKSUM(iphdr))));
mbed_official 0:51ac1d130fd4 843 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 844 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
mbed_official 0:51ac1d130fd4 845 ip4_addr1_16(&iphdr->src),
mbed_official 0:51ac1d130fd4 846 ip4_addr2_16(&iphdr->src),
mbed_official 0:51ac1d130fd4 847 ip4_addr3_16(&iphdr->src),
mbed_official 0:51ac1d130fd4 848 ip4_addr4_16(&iphdr->src)));
mbed_official 0:51ac1d130fd4 849 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 850 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
mbed_official 0:51ac1d130fd4 851 ip4_addr1_16(&iphdr->dest),
mbed_official 0:51ac1d130fd4 852 ip4_addr2_16(&iphdr->dest),
mbed_official 0:51ac1d130fd4 853 ip4_addr3_16(&iphdr->dest),
mbed_official 0:51ac1d130fd4 854 ip4_addr4_16(&iphdr->dest)));
mbed_official 0:51ac1d130fd4 855 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
mbed_official 0:51ac1d130fd4 856 }
mbed_official 0:51ac1d130fd4 857 #endif /* IP_DEBUG */