Commit 342f0234 authored by James Chapman's avatar James Chapman Committed by David S. Miller

[UDP]: Introduce UDP encapsulation type for L2TP

This patch adds a new UDP_ENCAP_L2TPINUDP encapsulation type for UDP
sockets. When a UDP socket's encap_type is UDP_ENCAP_L2TPINUDP, the
skb is delivered to a function pointed to by the udp_sock's
encap_rcv funcptr. If the skb isn't wanted by L2TP, it returns >0, which
causes it to be passed through to UDP.

Include padding to put the new encap_rcv field on a 4-byte boundary.

Previously, the only user of UDP encap sockets was ESP, so when
CONFIG_XFRM was not defined, some of the encap code was compiled
out. This patch changes that. As a result, udp_encap_rcv() will
now do a little more work when CONFIG_XFRM is not defined.
Signed-off-by: default avatarJames Chapman <jchapman@katalix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4417da66
...@@ -42,6 +42,7 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb) ...@@ -42,6 +42,7 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
/* UDP encapsulation types */ /* UDP encapsulation types */
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ #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_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */
#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/types.h> #include <linux/types.h>
...@@ -70,6 +71,11 @@ struct udp_sock { ...@@ -70,6 +71,11 @@ struct udp_sock {
#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */ #define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */ #define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
__u8 pcflag; /* marks socket as UDP-Lite if > 0 */ __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) static inline struct udp_sock *udp_sk(const struct sock *sk)
......
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
* Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind * Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind
* a single port at the same time. * a single port at the same time.
* Derek Atkins <derek@ihtfp.com>: Add Encapulation Support * 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 * This program is free software; you can redistribute it and/or
...@@ -923,12 +924,10 @@ int udp_disconnect(struct sock *sk, int flags) ...@@ -923,12 +924,10 @@ int udp_disconnect(struct sock *sk, int flags)
* 1 if the UDP system should process it * 1 if the UDP system should process it
* 0 if we should drop this packet * 0 if we should drop this packet
* -1 if it should get processed by xfrm4_rcv_encap * -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) 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 udp_sock *up = udp_sk(sk);
struct udphdr *uh; struct udphdr *uh;
struct iphdr *iph; struct iphdr *iph;
...@@ -983,8 +982,14 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) ...@@ -983,8 +982,14 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
/* Must be an IKE packet.. pass it through */ /* Must be an IKE packet.. pass it through */
return 1; return 1;
break; 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, /* At this point we are sure that this is an ESPinUDP packet,
* so we need to remove 'len' bytes from the packet (the UDP * so we need to remove 'len' bytes from the packet (the UDP
* header and optional ESP marker bytes) and then modify the * 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) ...@@ -1055,12 +1060,25 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
if (ret < 0) { if (ret == -1) {
/* process the ESP packet */ /* process the ESP packet */
ret = xfrm4_rcv_encap(skb, up->encap_type); ret = xfrm4_rcv_encap(skb, up->encap_type);
UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
return -ret; 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 */ /* FALLTHROUGH -- it's a UDP Packet */
} }
...@@ -1349,6 +1367,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, ...@@ -1349,6 +1367,7 @@ 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:
case UDP_ENCAP_L2TPINUDP:
up->encap_type = val; up->encap_type = val;
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment