amt_update_handler() finds the gateway's tunnel by comparing
tunnel->addr.ip4 with ip_hdr(skb)->saddr, which on an IPv6 outer header
reads bytes 4-7 of the source address as an IPv4 address, so an IPv6
relay never accepts a Membership Update.

Take the outer source with amt_outer_saddr() on entry, by value, before
pskb_may_pull() and iptunnel_pull_header() can reallocate the header.
Match the tunnel with amt_addr_equal(), as amt_request_handler() does,
so the tunnel a Request created is the one its Updates find in both
families. The inner report parsing is unchanged.

Assisted-by: LLM
Signed-off-by: Omar Ramadan <[email protected]>
---
 drivers/net/amt.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 5e8a74c..b977b00 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -2620,14 +2620,14 @@ static bool amt_update_handler(struct amt_dev *amt, 
struct sk_buff *skb)
 {
        struct amt_header_membership_update *amtmu;
        struct amt_tunnel_list *tunnel;
+       union amt_addr saddr;
        struct ethhdr *eth;
        struct iphdr *iph;
        int len, hdr_size;
        u64 response_mac;
-       __be32 saddr;
        __be32 nonce;
 
-       saddr = ip_hdr(skb)->saddr;
+       amt_outer_saddr(amt, skb, &saddr);
 
        hdr_size = sizeof(*amtmu) + sizeof(struct udphdr);
        if (!pskb_may_pull(skb, hdr_size))
@@ -2646,7 +2646,7 @@ static bool amt_update_handler(struct amt_dev *amt, 
struct sk_buff *skb)
        skb_reset_network_header(skb);
 
        list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {
-               if (tunnel->addr.ip4 == saddr) {
+               if (amt_addr_equal(&tunnel->addr, &saddr)) {
                        if ((nonce == tunnel->nonce &&
                             response_mac == tunnel->mac)) {
                                mod_delayed_work(amt_wq, &tunnel->gc_wq,
-- 
2.43.0


Reply via email to