/** * Update (or insert) a IP/MAC address pair in the ARP cache. * * If a pending entry is resolved, any queued packets will be sent * at this point. * * @param netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. * @param flags @see definition of ETHARP_FLAG_* * * @return * - ERR_OK Succesfully updated ARP cache. * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */ static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); 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", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); /* non-unicast address? */ if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif) || ip_addr_ismulticast(ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n")); return ERR_ARG; } /* find or create ARP entry */ i = find_entry(ipaddr, flags); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } #if ETHARP_SUPPORT_STATIC_ENTRIES if (flags & ETHARP_FLAG_STATIC_ENTRY) { /* record static type */ arp_table[i].static_entry = 1; } #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; #if LWIP_SNMP /* record network interface */ arp_table[i].netif = netif; #endif /* LWIP_SNMP */ /* insert in SNMP ARP index tree */ snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); /* update address */ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; #if ARP_QUEUEING /* this is where we will send out queued packets! */ while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ struct etharp_q_entry *q = arp_table[i].q; /* pop first item off the queue */ arp_table[i].q = q->next; /* get the packet pointer */ p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } #endif /* ARP_QUEUEING */ return ERR_OK; }
/** * Update (or insert) a IP/MAC address pair in the ARP cache. * * If a pending entry is resolved, any queued packets will be sent * at this point. * * @param netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. * @param flags @see definition of ETHARP_FLAG_* * * @return * - ERR_OK Succesfully updated ARP cache. * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */ static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); 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", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); /* non-unicast address? */ if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif) || ip_addr_ismulticast(ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n")); return ERR_ARG; } /* find or create ARP entry */ i = find_entry(ipaddr, flags); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } #if ETHARP_SUPPORT_STATIC_ENTRIES if (flags & ETHARP_FLAG_STATIC_ENTRY) { /* record static type */ arp_table[i].static_entry = 1; } #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; #if LWIP_SNMP /* record network interface */ arp_table[i].netif = netif; #endif /* LWIP_SNMP */ /* insert in SNMP ARP index tree */ snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); /* update address */ ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; /* this is where we will send out queued packets! */ #if ARP_QUEUEING while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ struct etharp_q_entry *q = arp_table[i].q; /* pop first item off the queue */ arp_table[i].q = q->next; /* get the packet pointer */ p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); #else /* ARP_QUEUEING */ if (arp_table[i].q != NULL) { struct pbuf *p = arp_table[i].q; arp_table[i].q = NULL; #endif /* ARP_QUEUEING */ /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } return ERR_OK; } #if ETHARP_SUPPORT_STATIC_ENTRIES /** Add a new static entry to the ARP table. If an entry exists for the * specified IP address, this entry is overwritten. * If packets are queued for the specified IP address, they are sent out. * * @param ipaddr IP address for the new static entry * @param ethaddr ethernet address for the new static entry * @return @see return values of etharp_add_static_entry */ err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) { struct netif *netif; 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", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); netif = ip_route(ipaddr); if (netif == NULL) { return ERR_RTE; } return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); } /** Remove a static entry from the ARP table previously added with a call to * etharp_add_static_entry. * * @param ipaddr IP address of the static entry to remove * @return ERR_OK: entry removed * ERR_MEM: entry wasn't found * ERR_ARG: entry wasn't a static entry but a dynamic one */ err_t etharp_remove_static_entry(ip_addr_t *ipaddr) { s8_t i; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); /* find or create ARP entry */ i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); /* bail out if no entry could be found */ if (i < 0) { return (err_t)i; } if ((arp_table[i].state != ETHARP_STATE_STABLE) || (arp_table[i].static_entry == 0)) { /* entry wasn't a static entry, cannot remove it */ return ERR_ARG; } /* entry found, free it */ free_entry(i); return ERR_OK; }