Skip to content
Permalink
Browse files

net: arp: Use proper dest hw address after receiving a request

If a packet is received with Ethernet source address different
from ARP's sender hardware address field, then DUT must use the
latter address in response packets.

Fixes #16098

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
  • Loading branch information...
jukkar committed May 13, 2019
1 parent 58e9ac6 commit a84e9345a61eeb70bdcfe453c2b5426aa10cd0d4
Showing with 28 additions and 6 deletions.
  1. +28 −6 subsys/net/l2/ethernet/arp.c
@@ -440,6 +440,23 @@ static void arp_update(struct net_if *iface,
if (entry) {
memcpy(&entry->eth, hwaddr,
sizeof(struct net_eth_addr));
} else {
/* Add new entry as it was not found and force
* was set.
*/
entry = arp_entry_get_free();
if (!entry) {
/* Then let's take one from table? */
entry = arp_entry_get_last_from_table();
}

if (entry) {
entry->req_start = k_uptime_get();
entry->iface = iface;
net_ipaddr_copy(&entry->ip, src);
memcpy(&entry->eth, hwaddr, sizeof(entry->eth));
sys_slist_prepend(&arp_table, &entry->node);
}
}
}

@@ -468,7 +485,8 @@ static void arp_update(struct net_if *iface,

static inline struct net_pkt *arp_prepare_reply(struct net_if *iface,
struct net_pkt *req,
struct net_eth_hdr *eth_query)
struct net_eth_hdr *eth_query,
struct net_eth_addr *dst_addr)
{
struct net_arp_hdr *hdr, *query;
struct net_pkt *pkt;
@@ -492,7 +510,7 @@ static inline struct net_pkt *arp_prepare_reply(struct net_if *iface,
hdr->protolen = sizeof(struct in_addr);
hdr->opcode = htons(NET_ARP_REPLY);

memcpy(&hdr->dst_hwaddr.addr, &eth_query->src.addr,
memcpy(&hdr->dst_hwaddr.addr, &dst_addr->addr,
sizeof(struct net_eth_addr));
memcpy(&hdr->src_hwaddr.addr, net_if_get_link_addr(iface)->addr,
sizeof(struct net_eth_addr));
@@ -526,6 +544,7 @@ static bool arp_hdr_check(struct net_arp_hdr *arp_hdr)
enum net_verdict net_arp_input(struct net_pkt *pkt,
struct net_eth_hdr *eth_hdr)
{
struct net_eth_addr *dst_hw_addr;
struct net_arp_hdr *arp_hdr;
struct net_pkt *reply;
struct in_addr *addr;
@@ -594,9 +613,7 @@ enum net_verdict net_arp_input(struct net_pkt *pkt,
* changed. In this case the target MAC address is all zeros
* and the target IP address is our address.
*/
if (memcmp(&eth_hdr->src, &arp_hdr->src_hwaddr,
sizeof(struct net_eth_addr)) == 0 &&
net_eth_is_addr_unspecified(&arp_hdr->dst_hwaddr)) {
if (net_eth_is_addr_unspecified(&arp_hdr->dst_hwaddr)) {
NET_DBG("Updating ARP cache for %s [%s]",
log_strdup(net_sprint_ipv4_addr(
&arp_hdr->src_ipaddr)),
@@ -608,10 +625,15 @@ enum net_verdict net_arp_input(struct net_pkt *pkt,
&arp_hdr->src_ipaddr,
&arp_hdr->src_hwaddr,
false, true);

dst_hw_addr = &arp_hdr->src_hwaddr;
} else {
dst_hw_addr = &eth_hdr->src;
}

/* Send reply */
reply = arp_prepare_reply(net_pkt_iface(pkt), pkt, eth_hdr);
reply = arp_prepare_reply(net_pkt_iface(pkt), pkt, eth_hdr,
dst_hw_addr);
if (reply) {
net_if_queue_tx(net_pkt_iface(reply), reply);
} else {

0 comments on commit a84e934

Please sign in to comment.
You can’t perform that action at this time.