Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed

Dependencies:   mbed

Committer:
pehrhovey
Date:
Sun Mar 14 00:54:12 2010 +0000
Revision:
0:a548a085de55

        

Who changed what in which revision?

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