mbed unsupported / lwip

Dependents:   AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more

Committer:
root@mbed.org
Date:
Tue May 08 15:32:10 2012 +0100
Revision:
0:5e1631496985
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
root@mbed.org 0:5e1631496985 1 /**
root@mbed.org 0:5e1631496985 2 * @file
root@mbed.org 0:5e1631496985 3 * This is the IPv4 layer implementation for incoming and outgoing IP traffic.
root@mbed.org 0:5e1631496985 4 *
root@mbed.org 0:5e1631496985 5 * @see ip_frag.c
root@mbed.org 0:5e1631496985 6 *
root@mbed.org 0:5e1631496985 7 */
root@mbed.org 0:5e1631496985 8
root@mbed.org 0:5e1631496985 9 /*
root@mbed.org 0:5e1631496985 10 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
root@mbed.org 0:5e1631496985 11 * All rights reserved.
root@mbed.org 0:5e1631496985 12 *
root@mbed.org 0:5e1631496985 13 * Redistribution and use in source and binary forms, with or without modification,
root@mbed.org 0:5e1631496985 14 * are permitted provided that the following conditions are met:
root@mbed.org 0:5e1631496985 15 *
root@mbed.org 0:5e1631496985 16 * 1. Redistributions of source code must retain the above copyright notice,
root@mbed.org 0:5e1631496985 17 * this list of conditions and the following disclaimer.
root@mbed.org 0:5e1631496985 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
root@mbed.org 0:5e1631496985 19 * this list of conditions and the following disclaimer in the documentation
root@mbed.org 0:5e1631496985 20 * and/or other materials provided with the distribution.
root@mbed.org 0:5e1631496985 21 * 3. The name of the author may not be used to endorse or promote products
root@mbed.org 0:5e1631496985 22 * derived from this software without specific prior written permission.
root@mbed.org 0:5e1631496985 23 *
root@mbed.org 0:5e1631496985 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
root@mbed.org 0:5e1631496985 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
root@mbed.org 0:5e1631496985 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
root@mbed.org 0:5e1631496985 27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
root@mbed.org 0:5e1631496985 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
root@mbed.org 0:5e1631496985 29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
root@mbed.org 0:5e1631496985 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
root@mbed.org 0:5e1631496985 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
root@mbed.org 0:5e1631496985 32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
root@mbed.org 0:5e1631496985 33 * OF SUCH DAMAGE.
root@mbed.org 0:5e1631496985 34 *
root@mbed.org 0:5e1631496985 35 * This file is part of the lwIP TCP/IP stack.
root@mbed.org 0:5e1631496985 36 *
root@mbed.org 0:5e1631496985 37 * Author: Adam Dunkels <adam@sics.se>
root@mbed.org 0:5e1631496985 38 *
root@mbed.org 0:5e1631496985 39 */
root@mbed.org 0:5e1631496985 40
root@mbed.org 0:5e1631496985 41 #include "lwip/opt.h"
root@mbed.org 0:5e1631496985 42 #include "lwip/ip.h"
root@mbed.org 0:5e1631496985 43 #include "lwip/def.h"
root@mbed.org 0:5e1631496985 44 #include "lwip/mem.h"
root@mbed.org 0:5e1631496985 45 #include "lwip/ip_frag.h"
root@mbed.org 0:5e1631496985 46 #include "lwip/inet.h"
root@mbed.org 0:5e1631496985 47 #include "lwip/inet_chksum.h"
root@mbed.org 0:5e1631496985 48 #include "lwip/netif.h"
root@mbed.org 0:5e1631496985 49 #include "lwip/icmp.h"
root@mbed.org 0:5e1631496985 50 #include "lwip/igmp.h"
root@mbed.org 0:5e1631496985 51 #include "lwip/raw.h"
root@mbed.org 0:5e1631496985 52 #include "lwip/udp.h"
root@mbed.org 0:5e1631496985 53 #include "lwip/tcp.h"
root@mbed.org 0:5e1631496985 54 #include "lwip/snmp.h"
root@mbed.org 0:5e1631496985 55 #include "lwip/dhcp.h"
root@mbed.org 0:5e1631496985 56 #include "lwip/stats.h"
root@mbed.org 0:5e1631496985 57 #include "arch/perf.h"
root@mbed.org 0:5e1631496985 58
root@mbed.org 0:5e1631496985 59 /**
root@mbed.org 0:5e1631496985 60 * Finds the appropriate network interface for a given IP address. It
root@mbed.org 0:5e1631496985 61 * searches the list of network interfaces linearly. A match is found
root@mbed.org 0:5e1631496985 62 * if the masked IP address of the network interface equals the masked
root@mbed.org 0:5e1631496985 63 * IP address given to the function.
root@mbed.org 0:5e1631496985 64 *
root@mbed.org 0:5e1631496985 65 * @param dest the destination IP address for which to find the route
root@mbed.org 0:5e1631496985 66 * @return the netif on which to send to reach dest
root@mbed.org 0:5e1631496985 67 */
root@mbed.org 0:5e1631496985 68 struct netif *
root@mbed.org 0:5e1631496985 69 ip_route(struct ip_addr *dest)
root@mbed.org 0:5e1631496985 70 {
root@mbed.org 0:5e1631496985 71 struct netif *netif;
root@mbed.org 0:5e1631496985 72
root@mbed.org 0:5e1631496985 73 /* iterate through netifs */
root@mbed.org 0:5e1631496985 74 for(netif = netif_list; netif != NULL; netif = netif->next) {
root@mbed.org 0:5e1631496985 75 /* network mask matches? */
root@mbed.org 0:5e1631496985 76 if (netif_is_up(netif)) {
root@mbed.org 0:5e1631496985 77 if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
root@mbed.org 0:5e1631496985 78 /* return netif on which to forward IP packet */
root@mbed.org 0:5e1631496985 79 return netif;
root@mbed.org 0:5e1631496985 80 }
root@mbed.org 0:5e1631496985 81 }
root@mbed.org 0:5e1631496985 82 }
root@mbed.org 0:5e1631496985 83 if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
root@mbed.org 0:5e1631496985 84 LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
root@mbed.org 0:5e1631496985 85 IP_STATS_INC(ip.rterr);
root@mbed.org 0:5e1631496985 86 snmp_inc_ipoutnoroutes();
root@mbed.org 0:5e1631496985 87 return (struct netif *)(NULL); // static_cast<struct netif *>(x)
root@mbed.org 0:5e1631496985 88 }
root@mbed.org 0:5e1631496985 89 /* no matching netif found, use default netif */
root@mbed.org 0:5e1631496985 90 return netif_default;
root@mbed.org 0:5e1631496985 91 }
root@mbed.org 0:5e1631496985 92
root@mbed.org 0:5e1631496985 93 #if IP_FORWARD
root@mbed.org 0:5e1631496985 94 /**
root@mbed.org 0:5e1631496985 95 * Forwards an IP packet. It finds an appropriate route for the
root@mbed.org 0:5e1631496985 96 * packet, decrements the TTL value of the packet, adjusts the
root@mbed.org 0:5e1631496985 97 * checksum and outputs the packet on the appropriate interface.
root@mbed.org 0:5e1631496985 98 *
root@mbed.org 0:5e1631496985 99 * @param p the packet to forward (p->payload points to IP header)
root@mbed.org 0:5e1631496985 100 * @param iphdr the IP header of the input packet
root@mbed.org 0:5e1631496985 101 * @param inp the netif on which this packet was received
root@mbed.org 0:5e1631496985 102 * @return the netif on which the packet was sent (NULL if it wasn't sent)
root@mbed.org 0:5e1631496985 103 */
root@mbed.org 0:5e1631496985 104 static struct netif *
root@mbed.org 0:5e1631496985 105 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
root@mbed.org 0:5e1631496985 106 {
root@mbed.org 0:5e1631496985 107 struct netif *netif;
root@mbed.org 0:5e1631496985 108
root@mbed.org 0:5e1631496985 109 PERF_START;
root@mbed.org 0:5e1631496985 110 /* Find network interface where to forward this IP packet to. */
root@mbed.org 0:5e1631496985 111 netif = ip_route((struct ip_addr *)&(iphdr->dest));
root@mbed.org 0:5e1631496985 112 if (netif == NULL) {
root@mbed.org 0:5e1631496985 113 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
root@mbed.org 0:5e1631496985 114 iphdr->dest.addr));
root@mbed.org 0:5e1631496985 115 snmp_inc_ipoutnoroutes();
root@mbed.org 0:5e1631496985 116 return (struct netif *)NULL;
root@mbed.org 0:5e1631496985 117 }
root@mbed.org 0:5e1631496985 118 /* Do not forward packets onto the same network interface on which
root@mbed.org 0:5e1631496985 119 * they arrived. */
root@mbed.org 0:5e1631496985 120 if (netif == inp) {
root@mbed.org 0:5e1631496985 121 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
root@mbed.org 0:5e1631496985 122 snmp_inc_ipoutnoroutes();
root@mbed.org 0:5e1631496985 123 return (struct netif *)NULL;
root@mbed.org 0:5e1631496985 124 }
root@mbed.org 0:5e1631496985 125
root@mbed.org 0:5e1631496985 126 /* decrement TTL */
root@mbed.org 0:5e1631496985 127 IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
root@mbed.org 0:5e1631496985 128 /* send ICMP if TTL == 0 */
root@mbed.org 0:5e1631496985 129 if (IPH_TTL(iphdr) == 0) {
root@mbed.org 0:5e1631496985 130 snmp_inc_ipinhdrerrors();
root@mbed.org 0:5e1631496985 131 #if LWIP_ICMP
root@mbed.org 0:5e1631496985 132 /* Don't send ICMP messages in response to ICMP messages */
root@mbed.org 0:5e1631496985 133 if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
root@mbed.org 0:5e1631496985 134 icmp_time_exceeded(p, ICMP_TE_TTL);
root@mbed.org 0:5e1631496985 135 }
root@mbed.org 0:5e1631496985 136 #endif /* LWIP_ICMP */
root@mbed.org 0:5e1631496985 137 return (struct netif *)NULL;
root@mbed.org 0:5e1631496985 138 }
root@mbed.org 0:5e1631496985 139
root@mbed.org 0:5e1631496985 140 /* Incrementally update the IP checksum. */
root@mbed.org 0:5e1631496985 141 if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
root@mbed.org 0:5e1631496985 142 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
root@mbed.org 0:5e1631496985 143 } else {
root@mbed.org 0:5e1631496985 144 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
root@mbed.org 0:5e1631496985 145 }
root@mbed.org 0:5e1631496985 146
root@mbed.org 0:5e1631496985 147 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
root@mbed.org 0:5e1631496985 148 iphdr->dest.addr));
root@mbed.org 0:5e1631496985 149
root@mbed.org 0:5e1631496985 150 IP_STATS_INC(ip.fw);
root@mbed.org 0:5e1631496985 151 IP_STATS_INC(ip.xmit);
root@mbed.org 0:5e1631496985 152 snmp_inc_ipforwdatagrams();
root@mbed.org 0:5e1631496985 153
root@mbed.org 0:5e1631496985 154 PERF_STOP("ip_forward");
root@mbed.org 0:5e1631496985 155 /* transmit pbuf on chosen interface */
root@mbed.org 0:5e1631496985 156 netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
root@mbed.org 0:5e1631496985 157 return netif;
root@mbed.org 0:5e1631496985 158 }
root@mbed.org 0:5e1631496985 159 #endif /* IP_FORWARD */
root@mbed.org 0:5e1631496985 160
root@mbed.org 0:5e1631496985 161 /**
root@mbed.org 0:5e1631496985 162 * This function is called by the network interface device driver when
root@mbed.org 0:5e1631496985 163 * an IP packet is received. The function does the basic checks of the
root@mbed.org 0:5e1631496985 164 * IP header such as packet size being at least larger than the header
root@mbed.org 0:5e1631496985 165 * size etc. If the packet was not destined for us, the packet is
root@mbed.org 0:5e1631496985 166 * forwarded (using ip_forward). The IP checksum is always checked.
root@mbed.org 0:5e1631496985 167 *
root@mbed.org 0:5e1631496985 168 * Finally, the packet is sent to the upper layer protocol input function.
root@mbed.org 0:5e1631496985 169 *
root@mbed.org 0:5e1631496985 170 * @param p the received IP packet (p->payload points to IP header)
root@mbed.org 0:5e1631496985 171 * @param inp the netif on which this packet was received
root@mbed.org 0:5e1631496985 172 * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
root@mbed.org 0:5e1631496985 173 * processed, but currently always returns ERR_OK)
root@mbed.org 0:5e1631496985 174 */
root@mbed.org 0:5e1631496985 175 err_t
root@mbed.org 0:5e1631496985 176 ip_input(struct pbuf *p, struct netif *inp)
root@mbed.org 0:5e1631496985 177 {
root@mbed.org 0:5e1631496985 178 struct ip_hdr *iphdr;
root@mbed.org 0:5e1631496985 179 struct netif *netif;
root@mbed.org 0:5e1631496985 180 u16_t iphdr_hlen;
root@mbed.org 0:5e1631496985 181 u16_t iphdr_len;
root@mbed.org 0:5e1631496985 182 #if LWIP_DHCP
root@mbed.org 0:5e1631496985 183 int check_ip_src=1;
root@mbed.org 0:5e1631496985 184 #endif /* LWIP_DHCP */
root@mbed.org 0:5e1631496985 185
root@mbed.org 0:5e1631496985 186 IP_STATS_INC(ip.recv);
root@mbed.org 0:5e1631496985 187 snmp_inc_ipinreceives();
root@mbed.org 0:5e1631496985 188
root@mbed.org 0:5e1631496985 189 /* identify the IP header */
root@mbed.org 0:5e1631496985 190 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x)
root@mbed.org 0:5e1631496985 191 if (IPH_V(iphdr) != 4) {
root@mbed.org 0:5e1631496985 192 LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
root@mbed.org 0:5e1631496985 193 ip_debug_print(p);
root@mbed.org 0:5e1631496985 194 pbuf_free(p);
root@mbed.org 0:5e1631496985 195 IP_STATS_INC(ip.err);
root@mbed.org 0:5e1631496985 196 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 197 snmp_inc_ipinhdrerrors();
root@mbed.org 0:5e1631496985 198 return ERR_OK;
root@mbed.org 0:5e1631496985 199 }
root@mbed.org 0:5e1631496985 200
root@mbed.org 0:5e1631496985 201 /* obtain IP header length in number of 32-bit words */
root@mbed.org 0:5e1631496985 202 iphdr_hlen = IPH_HL(iphdr);
root@mbed.org 0:5e1631496985 203 /* calculate IP header length in bytes */
root@mbed.org 0:5e1631496985 204 iphdr_hlen *= 4;
root@mbed.org 0:5e1631496985 205 /* obtain ip length in bytes */
root@mbed.org 0:5e1631496985 206 iphdr_len = ntohs(IPH_LEN(iphdr));
root@mbed.org 0:5e1631496985 207
root@mbed.org 0:5e1631496985 208 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
root@mbed.org 0:5e1631496985 209 if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
root@mbed.org 0:5e1631496985 210 if (iphdr_hlen > p->len)
root@mbed.org 0:5e1631496985 211 LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
root@mbed.org 0:5e1631496985 212 iphdr_hlen, p->len));
root@mbed.org 0:5e1631496985 213 if (iphdr_len > p->tot_len)
root@mbed.org 0:5e1631496985 214 LWIP_DEBUGF(IP_DEBUG | 2, ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), "
root@mbed.org 0:5e1631496985 215 "IP packet dropped.\n",
root@mbed.org 0:5e1631496985 216 iphdr_len, p->tot_len));
root@mbed.org 0:5e1631496985 217 /* free (drop) packet pbufs */
root@mbed.org 0:5e1631496985 218 pbuf_free(p);
root@mbed.org 0:5e1631496985 219 IP_STATS_INC(ip.lenerr);
root@mbed.org 0:5e1631496985 220 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 221 snmp_inc_ipindiscards();
root@mbed.org 0:5e1631496985 222 return ERR_OK;
root@mbed.org 0:5e1631496985 223 }
root@mbed.org 0:5e1631496985 224
root@mbed.org 0:5e1631496985 225 /* verify checksum */
root@mbed.org 0:5e1631496985 226 #if CHECKSUM_CHECK_IP
root@mbed.org 0:5e1631496985 227 if (inet_chksum(iphdr, iphdr_hlen) != 0) {
root@mbed.org 0:5e1631496985 228
root@mbed.org 0:5e1631496985 229 LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
root@mbed.org 0:5e1631496985 230 ip_debug_print(p);
root@mbed.org 0:5e1631496985 231 pbuf_free(p);
root@mbed.org 0:5e1631496985 232 IP_STATS_INC(ip.chkerr);
root@mbed.org 0:5e1631496985 233 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 234 snmp_inc_ipinhdrerrors();
root@mbed.org 0:5e1631496985 235 return ERR_OK;
root@mbed.org 0:5e1631496985 236 }
root@mbed.org 0:5e1631496985 237 #endif
root@mbed.org 0:5e1631496985 238
root@mbed.org 0:5e1631496985 239 /* Trim pbuf. This should have been done at the netif layer,
root@mbed.org 0:5e1631496985 240 * but we'll do it anyway just to be sure that its done. */
root@mbed.org 0:5e1631496985 241 pbuf_realloc(p, iphdr_len);
root@mbed.org 0:5e1631496985 242
root@mbed.org 0:5e1631496985 243 /* match packet against an interface, i.e. is this packet for us? */
root@mbed.org 0:5e1631496985 244 #if LWIP_IGMP
root@mbed.org 0:5e1631496985 245 if (ip_addr_ismulticast(&(iphdr->dest))) {
root@mbed.org 0:5e1631496985 246 if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) {
root@mbed.org 0:5e1631496985 247 netif = inp;
root@mbed.org 0:5e1631496985 248 } else {
root@mbed.org 0:5e1631496985 249 netif = NULL;
root@mbed.org 0:5e1631496985 250 }
root@mbed.org 0:5e1631496985 251 } else
root@mbed.org 0:5e1631496985 252 #endif /* LWIP_IGMP */
root@mbed.org 0:5e1631496985 253 {
root@mbed.org 0:5e1631496985 254 /* start trying with inp. if that's not acceptable, start walking the
root@mbed.org 0:5e1631496985 255 list of configured netifs.
root@mbed.org 0:5e1631496985 256 'first' is used as a boolean to mark whether we started walking the list */
root@mbed.org 0:5e1631496985 257 int first = 1;
root@mbed.org 0:5e1631496985 258 netif = inp;
root@mbed.org 0:5e1631496985 259 do {
root@mbed.org 0:5e1631496985 260 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",
root@mbed.org 0:5e1631496985 261 iphdr->dest.addr, netif->ip_addr.addr,
root@mbed.org 0:5e1631496985 262 iphdr->dest.addr & netif->netmask.addr,
root@mbed.org 0:5e1631496985 263 netif->ip_addr.addr & netif->netmask.addr,
root@mbed.org 0:5e1631496985 264 iphdr->dest.addr & ~(netif->netmask.addr)));
root@mbed.org 0:5e1631496985 265
root@mbed.org 0:5e1631496985 266 /* interface is up and configured? */
root@mbed.org 0:5e1631496985 267 if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
root@mbed.org 0:5e1631496985 268 /* unicast to this interface address? */
root@mbed.org 0:5e1631496985 269 if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
root@mbed.org 0:5e1631496985 270 /* or broadcast on this interface network address? */
root@mbed.org 0:5e1631496985 271 ip_addr_isbroadcast(&(iphdr->dest), netif)) {
root@mbed.org 0:5e1631496985 272 LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
root@mbed.org 0:5e1631496985 273 netif->name[0], netif->name[1]));
root@mbed.org 0:5e1631496985 274 /* break out of for loop */
root@mbed.org 0:5e1631496985 275 break;
root@mbed.org 0:5e1631496985 276 }
root@mbed.org 0:5e1631496985 277 }
root@mbed.org 0:5e1631496985 278 if (first) {
root@mbed.org 0:5e1631496985 279 first = 0;
root@mbed.org 0:5e1631496985 280 netif = netif_list;
root@mbed.org 0:5e1631496985 281 } else {
root@mbed.org 0:5e1631496985 282 netif = netif->next;
root@mbed.org 0:5e1631496985 283 }
root@mbed.org 0:5e1631496985 284 if (netif == inp) {
root@mbed.org 0:5e1631496985 285 netif = netif->next;
root@mbed.org 0:5e1631496985 286 }
root@mbed.org 0:5e1631496985 287 } while(netif != NULL);
root@mbed.org 0:5e1631496985 288 }
root@mbed.org 0:5e1631496985 289
root@mbed.org 0:5e1631496985 290 #if LWIP_DHCP
root@mbed.org 0:5e1631496985 291 /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
root@mbed.org 0:5e1631496985 292 * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
root@mbed.org 0:5e1631496985 293 * According to RFC 1542 section 3.1.1, referred by RFC 2131).
root@mbed.org 0:5e1631496985 294 */
root@mbed.org 0:5e1631496985 295 if (netif == NULL) {
root@mbed.org 0:5e1631496985 296 /* remote port is DHCP server? */
root@mbed.org 0:5e1631496985 297 if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
root@mbed.org 0:5e1631496985 298 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
root@mbed.org 0:5e1631496985 299 ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
root@mbed.org 0:5e1631496985 300 if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
root@mbed.org 0:5e1631496985 301 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
root@mbed.org 0:5e1631496985 302 netif = inp;
root@mbed.org 0:5e1631496985 303 check_ip_src = 0;
root@mbed.org 0:5e1631496985 304 }
root@mbed.org 0:5e1631496985 305 }
root@mbed.org 0:5e1631496985 306 }
root@mbed.org 0:5e1631496985 307 #endif /* LWIP_DHCP */
root@mbed.org 0:5e1631496985 308
root@mbed.org 0:5e1631496985 309 /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
root@mbed.org 0:5e1631496985 310 #if LWIP_DHCP
root@mbed.org 0:5e1631496985 311 if (check_ip_src)
root@mbed.org 0:5e1631496985 312 #endif /* LWIP_DHCP */
root@mbed.org 0:5e1631496985 313 { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
root@mbed.org 0:5e1631496985 314 (ip_addr_ismulticast(&(iphdr->src)))) {
root@mbed.org 0:5e1631496985 315 /* packet source is not valid */
root@mbed.org 0:5e1631496985 316 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet source is not valid.\n"));
root@mbed.org 0:5e1631496985 317 /* free (drop) packet pbufs */
root@mbed.org 0:5e1631496985 318 pbuf_free(p);
root@mbed.org 0:5e1631496985 319 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 320 snmp_inc_ipinaddrerrors();
root@mbed.org 0:5e1631496985 321 snmp_inc_ipindiscards();
root@mbed.org 0:5e1631496985 322 return ERR_OK;
root@mbed.org 0:5e1631496985 323 }
root@mbed.org 0:5e1631496985 324 }
root@mbed.org 0:5e1631496985 325
root@mbed.org 0:5e1631496985 326 /* packet not for us? */
root@mbed.org 0:5e1631496985 327 if (netif == NULL) {
root@mbed.org 0:5e1631496985 328 /* packet not for us, route or discard */
root@mbed.org 0:5e1631496985 329 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
root@mbed.org 0:5e1631496985 330 #if IP_FORWARD
root@mbed.org 0:5e1631496985 331 /* non-broadcast packet? */
root@mbed.org 0:5e1631496985 332 if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
root@mbed.org 0:5e1631496985 333 /* try to forward IP packet on (other) interfaces */
root@mbed.org 0:5e1631496985 334 ip_forward(p, iphdr, inp);
root@mbed.org 0:5e1631496985 335 } else
root@mbed.org 0:5e1631496985 336 #endif /* IP_FORWARD */
root@mbed.org 0:5e1631496985 337 {
root@mbed.org 0:5e1631496985 338 snmp_inc_ipinaddrerrors();
root@mbed.org 0:5e1631496985 339 snmp_inc_ipindiscards();
root@mbed.org 0:5e1631496985 340 }
root@mbed.org 0:5e1631496985 341 pbuf_free(p);
root@mbed.org 0:5e1631496985 342 return ERR_OK;
root@mbed.org 0:5e1631496985 343 }
root@mbed.org 0:5e1631496985 344 /* packet consists of multiple fragments? */
root@mbed.org 0:5e1631496985 345 if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
root@mbed.org 0:5e1631496985 346 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
root@mbed.org 0:5e1631496985 347 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",
root@mbed.org 0:5e1631496985 348 ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
root@mbed.org 0:5e1631496985 349 /* reassemble the packet*/
root@mbed.org 0:5e1631496985 350 p = ip_reass(p);
root@mbed.org 0:5e1631496985 351 /* packet not fully reassembled yet? */
root@mbed.org 0:5e1631496985 352 if (p == NULL) {
root@mbed.org 0:5e1631496985 353 return ERR_OK;
root@mbed.org 0:5e1631496985 354 }
root@mbed.org 0:5e1631496985 355 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x)
root@mbed.org 0:5e1631496985 356 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
root@mbed.org 0:5e1631496985 357 pbuf_free(p);
root@mbed.org 0:5e1631496985 358 LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
root@mbed.org 0:5e1631496985 359 ntohs(IPH_OFFSET(iphdr))));
root@mbed.org 0:5e1631496985 360 IP_STATS_INC(ip.opterr);
root@mbed.org 0:5e1631496985 361 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 362 /* unsupported protocol feature */
root@mbed.org 0:5e1631496985 363 snmp_inc_ipinunknownprotos();
root@mbed.org 0:5e1631496985 364 return ERR_OK;
root@mbed.org 0:5e1631496985 365 #endif /* IP_REASSEMBLY */
root@mbed.org 0:5e1631496985 366 }
root@mbed.org 0:5e1631496985 367
root@mbed.org 0:5e1631496985 368 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
root@mbed.org 0:5e1631496985 369
root@mbed.org 0:5e1631496985 370 #if LWIP_IGMP
root@mbed.org 0:5e1631496985 371 /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
root@mbed.org 0:5e1631496985 372 if((iphdr_hlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
root@mbed.org 0:5e1631496985 373 #else
root@mbed.org 0:5e1631496985 374 if (iphdr_hlen > IP_HLEN) {
root@mbed.org 0:5e1631496985 375 #endif /* LWIP_IGMP */
root@mbed.org 0:5e1631496985 376 LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
root@mbed.org 0:5e1631496985 377 pbuf_free(p);
root@mbed.org 0:5e1631496985 378 IP_STATS_INC(ip.opterr);
root@mbed.org 0:5e1631496985 379 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 380 /* unsupported protocol feature */
root@mbed.org 0:5e1631496985 381 snmp_inc_ipinunknownprotos();
root@mbed.org 0:5e1631496985 382 return ERR_OK;
root@mbed.org 0:5e1631496985 383 }
root@mbed.org 0:5e1631496985 384 #endif /* IP_OPTIONS_ALLOWED == 0 */
root@mbed.org 0:5e1631496985 385
root@mbed.org 0:5e1631496985 386 /* send to upper layers */
root@mbed.org 0:5e1631496985 387 LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
root@mbed.org 0:5e1631496985 388 ip_debug_print(p);
root@mbed.org 0:5e1631496985 389 LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
root@mbed.org 0:5e1631496985 390
root@mbed.org 0:5e1631496985 391 #if LWIP_RAW
root@mbed.org 0:5e1631496985 392 /* raw input did not eat the packet? */
root@mbed.org 0:5e1631496985 393 if (raw_input(p, inp) == 0)
root@mbed.org 0:5e1631496985 394 #endif /* LWIP_RAW */
root@mbed.org 0:5e1631496985 395 {
root@mbed.org 0:5e1631496985 396
root@mbed.org 0:5e1631496985 397 switch (IPH_PROTO(iphdr)) {
root@mbed.org 0:5e1631496985 398 #if LWIP_UDP
root@mbed.org 0:5e1631496985 399 case IP_PROTO_UDP:
root@mbed.org 0:5e1631496985 400 #if LWIP_UDPLITE
root@mbed.org 0:5e1631496985 401 case IP_PROTO_UDPLITE:
root@mbed.org 0:5e1631496985 402 #endif /* LWIP_UDPLITE */
root@mbed.org 0:5e1631496985 403 snmp_inc_ipindelivers();
root@mbed.org 0:5e1631496985 404 udp_input(p, inp);
root@mbed.org 0:5e1631496985 405 break;
root@mbed.org 0:5e1631496985 406 #endif /* LWIP_UDP */
root@mbed.org 0:5e1631496985 407 #if LWIP_TCP
root@mbed.org 0:5e1631496985 408 case IP_PROTO_TCP:
root@mbed.org 0:5e1631496985 409 snmp_inc_ipindelivers();
root@mbed.org 0:5e1631496985 410 tcp_input(p, inp);
root@mbed.org 0:5e1631496985 411 break;
root@mbed.org 0:5e1631496985 412 #endif /* LWIP_TCP */
root@mbed.org 0:5e1631496985 413 #if LWIP_ICMP
root@mbed.org 0:5e1631496985 414 case IP_PROTO_ICMP:
root@mbed.org 0:5e1631496985 415 snmp_inc_ipindelivers();
root@mbed.org 0:5e1631496985 416 icmp_input(p, inp);
root@mbed.org 0:5e1631496985 417 break;
root@mbed.org 0:5e1631496985 418 #endif /* LWIP_ICMP */
root@mbed.org 0:5e1631496985 419 #if LWIP_IGMP
root@mbed.org 0:5e1631496985 420 case IP_PROTO_IGMP:
root@mbed.org 0:5e1631496985 421 igmp_input(p,inp,&(iphdr->dest));
root@mbed.org 0:5e1631496985 422 break;
root@mbed.org 0:5e1631496985 423 #endif /* LWIP_IGMP */
root@mbed.org 0:5e1631496985 424 default:
root@mbed.org 0:5e1631496985 425 #if LWIP_ICMP
root@mbed.org 0:5e1631496985 426 /* send ICMP destination protocol unreachable unless is was a broadcast */
root@mbed.org 0:5e1631496985 427 if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
root@mbed.org 0:5e1631496985 428 !ip_addr_ismulticast(&(iphdr->dest))) {
root@mbed.org 0:5e1631496985 429 p->payload = iphdr;
root@mbed.org 0:5e1631496985 430 icmp_dest_unreach(p, ICMP_DUR_PROTO);
root@mbed.org 0:5e1631496985 431 }
root@mbed.org 0:5e1631496985 432 #endif /* LWIP_ICMP */
root@mbed.org 0:5e1631496985 433 pbuf_free(p);
root@mbed.org 0:5e1631496985 434
root@mbed.org 0:5e1631496985 435 LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
root@mbed.org 0:5e1631496985 436
root@mbed.org 0:5e1631496985 437 IP_STATS_INC(ip.proterr);
root@mbed.org 0:5e1631496985 438 IP_STATS_INC(ip.drop);
root@mbed.org 0:5e1631496985 439 snmp_inc_ipinunknownprotos();
root@mbed.org 0:5e1631496985 440 }
root@mbed.org 0:5e1631496985 441 }
root@mbed.org 0:5e1631496985 442
root@mbed.org 0:5e1631496985 443 return ERR_OK;
root@mbed.org 0:5e1631496985 444 }
root@mbed.org 0:5e1631496985 445
root@mbed.org 0:5e1631496985 446 /**
root@mbed.org 0:5e1631496985 447 * Sends an IP packet on a network interface. This function constructs
root@mbed.org 0:5e1631496985 448 * the IP header and calculates the IP header checksum. If the source
root@mbed.org 0:5e1631496985 449 * IP address is NULL, the IP address of the outgoing network
root@mbed.org 0:5e1631496985 450 * interface is filled in as source address.
root@mbed.org 0:5e1631496985 451 * If the destination IP address is IP_HDRINCL, p is assumed to already
root@mbed.org 0:5e1631496985 452 * include an IP header and p->payload points to it instead of the data.
root@mbed.org 0:5e1631496985 453 *
root@mbed.org 0:5e1631496985 454 * @param p the packet to send (p->payload points to the data, e.g. next
root@mbed.org 0:5e1631496985 455 protocol header; if dest == IP_HDRINCL, p already includes an IP
root@mbed.org 0:5e1631496985 456 header and p->payload points to that IP header)
root@mbed.org 0:5e1631496985 457 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
root@mbed.org 0:5e1631496985 458 * IP address of the netif used to send is used as source address)
root@mbed.org 0:5e1631496985 459 * @param dest the destination IP address to send the packet to
root@mbed.org 0:5e1631496985 460 * @param ttl the TTL value to be set in the IP header
root@mbed.org 0:5e1631496985 461 * @param tos the TOS value to be set in the IP header
root@mbed.org 0:5e1631496985 462 * @param proto the PROTOCOL to be set in the IP header
root@mbed.org 0:5e1631496985 463 * @param netif the netif on which to send this packet
root@mbed.org 0:5e1631496985 464 * @return ERR_OK if the packet was sent OK
root@mbed.org 0:5e1631496985 465 * ERR_BUF if p doesn't have enough space for IP/LINK headers
root@mbed.org 0:5e1631496985 466 * returns errors returned by netif->output
root@mbed.org 0:5e1631496985 467 *
root@mbed.org 0:5e1631496985 468 * @note ip_id: RFC791 "some host may be able to simply use
root@mbed.org 0:5e1631496985 469 * unique identifiers independent of destination"
root@mbed.org 0:5e1631496985 470 */
root@mbed.org 0:5e1631496985 471 err_t
root@mbed.org 0:5e1631496985 472 ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
root@mbed.org 0:5e1631496985 473 u8_t ttl, u8_t tos,
root@mbed.org 0:5e1631496985 474 u8_t proto, struct netif *netif)
root@mbed.org 0:5e1631496985 475 {
root@mbed.org 0:5e1631496985 476 struct ip_hdr *iphdr;
root@mbed.org 0:5e1631496985 477 static u16_t ip_id = 0;
root@mbed.org 0:5e1631496985 478
root@mbed.org 0:5e1631496985 479 snmp_inc_ipoutrequests();
root@mbed.org 0:5e1631496985 480
root@mbed.org 0:5e1631496985 481 /* Should the IP header be generated or is it already included in p? */
root@mbed.org 0:5e1631496985 482 if (dest != IP_HDRINCL) {
root@mbed.org 0:5e1631496985 483 /* generate IP header */
root@mbed.org 0:5e1631496985 484 if (pbuf_header(p, IP_HLEN)) {
root@mbed.org 0:5e1631496985 485 LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
root@mbed.org 0:5e1631496985 486
root@mbed.org 0:5e1631496985 487 IP_STATS_INC(ip.err);
root@mbed.org 0:5e1631496985 488 snmp_inc_ipoutdiscards();
root@mbed.org 0:5e1631496985 489 return ERR_BUF;
root@mbed.org 0:5e1631496985 490 }
root@mbed.org 0:5e1631496985 491
root@mbed.org 0:5e1631496985 492 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x)
root@mbed.org 0:5e1631496985 493 LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
root@mbed.org 0:5e1631496985 494 (p->len >= sizeof(struct ip_hdr)));
root@mbed.org 0:5e1631496985 495
root@mbed.org 0:5e1631496985 496 IPH_TTL_SET(iphdr, ttl);
root@mbed.org 0:5e1631496985 497 IPH_PROTO_SET(iphdr, proto);
root@mbed.org 0:5e1631496985 498
root@mbed.org 0:5e1631496985 499 ip_addr_set(&(iphdr->dest), dest);
root@mbed.org 0:5e1631496985 500
root@mbed.org 0:5e1631496985 501 IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
root@mbed.org 0:5e1631496985 502 IPH_LEN_SET(iphdr, htons(p->tot_len));
root@mbed.org 0:5e1631496985 503 IPH_OFFSET_SET(iphdr, 0);
root@mbed.org 0:5e1631496985 504 IPH_ID_SET(iphdr, htons(ip_id));
root@mbed.org 0:5e1631496985 505 ++ip_id;
root@mbed.org 0:5e1631496985 506
root@mbed.org 0:5e1631496985 507 if (ip_addr_isany(src)) {
root@mbed.org 0:5e1631496985 508 ip_addr_set(&(iphdr->src), &(netif->ip_addr));
root@mbed.org 0:5e1631496985 509 } else {
root@mbed.org 0:5e1631496985 510 ip_addr_set(&(iphdr->src), src);
root@mbed.org 0:5e1631496985 511 }
root@mbed.org 0:5e1631496985 512
root@mbed.org 0:5e1631496985 513 IPH_CHKSUM_SET(iphdr, 0);
root@mbed.org 0:5e1631496985 514 #if CHECKSUM_GEN_IP
root@mbed.org 0:5e1631496985 515 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
root@mbed.org 0:5e1631496985 516 #endif
root@mbed.org 0:5e1631496985 517 } else {
root@mbed.org 0:5e1631496985 518 /* IP header already included in p */
root@mbed.org 0:5e1631496985 519 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x)
root@mbed.org 0:5e1631496985 520 struct ip_addr dest_addr;
root@mbed.org 0:5e1631496985 521 dest_addr.addr = iphdr->dest.addr;
root@mbed.org 0:5e1631496985 522 dest = &dest_addr;
root@mbed.org 0:5e1631496985 523 }
root@mbed.org 0:5e1631496985 524
root@mbed.org 0:5e1631496985 525 #if IP_FRAG
root@mbed.org 0:5e1631496985 526 /* don't fragment if interface has mtu set to 0 [loopif] */
root@mbed.org 0:5e1631496985 527 if (netif->mtu && (p->tot_len > netif->mtu))
root@mbed.org 0:5e1631496985 528 return ip_frag(p,netif,dest);
root@mbed.org 0:5e1631496985 529 #endif
root@mbed.org 0:5e1631496985 530
root@mbed.org 0:5e1631496985 531 IP_STATS_INC(ip.xmit);
root@mbed.org 0:5e1631496985 532
root@mbed.org 0:5e1631496985 533 LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
root@mbed.org 0:5e1631496985 534 ip_debug_print(p);
root@mbed.org 0:5e1631496985 535
root@mbed.org 0:5e1631496985 536 #if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
root@mbed.org 0:5e1631496985 537 if (ip_addr_cmp(dest, &netif->ip_addr)) {
root@mbed.org 0:5e1631496985 538 /* Packet to self, enqueue it for loopback */
root@mbed.org 0:5e1631496985 539 LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
root@mbed.org 0:5e1631496985 540
root@mbed.org 0:5e1631496985 541 return netif_loop_output(netif, p, dest);
root@mbed.org 0:5e1631496985 542 } else
root@mbed.org 0:5e1631496985 543 #endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */
root@mbed.org 0:5e1631496985 544 {
root@mbed.org 0:5e1631496985 545 LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
root@mbed.org 0:5e1631496985 546
root@mbed.org 0:5e1631496985 547 return netif->output(netif, p, dest);
root@mbed.org 0:5e1631496985 548 }
root@mbed.org 0:5e1631496985 549 }
root@mbed.org 0:5e1631496985 550
root@mbed.org 0:5e1631496985 551 /**
root@mbed.org 0:5e1631496985 552 * Simple interface to ip_output_if. It finds the outgoing network
root@mbed.org 0:5e1631496985 553 * interface and calls upon ip_output_if to do the actual work.
root@mbed.org 0:5e1631496985 554 *
root@mbed.org 0:5e1631496985 555 * @param p the packet to send (p->payload points to the data, e.g. next
root@mbed.org 0:5e1631496985 556 protocol header; if dest == IP_HDRINCL, p already includes an IP
root@mbed.org 0:5e1631496985 557 header and p->payload points to that IP header)
root@mbed.org 0:5e1631496985 558 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
root@mbed.org 0:5e1631496985 559 * IP address of the netif used to send is used as source address)
root@mbed.org 0:5e1631496985 560 * @param dest the destination IP address to send the packet to
root@mbed.org 0:5e1631496985 561 * @param ttl the TTL value to be set in the IP header
root@mbed.org 0:5e1631496985 562 * @param tos the TOS value to be set in the IP header
root@mbed.org 0:5e1631496985 563 * @param proto the PROTOCOL to be set in the IP header
root@mbed.org 0:5e1631496985 564 *
root@mbed.org 0:5e1631496985 565 * @return ERR_RTE if no route is found
root@mbed.org 0:5e1631496985 566 * see ip_output_if() for more return values
root@mbed.org 0:5e1631496985 567 */
root@mbed.org 0:5e1631496985 568 err_t
root@mbed.org 0:5e1631496985 569 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
root@mbed.org 0:5e1631496985 570 u8_t ttl, u8_t tos, u8_t proto)
root@mbed.org 0:5e1631496985 571 {
root@mbed.org 0:5e1631496985 572 struct netif *netif;
root@mbed.org 0:5e1631496985 573
root@mbed.org 0:5e1631496985 574 if ((netif = ip_route(dest)) == NULL) {
root@mbed.org 0:5e1631496985 575 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
root@mbed.org 0:5e1631496985 576 IP_STATS_INC(ip.rterr);
root@mbed.org 0:5e1631496985 577 return ERR_RTE;
root@mbed.org 0:5e1631496985 578 }
root@mbed.org 0:5e1631496985 579
root@mbed.org 0:5e1631496985 580 return ip_output_if(p, src, dest, ttl, tos, proto, netif);
root@mbed.org 0:5e1631496985 581 }
root@mbed.org 0:5e1631496985 582
root@mbed.org 0:5e1631496985 583 #if LWIP_NETIF_HWADDRHINT
root@mbed.org 0:5e1631496985 584 /** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
root@mbed.org 0:5e1631496985 585 * before calling ip_output_if.
root@mbed.org 0:5e1631496985 586 *
root@mbed.org 0:5e1631496985 587 * @param p the packet to send (p->payload points to the data, e.g. next
root@mbed.org 0:5e1631496985 588 protocol header; if dest == IP_HDRINCL, p already includes an IP
root@mbed.org 0:5e1631496985 589 header and p->payload points to that IP header)
root@mbed.org 0:5e1631496985 590 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
root@mbed.org 0:5e1631496985 591 * IP address of the netif used to send is used as source address)
root@mbed.org 0:5e1631496985 592 * @param dest the destination IP address to send the packet to
root@mbed.org 0:5e1631496985 593 * @param ttl the TTL value to be set in the IP header
root@mbed.org 0:5e1631496985 594 * @param tos the TOS value to be set in the IP header
root@mbed.org 0:5e1631496985 595 * @param proto the PROTOCOL to be set in the IP header
root@mbed.org 0:5e1631496985 596 * @param addr_hint address hint pointer set to netif->addr_hint before
root@mbed.org 0:5e1631496985 597 * calling ip_output_if()
root@mbed.org 0:5e1631496985 598 *
root@mbed.org 0:5e1631496985 599 * @return ERR_RTE if no route is found
root@mbed.org 0:5e1631496985 600 * see ip_output_if() for more return values
root@mbed.org 0:5e1631496985 601 */
root@mbed.org 0:5e1631496985 602 err_t
root@mbed.org 0:5e1631496985 603 ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
root@mbed.org 0:5e1631496985 604 u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
root@mbed.org 0:5e1631496985 605 {
root@mbed.org 0:5e1631496985 606 struct netif *netif;
root@mbed.org 0:5e1631496985 607 err_t err;
root@mbed.org 0:5e1631496985 608
root@mbed.org 0:5e1631496985 609 if ((netif = ip_route(dest)) == NULL) {
root@mbed.org 0:5e1631496985 610 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
root@mbed.org 0:5e1631496985 611 IP_STATS_INC(ip.rterr);
root@mbed.org 0:5e1631496985 612 return ERR_RTE;
root@mbed.org 0:5e1631496985 613 }
root@mbed.org 0:5e1631496985 614
root@mbed.org 0:5e1631496985 615 netif->addr_hint = addr_hint;
root@mbed.org 0:5e1631496985 616 err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
root@mbed.org 0:5e1631496985 617 netif->addr_hint = NULL;
root@mbed.org 0:5e1631496985 618
root@mbed.org 0:5e1631496985 619 return err;
root@mbed.org 0:5e1631496985 620 }
root@mbed.org 0:5e1631496985 621 #endif /* LWIP_NETIF_HWADDRHINT*/
root@mbed.org 0:5e1631496985 622
root@mbed.org 0:5e1631496985 623 #if IP_DEBUG
root@mbed.org 0:5e1631496985 624 /* Print an IP header by using LWIP_DEBUGF
root@mbed.org 0:5e1631496985 625 * @param p an IP packet, p->payload pointing to the IP header
root@mbed.org 0:5e1631496985 626 */
root@mbed.org 0:5e1631496985 627 void
root@mbed.org 0:5e1631496985 628 ip_debug_print(struct pbuf *p)
root@mbed.org 0:5e1631496985 629 {
root@mbed.org 0:5e1631496985 630 struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; // static_cast<struct ip_hdr *>(x)
root@mbed.org 0:5e1631496985 631 u8_t *payload;
root@mbed.org 0:5e1631496985 632
root@mbed.org 0:5e1631496985 633 payload = (u8_t *)iphdr + IP_HLEN;
root@mbed.org 0:5e1631496985 634
root@mbed.org 0:5e1631496985 635 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
root@mbed.org 0:5e1631496985 636 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
root@mbed.org 0:5e1631496985 637 LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
root@mbed.org 0:5e1631496985 638 IPH_V(iphdr),
root@mbed.org 0:5e1631496985 639 IPH_HL(iphdr),
root@mbed.org 0:5e1631496985 640 IPH_TOS(iphdr),
root@mbed.org 0:5e1631496985 641 ntohs(IPH_LEN(iphdr))));
root@mbed.org 0:5e1631496985 642 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
root@mbed.org 0:5e1631496985 643 LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
root@mbed.org 0:5e1631496985 644 ntohs(IPH_ID(iphdr)),
root@mbed.org 0:5e1631496985 645 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
root@mbed.org 0:5e1631496985 646 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
root@mbed.org 0:5e1631496985 647 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
root@mbed.org 0:5e1631496985 648 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
root@mbed.org 0:5e1631496985 649 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
root@mbed.org 0:5e1631496985 650 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
root@mbed.org 0:5e1631496985 651 IPH_TTL(iphdr),
root@mbed.org 0:5e1631496985 652 IPH_PROTO(iphdr),
root@mbed.org 0:5e1631496985 653 ntohs(IPH_CHKSUM(iphdr))));
root@mbed.org 0:5e1631496985 654 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
root@mbed.org 0:5e1631496985 655 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
root@mbed.org 0:5e1631496985 656 ip4_addr1(&iphdr->src),
root@mbed.org 0:5e1631496985 657 ip4_addr2(&iphdr->src),
root@mbed.org 0:5e1631496985 658 ip4_addr3(&iphdr->src),
root@mbed.org 0:5e1631496985 659 ip4_addr4(&iphdr->src)));
root@mbed.org 0:5e1631496985 660 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
root@mbed.org 0:5e1631496985 661 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
root@mbed.org 0:5e1631496985 662 ip4_addr1(&iphdr->dest),
root@mbed.org 0:5e1631496985 663 ip4_addr2(&iphdr->dest),
root@mbed.org 0:5e1631496985 664 ip4_addr3(&iphdr->dest),
root@mbed.org 0:5e1631496985 665 ip4_addr4(&iphdr->dest)));
root@mbed.org 0:5e1631496985 666 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
root@mbed.org 0:5e1631496985 667 }
root@mbed.org 0:5e1631496985 668 #endif /* IP_DEBUG */