1616#include <linux/netfilter_ipv6.h>
1717#include <net/ipv6.h>
1818#include <net/xfrm.h>
19+ #include <net/protocol.h>
20+ #include <net/gro.h>
1921
2022int xfrm6_rcv_spi (struct sk_buff * skb , int nexthdr , __be32 spi ,
2123 struct ip6_tnl * t )
@@ -67,14 +69,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
6769 return 0 ;
6870}
6971
70- /* If it's a keepalive packet, then just eat it.
71- * If it's an encapsulated packet, then pass it to the
72- * IPsec xfrm input.
73- * Returns 0 if skb passed to xfrm or was dropped.
74- * Returns >0 if skb should be passed to UDP.
75- * Returns <0 if skb should be resubmitted (-ret is protocol)
76- */
77- int xfrm6_udp_encap_rcv (struct sock * sk , struct sk_buff * skb )
72+ static int __xfrm6_udp_encap_rcv (struct sock * sk , struct sk_buff * skb , bool pull )
7873{
7974 struct udp_sock * up = udp_sk (sk );
8075 struct udphdr * uh ;
@@ -109,7 +104,7 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
109104 case UDP_ENCAP_ESPINUDP :
110105 /* Check if this is a keepalive packet. If so, eat it. */
111106 if (len == 1 && udpdata [0 ] == 0xff ) {
112- goto drop ;
107+ return - EINVAL ;
113108 } else if (len > sizeof (struct ip_esp_hdr ) && udpdata32 [0 ] != 0 ) {
114109 /* ESP Packet without Non-ESP header */
115110 len = sizeof (struct udphdr );
@@ -120,7 +115,7 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
120115 case UDP_ENCAP_ESPINUDP_NON_IKE :
121116 /* Check if this is a keepalive packet. If so, eat it. */
122117 if (len == 1 && udpdata [0 ] == 0xff ) {
123- goto drop ;
118+ return - EINVAL ;
124119 } else if (len > 2 * sizeof (u32 ) + sizeof (struct ip_esp_hdr ) &&
125120 udpdata32 [0 ] == 0 && udpdata32 [1 ] == 0 ) {
126121
@@ -138,31 +133,94 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
138133 * protocol to ESP, and then call into the transform receiver.
139134 */
140135 if (skb_unclone (skb , GFP_ATOMIC ))
141- goto drop ;
136+ return - EINVAL ;
142137
143138 /* Now we can update and verify the packet length... */
144139 ip6h = ipv6_hdr (skb );
145140 ip6h -> payload_len = htons (ntohs (ip6h -> payload_len ) - len );
146141 if (skb -> len < ip6hlen + len ) {
147142 /* packet is too small!?! */
148- goto drop ;
143+ return - EINVAL ;
149144 }
150145
151146 /* pull the data buffer up to the ESP header and set the
152147 * transport header to point to ESP. Keep UDP on the stack
153148 * for later.
154149 */
155- __skb_pull (skb , len );
156- skb_reset_transport_header (skb );
150+ if (pull ) {
151+ __skb_pull (skb , len );
152+ skb_reset_transport_header (skb );
153+ } else {
154+ skb_set_transport_header (skb , len );
155+ }
157156
158157 /* process ESP */
159- return xfrm6_rcv_encap (skb , IPPROTO_ESP , 0 , encap_type );
160-
161- drop :
162- kfree_skb (skb );
163158 return 0 ;
164159}
165160
161+ /* If it's a keepalive packet, then just eat it.
162+ * If it's an encapsulated packet, then pass it to the
163+ * IPsec xfrm input.
164+ * Returns 0 if skb passed to xfrm or was dropped.
165+ * Returns >0 if skb should be passed to UDP.
166+ * Returns <0 if skb should be resubmitted (-ret is protocol)
167+ */
168+ int xfrm6_udp_encap_rcv (struct sock * sk , struct sk_buff * skb )
169+ {
170+ int ret ;
171+
172+ ret = __xfrm6_udp_encap_rcv (sk , skb , true);
173+ if (!ret )
174+ return xfrm6_rcv_encap (skb , IPPROTO_ESP , 0 ,
175+ udp_sk (sk )-> encap_type );
176+
177+ if (ret < 0 ) {
178+ kfree_skb (skb );
179+ return 0 ;
180+ }
181+
182+ return ret ;
183+ }
184+
185+ struct sk_buff * xfrm6_gro_udp_encap_rcv (struct sock * sk , struct list_head * head ,
186+ struct sk_buff * skb )
187+ {
188+ int offset = skb_gro_offset (skb );
189+ const struct net_offload * ops ;
190+ struct sk_buff * pp = NULL ;
191+ int ret ;
192+
193+ offset = offset - sizeof (struct udphdr );
194+
195+ if (!pskb_pull (skb , offset ))
196+ return NULL ;
197+
198+ rcu_read_lock ();
199+ ops = rcu_dereference (inet6_offloads [IPPROTO_ESP ]);
200+ if (!ops || !ops -> callbacks .gro_receive )
201+ goto out ;
202+
203+ ret = __xfrm6_udp_encap_rcv (sk , skb , false);
204+ if (ret )
205+ goto out ;
206+
207+ skb_push (skb , offset );
208+ NAPI_GRO_CB (skb )-> proto = IPPROTO_UDP ;
209+
210+ pp = call_gro_receive (ops -> callbacks .gro_receive , head , skb );
211+ rcu_read_unlock ();
212+
213+ return pp ;
214+
215+ out :
216+ rcu_read_unlock ();
217+ skb_push (skb , offset );
218+ NAPI_GRO_CB (skb )-> same_flow = 0 ;
219+ NAPI_GRO_CB (skb )-> flush = 1 ;
220+
221+ return NULL ;
222+ }
223+
166224int xfrm6_rcv_tnl (struct sk_buff * skb , struct ip6_tnl * t )
167225{
168226 return xfrm6_rcv_spi (skb , skb_network_header (skb )[IP6CB (skb )-> nhoff ],
0 commit comments