Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

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