diff options
author | James Chapman <jchapman@katalix.com> | 2007-06-27 18:37:46 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:15:57 -0400 |
commit | 342f0234c71b40da785dd6a7ce1dd481ecbfdb81 (patch) | |
tree | b6d7295cd484449f3f6478fe3e796fc8988534a3 | |
parent | 4417da668c0021903464f92db278ddae348e0299 (diff) |
[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: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-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 6de445c31a64..8ec703f462da 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) | |||
42 | /* UDP encapsulation types */ | 42 | /* UDP encapsulation types */ |
43 | #define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ | 43 | #define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ |
44 | #define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ | 44 | #define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ |
45 | #define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */ | ||
45 | 46 | ||
46 | #ifdef __KERNEL__ | 47 | #ifdef __KERNEL__ |
47 | #include <linux/types.h> | 48 | #include <linux/types.h> |
@@ -70,6 +71,11 @@ struct udp_sock { | |||
70 | #define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */ | 71 | #define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */ |
71 | #define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */ | 72 | #define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */ |
72 | __u8 pcflag; /* marks socket as UDP-Lite if > 0 */ | 73 | __u8 pcflag; /* marks socket as UDP-Lite if > 0 */ |
74 | __u8 unused[3]; | ||
75 | /* | ||
76 | * For encapsulation sockets. | ||
77 | */ | ||
78 | int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); | ||
73 | }; | 79 | }; |
74 | 80 | ||
75 | static inline struct udp_sock *udp_sk(const struct sock *sk) | 81 | static inline struct udp_sock *udp_sk(const struct sock *sk) |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index facb7e29304e..b9276f8bdac5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -70,6 +70,7 @@ | |||
70 | * Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind | 70 | * Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind |
71 | * a single port at the same time. | 71 | * a single port at the same time. |
72 | * Derek Atkins <derek@ihtfp.com>: Add Encapulation Support | 72 | * Derek Atkins <derek@ihtfp.com>: Add Encapulation Support |
73 | * James Chapman : Add L2TP encapsulation type. | ||
73 | * | 74 | * |
74 | * | 75 | * |
75 | * This program is free software; you can redistribute it and/or | 76 | * This program is free software; you can redistribute it and/or |
@@ -923,12 +924,10 @@ int udp_disconnect(struct sock *sk, int flags) | |||
923 | * 1 if the UDP system should process it | 924 | * 1 if the UDP system should process it |
924 | * 0 if we should drop this packet | 925 | * 0 if we should drop this packet |
925 | * -1 if it should get processed by xfrm4_rcv_encap | 926 | * -1 if it should get processed by xfrm4_rcv_encap |
927 | * -2 if it should get processed by l2tp | ||
926 | */ | 928 | */ |
927 | static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | 929 | static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) |
928 | { | 930 | { |
929 | #ifndef CONFIG_XFRM | ||
930 | return 1; | ||
931 | #else | ||
932 | struct udp_sock *up = udp_sk(sk); | 931 | struct udp_sock *up = udp_sk(sk); |
933 | struct udphdr *uh; | 932 | struct udphdr *uh; |
934 | struct iphdr *iph; | 933 | struct iphdr *iph; |
@@ -983,8 +982,14 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | |||
983 | /* Must be an IKE packet.. pass it through */ | 982 | /* Must be an IKE packet.. pass it through */ |
984 | return 1; | 983 | return 1; |
985 | break; | 984 | break; |
985 | case UDP_ENCAP_L2TPINUDP: | ||
986 | /* Let caller know to send this to l2tp */ | ||
987 | return -2; | ||
986 | } | 988 | } |
987 | 989 | ||
990 | #ifndef CONFIG_XFRM | ||
991 | return 1; | ||
992 | #else | ||
988 | /* At this point we are sure that this is an ESPinUDP packet, | 993 | /* At this point we are sure that this is an ESPinUDP packet, |
989 | * so we need to remove 'len' bytes from the packet (the UDP | 994 | * so we need to remove 'len' bytes from the packet (the UDP |
990 | * header and optional ESP marker bytes) and then modify the | 995 | * 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 | kfree_skb(skb); | 1060 | kfree_skb(skb); |
1056 | return 0; | 1061 | return 0; |
1057 | } | 1062 | } |
1058 | if (ret < 0) { | 1063 | if (ret == -1) { |
1059 | /* process the ESP packet */ | 1064 | /* process the ESP packet */ |
1060 | ret = xfrm4_rcv_encap(skb, up->encap_type); | 1065 | ret = xfrm4_rcv_encap(skb, up->encap_type); |
1061 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); | 1066 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); |
1062 | return -ret; | 1067 | return -ret; |
1063 | } | 1068 | } |
1069 | if (ret == -2) { | ||
1070 | /* process the L2TP packet */ | ||
1071 | if (up->encap_rcv != NULL) { | ||
1072 | ret = (*up->encap_rcv)(sk, skb); | ||
1073 | if (ret <= 0) { | ||
1074 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); | ||
1075 | return ret; | ||
1076 | } | ||
1077 | |||
1078 | /* FALLTHROUGH -- pass up as UDP packet */ | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1064 | /* FALLTHROUGH -- it's a UDP Packet */ | 1082 | /* FALLTHROUGH -- it's a UDP Packet */ |
1065 | } | 1083 | } |
1066 | 1084 | ||
@@ -1349,6 +1367,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1349 | case 0: | 1367 | case 0: |
1350 | case UDP_ENCAP_ESPINUDP: | 1368 | case UDP_ENCAP_ESPINUDP: |
1351 | case UDP_ENCAP_ESPINUDP_NON_IKE: | 1369 | case UDP_ENCAP_ESPINUDP_NON_IKE: |
1370 | case UDP_ENCAP_L2TPINUDP: | ||
1352 | up->encap_type = val; | 1371 | up->encap_type = val; |
1353 | break; | 1372 | break; |
1354 | default: | 1373 | default: |