Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

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

Who changed what in which revision?

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