Skip to content

Commit a84e934

Browse files
committed
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 <[email protected]>
1 parent 58e9ac6 commit a84e934

File tree

1 file changed

+28
-6
lines changed
  • subsys/net/l2/ethernet

1 file changed

+28
-6
lines changed

subsys/net/l2/ethernet/arp.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,23 @@ static void arp_update(struct net_if *iface,
440440
if (entry) {
441441
memcpy(&entry->eth, hwaddr,
442442
sizeof(struct net_eth_addr));
443+
} else {
444+
/* Add new entry as it was not found and force
445+
* was set.
446+
*/
447+
entry = arp_entry_get_free();
448+
if (!entry) {
449+
/* Then let's take one from table? */
450+
entry = arp_entry_get_last_from_table();
451+
}
452+
453+
if (entry) {
454+
entry->req_start = k_uptime_get();
455+
entry->iface = iface;
456+
net_ipaddr_copy(&entry->ip, src);
457+
memcpy(&entry->eth, hwaddr, sizeof(entry->eth));
458+
sys_slist_prepend(&arp_table, &entry->node);
459+
}
443460
}
444461
}
445462

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

469486
static inline struct net_pkt *arp_prepare_reply(struct net_if *iface,
470487
struct net_pkt *req,
471-
struct net_eth_hdr *eth_query)
488+
struct net_eth_hdr *eth_query,
489+
struct net_eth_addr *dst_addr)
472490
{
473491
struct net_arp_hdr *hdr, *query;
474492
struct net_pkt *pkt;
@@ -492,7 +510,7 @@ static inline struct net_pkt *arp_prepare_reply(struct net_if *iface,
492510
hdr->protolen = sizeof(struct in_addr);
493511
hdr->opcode = htons(NET_ARP_REPLY);
494512

495-
memcpy(&hdr->dst_hwaddr.addr, &eth_query->src.addr,
513+
memcpy(&hdr->dst_hwaddr.addr, &dst_addr->addr,
496514
sizeof(struct net_eth_addr));
497515
memcpy(&hdr->src_hwaddr.addr, net_if_get_link_addr(iface)->addr,
498516
sizeof(struct net_eth_addr));
@@ -526,6 +544,7 @@ static bool arp_hdr_check(struct net_arp_hdr *arp_hdr)
526544
enum net_verdict net_arp_input(struct net_pkt *pkt,
527545
struct net_eth_hdr *eth_hdr)
528546
{
547+
struct net_eth_addr *dst_hw_addr;
529548
struct net_arp_hdr *arp_hdr;
530549
struct net_pkt *reply;
531550
struct in_addr *addr;
@@ -594,9 +613,7 @@ enum net_verdict net_arp_input(struct net_pkt *pkt,
594613
* changed. In this case the target MAC address is all zeros
595614
* and the target IP address is our address.
596615
*/
597-
if (memcmp(&eth_hdr->src, &arp_hdr->src_hwaddr,
598-
sizeof(struct net_eth_addr)) == 0 &&
599-
net_eth_is_addr_unspecified(&arp_hdr->dst_hwaddr)) {
616+
if (net_eth_is_addr_unspecified(&arp_hdr->dst_hwaddr)) {
600617
NET_DBG("Updating ARP cache for %s [%s]",
601618
log_strdup(net_sprint_ipv4_addr(
602619
&arp_hdr->src_ipaddr)),
@@ -608,10 +625,15 @@ enum net_verdict net_arp_input(struct net_pkt *pkt,
608625
&arp_hdr->src_ipaddr,
609626
&arp_hdr->src_hwaddr,
610627
false, true);
628+
629+
dst_hw_addr = &arp_hdr->src_hwaddr;
630+
} else {
631+
dst_hw_addr = &eth_hdr->src;
611632
}
612633

613634
/* Send reply */
614-
reply = arp_prepare_reply(net_pkt_iface(pkt), pkt, eth_hdr);
635+
reply = arp_prepare_reply(net_pkt_iface(pkt), pkt, eth_hdr,
636+
dst_hw_addr);
615637
if (reply) {
616638
net_if_queue_tx(net_pkt_iface(reply), reply);
617639
} else {

0 commit comments

Comments
 (0)