diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index e4c51ca47301..acacaae05cc4 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1063,6 +1063,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, static int ipmr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt, vifi_t vifi, int assert) { + unsigned char pkt_cb[sizeof(pkt->cb)]; const int ihl = ip_hdrlen(pkt); struct sock *mroute_sk; struct igmphdr *igmp; @@ -1118,8 +1119,6 @@ static int ipmr_cache_report(const struct mr_table *mrt, msg = (struct igmpmsg *)skb_network_header(skb); msg->im_vif = vifi; msg->im_vif_hi = vifi >> 8; - ipv4_pktinfo_prepare(mroute_sk, pkt, false); - memcpy(skb->cb, pkt->cb, sizeof(skb->cb)); /* Add our header. * Note that code, csum and group fields are cleared. */ @@ -1130,6 +1129,15 @@ static int ipmr_cache_report(const struct mr_table *mrt, skb->transport_header = skb->network_header; } + memset(skb->cb, 0, sizeof(skb->cb)); + /* Route queries from ipmr_get_route() carry NETLINK_CB, not IPCB. */ + if (ip_hdr(pkt)->version) { + memcpy(pkt_cb, pkt->cb, sizeof(pkt_cb)); + ipv4_pktinfo_prepare(mroute_sk, pkt, false); + *PKTINFO_SKB_CB(skb) = *PKTINFO_SKB_CB(pkt); + memcpy(pkt->cb, pkt_cb, sizeof(pkt_cb)); + } + igmpmsg_netlink_event(mrt, skb); /* Deliver to mrouted */