aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/udp.h6
-rw-r--r--net/ipv4/udp.c27
2 files changed, 29 insertions, 4 deletions
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 6de445c..8ec703f 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -42,6 +42,7 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
/* UDP encapsulation types */
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */
+#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
#ifdef __KERNEL__
#include <linux/types.h>
@@ -70,6 +71,11 @@ struct udp_sock {
#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
__u8 pcflag; /* marks socket as UDP-Lite if > 0 */
+ __u8 unused[3];
+ /*
+ * For encapsulation sockets.
+ */
+ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
};
static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index facb7e2..b9276f8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -70,6 +70,7 @@
* Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind
* a single port at the same time.
* Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
+ * James Chapman : Add L2TP encapsulation type.
*
*
* This program is free software; you can redistribute it and/or
@@ -923,12 +924,10 @@ int udp_disconnect(struct sock *sk, int flags)
* 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)
{
-#ifndef CONFIG_XFRM
- return 1;
-#else
struct udp_sock *up = udp_sk(sk);
struct udphdr *uh;
struct iphdr *iph;
@@ -983,8 +982,14 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
/* 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
@@ -1055,12 +1060,25 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
kfree_skb(skb);
return 0;
}
- if (ret < 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 */
+ }
+ }
+
/* FALLTHROUGH -- it's a UDP Packet */
}
@@ -1349,6 +1367,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
case 0:
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
+ case UDP_ENCAP_L2TPINUDP:
up->encap_type = val;
break;
default: