@@ -116,15 +116,15 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
116116 return false;
117117}
118118
119- static void * ipvlan_get_L3_hdr (struct sk_buff * skb , int * type )
119+ static void * ipvlan_get_L3_hdr (struct ipvl_port * port , struct sk_buff * skb , int * type )
120120{
121121 void * lyr3h = NULL ;
122122
123123 switch (skb -> protocol ) {
124124 case htons (ETH_P_ARP ): {
125125 struct arphdr * arph ;
126126
127- if (unlikely (!pskb_may_pull (skb , sizeof ( * arph ))))
127+ if (unlikely (!pskb_may_pull (skb , arp_hdr_len ( port -> dev ))))
128128 return NULL ;
129129
130130 arph = arp_hdr (skb );
@@ -165,8 +165,26 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
165165 /* Only Neighbour Solicitation pkts need different treatment */
166166 if (ipv6_addr_any (& ip6h -> saddr ) &&
167167 ip6h -> nexthdr == NEXTHDR_ICMP ) {
168+ struct icmp6hdr * icmph ;
169+
170+ if (unlikely (!pskb_may_pull (skb , sizeof (* ip6h ) + sizeof (* icmph ))))
171+ return NULL ;
172+
173+ ip6h = ipv6_hdr (skb );
174+ icmph = (struct icmp6hdr * )(ip6h + 1 );
175+
176+ if (icmph -> icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ) {
177+ /* Need to access the ipv6 address in body */
178+ if (unlikely (!pskb_may_pull (skb , sizeof (* ip6h ) + sizeof (* icmph )
179+ + sizeof (struct in6_addr ))))
180+ return NULL ;
181+
182+ ip6h = ipv6_hdr (skb );
183+ icmph = (struct icmp6hdr * )(ip6h + 1 );
184+ }
185+
168186 * type = IPVL_ICMPV6 ;
169- lyr3h = ip6h + 1 ;
187+ lyr3h = icmph ;
170188 }
171189 break ;
172190 }
@@ -510,7 +528,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
510528 struct ipvl_addr * addr ;
511529 int addr_type ;
512530
513- lyr3h = ipvlan_get_L3_hdr (skb , & addr_type );
531+ lyr3h = ipvlan_get_L3_hdr (ipvlan -> port , skb , & addr_type );
514532 if (!lyr3h )
515533 goto out ;
516534
@@ -539,7 +557,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
539557
540558 if (!ipvlan_is_vepa (ipvlan -> port ) &&
541559 ether_addr_equal (eth -> h_dest , eth -> h_source )) {
542- lyr3h = ipvlan_get_L3_hdr (skb , & addr_type );
560+ lyr3h = ipvlan_get_L3_hdr (ipvlan -> port , skb , & addr_type );
543561 if (lyr3h ) {
544562 addr = ipvlan_addr_lookup (ipvlan -> port , lyr3h , addr_type , true);
545563 if (addr ) {
@@ -606,7 +624,7 @@ static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port)
606624 int addr_type ;
607625
608626 if (ether_addr_equal (eth -> h_source , skb -> dev -> dev_addr )) {
609- lyr3h = ipvlan_get_L3_hdr (skb , & addr_type );
627+ lyr3h = ipvlan_get_L3_hdr (port , skb , & addr_type );
610628 if (!lyr3h )
611629 return true;
612630
@@ -627,7 +645,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
627645 struct sk_buff * skb = * pskb ;
628646 rx_handler_result_t ret = RX_HANDLER_PASS ;
629647
630- lyr3h = ipvlan_get_L3_hdr (skb , & addr_type );
648+ lyr3h = ipvlan_get_L3_hdr (port , skb , & addr_type );
631649 if (!lyr3h )
632650 goto out ;
633651
@@ -666,7 +684,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
666684 } else {
667685 struct ipvl_addr * addr ;
668686
669- lyr3h = ipvlan_get_L3_hdr (skb , & addr_type );
687+ lyr3h = ipvlan_get_L3_hdr (port , skb , & addr_type );
670688 if (!lyr3h )
671689 return ret ;
672690
@@ -717,7 +735,7 @@ static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
717735 if (!port || port -> mode != IPVLAN_MODE_L3S )
718736 goto out ;
719737
720- lyr3h = ipvlan_get_L3_hdr (skb , & addr_type );
738+ lyr3h = ipvlan_get_L3_hdr (port , skb , & addr_type );
721739 if (!lyr3h )
722740 goto out ;
723741
0 commit comments