Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

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

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

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

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

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

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

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

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 0:51ac1d130fd4 1 /**
mbed_official 0:51ac1d130fd4 2 * @file
mbed_official 0:51ac1d130fd4 3 * Address Resolution Protocol module for IP over Ethernet
mbed_official 0:51ac1d130fd4 4 *
mbed_official 0:51ac1d130fd4 5 * Functionally, ARP is divided into two parts. The first maps an IP address
mbed_official 0:51ac1d130fd4 6 * to a physical address when sending a packet, and the second part answers
mbed_official 0:51ac1d130fd4 7 * requests from other machines for our physical address.
mbed_official 0:51ac1d130fd4 8 *
mbed_official 0:51ac1d130fd4 9 * This implementation complies with RFC 826 (Ethernet ARP). It supports
mbed_official 0:51ac1d130fd4 10 * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
mbed_official 0:51ac1d130fd4 11 * if an interface calls etharp_gratuitous(our_netif) upon address change.
mbed_official 0:51ac1d130fd4 12 */
mbed_official 0:51ac1d130fd4 13
mbed_official 0:51ac1d130fd4 14 /*
mbed_official 0:51ac1d130fd4 15 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
mbed_official 0:51ac1d130fd4 16 * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
mbed_official 0:51ac1d130fd4 17 * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
mbed_official 0:51ac1d130fd4 18 * All rights reserved.
mbed_official 0:51ac1d130fd4 19 *
mbed_official 0:51ac1d130fd4 20 * Redistribution and use in source and binary forms, with or without modification,
mbed_official 0:51ac1d130fd4 21 * are permitted provided that the following conditions are met:
mbed_official 0:51ac1d130fd4 22 *
mbed_official 0:51ac1d130fd4 23 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 0:51ac1d130fd4 24 * this list of conditions and the following disclaimer.
mbed_official 0:51ac1d130fd4 25 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 0:51ac1d130fd4 26 * this list of conditions and the following disclaimer in the documentation
mbed_official 0:51ac1d130fd4 27 * and/or other materials provided with the distribution.
mbed_official 0:51ac1d130fd4 28 * 3. The name of the author may not be used to endorse or promote products
mbed_official 0:51ac1d130fd4 29 * derived from this software without specific prior written permission.
mbed_official 0:51ac1d130fd4 30 *
mbed_official 0:51ac1d130fd4 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
mbed_official 0:51ac1d130fd4 32 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 0:51ac1d130fd4 33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
mbed_official 0:51ac1d130fd4 34 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
mbed_official 0:51ac1d130fd4 35 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
mbed_official 0:51ac1d130fd4 36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
mbed_official 0:51ac1d130fd4 37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
mbed_official 0:51ac1d130fd4 38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
mbed_official 0:51ac1d130fd4 39 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
mbed_official 0:51ac1d130fd4 40 * OF SUCH DAMAGE.
mbed_official 0:51ac1d130fd4 41 *
mbed_official 0:51ac1d130fd4 42 * This file is part of the lwIP TCP/IP stack.
mbed_official 0:51ac1d130fd4 43 *
mbed_official 0:51ac1d130fd4 44 */
mbed_official 0:51ac1d130fd4 45
mbed_official 0:51ac1d130fd4 46 #include "lwip/opt.h"
mbed_official 0:51ac1d130fd4 47
mbed_official 0:51ac1d130fd4 48 #if LWIP_ARP || LWIP_ETHERNET
mbed_official 0:51ac1d130fd4 49
mbed_official 0:51ac1d130fd4 50 #include "lwip/ip_addr.h"
mbed_official 0:51ac1d130fd4 51 #include "lwip/def.h"
mbed_official 0:51ac1d130fd4 52 #include "lwip/ip.h"
mbed_official 0:51ac1d130fd4 53 #include "lwip/stats.h"
mbed_official 0:51ac1d130fd4 54 #include "lwip/snmp.h"
mbed_official 0:51ac1d130fd4 55 #include "lwip/dhcp.h"
mbed_official 0:51ac1d130fd4 56 #include "lwip/autoip.h"
mbed_official 0:51ac1d130fd4 57 #include "netif/etharp.h"
mbed_official 0:51ac1d130fd4 58
mbed_official 0:51ac1d130fd4 59 #if PPPOE_SUPPORT
mbed_official 0:51ac1d130fd4 60 #include "netif/ppp_oe.h"
mbed_official 0:51ac1d130fd4 61 #endif /* PPPOE_SUPPORT */
mbed_official 0:51ac1d130fd4 62
mbed_official 0:51ac1d130fd4 63 #include <string.h>
mbed_official 0:51ac1d130fd4 64
mbed_official 0:51ac1d130fd4 65 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
mbed_official 0:51ac1d130fd4 66 const struct eth_addr ethzero = {{0,0,0,0,0,0}};
mbed_official 0:51ac1d130fd4 67
mbed_official 0:51ac1d130fd4 68 #if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
mbed_official 0:51ac1d130fd4 69
mbed_official 0:51ac1d130fd4 70 /** the time an ARP entry stays valid after its last update,
mbed_official 0:51ac1d130fd4 71 * for ARP_TMR_INTERVAL = 5000, this is
mbed_official 0:51ac1d130fd4 72 * (240 * 5) seconds = 20 minutes.
mbed_official 0:51ac1d130fd4 73 */
mbed_official 0:51ac1d130fd4 74 #define ARP_MAXAGE 240
mbed_official 0:51ac1d130fd4 75 /** the time an ARP entry stays pending after first request,
mbed_official 0:51ac1d130fd4 76 * for ARP_TMR_INTERVAL = 5000, this is
mbed_official 0:51ac1d130fd4 77 * (2 * 5) seconds = 10 seconds.
mbed_official 0:51ac1d130fd4 78 *
mbed_official 0:51ac1d130fd4 79 * @internal Keep this number at least 2, otherwise it might
mbed_official 0:51ac1d130fd4 80 * run out instantly if the timeout occurs directly after a request.
mbed_official 0:51ac1d130fd4 81 */
mbed_official 0:51ac1d130fd4 82 #define ARP_MAXPENDING 2
mbed_official 0:51ac1d130fd4 83
mbed_official 0:51ac1d130fd4 84 #define HWTYPE_ETHERNET 1
mbed_official 0:51ac1d130fd4 85
mbed_official 0:51ac1d130fd4 86 enum etharp_state {
mbed_official 0:51ac1d130fd4 87 ETHARP_STATE_EMPTY = 0,
mbed_official 0:51ac1d130fd4 88 ETHARP_STATE_PENDING,
mbed_official 0:51ac1d130fd4 89 ETHARP_STATE_STABLE
mbed_official 0:51ac1d130fd4 90 };
mbed_official 0:51ac1d130fd4 91
mbed_official 0:51ac1d130fd4 92 struct etharp_entry {
mbed_official 0:51ac1d130fd4 93 #if ARP_QUEUEING
mbed_official 0:51ac1d130fd4 94 /** Pointer to queue of pending outgoing packets on this ARP entry. */
mbed_official 0:51ac1d130fd4 95 struct etharp_q_entry *q;
mbed_official 0:51ac1d130fd4 96 #else /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 97 /** Pointer to a single pending outgoing packet on this ARP entry. */
mbed_official 0:51ac1d130fd4 98 struct pbuf *q;
mbed_official 0:51ac1d130fd4 99 #endif /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 100 ip_addr_t ipaddr;
mbed_official 0:51ac1d130fd4 101 struct eth_addr ethaddr;
mbed_official 0:51ac1d130fd4 102 #if LWIP_SNMP
mbed_official 0:51ac1d130fd4 103 struct netif *netif;
mbed_official 0:51ac1d130fd4 104 #endif /* LWIP_SNMP */
mbed_official 0:51ac1d130fd4 105 u8_t state;
mbed_official 0:51ac1d130fd4 106 u8_t ctime;
mbed_official 0:51ac1d130fd4 107 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 108 u8_t static_entry;
mbed_official 0:51ac1d130fd4 109 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 110 };
mbed_official 0:51ac1d130fd4 111
mbed_official 0:51ac1d130fd4 112 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
mbed_official 0:51ac1d130fd4 113
mbed_official 0:51ac1d130fd4 114 #if !LWIP_NETIF_HWADDRHINT
mbed_official 0:51ac1d130fd4 115 static u8_t etharp_cached_entry;
mbed_official 0:51ac1d130fd4 116 #endif /* !LWIP_NETIF_HWADDRHINT */
mbed_official 0:51ac1d130fd4 117
mbed_official 0:51ac1d130fd4 118 /** Try hard to create a new entry - we want the IP address to appear in
mbed_official 0:51ac1d130fd4 119 the cache (even if this means removing an active entry or so). */
mbed_official 0:51ac1d130fd4 120 #define ETHARP_FLAG_TRY_HARD 1
mbed_official 0:51ac1d130fd4 121 #define ETHARP_FLAG_FIND_ONLY 2
mbed_official 0:51ac1d130fd4 122 #define ETHARP_FLAG_STATIC_ENTRY 4
mbed_official 0:51ac1d130fd4 123
mbed_official 0:51ac1d130fd4 124 #if LWIP_NETIF_HWADDRHINT
mbed_official 0:51ac1d130fd4 125 #define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
mbed_official 0:51ac1d130fd4 126 *((netif)->addr_hint) = (hint);
mbed_official 0:51ac1d130fd4 127 #else /* LWIP_NETIF_HWADDRHINT */
mbed_official 0:51ac1d130fd4 128 #define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint))
mbed_official 0:51ac1d130fd4 129 #endif /* LWIP_NETIF_HWADDRHINT */
mbed_official 0:51ac1d130fd4 130
mbed_official 0:51ac1d130fd4 131 static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags);
mbed_official 0:51ac1d130fd4 132
mbed_official 0:51ac1d130fd4 133
mbed_official 0:51ac1d130fd4 134 /* Some checks, instead of etharp_init(): */
mbed_official 0:51ac1d130fd4 135 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
mbed_official 0:51ac1d130fd4 136 #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
mbed_official 0:51ac1d130fd4 137 #endif
mbed_official 0:51ac1d130fd4 138
mbed_official 0:51ac1d130fd4 139
mbed_official 0:51ac1d130fd4 140 #if ARP_QUEUEING
mbed_official 0:51ac1d130fd4 141 /**
mbed_official 0:51ac1d130fd4 142 * Free a complete queue of etharp entries
mbed_official 0:51ac1d130fd4 143 *
mbed_official 0:51ac1d130fd4 144 * @param q a qeueue of etharp_q_entry's to free
mbed_official 0:51ac1d130fd4 145 */
mbed_official 0:51ac1d130fd4 146 static void
mbed_official 0:51ac1d130fd4 147 free_etharp_q(struct etharp_q_entry *q)
mbed_official 0:51ac1d130fd4 148 {
mbed_official 0:51ac1d130fd4 149 struct etharp_q_entry *r;
mbed_official 0:51ac1d130fd4 150 LWIP_ASSERT("q != NULL", q != NULL);
mbed_official 0:51ac1d130fd4 151 LWIP_ASSERT("q->p != NULL", q->p != NULL);
mbed_official 0:51ac1d130fd4 152 while (q) {
mbed_official 0:51ac1d130fd4 153 r = q;
mbed_official 0:51ac1d130fd4 154 q = q->next;
mbed_official 0:51ac1d130fd4 155 LWIP_ASSERT("r->p != NULL", (r->p != NULL));
mbed_official 0:51ac1d130fd4 156 pbuf_free(r->p);
mbed_official 0:51ac1d130fd4 157 memp_free(MEMP_ARP_QUEUE, r);
mbed_official 0:51ac1d130fd4 158 }
mbed_official 0:51ac1d130fd4 159 }
mbed_official 0:51ac1d130fd4 160 #else /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 161
mbed_official 0:51ac1d130fd4 162 /** Compatibility define: free the queued pbuf */
mbed_official 0:51ac1d130fd4 163 #define free_etharp_q(q) pbuf_free(q)
mbed_official 0:51ac1d130fd4 164
mbed_official 0:51ac1d130fd4 165 #endif /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 166
mbed_official 0:51ac1d130fd4 167 /** Clean up ARP table entries */
mbed_official 0:51ac1d130fd4 168 static void
mbed_official 0:51ac1d130fd4 169 free_entry(int i)
mbed_official 0:51ac1d130fd4 170 {
mbed_official 0:51ac1d130fd4 171 /* remove from SNMP ARP index tree */
mbed_official 0:51ac1d130fd4 172 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
mbed_official 0:51ac1d130fd4 173 /* and empty packet queue */
mbed_official 0:51ac1d130fd4 174 if (arp_table[i].q != NULL) {
mbed_official 0:51ac1d130fd4 175 /* remove all queued packets */
mbed_official 0:51ac1d130fd4 176 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
mbed_official 0:51ac1d130fd4 177 free_etharp_q(arp_table[i].q);
mbed_official 0:51ac1d130fd4 178 arp_table[i].q = NULL;
mbed_official 0:51ac1d130fd4 179 }
mbed_official 0:51ac1d130fd4 180 /* recycle entry for re-use */
mbed_official 0:51ac1d130fd4 181 arp_table[i].state = ETHARP_STATE_EMPTY;
mbed_official 0:51ac1d130fd4 182 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 183 arp_table[i].static_entry = 0;
mbed_official 0:51ac1d130fd4 184 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 185 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 186 /* for debugging, clean out the complete entry */
mbed_official 0:51ac1d130fd4 187 arp_table[i].ctime = 0;
mbed_official 0:51ac1d130fd4 188 #if LWIP_SNMP
mbed_official 0:51ac1d130fd4 189 arp_table[i].netif = NULL;
mbed_official 0:51ac1d130fd4 190 #endif /* LWIP_SNMP */
mbed_official 0:51ac1d130fd4 191 ip_addr_set_zero(&arp_table[i].ipaddr);
mbed_official 0:51ac1d130fd4 192 arp_table[i].ethaddr = ethzero;
mbed_official 0:51ac1d130fd4 193 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 194 }
mbed_official 0:51ac1d130fd4 195
mbed_official 0:51ac1d130fd4 196 /**
mbed_official 0:51ac1d130fd4 197 * Clears expired entries in the ARP table.
mbed_official 0:51ac1d130fd4 198 *
mbed_official 0:51ac1d130fd4 199 * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds),
mbed_official 0:51ac1d130fd4 200 * in order to expire entries in the ARP table.
mbed_official 0:51ac1d130fd4 201 */
mbed_official 0:51ac1d130fd4 202 void
mbed_official 0:51ac1d130fd4 203 etharp_tmr(void)
mbed_official 0:51ac1d130fd4 204 {
mbed_official 0:51ac1d130fd4 205 u8_t i;
mbed_official 0:51ac1d130fd4 206
mbed_official 0:51ac1d130fd4 207 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
mbed_official 0:51ac1d130fd4 208 /* remove expired entries from the ARP table */
mbed_official 0:51ac1d130fd4 209 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
mbed_official 0:51ac1d130fd4 210 u8_t state = arp_table[i].state;
mbed_official 0:51ac1d130fd4 211 if (state != ETHARP_STATE_EMPTY
mbed_official 0:51ac1d130fd4 212 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 213 && (arp_table[i].static_entry == 0)
mbed_official 0:51ac1d130fd4 214 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 215 ) {
mbed_official 0:51ac1d130fd4 216 arp_table[i].ctime++;
mbed_official 0:51ac1d130fd4 217 if ((arp_table[i].ctime >= ARP_MAXAGE) ||
mbed_official 0:51ac1d130fd4 218 ((arp_table[i].state == ETHARP_STATE_PENDING) &&
mbed_official 0:51ac1d130fd4 219 (arp_table[i].ctime >= ARP_MAXPENDING))) {
mbed_official 0:51ac1d130fd4 220 /* pending or stable entry has become old! */
mbed_official 0:51ac1d130fd4 221 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
mbed_official 0:51ac1d130fd4 222 arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
mbed_official 0:51ac1d130fd4 223 /* clean up entries that have just been expired */
mbed_official 0:51ac1d130fd4 224 free_entry(i);
mbed_official 0:51ac1d130fd4 225 }
mbed_official 0:51ac1d130fd4 226 #if ARP_QUEUEING
mbed_official 0:51ac1d130fd4 227 /* still pending entry? (not expired) */
mbed_official 0:51ac1d130fd4 228 if (arp_table[i].state == ETHARP_STATE_PENDING) {
mbed_official 0:51ac1d130fd4 229 /* resend an ARP query here? */
mbed_official 0:51ac1d130fd4 230 }
mbed_official 0:51ac1d130fd4 231 #endif /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 232 }
mbed_official 0:51ac1d130fd4 233 }
mbed_official 0:51ac1d130fd4 234 }
mbed_official 0:51ac1d130fd4 235
mbed_official 0:51ac1d130fd4 236 /**
mbed_official 0:51ac1d130fd4 237 * Search the ARP table for a matching or new entry.
mbed_official 0:51ac1d130fd4 238 *
mbed_official 0:51ac1d130fd4 239 * If an IP address is given, return a pending or stable ARP entry that matches
mbed_official 0:51ac1d130fd4 240 * the address. If no match is found, create a new entry with this address set,
mbed_official 0:51ac1d130fd4 241 * but in state ETHARP_EMPTY. The caller must check and possibly change the
mbed_official 0:51ac1d130fd4 242 * state of the returned entry.
mbed_official 0:51ac1d130fd4 243 *
mbed_official 0:51ac1d130fd4 244 * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
mbed_official 0:51ac1d130fd4 245 *
mbed_official 0:51ac1d130fd4 246 * In all cases, attempt to create new entries from an empty entry. If no
mbed_official 0:51ac1d130fd4 247 * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle
mbed_official 0:51ac1d130fd4 248 * old entries. Heuristic choose the least important entry for recycling.
mbed_official 0:51ac1d130fd4 249 *
mbed_official 0:51ac1d130fd4 250 * @param ipaddr IP address to find in ARP cache, or to add if not found.
mbed_official 0:51ac1d130fd4 251 * @param flags @see definition of ETHARP_FLAG_*
mbed_official 0:51ac1d130fd4 252 * @param netif netif related to this address (used for NETIF_HWADDRHINT)
mbed_official 0:51ac1d130fd4 253 *
mbed_official 0:51ac1d130fd4 254 * @return The ARP entry index that matched or is created, ERR_MEM if no
mbed_official 0:51ac1d130fd4 255 * entry is found or could be recycled.
mbed_official 0:51ac1d130fd4 256 */
mbed_official 0:51ac1d130fd4 257 static s8_t
mbed_official 0:51ac1d130fd4 258 find_entry(ip_addr_t *ipaddr, u8_t flags)
mbed_official 0:51ac1d130fd4 259 {
mbed_official 0:51ac1d130fd4 260 s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
mbed_official 0:51ac1d130fd4 261 s8_t empty = ARP_TABLE_SIZE;
mbed_official 0:51ac1d130fd4 262 u8_t i = 0, age_pending = 0, age_stable = 0;
mbed_official 0:51ac1d130fd4 263 /* oldest entry with packets on queue */
mbed_official 0:51ac1d130fd4 264 s8_t old_queue = ARP_TABLE_SIZE;
mbed_official 0:51ac1d130fd4 265 /* its age */
mbed_official 0:51ac1d130fd4 266 u8_t age_queue = 0;
mbed_official 0:51ac1d130fd4 267
mbed_official 0:51ac1d130fd4 268 /**
mbed_official 0:51ac1d130fd4 269 * a) do a search through the cache, remember candidates
mbed_official 0:51ac1d130fd4 270 * b) select candidate entry
mbed_official 0:51ac1d130fd4 271 * c) create new entry
mbed_official 0:51ac1d130fd4 272 */
mbed_official 0:51ac1d130fd4 273
mbed_official 0:51ac1d130fd4 274 /* a) in a single search sweep, do all of this
mbed_official 0:51ac1d130fd4 275 * 1) remember the first empty entry (if any)
mbed_official 0:51ac1d130fd4 276 * 2) remember the oldest stable entry (if any)
mbed_official 0:51ac1d130fd4 277 * 3) remember the oldest pending entry without queued packets (if any)
mbed_official 0:51ac1d130fd4 278 * 4) remember the oldest pending entry with queued packets (if any)
mbed_official 0:51ac1d130fd4 279 * 5) search for a matching IP entry, either pending or stable
mbed_official 0:51ac1d130fd4 280 * until 5 matches, or all entries are searched for.
mbed_official 0:51ac1d130fd4 281 */
mbed_official 0:51ac1d130fd4 282
mbed_official 0:51ac1d130fd4 283 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
mbed_official 0:51ac1d130fd4 284 u8_t state = arp_table[i].state;
mbed_official 0:51ac1d130fd4 285 /* no empty entry found yet and now we do find one? */
mbed_official 0:51ac1d130fd4 286 if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
mbed_official 0:51ac1d130fd4 287 LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
mbed_official 0:51ac1d130fd4 288 /* remember first empty entry */
mbed_official 0:51ac1d130fd4 289 empty = i;
mbed_official 0:51ac1d130fd4 290 } else if (state != ETHARP_STATE_EMPTY) {
mbed_official 0:51ac1d130fd4 291 LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE",
mbed_official 0:51ac1d130fd4 292 state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE);
mbed_official 0:51ac1d130fd4 293 /* if given, does IP address match IP address in ARP entry? */
mbed_official 0:51ac1d130fd4 294 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
mbed_official 0:51ac1d130fd4 295 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i));
mbed_official 0:51ac1d130fd4 296 /* found exact IP address match, simply bail out */
mbed_official 0:51ac1d130fd4 297 return i;
mbed_official 0:51ac1d130fd4 298 }
mbed_official 0:51ac1d130fd4 299 /* pending entry? */
mbed_official 0:51ac1d130fd4 300 if (state == ETHARP_STATE_PENDING) {
mbed_official 0:51ac1d130fd4 301 /* pending with queued packets? */
mbed_official 0:51ac1d130fd4 302 if (arp_table[i].q != NULL) {
mbed_official 0:51ac1d130fd4 303 if (arp_table[i].ctime >= age_queue) {
mbed_official 0:51ac1d130fd4 304 old_queue = i;
mbed_official 0:51ac1d130fd4 305 age_queue = arp_table[i].ctime;
mbed_official 0:51ac1d130fd4 306 }
mbed_official 0:51ac1d130fd4 307 } else
mbed_official 0:51ac1d130fd4 308 /* pending without queued packets? */
mbed_official 0:51ac1d130fd4 309 {
mbed_official 0:51ac1d130fd4 310 if (arp_table[i].ctime >= age_pending) {
mbed_official 0:51ac1d130fd4 311 old_pending = i;
mbed_official 0:51ac1d130fd4 312 age_pending = arp_table[i].ctime;
mbed_official 0:51ac1d130fd4 313 }
mbed_official 0:51ac1d130fd4 314 }
mbed_official 0:51ac1d130fd4 315 /* stable entry? */
mbed_official 0:51ac1d130fd4 316 } else if (state == ETHARP_STATE_STABLE) {
mbed_official 0:51ac1d130fd4 317 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 318 /* don't record old_stable for static entries since they never expire */
mbed_official 0:51ac1d130fd4 319 if (arp_table[i].static_entry == 0)
mbed_official 0:51ac1d130fd4 320 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 321 {
mbed_official 0:51ac1d130fd4 322 /* remember entry with oldest stable entry in oldest, its age in maxtime */
mbed_official 0:51ac1d130fd4 323 if (arp_table[i].ctime >= age_stable) {
mbed_official 0:51ac1d130fd4 324 old_stable = i;
mbed_official 0:51ac1d130fd4 325 age_stable = arp_table[i].ctime;
mbed_official 0:51ac1d130fd4 326 }
mbed_official 0:51ac1d130fd4 327 }
mbed_official 0:51ac1d130fd4 328 }
mbed_official 0:51ac1d130fd4 329 }
mbed_official 0:51ac1d130fd4 330 }
mbed_official 0:51ac1d130fd4 331 /* { we have no match } => try to create a new entry */
mbed_official 0:51ac1d130fd4 332
mbed_official 0:51ac1d130fd4 333 /* don't create new entry, only search? */
mbed_official 0:51ac1d130fd4 334 if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
mbed_official 0:51ac1d130fd4 335 /* or no empty entry found and not allowed to recycle? */
mbed_official 0:51ac1d130fd4 336 ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
mbed_official 0:51ac1d130fd4 337 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
mbed_official 0:51ac1d130fd4 338 return (s8_t)ERR_MEM;
mbed_official 0:51ac1d130fd4 339 }
mbed_official 0:51ac1d130fd4 340
mbed_official 0:51ac1d130fd4 341 /* b) choose the least destructive entry to recycle:
mbed_official 0:51ac1d130fd4 342 * 1) empty entry
mbed_official 0:51ac1d130fd4 343 * 2) oldest stable entry
mbed_official 0:51ac1d130fd4 344 * 3) oldest pending entry without queued packets
mbed_official 0:51ac1d130fd4 345 * 4) oldest pending entry with queued packets
mbed_official 0:51ac1d130fd4 346 *
mbed_official 0:51ac1d130fd4 347 * { ETHARP_FLAG_TRY_HARD is set at this point }
mbed_official 0:51ac1d130fd4 348 */
mbed_official 0:51ac1d130fd4 349
mbed_official 0:51ac1d130fd4 350 /* 1) empty entry available? */
mbed_official 0:51ac1d130fd4 351 if (empty < ARP_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 352 i = empty;
mbed_official 0:51ac1d130fd4 353 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
mbed_official 0:51ac1d130fd4 354 } else {
mbed_official 0:51ac1d130fd4 355 /* 2) found recyclable stable entry? */
mbed_official 0:51ac1d130fd4 356 if (old_stable < ARP_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 357 /* recycle oldest stable*/
mbed_official 0:51ac1d130fd4 358 i = old_stable;
mbed_official 0:51ac1d130fd4 359 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
mbed_official 0:51ac1d130fd4 360 /* no queued packets should exist on stable entries */
mbed_official 0:51ac1d130fd4 361 LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
mbed_official 0:51ac1d130fd4 362 /* 3) found recyclable pending entry without queued packets? */
mbed_official 0:51ac1d130fd4 363 } else if (old_pending < ARP_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 364 /* recycle oldest pending */
mbed_official 0:51ac1d130fd4 365 i = old_pending;
mbed_official 0:51ac1d130fd4 366 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
mbed_official 0:51ac1d130fd4 367 /* 4) found recyclable pending entry with queued packets? */
mbed_official 0:51ac1d130fd4 368 } else if (old_queue < ARP_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 369 /* recycle oldest pending (queued packets are free in free_entry) */
mbed_official 0:51ac1d130fd4 370 i = old_queue;
mbed_official 0:51ac1d130fd4 371 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
mbed_official 0:51ac1d130fd4 372 /* no empty or recyclable entries found */
mbed_official 0:51ac1d130fd4 373 } else {
mbed_official 0:51ac1d130fd4 374 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
mbed_official 0:51ac1d130fd4 375 return (s8_t)ERR_MEM;
mbed_official 0:51ac1d130fd4 376 }
mbed_official 0:51ac1d130fd4 377
mbed_official 0:51ac1d130fd4 378 /* { empty or recyclable entry found } */
mbed_official 0:51ac1d130fd4 379 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
mbed_official 0:51ac1d130fd4 380 free_entry(i);
mbed_official 0:51ac1d130fd4 381 }
mbed_official 0:51ac1d130fd4 382
mbed_official 0:51ac1d130fd4 383 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
mbed_official 0:51ac1d130fd4 384 LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
mbed_official 0:51ac1d130fd4 385 arp_table[i].state == ETHARP_STATE_EMPTY);
mbed_official 0:51ac1d130fd4 386
mbed_official 0:51ac1d130fd4 387 /* IP address given? */
mbed_official 0:51ac1d130fd4 388 if (ipaddr != NULL) {
mbed_official 0:51ac1d130fd4 389 /* set IP address */
mbed_official 0:51ac1d130fd4 390 ip_addr_copy(arp_table[i].ipaddr, *ipaddr);
mbed_official 0:51ac1d130fd4 391 }
mbed_official 0:51ac1d130fd4 392 arp_table[i].ctime = 0;
mbed_official 0:51ac1d130fd4 393 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 394 arp_table[i].static_entry = 0;
mbed_official 0:51ac1d130fd4 395 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 396 return (err_t)i;
mbed_official 0:51ac1d130fd4 397 }
mbed_official 0:51ac1d130fd4 398
mbed_official 0:51ac1d130fd4 399 /**
mbed_official 0:51ac1d130fd4 400 * Send an IP packet on the network using netif->linkoutput
mbed_official 0:51ac1d130fd4 401 * The ethernet header is filled in before sending.
mbed_official 0:51ac1d130fd4 402 *
mbed_official 0:51ac1d130fd4 403 * @params netif the lwIP network interface on which to send the packet
mbed_official 0:51ac1d130fd4 404 * @params p the packet to send, p->payload pointing to the (uninitialized) ethernet header
mbed_official 0:51ac1d130fd4 405 * @params src the source MAC address to be copied into the ethernet header
mbed_official 0:51ac1d130fd4 406 * @params dst the destination MAC address to be copied into the ethernet header
mbed_official 0:51ac1d130fd4 407 * @return ERR_OK if the packet was sent, any other err_t on failure
mbed_official 0:51ac1d130fd4 408 */
mbed_official 0:51ac1d130fd4 409 static err_t
mbed_official 0:51ac1d130fd4 410 etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
mbed_official 0:51ac1d130fd4 411 {
mbed_official 0:51ac1d130fd4 412 struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 413
mbed_official 0:51ac1d130fd4 414 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
mbed_official 0:51ac1d130fd4 415 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
mbed_official 0:51ac1d130fd4 416 ETHADDR32_COPY(&ethhdr->dest, dst);
mbed_official 0:51ac1d130fd4 417 ETHADDR16_COPY(&ethhdr->src, src);
mbed_official 0:51ac1d130fd4 418 ethhdr->type = PP_HTONS(ETHTYPE_IP);
mbed_official 0:51ac1d130fd4 419 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
mbed_official 0:51ac1d130fd4 420 /* send the packet */
mbed_official 0:51ac1d130fd4 421 return netif->linkoutput(netif, p);
mbed_official 0:51ac1d130fd4 422 }
mbed_official 0:51ac1d130fd4 423
mbed_official 0:51ac1d130fd4 424 /**
mbed_official 0:51ac1d130fd4 425 * Update (or insert) a IP/MAC address pair in the ARP cache.
mbed_official 0:51ac1d130fd4 426 *
mbed_official 0:51ac1d130fd4 427 * If a pending entry is resolved, any queued packets will be sent
mbed_official 0:51ac1d130fd4 428 * at this point.
mbed_official 0:51ac1d130fd4 429 *
mbed_official 0:51ac1d130fd4 430 * @param netif netif related to this entry (used for NETIF_ADDRHINT)
mbed_official 0:51ac1d130fd4 431 * @param ipaddr IP address of the inserted ARP entry.
mbed_official 0:51ac1d130fd4 432 * @param ethaddr Ethernet address of the inserted ARP entry.
mbed_official 0:51ac1d130fd4 433 * @param flags @see definition of ETHARP_FLAG_*
mbed_official 0:51ac1d130fd4 434 *
mbed_official 0:51ac1d130fd4 435 * @return
mbed_official 0:51ac1d130fd4 436 * - ERR_OK Succesfully updated ARP cache.
mbed_official 0:51ac1d130fd4 437 * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set.
mbed_official 0:51ac1d130fd4 438 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
mbed_official 0:51ac1d130fd4 439 *
mbed_official 0:51ac1d130fd4 440 * @see pbuf_free()
mbed_official 0:51ac1d130fd4 441 */
mbed_official 0:51ac1d130fd4 442 static err_t
mbed_official 0:51ac1d130fd4 443 update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
mbed_official 0:51ac1d130fd4 444 {
mbed_official 0:51ac1d130fd4 445 s8_t i;
mbed_official 0:51ac1d130fd4 446 LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
mbed_official 0:51ac1d130fd4 447 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
mbed_official 0:51ac1d130fd4 448 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
mbed_official 0:51ac1d130fd4 449 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
mbed_official 0:51ac1d130fd4 450 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
mbed_official 0:51ac1d130fd4 451 /* non-unicast address? */
mbed_official 0:51ac1d130fd4 452 if (ip_addr_isany(ipaddr) ||
mbed_official 0:51ac1d130fd4 453 ip_addr_isbroadcast(ipaddr, netif) ||
mbed_official 0:51ac1d130fd4 454 ip_addr_ismulticast(ipaddr)) {
mbed_official 0:51ac1d130fd4 455 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
mbed_official 0:51ac1d130fd4 456 return ERR_ARG;
mbed_official 0:51ac1d130fd4 457 }
mbed_official 0:51ac1d130fd4 458 /* find or create ARP entry */
mbed_official 0:51ac1d130fd4 459 i = find_entry(ipaddr, flags);
mbed_official 0:51ac1d130fd4 460 /* bail out if no entry could be found */
mbed_official 0:51ac1d130fd4 461 if (i < 0) {
mbed_official 0:51ac1d130fd4 462 return (err_t)i;
mbed_official 0:51ac1d130fd4 463 }
mbed_official 0:51ac1d130fd4 464
mbed_official 0:51ac1d130fd4 465 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 466 if (flags & ETHARP_FLAG_STATIC_ENTRY) {
mbed_official 0:51ac1d130fd4 467 /* record static type */
mbed_official 0:51ac1d130fd4 468 arp_table[i].static_entry = 1;
mbed_official 0:51ac1d130fd4 469 }
mbed_official 0:51ac1d130fd4 470 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 471
mbed_official 0:51ac1d130fd4 472 /* mark it stable */
mbed_official 0:51ac1d130fd4 473 arp_table[i].state = ETHARP_STATE_STABLE;
mbed_official 0:51ac1d130fd4 474
mbed_official 0:51ac1d130fd4 475 #if LWIP_SNMP
mbed_official 0:51ac1d130fd4 476 /* record network interface */
mbed_official 0:51ac1d130fd4 477 arp_table[i].netif = netif;
mbed_official 0:51ac1d130fd4 478 #endif /* LWIP_SNMP */
mbed_official 0:51ac1d130fd4 479 /* insert in SNMP ARP index tree */
mbed_official 0:51ac1d130fd4 480 snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
mbed_official 0:51ac1d130fd4 481
mbed_official 0:51ac1d130fd4 482 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
mbed_official 0:51ac1d130fd4 483 /* update address */
mbed_official 0:51ac1d130fd4 484 ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
mbed_official 0:51ac1d130fd4 485 /* reset time stamp */
mbed_official 0:51ac1d130fd4 486 arp_table[i].ctime = 0;
mbed_official 0:51ac1d130fd4 487 /* this is where we will send out queued packets! */
mbed_official 0:51ac1d130fd4 488 #if ARP_QUEUEING
mbed_official 0:51ac1d130fd4 489 while (arp_table[i].q != NULL) {
mbed_official 0:51ac1d130fd4 490 struct pbuf *p;
mbed_official 0:51ac1d130fd4 491 /* remember remainder of queue */
mbed_official 0:51ac1d130fd4 492 struct etharp_q_entry *q = arp_table[i].q;
mbed_official 0:51ac1d130fd4 493 /* pop first item off the queue */
mbed_official 0:51ac1d130fd4 494 arp_table[i].q = q->next;
mbed_official 0:51ac1d130fd4 495 /* get the packet pointer */
mbed_official 0:51ac1d130fd4 496 p = q->p;
mbed_official 0:51ac1d130fd4 497 /* now queue entry can be freed */
mbed_official 0:51ac1d130fd4 498 memp_free(MEMP_ARP_QUEUE, q);
mbed_official 0:51ac1d130fd4 499 #else /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 500 if (arp_table[i].q != NULL) {
mbed_official 0:51ac1d130fd4 501 struct pbuf *p = arp_table[i].q;
mbed_official 0:51ac1d130fd4 502 arp_table[i].q = NULL;
mbed_official 0:51ac1d130fd4 503 #endif /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 504 /* send the queued IP packet */
mbed_official 0:51ac1d130fd4 505 etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
mbed_official 0:51ac1d130fd4 506 /* free the queued IP packet */
mbed_official 0:51ac1d130fd4 507 pbuf_free(p);
mbed_official 0:51ac1d130fd4 508 }
mbed_official 0:51ac1d130fd4 509 return ERR_OK;
mbed_official 0:51ac1d130fd4 510 }
mbed_official 0:51ac1d130fd4 511
mbed_official 0:51ac1d130fd4 512 #if ETHARP_SUPPORT_STATIC_ENTRIES
mbed_official 0:51ac1d130fd4 513 /** Add a new static entry to the ARP table. If an entry exists for the
mbed_official 0:51ac1d130fd4 514 * specified IP address, this entry is overwritten.
mbed_official 0:51ac1d130fd4 515 * If packets are queued for the specified IP address, they are sent out.
mbed_official 0:51ac1d130fd4 516 *
mbed_official 0:51ac1d130fd4 517 * @param ipaddr IP address for the new static entry
mbed_official 0:51ac1d130fd4 518 * @param ethaddr ethernet address for the new static entry
mbed_official 0:51ac1d130fd4 519 * @return @see return values of etharp_add_static_entry
mbed_official 0:51ac1d130fd4 520 */
mbed_official 0:51ac1d130fd4 521 err_t
mbed_official 0:51ac1d130fd4 522 etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr)
mbed_official 0:51ac1d130fd4 523 {
mbed_official 0:51ac1d130fd4 524 struct netif *netif;
mbed_official 0:51ac1d130fd4 525 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
mbed_official 0:51ac1d130fd4 526 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
mbed_official 0:51ac1d130fd4 527 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
mbed_official 0:51ac1d130fd4 528 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
mbed_official 0:51ac1d130fd4 529
mbed_official 0:51ac1d130fd4 530 netif = ip_route(ipaddr);
mbed_official 0:51ac1d130fd4 531 if (netif == NULL) {
mbed_official 0:51ac1d130fd4 532 return ERR_RTE;
mbed_official 0:51ac1d130fd4 533 }
mbed_official 0:51ac1d130fd4 534
mbed_official 0:51ac1d130fd4 535 return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
mbed_official 0:51ac1d130fd4 536 }
mbed_official 0:51ac1d130fd4 537
mbed_official 0:51ac1d130fd4 538 /** Remove a static entry from the ARP table previously added with a call to
mbed_official 0:51ac1d130fd4 539 * etharp_add_static_entry.
mbed_official 0:51ac1d130fd4 540 *
mbed_official 0:51ac1d130fd4 541 * @param ipaddr IP address of the static entry to remove
mbed_official 0:51ac1d130fd4 542 * @return ERR_OK: entry removed
mbed_official 0:51ac1d130fd4 543 * ERR_MEM: entry wasn't found
mbed_official 0:51ac1d130fd4 544 * ERR_ARG: entry wasn't a static entry but a dynamic one
mbed_official 0:51ac1d130fd4 545 */
mbed_official 0:51ac1d130fd4 546 err_t
mbed_official 0:51ac1d130fd4 547 etharp_remove_static_entry(ip_addr_t *ipaddr)
mbed_official 0:51ac1d130fd4 548 {
mbed_official 0:51ac1d130fd4 549 s8_t i;
mbed_official 0:51ac1d130fd4 550 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
mbed_official 0:51ac1d130fd4 551 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
mbed_official 0:51ac1d130fd4 552
mbed_official 0:51ac1d130fd4 553 /* find or create ARP entry */
mbed_official 0:51ac1d130fd4 554 i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
mbed_official 0:51ac1d130fd4 555 /* bail out if no entry could be found */
mbed_official 0:51ac1d130fd4 556 if (i < 0) {
mbed_official 0:51ac1d130fd4 557 return (err_t)i;
mbed_official 0:51ac1d130fd4 558 }
mbed_official 0:51ac1d130fd4 559
mbed_official 0:51ac1d130fd4 560 if ((arp_table[i].state != ETHARP_STATE_STABLE) ||
mbed_official 0:51ac1d130fd4 561 (arp_table[i].static_entry == 0)) {
mbed_official 0:51ac1d130fd4 562 /* entry wasn't a static entry, cannot remove it */
mbed_official 0:51ac1d130fd4 563 return ERR_ARG;
mbed_official 0:51ac1d130fd4 564 }
mbed_official 0:51ac1d130fd4 565 /* entry found, free it */
mbed_official 0:51ac1d130fd4 566 free_entry(i);
mbed_official 0:51ac1d130fd4 567 return ERR_OK;
mbed_official 0:51ac1d130fd4 568 }
mbed_official 0:51ac1d130fd4 569 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
mbed_official 0:51ac1d130fd4 570
mbed_official 0:51ac1d130fd4 571 /**
mbed_official 0:51ac1d130fd4 572 * Finds (stable) ethernet/IP address pair from ARP table
mbed_official 0:51ac1d130fd4 573 * using interface and IP address index.
mbed_official 0:51ac1d130fd4 574 * @note the addresses in the ARP table are in network order!
mbed_official 0:51ac1d130fd4 575 *
mbed_official 0:51ac1d130fd4 576 * @param netif points to interface index
mbed_official 0:51ac1d130fd4 577 * @param ipaddr points to the (network order) IP address index
mbed_official 0:51ac1d130fd4 578 * @param eth_ret points to return pointer
mbed_official 0:51ac1d130fd4 579 * @param ip_ret points to return pointer
mbed_official 0:51ac1d130fd4 580 * @return table index if found, -1 otherwise
mbed_official 0:51ac1d130fd4 581 */
mbed_official 0:51ac1d130fd4 582 s8_t
mbed_official 0:51ac1d130fd4 583 etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
mbed_official 0:51ac1d130fd4 584 struct eth_addr **eth_ret, ip_addr_t **ip_ret)
mbed_official 0:51ac1d130fd4 585 {
mbed_official 0:51ac1d130fd4 586 s8_t i;
mbed_official 0:51ac1d130fd4 587
mbed_official 0:51ac1d130fd4 588 LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
mbed_official 0:51ac1d130fd4 589 eth_ret != NULL && ip_ret != NULL);
mbed_official 0:51ac1d130fd4 590
mbed_official 0:51ac1d130fd4 591 LWIP_UNUSED_ARG(netif);
mbed_official 0:51ac1d130fd4 592
mbed_official 0:51ac1d130fd4 593 i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
mbed_official 0:51ac1d130fd4 594 if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
mbed_official 0:51ac1d130fd4 595 *eth_ret = &arp_table[i].ethaddr;
mbed_official 0:51ac1d130fd4 596 *ip_ret = &arp_table[i].ipaddr;
mbed_official 0:51ac1d130fd4 597 return i;
mbed_official 0:51ac1d130fd4 598 }
mbed_official 0:51ac1d130fd4 599 return -1;
mbed_official 0:51ac1d130fd4 600 }
mbed_official 0:51ac1d130fd4 601
mbed_official 0:51ac1d130fd4 602 #if ETHARP_TRUST_IP_MAC
mbed_official 0:51ac1d130fd4 603 /**
mbed_official 0:51ac1d130fd4 604 * Updates the ARP table using the given IP packet.
mbed_official 0:51ac1d130fd4 605 *
mbed_official 0:51ac1d130fd4 606 * Uses the incoming IP packet's source address to update the
mbed_official 0:51ac1d130fd4 607 * ARP cache for the local network. The function does not alter
mbed_official 0:51ac1d130fd4 608 * or free the packet. This function must be called before the
mbed_official 0:51ac1d130fd4 609 * packet p is passed to the IP layer.
mbed_official 0:51ac1d130fd4 610 *
mbed_official 0:51ac1d130fd4 611 * @param netif The lwIP network interface on which the IP packet pbuf arrived.
mbed_official 0:51ac1d130fd4 612 * @param p The IP packet that arrived on netif.
mbed_official 0:51ac1d130fd4 613 *
mbed_official 0:51ac1d130fd4 614 * @return NULL
mbed_official 0:51ac1d130fd4 615 *
mbed_official 0:51ac1d130fd4 616 * @see pbuf_free()
mbed_official 0:51ac1d130fd4 617 */
mbed_official 0:51ac1d130fd4 618 static void
mbed_official 0:51ac1d130fd4 619 etharp_ip_input(struct netif *netif, struct pbuf *p)
mbed_official 0:51ac1d130fd4 620 {
mbed_official 0:51ac1d130fd4 621 struct eth_hdr *ethhdr;
mbed_official 0:51ac1d130fd4 622 struct ip_hdr *iphdr;
mbed_official 0:51ac1d130fd4 623 ip_addr_t iphdr_src;
mbed_official 0:51ac1d130fd4 624 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
mbed_official 0:51ac1d130fd4 625
mbed_official 0:51ac1d130fd4 626 /* Only insert an entry if the source IP address of the
mbed_official 0:51ac1d130fd4 627 incoming IP packet comes from a host on the local network. */
mbed_official 0:51ac1d130fd4 628 ethhdr = (struct eth_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 629 iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
mbed_official 0:51ac1d130fd4 630 #if ETHARP_SUPPORT_VLAN
mbed_official 0:51ac1d130fd4 631 if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
mbed_official 0:51ac1d130fd4 632 iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
mbed_official 0:51ac1d130fd4 633 }
mbed_official 0:51ac1d130fd4 634 #endif /* ETHARP_SUPPORT_VLAN */
mbed_official 0:51ac1d130fd4 635
mbed_official 0:51ac1d130fd4 636 ip_addr_copy(iphdr_src, iphdr->src);
mbed_official 0:51ac1d130fd4 637
mbed_official 0:51ac1d130fd4 638 /* source is not on the local network? */
mbed_official 0:51ac1d130fd4 639 if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) {
mbed_official 0:51ac1d130fd4 640 /* do nothing */
mbed_official 0:51ac1d130fd4 641 return;
mbed_official 0:51ac1d130fd4 642 }
mbed_official 0:51ac1d130fd4 643
mbed_official 0:51ac1d130fd4 644 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
mbed_official 0:51ac1d130fd4 645 /* update the source IP address in the cache, if present */
mbed_official 0:51ac1d130fd4 646 /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk
mbed_official 0:51ac1d130fd4 647 * back soon (for example, if the destination IP address is ours. */
mbed_official 0:51ac1d130fd4 648 update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
mbed_official 0:51ac1d130fd4 649 }
mbed_official 0:51ac1d130fd4 650 #endif /* ETHARP_TRUST_IP_MAC */
mbed_official 0:51ac1d130fd4 651
mbed_official 0:51ac1d130fd4 652 /**
mbed_official 0:51ac1d130fd4 653 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
mbed_official 0:51ac1d130fd4 654 * send out queued IP packets. Updates cache with snooped address pairs.
mbed_official 0:51ac1d130fd4 655 *
mbed_official 0:51ac1d130fd4 656 * Should be called for incoming ARP packets. The pbuf in the argument
mbed_official 0:51ac1d130fd4 657 * is freed by this function.
mbed_official 0:51ac1d130fd4 658 *
mbed_official 0:51ac1d130fd4 659 * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
mbed_official 0:51ac1d130fd4 660 * @param ethaddr Ethernet address of netif.
mbed_official 0:51ac1d130fd4 661 * @param p The ARP packet that arrived on netif. Is freed by this function.
mbed_official 0:51ac1d130fd4 662 *
mbed_official 0:51ac1d130fd4 663 * @return NULL
mbed_official 0:51ac1d130fd4 664 *
mbed_official 0:51ac1d130fd4 665 * @see pbuf_free()
mbed_official 0:51ac1d130fd4 666 */
mbed_official 0:51ac1d130fd4 667 static void
mbed_official 0:51ac1d130fd4 668 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
mbed_official 0:51ac1d130fd4 669 {
mbed_official 0:51ac1d130fd4 670 struct etharp_hdr *hdr;
mbed_official 0:51ac1d130fd4 671 struct eth_hdr *ethhdr;
mbed_official 0:51ac1d130fd4 672 /* these are aligned properly, whereas the ARP header fields might not be */
mbed_official 0:51ac1d130fd4 673 ip_addr_t sipaddr, dipaddr;
mbed_official 0:51ac1d130fd4 674 u8_t for_us;
mbed_official 0:51ac1d130fd4 675 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 676 const u8_t * ethdst_hwaddr;
mbed_official 0:51ac1d130fd4 677 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 678
mbed_official 0:51ac1d130fd4 679 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
mbed_official 0:51ac1d130fd4 680
mbed_official 0:51ac1d130fd4 681 /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
mbed_official 0:51ac1d130fd4 682 since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
mbed_official 0:51ac1d130fd4 683 if (p->len < SIZEOF_ETHARP_PACKET) {
mbed_official 0:51ac1d130fd4 684 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
mbed_official 0:51ac1d130fd4 685 ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
mbed_official 0:51ac1d130fd4 686 (s16_t)SIZEOF_ETHARP_PACKET));
mbed_official 0:51ac1d130fd4 687 ETHARP_STATS_INC(etharp.lenerr);
mbed_official 0:51ac1d130fd4 688 ETHARP_STATS_INC(etharp.drop);
mbed_official 0:51ac1d130fd4 689 pbuf_free(p);
mbed_official 0:51ac1d130fd4 690 return;
mbed_official 0:51ac1d130fd4 691 }
mbed_official 0:51ac1d130fd4 692
mbed_official 0:51ac1d130fd4 693 ethhdr = (struct eth_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 694 hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
mbed_official 0:51ac1d130fd4 695 #if ETHARP_SUPPORT_VLAN
mbed_official 0:51ac1d130fd4 696 if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
mbed_official 0:51ac1d130fd4 697 hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
mbed_official 0:51ac1d130fd4 698 }
mbed_official 0:51ac1d130fd4 699 #endif /* ETHARP_SUPPORT_VLAN */
mbed_official 0:51ac1d130fd4 700
mbed_official 0:51ac1d130fd4 701 /* RFC 826 "Packet Reception": */
mbed_official 0:51ac1d130fd4 702 if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
mbed_official 0:51ac1d130fd4 703 (hdr->hwlen != ETHARP_HWADDR_LEN) ||
mbed_official 0:51ac1d130fd4 704 (hdr->protolen != sizeof(ip_addr_t)) ||
mbed_official 0:51ac1d130fd4 705 (hdr->proto != PP_HTONS(ETHTYPE_IP))) {
mbed_official 0:51ac1d130fd4 706 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
mbed_official 0:51ac1d130fd4 707 ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
mbed_official 0:51ac1d130fd4 708 hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen));
mbed_official 0:51ac1d130fd4 709 ETHARP_STATS_INC(etharp.proterr);
mbed_official 0:51ac1d130fd4 710 ETHARP_STATS_INC(etharp.drop);
mbed_official 0:51ac1d130fd4 711 pbuf_free(p);
mbed_official 0:51ac1d130fd4 712 return;
mbed_official 0:51ac1d130fd4 713 }
mbed_official 0:51ac1d130fd4 714 ETHARP_STATS_INC(etharp.recv);
mbed_official 0:51ac1d130fd4 715
mbed_official 0:51ac1d130fd4 716 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 717 /* We have to check if a host already has configured our random
mbed_official 0:51ac1d130fd4 718 * created link local address and continously check if there is
mbed_official 0:51ac1d130fd4 719 * a host with this IP-address so we can detect collisions */
mbed_official 0:51ac1d130fd4 720 autoip_arp_reply(netif, hdr);
mbed_official 0:51ac1d130fd4 721 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 722
mbed_official 0:51ac1d130fd4 723 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
mbed_official 0:51ac1d130fd4 724 * structure packing (not using structure copy which breaks strict-aliasing rules). */
mbed_official 0:51ac1d130fd4 725 IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
mbed_official 0:51ac1d130fd4 726 IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
mbed_official 0:51ac1d130fd4 727
mbed_official 0:51ac1d130fd4 728 /* this interface is not configured? */
mbed_official 0:51ac1d130fd4 729 if (ip_addr_isany(&netif->ip_addr)) {
mbed_official 0:51ac1d130fd4 730 for_us = 0;
mbed_official 0:51ac1d130fd4 731 } else {
mbed_official 0:51ac1d130fd4 732 /* ARP packet directed to us? */
mbed_official 0:51ac1d130fd4 733 for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));
mbed_official 0:51ac1d130fd4 734 }
mbed_official 0:51ac1d130fd4 735
mbed_official 0:51ac1d130fd4 736 /* ARP message directed to us?
mbed_official 0:51ac1d130fd4 737 -> add IP address in ARP cache; assume requester wants to talk to us,
mbed_official 0:51ac1d130fd4 738 can result in directly sending the queued packets for this host.
mbed_official 0:51ac1d130fd4 739 ARP message not directed to us?
mbed_official 0:51ac1d130fd4 740 -> update the source IP address in the cache, if present */
mbed_official 0:51ac1d130fd4 741 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
mbed_official 0:51ac1d130fd4 742 for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
mbed_official 0:51ac1d130fd4 743
mbed_official 0:51ac1d130fd4 744 /* now act on the message itself */
mbed_official 0:51ac1d130fd4 745 switch (hdr->opcode) {
mbed_official 0:51ac1d130fd4 746 /* ARP request? */
mbed_official 0:51ac1d130fd4 747 case PP_HTONS(ARP_REQUEST):
mbed_official 0:51ac1d130fd4 748 /* ARP request. If it asked for our address, we send out a
mbed_official 0:51ac1d130fd4 749 * reply. In any case, we time-stamp any existing ARP entry,
mbed_official 0:51ac1d130fd4 750 * and possiby send out an IP packet that was queued on it. */
mbed_official 0:51ac1d130fd4 751
mbed_official 0:51ac1d130fd4 752 LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
mbed_official 0:51ac1d130fd4 753 /* ARP request for our address? */
mbed_official 0:51ac1d130fd4 754 if (for_us) {
mbed_official 0:51ac1d130fd4 755
mbed_official 0:51ac1d130fd4 756 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
mbed_official 0:51ac1d130fd4 757 /* Re-use pbuf to send ARP reply.
mbed_official 0:51ac1d130fd4 758 Since we are re-using an existing pbuf, we can't call etharp_raw since
mbed_official 0:51ac1d130fd4 759 that would allocate a new pbuf. */
mbed_official 0:51ac1d130fd4 760 hdr->opcode = htons(ARP_REPLY);
mbed_official 0:51ac1d130fd4 761
mbed_official 0:51ac1d130fd4 762 IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
mbed_official 0:51ac1d130fd4 763 IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr);
mbed_official 0:51ac1d130fd4 764
mbed_official 0:51ac1d130fd4 765 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
mbed_official 0:51ac1d130fd4 766 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
mbed_official 0:51ac1d130fd4 767 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 768 /* If we are using Link-Local, all ARP packets that contain a Link-Local
mbed_official 0:51ac1d130fd4 769 * 'sender IP address' MUST be sent using link-layer broadcast instead of
mbed_official 0:51ac1d130fd4 770 * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
mbed_official 0:51ac1d130fd4 771 ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
mbed_official 0:51ac1d130fd4 772 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 773
mbed_official 0:51ac1d130fd4 774 ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
mbed_official 0:51ac1d130fd4 775 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 776 ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
mbed_official 0:51ac1d130fd4 777 #else /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 778 ETHADDR16_COPY(&ethhdr->dest, &hdr->shwaddr);
mbed_official 0:51ac1d130fd4 779 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 780 ETHADDR16_COPY(&hdr->shwaddr, ethaddr);
mbed_official 0:51ac1d130fd4 781 ETHADDR16_COPY(&ethhdr->src, ethaddr);
mbed_official 0:51ac1d130fd4 782
mbed_official 0:51ac1d130fd4 783 /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
mbed_official 0:51ac1d130fd4 784 are already correct, we tested that before */
mbed_official 0:51ac1d130fd4 785
mbed_official 0:51ac1d130fd4 786 /* return ARP reply */
mbed_official 0:51ac1d130fd4 787 netif->linkoutput(netif, p);
mbed_official 0:51ac1d130fd4 788 /* we are not configured? */
mbed_official 0:51ac1d130fd4 789 } else if (ip_addr_isany(&netif->ip_addr)) {
mbed_official 0:51ac1d130fd4 790 /* { for_us == 0 and netif->ip_addr.addr == 0 } */
mbed_official 0:51ac1d130fd4 791 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
mbed_official 0:51ac1d130fd4 792 /* request was not directed to us */
mbed_official 0:51ac1d130fd4 793 } else {
mbed_official 0:51ac1d130fd4 794 /* { for_us == 0 and netif->ip_addr.addr != 0 } */
mbed_official 0:51ac1d130fd4 795 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
mbed_official 0:51ac1d130fd4 796 }
mbed_official 0:51ac1d130fd4 797 break;
mbed_official 0:51ac1d130fd4 798 case PP_HTONS(ARP_REPLY):
mbed_official 0:51ac1d130fd4 799 /* ARP reply. We already updated the ARP cache earlier. */
mbed_official 0:51ac1d130fd4 800 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
mbed_official 0:51ac1d130fd4 801 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
mbed_official 0:51ac1d130fd4 802 /* DHCP wants to know about ARP replies from any host with an
mbed_official 0:51ac1d130fd4 803 * IP address also offered to us by the DHCP server. We do not
mbed_official 0:51ac1d130fd4 804 * want to take a duplicate IP address on a single network.
mbed_official 0:51ac1d130fd4 805 * @todo How should we handle redundant (fail-over) interfaces? */
mbed_official 0:51ac1d130fd4 806 dhcp_arp_reply(netif, &sipaddr);
mbed_official 0:51ac1d130fd4 807 #endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
mbed_official 0:51ac1d130fd4 808 break;
mbed_official 0:51ac1d130fd4 809 default:
mbed_official 0:51ac1d130fd4 810 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
mbed_official 0:51ac1d130fd4 811 ETHARP_STATS_INC(etharp.err);
mbed_official 0:51ac1d130fd4 812 break;
mbed_official 0:51ac1d130fd4 813 }
mbed_official 0:51ac1d130fd4 814 /* free ARP packet */
mbed_official 0:51ac1d130fd4 815 pbuf_free(p);
mbed_official 0:51ac1d130fd4 816 }
mbed_official 0:51ac1d130fd4 817
mbed_official 0:51ac1d130fd4 818 /**
mbed_official 0:51ac1d130fd4 819 * Resolve and fill-in Ethernet address header for outgoing IP packet.
mbed_official 0:51ac1d130fd4 820 *
mbed_official 0:51ac1d130fd4 821 * For IP multicast and broadcast, corresponding Ethernet addresses
mbed_official 0:51ac1d130fd4 822 * are selected and the packet is transmitted on the link.
mbed_official 0:51ac1d130fd4 823 *
mbed_official 0:51ac1d130fd4 824 * For unicast addresses, the packet is submitted to etharp_query(). In
mbed_official 0:51ac1d130fd4 825 * case the IP address is outside the local network, the IP address of
mbed_official 0:51ac1d130fd4 826 * the gateway is used.
mbed_official 0:51ac1d130fd4 827 *
mbed_official 0:51ac1d130fd4 828 * @param netif The lwIP network interface which the IP packet will be sent on.
mbed_official 0:51ac1d130fd4 829 * @param q The pbuf(s) containing the IP packet to be sent.
mbed_official 0:51ac1d130fd4 830 * @param ipaddr The IP address of the packet destination.
mbed_official 0:51ac1d130fd4 831 *
mbed_official 0:51ac1d130fd4 832 * @return
mbed_official 0:51ac1d130fd4 833 * - ERR_RTE No route to destination (no gateway to external networks),
mbed_official 0:51ac1d130fd4 834 * or the return type of either etharp_query() or etharp_send_ip().
mbed_official 0:51ac1d130fd4 835 */
mbed_official 0:51ac1d130fd4 836 err_t
mbed_official 0:51ac1d130fd4 837 etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
mbed_official 0:51ac1d130fd4 838 {
mbed_official 0:51ac1d130fd4 839 struct eth_addr *dest, mcastaddr;
mbed_official 0:51ac1d130fd4 840
mbed_official 0:51ac1d130fd4 841 /* make room for Ethernet header - should not fail */
mbed_official 0:51ac1d130fd4 842 if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
mbed_official 0:51ac1d130fd4 843 /* bail out */
mbed_official 0:51ac1d130fd4 844 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
mbed_official 0:51ac1d130fd4 845 ("etharp_output: could not allocate room for header.\n"));
mbed_official 0:51ac1d130fd4 846 LINK_STATS_INC(link.lenerr);
mbed_official 0:51ac1d130fd4 847 return ERR_BUF;
mbed_official 0:51ac1d130fd4 848 }
mbed_official 0:51ac1d130fd4 849
mbed_official 0:51ac1d130fd4 850 /* assume unresolved Ethernet address */
mbed_official 0:51ac1d130fd4 851 dest = NULL;
mbed_official 0:51ac1d130fd4 852 /* Determine on destination hardware address. Broadcasts and multicasts
mbed_official 0:51ac1d130fd4 853 * are special, other IP addresses are looked up in the ARP table. */
mbed_official 0:51ac1d130fd4 854
mbed_official 0:51ac1d130fd4 855 /* broadcast destination IP address? */
mbed_official 0:51ac1d130fd4 856 if (ip_addr_isbroadcast(ipaddr, netif)) {
mbed_official 0:51ac1d130fd4 857 /* broadcast on Ethernet also */
mbed_official 0:51ac1d130fd4 858 dest = (struct eth_addr *)&ethbroadcast;
mbed_official 0:51ac1d130fd4 859 /* multicast destination IP address? */
mbed_official 0:51ac1d130fd4 860 } else if (ip_addr_ismulticast(ipaddr)) {
mbed_official 0:51ac1d130fd4 861 /* Hash IP multicast address to MAC address.*/
mbed_official 0:51ac1d130fd4 862 mcastaddr.addr[0] = 0x01;
mbed_official 0:51ac1d130fd4 863 mcastaddr.addr[1] = 0x00;
mbed_official 0:51ac1d130fd4 864 mcastaddr.addr[2] = 0x5e;
mbed_official 0:51ac1d130fd4 865 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mbed_official 0:51ac1d130fd4 866 mcastaddr.addr[4] = ip4_addr3(ipaddr);
mbed_official 0:51ac1d130fd4 867 mcastaddr.addr[5] = ip4_addr4(ipaddr);
mbed_official 0:51ac1d130fd4 868 /* destination Ethernet address is multicast */
mbed_official 0:51ac1d130fd4 869 dest = &mcastaddr;
mbed_official 0:51ac1d130fd4 870 /* unicast destination IP address? */
mbed_official 0:51ac1d130fd4 871 } else {
mbed_official 0:51ac1d130fd4 872 /* outside local network? */
mbed_official 0:51ac1d130fd4 873 if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
mbed_official 0:51ac1d130fd4 874 !ip_addr_islinklocal(ipaddr)) {
mbed_official 0:51ac1d130fd4 875 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 876 struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
mbed_official 0:51ac1d130fd4 877 sizeof(struct eth_hdr));
mbed_official 0:51ac1d130fd4 878 /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
mbed_official 0:51ac1d130fd4 879 a link-local source address must always be "directly to its destination
mbed_official 0:51ac1d130fd4 880 on the same physical link. The host MUST NOT send the packet to any
mbed_official 0:51ac1d130fd4 881 router for forwarding". */
mbed_official 0:51ac1d130fd4 882 if (!ip_addr_islinklocal(&iphdr->src))
mbed_official 0:51ac1d130fd4 883 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 884 {
mbed_official 0:51ac1d130fd4 885 /* interface has default gateway? */
mbed_official 0:51ac1d130fd4 886 if (!ip_addr_isany(&netif->gw)) {
mbed_official 0:51ac1d130fd4 887 /* send to hardware address of default gateway IP address */
mbed_official 0:51ac1d130fd4 888 ipaddr = &(netif->gw);
mbed_official 0:51ac1d130fd4 889 /* no default gateway available */
mbed_official 0:51ac1d130fd4 890 } else {
mbed_official 0:51ac1d130fd4 891 /* no route to destination error (default gateway missing) */
mbed_official 0:51ac1d130fd4 892 return ERR_RTE;
mbed_official 0:51ac1d130fd4 893 }
mbed_official 0:51ac1d130fd4 894 }
mbed_official 0:51ac1d130fd4 895 }
mbed_official 0:51ac1d130fd4 896 #if LWIP_NETIF_HWADDRHINT
mbed_official 0:51ac1d130fd4 897 if (netif->addr_hint != NULL) {
mbed_official 0:51ac1d130fd4 898 /* per-pcb cached entry was given */
mbed_official 0:51ac1d130fd4 899 u8_t etharp_cached_entry = *(netif->addr_hint);
mbed_official 0:51ac1d130fd4 900 if (etharp_cached_entry < ARP_TABLE_SIZE) {
mbed_official 0:51ac1d130fd4 901 #endif /* LWIP_NETIF_HWADDRHINT */
mbed_official 0:51ac1d130fd4 902 if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) &&
mbed_official 0:51ac1d130fd4 903 (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) {
mbed_official 0:51ac1d130fd4 904 /* the per-pcb-cached entry is stable and the right one! */
mbed_official 0:51ac1d130fd4 905 ETHARP_STATS_INC(etharp.cachehit);
mbed_official 0:51ac1d130fd4 906 return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),
mbed_official 0:51ac1d130fd4 907 &arp_table[etharp_cached_entry].ethaddr);
mbed_official 0:51ac1d130fd4 908 }
mbed_official 0:51ac1d130fd4 909 #if LWIP_NETIF_HWADDRHINT
mbed_official 0:51ac1d130fd4 910 }
mbed_official 0:51ac1d130fd4 911 }
mbed_official 0:51ac1d130fd4 912 #endif /* LWIP_NETIF_HWADDRHINT */
mbed_official 0:51ac1d130fd4 913 /* queue on destination Ethernet address belonging to ipaddr */
mbed_official 0:51ac1d130fd4 914 return etharp_query(netif, ipaddr, q);
mbed_official 0:51ac1d130fd4 915 }
mbed_official 0:51ac1d130fd4 916
mbed_official 0:51ac1d130fd4 917 /* continuation for multicast/broadcast destinations */
mbed_official 0:51ac1d130fd4 918 /* obtain source Ethernet address of the given interface */
mbed_official 0:51ac1d130fd4 919 /* send packet directly on the link */
mbed_official 0:51ac1d130fd4 920 return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
mbed_official 0:51ac1d130fd4 921 }
mbed_official 0:51ac1d130fd4 922
mbed_official 0:51ac1d130fd4 923 /**
mbed_official 0:51ac1d130fd4 924 * Send an ARP request for the given IP address and/or queue a packet.
mbed_official 0:51ac1d130fd4 925 *
mbed_official 0:51ac1d130fd4 926 * If the IP address was not yet in the cache, a pending ARP cache entry
mbed_official 0:51ac1d130fd4 927 * is added and an ARP request is sent for the given address. The packet
mbed_official 0:51ac1d130fd4 928 * is queued on this entry.
mbed_official 0:51ac1d130fd4 929 *
mbed_official 0:51ac1d130fd4 930 * If the IP address was already pending in the cache, a new ARP request
mbed_official 0:51ac1d130fd4 931 * is sent for the given address. The packet is queued on this entry.
mbed_official 0:51ac1d130fd4 932 *
mbed_official 0:51ac1d130fd4 933 * If the IP address was already stable in the cache, and a packet is
mbed_official 0:51ac1d130fd4 934 * given, it is directly sent and no ARP request is sent out.
mbed_official 0:51ac1d130fd4 935 *
mbed_official 0:51ac1d130fd4 936 * If the IP address was already stable in the cache, and no packet is
mbed_official 0:51ac1d130fd4 937 * given, an ARP request is sent out.
mbed_official 0:51ac1d130fd4 938 *
mbed_official 0:51ac1d130fd4 939 * @param netif The lwIP network interface on which ipaddr
mbed_official 0:51ac1d130fd4 940 * must be queried for.
mbed_official 0:51ac1d130fd4 941 * @param ipaddr The IP address to be resolved.
mbed_official 0:51ac1d130fd4 942 * @param q If non-NULL, a pbuf that must be delivered to the IP address.
mbed_official 0:51ac1d130fd4 943 * q is not freed by this function.
mbed_official 0:51ac1d130fd4 944 *
mbed_official 0:51ac1d130fd4 945 * @note q must only be ONE packet, not a packet queue!
mbed_official 0:51ac1d130fd4 946 *
mbed_official 0:51ac1d130fd4 947 * @return
mbed_official 0:51ac1d130fd4 948 * - ERR_BUF Could not make room for Ethernet header.
mbed_official 0:51ac1d130fd4 949 * - ERR_MEM Hardware address unknown, and no more ARP entries available
mbed_official 0:51ac1d130fd4 950 * to query for address or queue the packet.
mbed_official 0:51ac1d130fd4 951 * - ERR_MEM Could not queue packet due to memory shortage.
mbed_official 0:51ac1d130fd4 952 * - ERR_RTE No route to destination (no gateway to external networks).
mbed_official 0:51ac1d130fd4 953 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
mbed_official 0:51ac1d130fd4 954 *
mbed_official 0:51ac1d130fd4 955 */
mbed_official 0:51ac1d130fd4 956 err_t
mbed_official 0:51ac1d130fd4 957 etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
mbed_official 0:51ac1d130fd4 958 {
mbed_official 0:51ac1d130fd4 959 struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
mbed_official 0:51ac1d130fd4 960 err_t result = ERR_MEM;
mbed_official 0:51ac1d130fd4 961 s8_t i; /* ARP entry index */
mbed_official 0:51ac1d130fd4 962
mbed_official 0:51ac1d130fd4 963 /* non-unicast address? */
mbed_official 0:51ac1d130fd4 964 if (ip_addr_isbroadcast(ipaddr, netif) ||
mbed_official 0:51ac1d130fd4 965 ip_addr_ismulticast(ipaddr) ||
mbed_official 0:51ac1d130fd4 966 ip_addr_isany(ipaddr)) {
mbed_official 0:51ac1d130fd4 967 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
mbed_official 0:51ac1d130fd4 968 return ERR_ARG;
mbed_official 0:51ac1d130fd4 969 }
mbed_official 0:51ac1d130fd4 970
mbed_official 0:51ac1d130fd4 971 /* find entry in ARP cache, ask to create entry if queueing packet */
mbed_official 0:51ac1d130fd4 972 i = find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);
mbed_official 0:51ac1d130fd4 973
mbed_official 0:51ac1d130fd4 974 /* could not find or create entry? */
mbed_official 0:51ac1d130fd4 975 if (i < 0) {
mbed_official 0:51ac1d130fd4 976 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
mbed_official 0:51ac1d130fd4 977 if (q) {
mbed_official 0:51ac1d130fd4 978 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
mbed_official 0:51ac1d130fd4 979 ETHARP_STATS_INC(etharp.memerr);
mbed_official 0:51ac1d130fd4 980 }
mbed_official 0:51ac1d130fd4 981 return (err_t)i;
mbed_official 0:51ac1d130fd4 982 }
mbed_official 0:51ac1d130fd4 983
mbed_official 0:51ac1d130fd4 984 /* mark a fresh entry as pending (we just sent a request) */
mbed_official 0:51ac1d130fd4 985 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
mbed_official 0:51ac1d130fd4 986 arp_table[i].state = ETHARP_STATE_PENDING;
mbed_official 0:51ac1d130fd4 987 }
mbed_official 0:51ac1d130fd4 988
mbed_official 0:51ac1d130fd4 989 /* { i is either a STABLE or (new or existing) PENDING entry } */
mbed_official 0:51ac1d130fd4 990 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
mbed_official 0:51ac1d130fd4 991 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
mbed_official 0:51ac1d130fd4 992 (arp_table[i].state == ETHARP_STATE_STABLE)));
mbed_official 0:51ac1d130fd4 993
mbed_official 0:51ac1d130fd4 994 /* do we have a pending entry? or an implicit query request? */
mbed_official 0:51ac1d130fd4 995 if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
mbed_official 0:51ac1d130fd4 996 /* try to resolve it; send out ARP request */
mbed_official 0:51ac1d130fd4 997 result = etharp_request(netif, ipaddr);
mbed_official 0:51ac1d130fd4 998 if (result != ERR_OK) {
mbed_official 0:51ac1d130fd4 999 /* ARP request couldn't be sent */
mbed_official 0:51ac1d130fd4 1000 /* We don't re-send arp request in etharp_tmr, but we still queue packets,
mbed_official 0:51ac1d130fd4 1001 since this failure could be temporary, and the next packet calling
mbed_official 0:51ac1d130fd4 1002 etharp_query again could lead to sending the queued packets. */
mbed_official 0:51ac1d130fd4 1003 }
mbed_official 0:51ac1d130fd4 1004 if (q == NULL) {
mbed_official 0:51ac1d130fd4 1005 return result;
mbed_official 0:51ac1d130fd4 1006 }
mbed_official 0:51ac1d130fd4 1007 }
mbed_official 0:51ac1d130fd4 1008
mbed_official 0:51ac1d130fd4 1009 /* packet given? */
mbed_official 0:51ac1d130fd4 1010 LWIP_ASSERT("q != NULL", q != NULL);
mbed_official 0:51ac1d130fd4 1011 /* stable entry? */
mbed_official 0:51ac1d130fd4 1012 if (arp_table[i].state == ETHARP_STATE_STABLE) {
mbed_official 0:51ac1d130fd4 1013 /* we have a valid IP->Ethernet address mapping */
mbed_official 0:51ac1d130fd4 1014 ETHARP_SET_HINT(netif, i);
mbed_official 0:51ac1d130fd4 1015 /* send the packet */
mbed_official 0:51ac1d130fd4 1016 result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
mbed_official 0:51ac1d130fd4 1017 /* pending entry? (either just created or already pending */
mbed_official 0:51ac1d130fd4 1018 } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
mbed_official 0:51ac1d130fd4 1019 /* entry is still pending, queue the given packet 'q' */
mbed_official 0:51ac1d130fd4 1020 struct pbuf *p;
mbed_official 0:51ac1d130fd4 1021 int copy_needed = 0;
mbed_official 0:51ac1d130fd4 1022 /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
mbed_official 0:51ac1d130fd4 1023 * to copy the whole queue into a new PBUF_RAM (see bug #11400)
mbed_official 0:51ac1d130fd4 1024 * PBUF_ROMs can be left as they are, since ROM must not get changed. */
mbed_official 0:51ac1d130fd4 1025 p = q;
mbed_official 0:51ac1d130fd4 1026 while (p) {
mbed_official 0:51ac1d130fd4 1027 LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
mbed_official 0:51ac1d130fd4 1028 if(p->type != PBUF_ROM) {
mbed_official 0:51ac1d130fd4 1029 copy_needed = 1;
mbed_official 0:51ac1d130fd4 1030 break;
mbed_official 0:51ac1d130fd4 1031 }
mbed_official 0:51ac1d130fd4 1032 p = p->next;
mbed_official 0:51ac1d130fd4 1033 }
mbed_official 0:51ac1d130fd4 1034 if(copy_needed) {
mbed_official 0:51ac1d130fd4 1035 /* copy the whole packet into new pbufs */
mbed_official 0:51ac1d130fd4 1036 p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
mbed_official 0:51ac1d130fd4 1037 if(p != NULL) {
mbed_official 0:51ac1d130fd4 1038 if (pbuf_copy(p, q) != ERR_OK) {
mbed_official 0:51ac1d130fd4 1039 pbuf_free(p);
mbed_official 0:51ac1d130fd4 1040 p = NULL;
mbed_official 0:51ac1d130fd4 1041 }
mbed_official 0:51ac1d130fd4 1042 }
mbed_official 0:51ac1d130fd4 1043 } else {
mbed_official 0:51ac1d130fd4 1044 /* referencing the old pbuf is enough */
mbed_official 0:51ac1d130fd4 1045 p = q;
mbed_official 0:51ac1d130fd4 1046 pbuf_ref(p);
mbed_official 0:51ac1d130fd4 1047 }
mbed_official 0:51ac1d130fd4 1048 /* packet could be taken over? */
mbed_official 0:51ac1d130fd4 1049 if (p != NULL) {
mbed_official 0:51ac1d130fd4 1050 /* queue packet ... */
mbed_official 0:51ac1d130fd4 1051 #if ARP_QUEUEING
mbed_official 0:51ac1d130fd4 1052 struct etharp_q_entry *new_entry;
mbed_official 0:51ac1d130fd4 1053 /* allocate a new arp queue entry */
mbed_official 0:51ac1d130fd4 1054 new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
mbed_official 0:51ac1d130fd4 1055 if (new_entry != NULL) {
mbed_official 0:51ac1d130fd4 1056 new_entry->next = 0;
mbed_official 0:51ac1d130fd4 1057 new_entry->p = p;
mbed_official 0:51ac1d130fd4 1058 if(arp_table[i].q != NULL) {
mbed_official 0:51ac1d130fd4 1059 /* queue was already existent, append the new entry to the end */
mbed_official 0:51ac1d130fd4 1060 struct etharp_q_entry *r;
mbed_official 0:51ac1d130fd4 1061 r = arp_table[i].q;
mbed_official 0:51ac1d130fd4 1062 while (r->next != NULL) {
mbed_official 0:51ac1d130fd4 1063 r = r->next;
mbed_official 0:51ac1d130fd4 1064 }
mbed_official 0:51ac1d130fd4 1065 r->next = new_entry;
mbed_official 0:51ac1d130fd4 1066 } else {
mbed_official 0:51ac1d130fd4 1067 /* queue did not exist, first item in queue */
mbed_official 0:51ac1d130fd4 1068 arp_table[i].q = new_entry;
mbed_official 0:51ac1d130fd4 1069 }
mbed_official 0:51ac1d130fd4 1070 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
mbed_official 0:51ac1d130fd4 1071 result = ERR_OK;
mbed_official 0:51ac1d130fd4 1072 } else {
mbed_official 0:51ac1d130fd4 1073 /* the pool MEMP_ARP_QUEUE is empty */
mbed_official 0:51ac1d130fd4 1074 pbuf_free(p);
mbed_official 0:51ac1d130fd4 1075 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
mbed_official 0:51ac1d130fd4 1076 result = ERR_MEM;
mbed_official 0:51ac1d130fd4 1077 }
mbed_official 0:51ac1d130fd4 1078 #else /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 1079 /* always queue one packet per ARP request only, freeing a previously queued packet */
mbed_official 0:51ac1d130fd4 1080 if (arp_table[i].q != NULL) {
mbed_official 0:51ac1d130fd4 1081 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
mbed_official 0:51ac1d130fd4 1082 pbuf_free(arp_table[i].q);
mbed_official 0:51ac1d130fd4 1083 }
mbed_official 0:51ac1d130fd4 1084 arp_table[i].q = p;
mbed_official 0:51ac1d130fd4 1085 result = ERR_OK;
mbed_official 0:51ac1d130fd4 1086 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
mbed_official 0:51ac1d130fd4 1087 #endif /* ARP_QUEUEING */
mbed_official 0:51ac1d130fd4 1088 } else {
mbed_official 0:51ac1d130fd4 1089 ETHARP_STATS_INC(etharp.memerr);
mbed_official 0:51ac1d130fd4 1090 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
mbed_official 0:51ac1d130fd4 1091 result = ERR_MEM;
mbed_official 0:51ac1d130fd4 1092 }
mbed_official 0:51ac1d130fd4 1093 }
mbed_official 0:51ac1d130fd4 1094 return result;
mbed_official 0:51ac1d130fd4 1095 }
mbed_official 0:51ac1d130fd4 1096
mbed_official 0:51ac1d130fd4 1097 /**
mbed_official 0:51ac1d130fd4 1098 * Send a raw ARP packet (opcode and all addresses can be modified)
mbed_official 0:51ac1d130fd4 1099 *
mbed_official 0:51ac1d130fd4 1100 * @param netif the lwip network interface on which to send the ARP packet
mbed_official 0:51ac1d130fd4 1101 * @param ethsrc_addr the source MAC address for the ethernet header
mbed_official 0:51ac1d130fd4 1102 * @param ethdst_addr the destination MAC address for the ethernet header
mbed_official 0:51ac1d130fd4 1103 * @param hwsrc_addr the source MAC address for the ARP protocol header
mbed_official 0:51ac1d130fd4 1104 * @param ipsrc_addr the source IP address for the ARP protocol header
mbed_official 0:51ac1d130fd4 1105 * @param hwdst_addr the destination MAC address for the ARP protocol header
mbed_official 0:51ac1d130fd4 1106 * @param ipdst_addr the destination IP address for the ARP protocol header
mbed_official 0:51ac1d130fd4 1107 * @param opcode the type of the ARP packet
mbed_official 0:51ac1d130fd4 1108 * @return ERR_OK if the ARP packet has been sent
mbed_official 0:51ac1d130fd4 1109 * ERR_MEM if the ARP packet couldn't be allocated
mbed_official 0:51ac1d130fd4 1110 * any other err_t on failure
mbed_official 0:51ac1d130fd4 1111 */
mbed_official 0:51ac1d130fd4 1112 #if !LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 1113 static
mbed_official 0:51ac1d130fd4 1114 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 1115 err_t
mbed_official 0:51ac1d130fd4 1116 etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
mbed_official 0:51ac1d130fd4 1117 const struct eth_addr *ethdst_addr,
mbed_official 0:51ac1d130fd4 1118 const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
mbed_official 0:51ac1d130fd4 1119 const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
mbed_official 0:51ac1d130fd4 1120 const u16_t opcode)
mbed_official 0:51ac1d130fd4 1121 {
mbed_official 0:51ac1d130fd4 1122 struct pbuf *p;
mbed_official 0:51ac1d130fd4 1123 err_t result = ERR_OK;
mbed_official 0:51ac1d130fd4 1124 struct eth_hdr *ethhdr;
mbed_official 0:51ac1d130fd4 1125 struct etharp_hdr *hdr;
mbed_official 0:51ac1d130fd4 1126 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 1127 const u8_t * ethdst_hwaddr;
mbed_official 0:51ac1d130fd4 1128 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 1129
mbed_official 0:51ac1d130fd4 1130 /* allocate a pbuf for the outgoing ARP request packet */
mbed_official 0:51ac1d130fd4 1131 p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
mbed_official 0:51ac1d130fd4 1132 /* could allocate a pbuf for an ARP request? */
mbed_official 0:51ac1d130fd4 1133 if (p == NULL) {
mbed_official 0:51ac1d130fd4 1134 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
mbed_official 0:51ac1d130fd4 1135 ("etharp_raw: could not allocate pbuf for ARP request.\n"));
mbed_official 0:51ac1d130fd4 1136 ETHARP_STATS_INC(etharp.memerr);
mbed_official 0:51ac1d130fd4 1137 return ERR_MEM;
mbed_official 0:51ac1d130fd4 1138 }
mbed_official 0:51ac1d130fd4 1139 LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
mbed_official 0:51ac1d130fd4 1140 (p->len >= SIZEOF_ETHARP_PACKET));
mbed_official 0:51ac1d130fd4 1141
mbed_official 0:51ac1d130fd4 1142 ethhdr = (struct eth_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 1143 hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
mbed_official 0:51ac1d130fd4 1144 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
mbed_official 0:51ac1d130fd4 1145 hdr->opcode = htons(opcode);
mbed_official 0:51ac1d130fd4 1146
mbed_official 0:51ac1d130fd4 1147 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
mbed_official 0:51ac1d130fd4 1148 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
mbed_official 0:51ac1d130fd4 1149 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 1150 /* If we are using Link-Local, all ARP packets that contain a Link-Local
mbed_official 0:51ac1d130fd4 1151 * 'sender IP address' MUST be sent using link-layer broadcast instead of
mbed_official 0:51ac1d130fd4 1152 * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
mbed_official 0:51ac1d130fd4 1153 ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
mbed_official 0:51ac1d130fd4 1154 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 1155 /* Write the ARP MAC-Addresses */
mbed_official 0:51ac1d130fd4 1156 ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
mbed_official 0:51ac1d130fd4 1157 ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
mbed_official 0:51ac1d130fd4 1158 /* Write the Ethernet MAC-Addresses */
mbed_official 0:51ac1d130fd4 1159 #if LWIP_AUTOIP
mbed_official 0:51ac1d130fd4 1160 ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
mbed_official 0:51ac1d130fd4 1161 #else /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 1162 ETHADDR16_COPY(&ethhdr->dest, ethdst_addr);
mbed_official 0:51ac1d130fd4 1163 #endif /* LWIP_AUTOIP */
mbed_official 0:51ac1d130fd4 1164 ETHADDR16_COPY(&ethhdr->src, ethsrc_addr);
mbed_official 0:51ac1d130fd4 1165 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
mbed_official 0:51ac1d130fd4 1166 * structure packing. */
mbed_official 0:51ac1d130fd4 1167 IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
mbed_official 0:51ac1d130fd4 1168 IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
mbed_official 0:51ac1d130fd4 1169
mbed_official 0:51ac1d130fd4 1170 hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
mbed_official 0:51ac1d130fd4 1171 hdr->proto = PP_HTONS(ETHTYPE_IP);
mbed_official 0:51ac1d130fd4 1172 /* set hwlen and protolen */
mbed_official 0:51ac1d130fd4 1173 hdr->hwlen = ETHARP_HWADDR_LEN;
mbed_official 0:51ac1d130fd4 1174 hdr->protolen = sizeof(ip_addr_t);
mbed_official 0:51ac1d130fd4 1175
mbed_official 0:51ac1d130fd4 1176 ethhdr->type = PP_HTONS(ETHTYPE_ARP);
mbed_official 0:51ac1d130fd4 1177 /* send ARP query */
mbed_official 0:51ac1d130fd4 1178 result = netif->linkoutput(netif, p);
mbed_official 0:51ac1d130fd4 1179 ETHARP_STATS_INC(etharp.xmit);
mbed_official 0:51ac1d130fd4 1180 /* free ARP query packet */
mbed_official 0:51ac1d130fd4 1181 pbuf_free(p);
mbed_official 0:51ac1d130fd4 1182 p = NULL;
mbed_official 0:51ac1d130fd4 1183 /* could not allocate pbuf for ARP request */
mbed_official 0:51ac1d130fd4 1184
mbed_official 0:51ac1d130fd4 1185 return result;
mbed_official 0:51ac1d130fd4 1186 }
mbed_official 0:51ac1d130fd4 1187
mbed_official 0:51ac1d130fd4 1188 /**
mbed_official 0:51ac1d130fd4 1189 * Send an ARP request packet asking for ipaddr.
mbed_official 0:51ac1d130fd4 1190 *
mbed_official 0:51ac1d130fd4 1191 * @param netif the lwip network interface on which to send the request
mbed_official 0:51ac1d130fd4 1192 * @param ipaddr the IP address for which to ask
mbed_official 0:51ac1d130fd4 1193 * @return ERR_OK if the request has been sent
mbed_official 0:51ac1d130fd4 1194 * ERR_MEM if the ARP packet couldn't be allocated
mbed_official 0:51ac1d130fd4 1195 * any other err_t on failure
mbed_official 0:51ac1d130fd4 1196 */
mbed_official 0:51ac1d130fd4 1197 err_t
mbed_official 0:51ac1d130fd4 1198 etharp_request(struct netif *netif, ip_addr_t *ipaddr)
mbed_official 0:51ac1d130fd4 1199 {
mbed_official 0:51ac1d130fd4 1200 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
mbed_official 0:51ac1d130fd4 1201 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
mbed_official 0:51ac1d130fd4 1202 (struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
mbed_official 0:51ac1d130fd4 1203 ipaddr, ARP_REQUEST);
mbed_official 0:51ac1d130fd4 1204 }
mbed_official 0:51ac1d130fd4 1205 #endif /* LWIP_ARP */
mbed_official 0:51ac1d130fd4 1206
mbed_official 0:51ac1d130fd4 1207 /**
mbed_official 0:51ac1d130fd4 1208 * Process received ethernet frames. Using this function instead of directly
mbed_official 0:51ac1d130fd4 1209 * calling ip_input and passing ARP frames through etharp in ethernetif_input,
mbed_official 0:51ac1d130fd4 1210 * the ARP cache is protected from concurrent access.
mbed_official 0:51ac1d130fd4 1211 *
mbed_official 0:51ac1d130fd4 1212 * @param p the recevied packet, p->payload pointing to the ethernet header
mbed_official 0:51ac1d130fd4 1213 * @param netif the network interface on which the packet was received
mbed_official 0:51ac1d130fd4 1214 */
mbed_official 0:51ac1d130fd4 1215 err_t
mbed_official 0:51ac1d130fd4 1216 ethernet_input(struct pbuf *p, struct netif *netif)
mbed_official 0:51ac1d130fd4 1217 {
mbed_official 0:51ac1d130fd4 1218 struct eth_hdr* ethhdr;
mbed_official 0:51ac1d130fd4 1219 u16_t type;
mbed_official 0:51ac1d130fd4 1220 s16_t ip_hdr_offset = SIZEOF_ETH_HDR;
mbed_official 0:51ac1d130fd4 1221
mbed_official 0:51ac1d130fd4 1222 if (p->len <= SIZEOF_ETH_HDR) {
mbed_official 0:51ac1d130fd4 1223 /* a packet with only an ethernet header (or less) is not valid for us */
mbed_official 0:51ac1d130fd4 1224 ETHARP_STATS_INC(etharp.proterr);
mbed_official 0:51ac1d130fd4 1225 ETHARP_STATS_INC(etharp.drop);
mbed_official 0:51ac1d130fd4 1226 goto free_and_return;
mbed_official 0:51ac1d130fd4 1227 }
mbed_official 0:51ac1d130fd4 1228
mbed_official 0:51ac1d130fd4 1229 /* points to packet payload, which starts with an Ethernet header */
mbed_official 0:51ac1d130fd4 1230 ethhdr = (struct eth_hdr *)p->payload;
mbed_official 0:51ac1d130fd4 1231 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
mbed_official 0:51ac1d130fd4 1232 ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",
mbed_official 0:51ac1d130fd4 1233 (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
mbed_official 0:51ac1d130fd4 1234 (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
mbed_official 0:51ac1d130fd4 1235 (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
mbed_official 0:51ac1d130fd4 1236 (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
mbed_official 0:51ac1d130fd4 1237 (unsigned)htons(ethhdr->type)));
mbed_official 0:51ac1d130fd4 1238
mbed_official 0:51ac1d130fd4 1239 type = ethhdr->type;
mbed_official 0:51ac1d130fd4 1240 #if ETHARP_SUPPORT_VLAN
mbed_official 0:51ac1d130fd4 1241 if (type == PP_HTONS(ETHTYPE_VLAN)) {
mbed_official 0:51ac1d130fd4 1242 struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
mbed_official 0:51ac1d130fd4 1243 if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
mbed_official 0:51ac1d130fd4 1244 /* a packet with only an ethernet/vlan header (or less) is not valid for us */
mbed_official 0:51ac1d130fd4 1245 ETHARP_STATS_INC(etharp.proterr);
mbed_official 0:51ac1d130fd4 1246 ETHARP_STATS_INC(etharp.drop);
mbed_official 0:51ac1d130fd4 1247 goto free_and_return;
mbed_official 0:51ac1d130fd4 1248 }
mbed_official 0:51ac1d130fd4 1249 #ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
mbed_official 0:51ac1d130fd4 1250 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
mbed_official 0:51ac1d130fd4 1251 /* silently ignore this packet: not for our VLAN */
mbed_official 0:51ac1d130fd4 1252 pbuf_free(p);
mbed_official 0:51ac1d130fd4 1253 return ERR_OK;
mbed_official 0:51ac1d130fd4 1254 }
mbed_official 0:51ac1d130fd4 1255 #endif /* ETHARP_VLAN_CHECK */
mbed_official 0:51ac1d130fd4 1256 type = vlan->tpid;
mbed_official 0:51ac1d130fd4 1257 ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
mbed_official 0:51ac1d130fd4 1258 }
mbed_official 0:51ac1d130fd4 1259 #endif /* ETHARP_SUPPORT_VLAN */
mbed_official 0:51ac1d130fd4 1260
mbed_official 0:51ac1d130fd4 1261 #if LWIP_ARP_FILTER_NETIF
mbed_official 0:51ac1d130fd4 1262 netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
mbed_official 0:51ac1d130fd4 1263 #endif /* LWIP_ARP_FILTER_NETIF*/
mbed_official 0:51ac1d130fd4 1264
mbed_official 0:51ac1d130fd4 1265 switch (type) {
mbed_official 0:51ac1d130fd4 1266 #if LWIP_ARP
mbed_official 0:51ac1d130fd4 1267 /* IP packet? */
mbed_official 0:51ac1d130fd4 1268 case PP_HTONS(ETHTYPE_IP):
mbed_official 0:51ac1d130fd4 1269 if (!(netif->flags & NETIF_FLAG_ETHARP)) {
mbed_official 0:51ac1d130fd4 1270 goto free_and_return;
mbed_official 0:51ac1d130fd4 1271 }
mbed_official 0:51ac1d130fd4 1272 #if ETHARP_TRUST_IP_MAC
mbed_official 0:51ac1d130fd4 1273 /* update ARP table */
mbed_official 0:51ac1d130fd4 1274 etharp_ip_input(netif, p);
mbed_official 0:51ac1d130fd4 1275 #endif /* ETHARP_TRUST_IP_MAC */
mbed_official 0:51ac1d130fd4 1276 /* skip Ethernet header */
mbed_official 0:51ac1d130fd4 1277 if(pbuf_header(p, -ip_hdr_offset)) {
mbed_official 0:51ac1d130fd4 1278 LWIP_ASSERT("Can't move over header in packet", 0);
mbed_official 0:51ac1d130fd4 1279 goto free_and_return;
mbed_official 0:51ac1d130fd4 1280 } else {
mbed_official 0:51ac1d130fd4 1281 /* pass to IP layer */
mbed_official 0:51ac1d130fd4 1282 ip_input(p, netif);
mbed_official 0:51ac1d130fd4 1283 }
mbed_official 0:51ac1d130fd4 1284 break;
mbed_official 0:51ac1d130fd4 1285
mbed_official 0:51ac1d130fd4 1286 case PP_HTONS(ETHTYPE_ARP):
mbed_official 0:51ac1d130fd4 1287 if (!(netif->flags & NETIF_FLAG_ETHARP)) {
mbed_official 0:51ac1d130fd4 1288 goto free_and_return;
mbed_official 0:51ac1d130fd4 1289 }
mbed_official 0:51ac1d130fd4 1290 /* pass p to ARP module */
mbed_official 0:51ac1d130fd4 1291 etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
mbed_official 0:51ac1d130fd4 1292 break;
mbed_official 0:51ac1d130fd4 1293 #endif /* LWIP_ARP */
mbed_official 0:51ac1d130fd4 1294 #if PPPOE_SUPPORT
mbed_official 0:51ac1d130fd4 1295 case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
mbed_official 0:51ac1d130fd4 1296 pppoe_disc_input(netif, p);
mbed_official 0:51ac1d130fd4 1297 break;
mbed_official 0:51ac1d130fd4 1298
mbed_official 0:51ac1d130fd4 1299 case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */
mbed_official 0:51ac1d130fd4 1300 pppoe_data_input(netif, p);
mbed_official 0:51ac1d130fd4 1301 break;
mbed_official 0:51ac1d130fd4 1302 #endif /* PPPOE_SUPPORT */
mbed_official 0:51ac1d130fd4 1303
mbed_official 0:51ac1d130fd4 1304 default:
mbed_official 0:51ac1d130fd4 1305 ETHARP_STATS_INC(etharp.proterr);
mbed_official 0:51ac1d130fd4 1306 ETHARP_STATS_INC(etharp.drop);
mbed_official 0:51ac1d130fd4 1307 goto free_and_return;
mbed_official 0:51ac1d130fd4 1308 }
mbed_official 0:51ac1d130fd4 1309
mbed_official 0:51ac1d130fd4 1310 /* This means the pbuf is freed or consumed,
mbed_official 0:51ac1d130fd4 1311 so the caller doesn't have to free it again */
mbed_official 0:51ac1d130fd4 1312 return ERR_OK;
mbed_official 0:51ac1d130fd4 1313
mbed_official 0:51ac1d130fd4 1314 free_and_return:
mbed_official 0:51ac1d130fd4 1315 pbuf_free(p);
mbed_official 0:51ac1d130fd4 1316 return ERR_OK;
mbed_official 0:51ac1d130fd4 1317 }
mbed_official 0:51ac1d130fd4 1318 #endif /* LWIP_ARP || LWIP_ETHERNET */