diff options
-rw-r--r-- | include/linux/udp.h | 6 | ||||
-rw-r--r-- | net/ipv4/udp.c | 27 |
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: |