48#if LWIP_ARP || LWIP_ETHERNET
50#include "lwip/ip_addr.h"
65const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
66const struct eth_addr ethzero = {{0,0,0,0,0,0}};
69#define LL_MULTICAST_ADDR_0 0x01
70#define LL_MULTICAST_ADDR_1 0x00
71#define LL_MULTICAST_ADDR_2 0x5e
82#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12)
91#define ARP_MAXPENDING 2
93#define HWTYPE_ETHERNET 1
96 ETHARP_STATE_EMPTY = 0,
99 ETHARP_STATE_STABLE_REREQUESTING
100#if ETHARP_SUPPORT_STATIC_ENTRIES
108 struct etharp_q_entry *
q;
115 struct eth_addr ethaddr;
122#if !LWIP_NETIF_HWADDRHINT
123static u8_t etharp_cached_entry;
128#define ETHARP_FLAG_TRY_HARD 1
129#define ETHARP_FLAG_FIND_ONLY 2
130#if ETHARP_SUPPORT_STATIC_ENTRIES
131#define ETHARP_FLAG_STATIC_ENTRY 4
134#if LWIP_NETIF_HWADDRHINT
135#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \
136 *((netif)->addr_hint) = (hint);
138#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint))
143#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
144 #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
155free_etharp_q(
struct etharp_q_entry *
q)
157 struct etharp_q_entry *
r;
171#define free_etharp_q(q) pbuf_free(q)
177etharp_free_entry(
int i)
182 if (arp_table[
i].
q !=
NULL) {
185 free_etharp_q(arp_table[
i].
q);
186 arp_table[
i].q =
NULL;
189 arp_table[
i].state = ETHARP_STATE_EMPTY;
192 arp_table[
i].ctime = 0;
193 arp_table[
i].netif =
NULL;
195 arp_table[
i].ethaddr = ethzero;
214 if (
state != ETHARP_STATE_EMPTY
216 && (
state != ETHARP_STATE_STATIC)
219 arp_table[
i].ctime++;
220 if ((arp_table[
i].
ctime >= ARP_MAXAGE) ||
221 ((arp_table[
i].
state == ETHARP_STATE_PENDING) &&
222 (arp_table[
i].
ctime >= ARP_MAXPENDING))) {
225 arp_table[
i].
state >= ETHARP_STATE_STABLE ?
"stable" :
"pending", (
u16_t)
i));
227 etharp_free_entry(
i);
229 else if (arp_table[
i].
state == ETHARP_STATE_STABLE_REREQUESTING) {
232 arp_table[
i].state = ETHARP_STATE_STABLE;
236 if (arp_table[
i].
state == ETHARP_STATE_PENDING) {
270 u8_t i = 0, age_pending = 0, age_stable = 0;
298 }
else if (
state != ETHARP_STATE_EMPTY) {
299 LWIP_ASSERT(
"state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
300 state == ETHARP_STATE_PENDING ||
state >= ETHARP_STATE_STABLE);
302 if (ipaddr &&
ip_addr_cmp(ipaddr, &arp_table[
i].ipaddr)) {
308 if (
state == ETHARP_STATE_PENDING) {
310 if (arp_table[
i].
q !=
NULL) {
311 if (arp_table[
i].
ctime >= age_queue) {
313 age_queue = arp_table[
i].ctime;
318 if (arp_table[
i].
ctime >= age_pending) {
320 age_pending = arp_table[
i].ctime;
324 }
else if (
state >= ETHARP_STATE_STABLE) {
325#if ETHARP_SUPPORT_STATIC_ENTRIES
327 if (
state < ETHARP_STATE_STATIC)
331 if (arp_table[
i].
ctime >= age_stable) {
333 age_stable = arp_table[
i].ctime;
342 if (((
flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
388 etharp_free_entry(
i);
392 LWIP_ASSERT(
"arp_table[i].state == ETHARP_STATE_EMPTY",
393 arp_table[
i].
state == ETHARP_STATE_EMPTY);
396 if (ipaddr !=
NULL) {
400 arp_table[
i].ctime = 0;
417 struct eth_hdr *ethhdr = (
struct eth_hdr *)
p->payload;
419 LWIP_ASSERT(
"netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
421 ETHADDR32_COPY(ðhdr->dest,
dst);
422 ETHADDR16_COPY(ðhdr->src,
src);
423 ethhdr->type =
PP_HTONS(ETHTYPE_IP);
454 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
455 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
464 i = etharp_find_entry(ipaddr,
flags);
470#if ETHARP_SUPPORT_STATIC_ENTRIES
471 if (
flags & ETHARP_FLAG_STATIC_ENTRY) {
473 arp_table[
i].state = ETHARP_STATE_STATIC;
478 arp_table[
i].state = ETHARP_STATE_STABLE;
482 arp_table[
i].netif =
netif;
488 ETHADDR32_COPY(&arp_table[
i].ethaddr, ethaddr);
490 arp_table[
i].ctime = 0;
493 while (arp_table[
i].
q !=
NULL) {
496 struct etharp_q_entry *
q = arp_table[
i].q;
498 arp_table[
i].q =
q->next;
504 if (arp_table[
i].
q !=
NULL) {
505 struct pbuf *
p = arp_table[
i].q;
506 arp_table[
i].q =
NULL;
516#if ETHARP_SUPPORT_STATIC_ENTRIES
526etharp_add_static_entry(
ip_addr_t *ipaddr,
struct eth_addr *ethaddr)
531 ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
532 ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
539 return etharp_update_arp_entry(
netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
551etharp_remove_static_entry(
ip_addr_t *ipaddr)
558 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
564 if (arp_table[
i].
state != ETHARP_STATE_STATIC) {
569 etharp_free_entry(
i);
586 etharp_free_entry(
i);
604 struct eth_addr **eth_ret,
ip_addr_t **ip_ret)
613 i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
614 if((
i >= 0) && (arp_table[
i].
state >= ETHARP_STATE_STABLE)) {
615 *eth_ret = &arp_table[
i].ethaddr;
616 *ip_ret = &arp_table[
i].ipaddr;
622#if ETHARP_TRUST_IP_MAC
641 struct eth_hdr *ethhdr;
648 ethhdr = (
struct eth_hdr *)
p->payload;
649 iphdr = (
struct ip_hdr *)((
u8_t*)ethhdr + SIZEOF_ETH_HDR);
650#if ETHARP_SUPPORT_VLAN
651 if (ethhdr->type ==
PP_HTONS(ETHTYPE_VLAN)) {
652 iphdr = (
struct ip_hdr *)((
u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
668 etharp_update_arp_entry(
netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
688etharp_arp_input(
struct netif *
netif,
struct eth_addr *ethaddr,
struct pbuf *
p)
690 struct etharp_hdr *
hdr;
691 struct eth_hdr *ethhdr;
696 const u8_t * ethdst_hwaddr;
703 if (
p->len < SIZEOF_ETHARP_PACKET) {
705 (
"etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n",
p->tot_len,
706 (
s16_t)SIZEOF_ETHARP_PACKET));
713 ethhdr = (
struct eth_hdr *)
p->payload;
714 hdr = (
struct etharp_hdr *)((
u8_t*)ethhdr + SIZEOF_ETH_HDR);
715#if ETHARP_SUPPORT_VLAN
716 if (ethhdr->type ==
PP_HTONS(ETHTYPE_VLAN)) {
717 hdr = (
struct etharp_hdr *)(((
u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
723 (
hdr->hwlen != ETHARP_HWADDR_LEN) ||
727 (
"etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
761 etharp_update_arp_entry(
netif, &sipaddr, &(
hdr->shwaddr),
762 for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
765 switch (
hdr->opcode) {
785 LWIP_ASSERT(
"netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
794 ETHADDR16_COPY(&
hdr->dhwaddr, &
hdr->shwaddr);
796 ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr);
798 ETHADDR16_COPY(ðhdr->dest, &
hdr->shwaddr);
800 ETHADDR16_COPY(&
hdr->shwaddr, ethaddr);
801 ETHADDR16_COPY(ðhdr->src, ethaddr);
821#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
826 dhcp_arp_reply(
netif, &sipaddr);
844 LWIP_ASSERT(
"arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
845 arp_table[arp_idx].
state >= ETHARP_STATE_STABLE);
849 if ((arp_table[arp_idx].
state == ETHARP_STATE_STABLE) &&
850 (arp_table[arp_idx].
ctime >= ARP_AGE_REREQUEST_USED)) {
851 if (etharp_request(
netif, &arp_table[arp_idx].ipaddr) ==
ERR_OK) {
852 arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING;
857 &arp_table[arp_idx].ethaddr);
881 struct eth_addr *
dest;
882 struct eth_addr mcastaddr;
893 (
"etharp_output: could not allocate room for header.\n"));
904 dest = (
struct eth_addr *)ðbroadcast;
908 mcastaddr.addr[0] = LL_MULTICAST_ADDR_0;
909 mcastaddr.addr[1] = LL_MULTICAST_ADDR_1;
910 mcastaddr.addr[2] = LL_MULTICAST_ADDR_2;
911 mcastaddr.addr[3] =
ip4_addr2(ipaddr) & 0x7f;
925 sizeof(
struct eth_hdr));
944#if LWIP_NETIF_HWADDRHINT
947 u8_t etharp_cached_entry = *(
netif->addr_hint);
950 if ((arp_table[etharp_cached_entry].
state >= ETHARP_STATE_STABLE) &&
951 (
ip_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) {
954 return etharp_output_to_arp_index(
netif,
q, etharp_cached_entry);
956#if LWIP_NETIF_HWADDRHINT
964 if ((arp_table[
i].
state >= ETHARP_STATE_STABLE) &&
967 ETHARP_SET_HINT(
netif,
i);
968 return etharp_output_to_arp_index(
netif,
q,
i);
973 return etharp_query(
netif, dst_addr,
q);
1018 struct eth_addr * srcaddr = (
struct eth_addr *)
netif->
hwaddr;
1031 i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);
1044 if (arp_table[
i].
state == ETHARP_STATE_EMPTY) {
1045 arp_table[
i].state = ETHARP_STATE_PENDING;
1049 LWIP_ASSERT(
"arp_table[i].state == PENDING or STABLE",
1050 ((arp_table[
i].
state == ETHARP_STATE_PENDING) ||
1051 (arp_table[
i].
state >= ETHARP_STATE_STABLE)));
1054 if ((arp_table[
i].
state == ETHARP_STATE_PENDING) || (
q ==
NULL)) {
1071 if (arp_table[
i].
state >= ETHARP_STATE_STABLE) {
1073 ETHARP_SET_HINT(
netif,
i);
1075 result = etharp_send_ip(
netif,
q, srcaddr, &(arp_table[
i].ethaddr));
1077 }
else if (arp_table[
i].
state == ETHARP_STATE_PENDING) {
1080 int copy_needed = 0;
1086 LWIP_ASSERT(
"no packet queues allowed!", (
p->len !=
p->tot_len) || (
p->next == 0));
1111 struct etharp_q_entry *new_entry;
1113 new_entry = (
struct etharp_q_entry *)
memp_malloc(MEMP_ARP_QUEUE);
1114 if (new_entry !=
NULL) {
1115 new_entry->next = 0;
1117 if(arp_table[
i].
q !=
NULL) {
1119 struct etharp_q_entry *
r;
1121 while (
r->next !=
NULL) {
1124 r->next = new_entry;
1127 arp_table[
i].q = new_entry;
1139 if (arp_table[
i].
q !=
NULL) {
1175etharp_raw(
struct netif *
netif,
const struct eth_addr *ethsrc_addr,
1176 const struct eth_addr *ethdst_addr,
1177 const struct eth_addr *hwsrc_addr,
const ip_addr_t *ipsrc_addr,
1178 const struct eth_addr *hwdst_addr,
const ip_addr_t *ipdst_addr,
1183 struct eth_hdr *ethhdr;
1184 struct etharp_hdr *
hdr;
1186 const u8_t * ethdst_hwaddr;
1196 (
"etharp_raw: could not allocate pbuf for ARP request.\n"));
1200 LWIP_ASSERT(
"check that first pbuf can hold struct etharp_hdr",
1201 (
p->len >= SIZEOF_ETHARP_PACKET));
1203 ethhdr = (
struct eth_hdr *)
p->payload;
1204 hdr = (
struct etharp_hdr *)((
u8_t*)ethhdr + SIZEOF_ETH_HDR);
1208 LWIP_ASSERT(
"netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
1217 ETHADDR16_COPY(&
hdr->shwaddr, hwsrc_addr);
1218 ETHADDR16_COPY(&
hdr->dhwaddr, hwdst_addr);
1221 ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr);
1223 ETHADDR16_COPY(ðhdr->dest, ethdst_addr);
1225 ETHADDR16_COPY(ðhdr->src, ethsrc_addr);
1234 hdr->hwlen = ETHARP_HWADDR_LEN;
1237 ethhdr->type =
PP_HTONS(ETHTYPE_ARP);
1279 struct eth_hdr* ethhdr;
1281#if LWIP_ARP || ETHARP_SUPPORT_VLAN
1282 s16_t ip_hdr_offset = SIZEOF_ETH_HDR;
1285 if (
p->len <= SIZEOF_ETH_HDR) {
1289 goto free_and_return;
1293 ethhdr = (
struct eth_hdr *)
p->payload;
1296 (
unsigned)ethhdr->dest.addr[0], (
unsigned)ethhdr->dest.addr[1], (
unsigned)ethhdr->dest.addr[2],
1297 (
unsigned)ethhdr->dest.addr[3], (
unsigned)ethhdr->dest.addr[4], (
unsigned)ethhdr->dest.addr[5],
1298 (
unsigned)ethhdr->src.addr[0], (
unsigned)ethhdr->src.addr[1], (
unsigned)ethhdr->src.addr[2],
1299 (
unsigned)ethhdr->src.addr[3], (
unsigned)ethhdr->src.addr[4], (
unsigned)ethhdr->src.addr[5],
1300 (
unsigned)
htons(ethhdr->type)));
1302 type = ethhdr->type;
1303#if ETHARP_SUPPORT_VLAN
1305 struct eth_vlan_hdr *vlan = (
struct eth_vlan_hdr*)(((
char*)ethhdr) + SIZEOF_ETH_HDR);
1306 if (
p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
1310 goto free_and_return;
1312#if defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN)
1313#ifdef ETHARP_VLAN_CHECK_FN
1314 if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) {
1315#elif defined(ETHARP_VLAN_CHECK)
1316 if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
1324 ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
1328#if LWIP_ARP_FILTER_NETIF
1332 if (ethhdr->dest.addr[0] & 1) {
1334 if (ethhdr->dest.addr[0] == LL_MULTICAST_ADDR_0) {
1335 if ((ethhdr->dest.addr[1] == LL_MULTICAST_ADDR_1) &&
1336 (ethhdr->dest.addr[2] == LL_MULTICAST_ADDR_2)) {
1340 }
else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) {
1351 goto free_and_return;
1353#if ETHARP_TRUST_IP_MAC
1355 etharp_ip_input(
netif,
p);
1359 LWIP_ASSERT(
"Can't move over header in packet", 0);
1360 goto free_and_return;
1369 goto free_and_return;
1377 pppoe_disc_input(
netif,
p);
1381 pppoe_data_input(
netif,
p);
1388 goto free_and_return;
#define LWIP_UNUSED_ARG(x)
static const WCHAR empty[]
#define LWIP_DBG_LEVEL_SERIOUS
#define LWIP_DEBUGF(debug, message)
#define LWIP_DBG_LEVEL_WARNING
#define LWIP_ERROR(message, expression, handler)
#define LWIP_ASSERT(message, assertion)
#define snmp_delete_arpidx_tree(ni, ip)
#define snmp_insert_arpidx_tree(ni, ip)
GLuint GLuint GLsizei GLenum type
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
#define ip_addr_cmp(addr1, addr2)
#define ip_addr_isany(addr1)
#define ip4_addr1_16(ipaddr)
#define ip_addr_ismulticast(addr1)
#define ip_addr_netcmp(addr1, addr2, mask)
#define ip4_addr2_16(ipaddr)
#define ip_addr_islinklocal(addr1)
#define ip_addr_copy(dest, src)
#define ip4_addr4(ipaddr)
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
#define ip_addr_isbroadcast(ipaddr, netif)
#define ip4_addr3_16(ipaddr)
#define ip_addr_set_zero(ipaddr)
#define IPADDR2_COPY(dest, src)
#define ip4_addr4_16(ipaddr)
#define ip4_addr3(ipaddr)
#define ip4_addr2(ipaddr)
err_t ip_input(struct pbuf *p, struct netif *inp)
struct netif * ip_route(ip_addr_t *dest)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
#define NETIF_FLAG_ETHARP
#define ETHARP_SUPPORT_STATIC_ENTRIES
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
void pbuf_ref(struct pbuf *p)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
#define PBUF_FLAG_LLBCAST
#define PBUF_FLAG_LLMCAST
#define LINK_STATS_INC(x)
#define ETHARP_STATS_INC(x)
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
netif_linkoutput_fn linkoutput