|
@@ -920,108 +920,6 @@ int udp_disconnect(struct sock *sk, int flags)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/* return:
|
|
|
|
- * 1 if the UDP system should process it
|
|
|
|
- * 0 if we should drop this packet
|
|
|
|
- * -1 if it should get processed by xfrm4_rcv_encap
|
|
|
|
- * -2 if it should get processed by l2tp
|
|
|
|
- */
|
|
|
|
-static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
|
|
|
|
-{
|
|
|
|
- struct udp_sock *up = udp_sk(sk);
|
|
|
|
- struct udphdr *uh;
|
|
|
|
- struct iphdr *iph;
|
|
|
|
- int iphlen, len;
|
|
|
|
-
|
|
|
|
- __u8 *udpdata;
|
|
|
|
- __be32 *udpdata32;
|
|
|
|
- __u16 encap_type = up->encap_type;
|
|
|
|
-
|
|
|
|
- /* if we're overly short, let UDP handle it */
|
|
|
|
- len = skb->len - sizeof(struct udphdr);
|
|
|
|
- if (len <= 0)
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
- /* if this is not encapsulated socket, then just return now */
|
|
|
|
- if (!encap_type)
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
- /* If this is a paged skb, make sure we pull up
|
|
|
|
- * whatever data we need to look at. */
|
|
|
|
- if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
- /* Now we can get the pointers */
|
|
|
|
- uh = udp_hdr(skb);
|
|
|
|
- udpdata = (__u8 *)uh + sizeof(struct udphdr);
|
|
|
|
- udpdata32 = (__be32 *)udpdata;
|
|
|
|
-
|
|
|
|
- switch (encap_type) {
|
|
|
|
- default:
|
|
|
|
- case UDP_ENCAP_ESPINUDP:
|
|
|
|
- /* Check if this is a keepalive packet. If so, eat it. */
|
|
|
|
- if (len == 1 && udpdata[0] == 0xff) {
|
|
|
|
- return 0;
|
|
|
|
- } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
|
|
|
|
- /* ESP Packet without Non-ESP header */
|
|
|
|
- len = sizeof(struct udphdr);
|
|
|
|
- } else
|
|
|
|
- /* Must be an IKE packet.. pass it through */
|
|
|
|
- return 1;
|
|
|
|
- break;
|
|
|
|
- case UDP_ENCAP_ESPINUDP_NON_IKE:
|
|
|
|
- /* Check if this is a keepalive packet. If so, eat it. */
|
|
|
|
- if (len == 1 && udpdata[0] == 0xff) {
|
|
|
|
- return 0;
|
|
|
|
- } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
|
|
|
|
- udpdata32[0] == 0 && udpdata32[1] == 0) {
|
|
|
|
-
|
|
|
|
- /* ESP Packet with Non-IKE marker */
|
|
|
|
- len = sizeof(struct udphdr) + 2 * sizeof(u32);
|
|
|
|
- } else
|
|
|
|
- /* Must be an IKE packet.. pass it through */
|
|
|
|
- return 1;
|
|
|
|
- break;
|
|
|
|
- case UDP_ENCAP_L2TPINUDP:
|
|
|
|
- /* Let caller know to send this to l2tp */
|
|
|
|
- return -2;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-#ifndef CONFIG_XFRM
|
|
|
|
- return 1;
|
|
|
|
-#else
|
|
|
|
- /* At this point we are sure that this is an ESPinUDP packet,
|
|
|
|
- * so we need to remove 'len' bytes from the packet (the UDP
|
|
|
|
- * header and optional ESP marker bytes) and then modify the
|
|
|
|
- * protocol to ESP, and then call into the transform receiver.
|
|
|
|
- */
|
|
|
|
- if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- /* Now we can update and verify the packet length... */
|
|
|
|
- iph = ip_hdr(skb);
|
|
|
|
- iphlen = iph->ihl << 2;
|
|
|
|
- iph->tot_len = htons(ntohs(iph->tot_len) - len);
|
|
|
|
- if (skb->len < iphlen + len) {
|
|
|
|
- /* packet is too small!?! */
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* pull the data buffer up to the ESP header and set the
|
|
|
|
- * transport header to point to ESP. Keep UDP on the stack
|
|
|
|
- * for later.
|
|
|
|
- */
|
|
|
|
- __skb_pull(skb, len);
|
|
|
|
- skb_reset_transport_header(skb);
|
|
|
|
-
|
|
|
|
- /* modify the protocol (it's ESP!) */
|
|
|
|
- iph->protocol = IPPROTO_ESP;
|
|
|
|
-
|
|
|
|
- /* and let the caller know to send this into the ESP processor... */
|
|
|
|
- return -1;
|
|
|
|
-#endif
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* returns:
|
|
/* returns:
|
|
* -1: error
|
|
* -1: error
|
|
* 0: success
|
|
* 0: success
|
|
@@ -1044,44 +942,36 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
|
|
|
|
|
|
if (up->encap_type) {
|
|
if (up->encap_type) {
|
|
/*
|
|
/*
|
|
- * This is an encapsulation socket, so let's see if this is
|
|
|
|
- * an encapsulated packet.
|
|
|
|
- * If it's a keepalive packet, then just eat it.
|
|
|
|
- * If it's an encapsulateed packet, then pass it to the
|
|
|
|
- * IPsec xfrm input and return the response
|
|
|
|
- * appropriately. Otherwise, just fall through and
|
|
|
|
- * pass this up the UDP socket.
|
|
|
|
|
|
+ * This is an encapsulation socket so pass the skb to
|
|
|
|
+ * the socket's udp_encap_rcv() hook. Otherwise, just
|
|
|
|
+ * fall through and pass this up the UDP socket.
|
|
|
|
+ * up->encap_rcv() returns the following value:
|
|
|
|
+ * =0 if skb was successfully passed to the encap
|
|
|
|
+ * handler or was discarded by it.
|
|
|
|
+ * >0 if skb should be passed on to UDP.
|
|
|
|
+ * <0 if skb should be resubmitted as proto -N
|
|
*/
|
|
*/
|
|
- int ret;
|
|
|
|
|
|
+ unsigned int len;
|
|
|
|
|
|
- ret = udp_encap_rcv(sk, skb);
|
|
|
|
- if (ret == 0) {
|
|
|
|
- /* Eat the packet .. */
|
|
|
|
- kfree_skb(skb);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- if (ret == -1) {
|
|
|
|
- /* process the ESP packet */
|
|
|
|
- ret = xfrm4_rcv_encap(skb, up->encap_type);
|
|
|
|
- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
|
|
|
|
- return -ret;
|
|
|
|
- }
|
|
|
|
- if (ret == -2) {
|
|
|
|
- /* process the L2TP packet */
|
|
|
|
- if (up->encap_rcv != NULL) {
|
|
|
|
- ret = (*up->encap_rcv)(sk, skb);
|
|
|
|
- if (ret <= 0) {
|
|
|
|
- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* FALLTHROUGH -- pass up as UDP packet */
|
|
|
|
|
|
+ /* if we're overly short, let UDP handle it */
|
|
|
|
+ len = skb->len - sizeof(struct udphdr);
|
|
|
|
+ if (len <= 0)
|
|
|
|
+ goto udp;
|
|
|
|
+
|
|
|
|
+ if (up->encap_rcv != NULL) {
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = (*up->encap_rcv)(sk, skb);
|
|
|
|
+ if (ret <= 0) {
|
|
|
|
+ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
|
|
|
|
+ return -ret;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* FALLTHROUGH -- it's a UDP Packet */
|
|
/* FALLTHROUGH -- it's a UDP Packet */
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+udp:
|
|
/*
|
|
/*
|
|
* UDP-Lite specific tests, ignored on UDP sockets
|
|
* UDP-Lite specific tests, ignored on UDP sockets
|
|
*/
|
|
*/
|
|
@@ -1367,6 +1257,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
|
|
case 0:
|
|
case 0:
|
|
case UDP_ENCAP_ESPINUDP:
|
|
case UDP_ENCAP_ESPINUDP:
|
|
case UDP_ENCAP_ESPINUDP_NON_IKE:
|
|
case UDP_ENCAP_ESPINUDP_NON_IKE:
|
|
|
|
+ up->encap_rcv = xfrm4_udp_encap_rcv;
|
|
|
|
+ /* FALLTHROUGH */
|
|
case UDP_ENCAP_L2TPINUDP:
|
|
case UDP_ENCAP_L2TPINUDP:
|
|
up->encap_type = val;
|
|
up->encap_type = val;
|
|
break;
|
|
break;
|