00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "lwip/opt.h"
00047
00048 #if LWIP_ARP
00049
00050 #include "lwip/inet.h"
00051 #include "lwip/ip.h"
00052 #include "lwip/stats.h"
00053 #include "lwip/snmp.h"
00054 #include "lwip/dhcp.h"
00055 #include "lwip/autoip.h"
00056 #include "netif/etharp.h"
00057
00058 #if PPPOE_SUPPORT
00059 #include "netif/ppp_oe.h"
00060 #endif
00061
00062 #include <string.h>
00063
00064
00065
00066
00067
00068 #define ARP_MAXAGE 240
00069
00070
00071
00072
00073
00074
00075
00076 #define ARP_MAXPENDING 2
00077
00078 #define HWTYPE_ETHERNET 1
00079
00080 #define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
00081 #define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
00082
00083 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
00084 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
00085
00086 enum etharp_state {
00087 ETHARP_STATE_EMPTY = 0,
00088 ETHARP_STATE_PENDING,
00089 ETHARP_STATE_STABLE
00090 };
00091
00092 struct etharp_entry {
00093 #if ARP_QUEUEING
00094
00095
00096
00097 struct etharp_q_entry *q;
00098 #endif
00099 struct ip_addr ipaddr;
00100 struct eth_addr ethaddr;
00101 enum etharp_state state;
00102 u8_t ctime;
00103 struct netif *netif;
00104 };
00105
00106 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
00107 const struct eth_addr ethzero = {{0,0,0,0,0,0}};
00108 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
00109 #if !LWIP_NETIF_HWADDRHINT
00110 static u8_t etharp_cached_entry;
00111 #endif
00112
00113
00114
00115
00116 #define ETHARP_TRY_HARD 1
00117 #define ETHARP_FIND_ONLY 2
00118
00119 #if LWIP_NETIF_HWADDRHINT
00120 #define NETIF_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
00121 *((netif)->addr_hint) = (hint);
00122 static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif);
00123 #else
00124 static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
00125 #endif
00126
00127 static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
00128
00129
00130
00131 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
00132 #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
00133 #endif
00134
00135
00136 #if ARP_QUEUEING
00137
00138
00139
00140
00141
00142 static void
00143 free_etharp_q(struct etharp_q_entry *q)
00144 {
00145 struct etharp_q_entry *r;
00146 LWIP_ASSERT("q != NULL", q != NULL);
00147 LWIP_ASSERT("q->p != NULL", q->p != NULL);
00148 while (q) {
00149 r = q;
00150 q = q->next;
00151 LWIP_ASSERT("r->p != NULL", (r->p != NULL));
00152 pbuf_free(r->p);
00153 memp_free(MEMP_ARP_QUEUE, r);
00154 }
00155 }
00156 #endif
00157
00158
00159
00160
00161
00162
00163
00164 void
00165 etharp_tmr(void)
00166 {
00167 u8_t i;
00168
00169 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
00170
00171 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
00172 arp_table[i].ctime++;
00173 if (((arp_table[i].state == ETHARP_STATE_STABLE) &&
00174 (arp_table[i].ctime >= ARP_MAXAGE)) ||
00175 ((arp_table[i].state == ETHARP_STATE_PENDING) &&
00176 (arp_table[i].ctime >= ARP_MAXPENDING))) {
00177
00178 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
00179 arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
00180
00181
00182 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
00183 #if ARP_QUEUEING
00184
00185 if (arp_table[i].q != NULL) {
00186
00187 LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
00188 free_etharp_q(arp_table[i].q);
00189 arp_table[i].q = NULL;
00190 }
00191 #endif
00192
00193 arp_table[i].state = ETHARP_STATE_EMPTY;
00194 }
00195 #if ARP_QUEUEING
00196
00197 if (arp_table[i].state == ETHARP_STATE_PENDING) {
00198
00199 }
00200 #endif
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 static s8_t
00227 #if LWIP_NETIF_HWADDRHINT
00228 find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif)
00229 #else
00230 find_entry(struct ip_addr *ipaddr, u8_t flags)
00231 #endif
00232 {
00233 s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
00234 s8_t empty = ARP_TABLE_SIZE;
00235 u8_t i = 0, age_pending = 0, age_stable = 0;
00236 #if ARP_QUEUEING
00237
00238 s8_t old_queue = ARP_TABLE_SIZE;
00239
00240 u8_t age_queue = 0;
00241 #endif
00242
00243
00244
00245 if (ipaddr) {
00246
00247 #if LWIP_NETIF_HWADDRHINT
00248 if ((netif != NULL) && (netif->addr_hint != NULL)) {
00249
00250 u8_t per_pcb_cache = *(netif->addr_hint);
00251 if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) {
00252
00253 if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) {
00254
00255 ETHARP_STATS_INC(etharp.cachehit);
00256 return per_pcb_cache;
00257 }
00258 }
00259 }
00260 #else
00261 if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) {
00262
00263 if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) {
00264
00265 ETHARP_STATS_INC(etharp.cachehit);
00266 return etharp_cached_entry;
00267 }
00268 }
00269 #endif
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 for (i = 0; i < ARP_TABLE_SIZE; ++i) {
00288
00289 if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
00290 LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
00291
00292 empty = i;
00293 }
00294
00295 else if (arp_table[i].state == ETHARP_STATE_PENDING) {
00296
00297 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00298 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
00299
00300 #if LWIP_NETIF_HWADDRHINT
00301 NETIF_SET_HINT(netif, i);
00302 #else
00303 etharp_cached_entry = i;
00304 #endif
00305 return i;
00306 #if ARP_QUEUEING
00307
00308 } else if (arp_table[i].q != NULL) {
00309 if (arp_table[i].ctime >= age_queue) {
00310 old_queue = i;
00311 age_queue = arp_table[i].ctime;
00312 }
00313 #endif
00314
00315 } else {
00316 if (arp_table[i].ctime >= age_pending) {
00317 old_pending = i;
00318 age_pending = arp_table[i].ctime;
00319 }
00320 }
00321 }
00322
00323 else if (arp_table[i].state == ETHARP_STATE_STABLE) {
00324
00325 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00326 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
00327
00328 #if LWIP_NETIF_HWADDRHINT
00329 NETIF_SET_HINT(netif, i);
00330 #else
00331 etharp_cached_entry = i;
00332 #endif
00333 return i;
00334
00335 } else if (arp_table[i].ctime >= age_stable) {
00336 old_stable = i;
00337 age_stable = arp_table[i].ctime;
00338 }
00339 }
00340 }
00341
00342
00343
00344 if (((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))
00345
00346 || ((flags & ETHARP_FIND_ONLY) != 0)) {
00347 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
00348 return (s8_t)ERR_MEM;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 if (empty < ARP_TABLE_SIZE) {
00362 i = empty;
00363 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
00364 }
00365
00366 else if (old_stable < ARP_TABLE_SIZE) {
00367
00368 i = old_stable;
00369 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
00370 #if ARP_QUEUEING
00371
00372 LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
00373 #endif
00374
00375 } else if (old_pending < ARP_TABLE_SIZE) {
00376
00377 i = old_pending;
00378 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
00379 #if ARP_QUEUEING
00380
00381 } else if (old_queue < ARP_TABLE_SIZE) {
00382
00383 i = old_queue;
00384 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)));
00385 free_etharp_q(arp_table[i].q);
00386 arp_table[i].q = NULL;
00387 #endif
00388
00389 } else {
00390 return (s8_t)ERR_MEM;
00391 }
00392
00393
00394 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
00395
00396 if (arp_table[i].state != ETHARP_STATE_EMPTY)
00397 {
00398 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
00399 }
00400
00401 arp_table[i].state = ETHARP_STATE_EMPTY;
00402
00403
00404 if (ipaddr != NULL) {
00405
00406 ip_addr_set(&arp_table[i].ipaddr, ipaddr);
00407 }
00408 arp_table[i].ctime = 0;
00409 #if LWIP_NETIF_HWADDRHINT
00410 NETIF_SET_HINT(netif, i);
00411 #else
00412 etharp_cached_entry = i;
00413 #endif
00414 return (err_t)i;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 static err_t
00428 etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
00429 {
00430 struct eth_hdr *ethhdr = p->payload;
00431 u8_t k;
00432
00433 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
00434 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
00435 k = ETHARP_HWADDR_LEN;
00436 while(k > 0) {
00437 k--;
00438 ethhdr->dest.addr[k] = dst->addr[k];
00439 ethhdr->src.addr[k] = src->addr[k];
00440 }
00441 ethhdr->type = htons(ETHTYPE_IP);
00442 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
00443
00444 return netif->linkoutput(netif, p);
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 static err_t
00467 update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
00468 {
00469 s8_t i;
00470 u8_t k;
00471 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n"));
00472 LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
00473 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",
00474 ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
00475 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
00476 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
00477
00478 if (ip_addr_isany(ipaddr) ||
00479 ip_addr_isbroadcast(ipaddr, netif) ||
00480 ip_addr_ismulticast(ipaddr)) {
00481 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
00482 return ERR_ARG;
00483 }
00484
00485 #if LWIP_NETIF_HWADDRHINT
00486 i = find_entry(ipaddr, flags, netif);
00487 #else
00488 i = find_entry(ipaddr, flags);
00489 #endif
00490
00491 if (i < 0)
00492 return (err_t)i;
00493
00494
00495 arp_table[i].state = ETHARP_STATE_STABLE;
00496
00497 arp_table[i].netif = netif;
00498
00499
00500 snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
00501
00502 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
00503
00504 k = ETHARP_HWADDR_LEN;
00505 while (k > 0) {
00506 k--;
00507 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
00508 }
00509
00510 arp_table[i].ctime = 0;
00511 #if ARP_QUEUEING
00512
00513 while (arp_table[i].q != NULL) {
00514 struct pbuf *p;
00515
00516 struct etharp_q_entry *q = arp_table[i].q;
00517
00518 arp_table[i].q = q->next;
00519
00520 p = q->p;
00521
00522 memp_free(MEMP_ARP_QUEUE, q);
00523
00524 etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
00525
00526 pbuf_free(p);
00527 }
00528 #endif
00529 return ERR_OK;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 s8_t
00544 etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
00545 struct eth_addr **eth_ret, struct ip_addr **ip_ret)
00546 {
00547 s8_t i;
00548
00549 LWIP_UNUSED_ARG(netif);
00550
00551 #if LWIP_NETIF_HWADDRHINT
00552 i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);
00553 #else
00554 i = find_entry(ipaddr, ETHARP_FIND_ONLY);
00555 #endif
00556 if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
00557 *eth_ret = &arp_table[i].ethaddr;
00558 *ip_ret = &arp_table[i].ipaddr;
00559 return i;
00560 }
00561 return -1;
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 void
00580 etharp_ip_input(struct netif *netif, struct pbuf *p)
00581 {
00582 struct eth_hdr *ethhdr;
00583 struct ip_hdr *iphdr;
00584 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00585
00586
00587 ethhdr = p->payload;
00588 iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
00589 #if ETHARP_SUPPORT_VLAN
00590 if (ethhdr->type == ETHTYPE_VLAN) {
00591 iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
00592 }
00593 #endif
00594
00595
00596 if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) {
00597
00598 return;
00599 }
00600
00601 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
00602
00603
00604
00605 update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0);
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 void
00625 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
00626 {
00627 struct etharp_hdr *hdr;
00628 struct eth_hdr *ethhdr;
00629
00630 struct ip_addr sipaddr, dipaddr;
00631 u8_t i;
00632 u8_t for_us;
00633 #if LWIP_AUTOIP
00634 const u8_t * ethdst_hwaddr;
00635 #endif
00636
00637 LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00638
00639
00640
00641 if (p->len < SIZEOF_ETHARP_PACKET) {
00642 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
00643 ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
00644 (s16_t)SIZEOF_ETHARP_PACKET));
00645 ETHARP_STATS_INC(etharp.lenerr);
00646 ETHARP_STATS_INC(etharp.drop);
00647 pbuf_free(p);
00648 return;
00649 }
00650
00651 ethhdr = p->payload;
00652 hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
00653 #if ETHARP_SUPPORT_VLAN
00654 if (ethhdr->type == ETHTYPE_VLAN) {
00655 hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
00656 }
00657 #endif
00658
00659
00660 if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) ||
00661 (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) ||
00662 (hdr->proto != htons(ETHTYPE_IP)) ||
00663 (ethhdr->type != htons(ETHTYPE_ARP))) {
00664 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
00665 ("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",
00666 hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type));
00667 ETHARP_STATS_INC(etharp.proterr);
00668 ETHARP_STATS_INC(etharp.drop);
00669 pbuf_free(p);
00670 return;
00671 }
00672 ETHARP_STATS_INC(etharp.recv);
00673
00674 #if LWIP_AUTOIP
00675
00676
00677
00678 autoip_arp_reply(netif, hdr);
00679 #endif
00680
00681
00682
00683 SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
00684 SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
00685
00686
00687 if (netif->ip_addr.addr == 0) {
00688 for_us = 0;
00689 } else {
00690
00691 for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
00692 }
00693
00694
00695 if (for_us) {
00696
00697
00698 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
00699
00700 } else {
00701
00702 update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
00703 }
00704
00705
00706 switch (htons(hdr->opcode)) {
00707
00708 case ARP_REQUEST:
00709
00710
00711
00712
00713 LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
00714
00715 if (for_us) {
00716
00717 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
00718
00719
00720
00721 hdr->opcode = htons(ARP_REPLY);
00722
00723 hdr->dipaddr = hdr->sipaddr;
00724 SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr));
00725
00726 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
00727 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
00728 i = ETHARP_HWADDR_LEN;
00729 #if LWIP_AUTOIP
00730
00731
00732 ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
00733 #endif
00734
00735 while(i > 0) {
00736 i--;
00737 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
00738 #if LWIP_AUTOIP
00739 ethhdr->dest.addr[i] = ethdst_hwaddr[i];
00740 #else
00741 ethhdr->dest.addr[i] = hdr->shwaddr.addr[i];
00742 #endif
00743 hdr->shwaddr.addr[i] = ethaddr->addr[i];
00744 ethhdr->src.addr[i] = ethaddr->addr[i];
00745 }
00746
00747
00748
00749
00750
00751 netif->linkoutput(netif, p);
00752
00753 } else if (netif->ip_addr.addr == 0) {
00754
00755 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
00756
00757 } else {
00758
00759 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
00760 }
00761 break;
00762 case ARP_REPLY:
00763
00764 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
00765 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
00766
00767
00768
00769
00770 dhcp_arp_reply(netif, &sipaddr);
00771 #endif
00772 break;
00773 default:
00774 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
00775 ETHARP_STATS_INC(etharp.err);
00776 break;
00777 }
00778
00779 pbuf_free(p);
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 err_t
00801 etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr)
00802 {
00803 struct eth_addr *dest, mcastaddr;
00804
00805
00806 if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
00807
00808 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00809 ("etharp_output: could not allocate room for header.\n"));
00810 LINK_STATS_INC(link.lenerr);
00811 return ERR_BUF;
00812 }
00813
00814
00815 dest = NULL;
00816
00817
00818
00819
00820 if (ip_addr_isbroadcast(ipaddr, netif)) {
00821
00822 dest = (struct eth_addr *)ðbroadcast;
00823
00824 } else if (ip_addr_ismulticast(ipaddr)) {
00825
00826 mcastaddr.addr[0] = 0x01;
00827 mcastaddr.addr[1] = 0x00;
00828 mcastaddr.addr[2] = 0x5e;
00829 mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
00830 mcastaddr.addr[4] = ip4_addr3(ipaddr);
00831 mcastaddr.addr[5] = ip4_addr4(ipaddr);
00832
00833 dest = &mcastaddr;
00834
00835 } else {
00836
00837 if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
00838
00839 if (netif->gw.addr != 0) {
00840
00841 ipaddr = &(netif->gw);
00842
00843 } else {
00844
00845 return ERR_RTE;
00846 }
00847 }
00848
00849 return etharp_query(netif, ipaddr, q);
00850 }
00851
00852
00853
00854
00855 return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
00856 }
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 err_t
00892 etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
00893 {
00894 struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
00895 err_t result = ERR_MEM;
00896 s8_t i;
00897
00898
00899 if (ip_addr_isbroadcast(ipaddr, netif) ||
00900 ip_addr_ismulticast(ipaddr) ||
00901 ip_addr_isany(ipaddr)) {
00902 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
00903 return ERR_ARG;
00904 }
00905
00906
00907 #if LWIP_NETIF_HWADDRHINT
00908 i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);
00909 #else
00910 i = find_entry(ipaddr, ETHARP_TRY_HARD);
00911 #endif
00912
00913
00914 if (i < 0) {
00915 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
00916 if (q) {
00917 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
00918 ETHARP_STATS_INC(etharp.memerr);
00919 }
00920 return (err_t)i;
00921 }
00922
00923
00924 if (arp_table[i].state == ETHARP_STATE_EMPTY) {
00925 arp_table[i].state = ETHARP_STATE_PENDING;
00926 }
00927
00928
00929 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
00930 ((arp_table[i].state == ETHARP_STATE_PENDING) ||
00931 (arp_table[i].state == ETHARP_STATE_STABLE)));
00932
00933
00934 if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
00935
00936 result = etharp_request(netif, ipaddr);
00937 if (result != ERR_OK) {
00938
00939
00940
00941
00942 }
00943 }
00944
00945
00946 if (q != NULL) {
00947
00948 if (arp_table[i].state == ETHARP_STATE_STABLE) {
00949
00950
00951 result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
00952
00953 } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
00954 #if ARP_QUEUEING
00955 struct pbuf *p;
00956 int copy_needed = 0;
00957
00958
00959
00960 p = q;
00961 while (p) {
00962 LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
00963 if(p->type != PBUF_ROM) {
00964 copy_needed = 1;
00965 break;
00966 }
00967 p = p->next;
00968 }
00969 if(copy_needed) {
00970
00971 p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
00972 if(p != NULL) {
00973 if (pbuf_copy(p, q) != ERR_OK) {
00974 pbuf_free(p);
00975 p = NULL;
00976 }
00977 }
00978 } else {
00979
00980 p = q;
00981 pbuf_ref(p);
00982 }
00983
00984 if (p != NULL) {
00985
00986 struct etharp_q_entry *new_entry;
00987
00988 new_entry = memp_malloc(MEMP_ARP_QUEUE);
00989 if (new_entry != NULL) {
00990 new_entry->next = 0;
00991 new_entry->p = p;
00992 if(arp_table[i].q != NULL) {
00993
00994 struct etharp_q_entry *r;
00995 r = arp_table[i].q;
00996 while (r->next != NULL) {
00997 r = r->next;
00998 }
00999 r->next = new_entry;
01000 } else {
01001
01002 arp_table[i].q = new_entry;
01003 }
01004 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
01005 result = ERR_OK;
01006 } else {
01007
01008 pbuf_free(p);
01009 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));
01010
01011 }
01012 } else {
01013 ETHARP_STATS_INC(etharp.memerr);
01014 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));
01015
01016 }
01017 #else
01018
01019
01020 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
01021 #endif
01022 }
01023 }
01024 return result;
01025 }
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042 #if !LWIP_AUTOIP
01043 static
01044 #endif
01045 err_t
01046 etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
01047 const struct eth_addr *ethdst_addr,
01048 const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr,
01049 const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr,
01050 const u16_t opcode)
01051 {
01052 struct pbuf *p;
01053 err_t result = ERR_OK;
01054 u8_t k;
01055 struct eth_hdr *ethhdr;
01056 struct etharp_hdr *hdr;
01057 #if LWIP_AUTOIP
01058 const u8_t * ethdst_hwaddr;
01059 #endif
01060
01061
01062 p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
01063
01064 if (p == NULL) {
01065 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01066 ("etharp_raw: could not allocate pbuf for ARP request.\n"));
01067 ETHARP_STATS_INC(etharp.memerr);
01068 return ERR_MEM;
01069 }
01070 LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
01071 (p->len >= SIZEOF_ETHARP_PACKET));
01072
01073 ethhdr = p->payload;
01074 hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
01075 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
01076 hdr->opcode = htons(opcode);
01077
01078 LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
01079 (netif->hwaddr_len == ETHARP_HWADDR_LEN));
01080 k = ETHARP_HWADDR_LEN;
01081 #if LWIP_AUTOIP
01082
01083
01084 ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
01085 #endif
01086
01087 while(k > 0) {
01088 k--;
01089
01090 hdr->shwaddr.addr[k] = hwsrc_addr->addr[k];
01091 hdr->dhwaddr.addr[k] = hwdst_addr->addr[k];
01092
01093 #if LWIP_AUTOIP
01094 ethhdr->dest.addr[k] = ethdst_hwaddr[k];
01095 #else
01096 ethhdr->dest.addr[k] = ethdst_addr->addr[k];
01097 #endif
01098 ethhdr->src.addr[k] = ethsrc_addr->addr[k];
01099 }
01100 hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr;
01101 hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr;
01102
01103 hdr->hwtype = htons(HWTYPE_ETHERNET);
01104 hdr->proto = htons(ETHTYPE_IP);
01105
01106 hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr));
01107
01108 ethhdr->type = htons(ETHTYPE_ARP);
01109
01110 result = netif->linkoutput(netif, p);
01111 ETHARP_STATS_INC(etharp.xmit);
01112
01113 pbuf_free(p);
01114 p = NULL;
01115
01116
01117 return result;
01118 }
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 err_t
01130 etharp_request(struct netif *netif, struct ip_addr *ipaddr)
01131 {
01132 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
01133 return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast,
01134 (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero,
01135 ipaddr, ARP_REQUEST);
01136 }
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 err_t
01147 ethernet_input(struct pbuf *p, struct netif *netif)
01148 {
01149 struct eth_hdr* ethhdr;
01150 u16_t type;
01151
01152
01153 ethhdr = p->payload;
01154 LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
01155 ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n",
01156 (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
01157 (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
01158 (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
01159 (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
01160 (unsigned)htons(ethhdr->type)));
01161
01162 type = htons(ethhdr->type);
01163 #if ETHARP_SUPPORT_VLAN
01164 if (type == ETHTYPE_VLAN) {
01165 struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
01166 #ifdef ETHARP_VLAN_CHECK
01167 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
01168
01169 pbuf_free(p);
01170 return ERR_OK;
01171 }
01172 #endif
01173 type = htons(vlan->tpid);
01174 }
01175 #endif
01176
01177 switch (type) {
01178
01179 case ETHTYPE_IP:
01180 #if ETHARP_TRUST_IP_MAC
01181
01182 etharp_ip_input(netif, p);
01183 #endif
01184
01185 if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) {
01186 LWIP_ASSERT("Can't move over header in packet", 0);
01187 pbuf_free(p);
01188 p = NULL;
01189 } else {
01190
01191 ip_input(p, netif);
01192 }
01193 break;
01194
01195 case ETHTYPE_ARP:
01196
01197 etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
01198 break;
01199
01200 #if PPPOE_SUPPORT
01201 case ETHTYPE_PPPOEDISC:
01202 pppoe_disc_input(netif, p);
01203 break;
01204
01205 case ETHTYPE_PPPOE:
01206 pppoe_data_input(netif, p);
01207 break;
01208 #endif
01209
01210 default:
01211 ETHARP_STATS_INC(etharp.proterr);
01212 ETHARP_STATS_INC(etharp.drop);
01213 pbuf_free(p);
01214 p = NULL;
01215 break;
01216 }
01217
01218
01219
01220 return ERR_OK;
01221 }
01222 #endif