diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/udp.c | 156 | ||||
-rw-r--r-- | net/ipv4/xfrm4_input.c | 114 |
2 files changed, 130 insertions, 140 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b9276f8bdac5..4ec4a25a8d0c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -920,108 +920,6 @@ int udp_disconnect(struct sock *sk, int flags) | |||
920 | return 0; | 920 | return 0; |
921 | } | 921 | } |
922 | 922 | ||
923 | /* return: | ||
924 | * 1 if the UDP system should process it | ||
925 | * 0 if we should drop this packet | ||
926 | * -1 if it should get processed by xfrm4_rcv_encap | ||
927 | * -2 if it should get processed by l2tp | ||
928 | */ | ||
929 | static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) | ||
930 | { | ||
931 | struct udp_sock *up = udp_sk(sk); | ||
932 | struct udphdr *uh; | ||
933 | struct iphdr *iph; | ||
934 | int iphlen, len; | ||
935 | |||
936 | __u8 *udpdata; | ||
937 | __be32 *udpdata32; | ||
938 | __u16 encap_type = up->encap_type; | ||
939 | |||
940 | /* if we're overly short, let UDP handle it */ | ||
941 | len = skb->len - sizeof(struct udphdr); | ||
942 | if (len <= 0) | ||
943 | return 1; | ||
944 | |||
945 | /* if this is not encapsulated socket, then just return now */ | ||
946 | if (!encap_type) | ||
947 | return 1; | ||
948 | |||
949 | /* If this is a paged skb, make sure we pull up | ||
950 | * whatever data we need to look at. */ | ||
951 | if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) | ||
952 | return 1; | ||
953 | |||
954 | /* Now we can get the pointers */ | ||
955 | uh = udp_hdr(skb); | ||
956 | udpdata = (__u8 *)uh + sizeof(struct udphdr); | ||
957 | udpdata32 = (__be32 *)udpdata; | ||
958 | |||
959 | switch (encap_type) { | ||
960 | default: | ||
961 | case UDP_ENCAP_ESPINUDP: | ||
962 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
963 | if (len == 1 && udpdata[0] == 0xff) { | ||
964 | return 0; | ||
965 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { | ||
966 | /* ESP Packet without Non-ESP header */ | ||
967 | len = sizeof(struct udphdr); | ||
968 | } else | ||
969 | /* Must be an IKE packet.. pass it through */ | ||
970 | return 1; | ||
971 | break; | ||
972 | case UDP_ENCAP_ESPINUDP_NON_IKE: | ||
973 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
974 | if (len == 1 && udpdata[0] == 0xff) { | ||
975 | return 0; | ||
976 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && | ||
977 | udpdata32[0] == 0 && udpdata32[1] == 0) { | ||
978 | |||
979 | /* ESP Packet with Non-IKE marker */ | ||
980 | len = sizeof(struct udphdr) + 2 * sizeof(u32); | ||
981 | } else | ||
982 | /* Must be an IKE packet.. pass it through */ | ||
983 | return 1; | ||
984 | break; | ||
985 | case UDP_ENCAP_L2TPINUDP: | ||
986 | /* Let caller know to send this to l2tp */ | ||
987 | return -2; | ||
988 | } | ||
989 | |||
990 | #ifndef CONFIG_XFRM | ||
991 | return 1; | ||
992 | #else | ||
993 | /* At this point we are sure that this is an ESPinUDP packet, | ||
994 | * so we need to remove 'len' bytes from the packet (the UDP | ||
995 | * header and optional ESP marker bytes) and then modify the | ||
996 | * protocol to ESP, and then call into the transform receiver. | ||
997 | */ | ||
998 | if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | ||
999 | return 0; | ||
1000 | |||
1001 | /* Now we can update and verify the packet length... */ | ||
1002 | iph = ip_hdr(skb); | ||
1003 | iphlen = iph->ihl << 2; | ||
1004 | iph->tot_len = htons(ntohs(iph->tot_len) - len); | ||
1005 | if (skb->len < iphlen + len) { | ||
1006 | /* packet is too small!?! */ | ||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | /* pull the data buffer up to the ESP header and set the | ||
1011 | * transport header to point to ESP. Keep UDP on the stack | ||
1012 | * for later. | ||
1013 | */ | ||
1014 | __skb_pull(skb, len); | ||
1015 | skb_reset_transport_header(skb); | ||
1016 | |||
1017 | /* modify the protocol (it's ESP!) */ | ||
1018 | iph->protocol = IPPROTO_ESP; | ||
1019 | |||
1020 | /* and let the caller know to send this into the ESP processor... */ | ||
1021 | return -1; | ||
1022 | #endif | ||
1023 | } | ||
1024 | |||
1025 | /* returns: | 923 | /* returns: |
1026 | * -1: error | 924 | * -1: error |
1027 | * 0: success | 925 | * 0: success |
@@ -1044,44 +942,36 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
1044 | 942 | ||
1045 | if (up->encap_type) { | 943 | if (up->encap_type) { |
1046 | /* | 944 | /* |
1047 | * This is an encapsulation socket, so let's see if this is | 945 | * This is an encapsulation socket so pass the skb to |
1048 | * an encapsulated packet. | 946 | * the socket's udp_encap_rcv() hook. Otherwise, just |
1049 | * If it's a keepalive packet, then just eat it. | 947 | * fall through and pass this up the UDP socket. |
1050 | * If it's an encapsulateed packet, then pass it to the | 948 | * up->encap_rcv() returns the following value: |
1051 | * IPsec xfrm input and return the response | 949 | * =0 if skb was successfully passed to the encap |
1052 | * appropriately. Otherwise, just fall through and | 950 | * handler or was discarded by it. |
1053 | * pass this up the UDP socket. | 951 | * >0 if skb should be passed on to UDP. |
952 | * <0 if skb should be resubmitted as proto -N | ||
1054 | */ | 953 | */ |
1055 | int ret; | 954 | unsigned int len; |
1056 | 955 | ||
1057 | ret = udp_encap_rcv(sk, skb); | 956 | /* if we're overly short, let UDP handle it */ |
1058 | if (ret == 0) { | 957 | len = skb->len - sizeof(struct udphdr); |
1059 | /* Eat the packet .. */ | 958 | if (len <= 0) |
1060 | kfree_skb(skb); | 959 | goto udp; |
1061 | return 0; | 960 | |
1062 | } | 961 | if (up->encap_rcv != NULL) { |
1063 | if (ret == -1) { | 962 | int ret; |
1064 | /* process the ESP packet */ | 963 | |
1065 | ret = xfrm4_rcv_encap(skb, up->encap_type); | 964 | ret = (*up->encap_rcv)(sk, skb); |
1066 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); | 965 | if (ret <= 0) { |
1067 | return -ret; | 966 | UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); |
1068 | } | 967 | return -ret; |
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 | } | 968 | } |
1080 | } | 969 | } |
1081 | 970 | ||
1082 | /* FALLTHROUGH -- it's a UDP Packet */ | 971 | /* FALLTHROUGH -- it's a UDP Packet */ |
1083 | } | 972 | } |
1084 | 973 | ||
974 | udp: | ||
1085 | /* | 975 | /* |
1086 | * UDP-Lite specific tests, ignored on UDP sockets | 976 | * UDP-Lite specific tests, ignored on UDP sockets |
1087 | */ | 977 | */ |
@@ -1367,6 +1257,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1367 | case 0: | 1257 | case 0: |
1368 | case UDP_ENCAP_ESPINUDP: | 1258 | case UDP_ENCAP_ESPINUDP: |
1369 | case UDP_ENCAP_ESPINUDP_NON_IKE: | 1259 | case UDP_ENCAP_ESPINUDP_NON_IKE: |
1260 | up->encap_rcv = xfrm4_udp_encap_rcv; | ||
1261 | /* FALLTHROUGH */ | ||
1370 | case UDP_ENCAP_L2TPINUDP: | 1262 | case UDP_ENCAP_L2TPINUDP: |
1371 | up->encap_type = val; | 1263 | up->encap_type = val; |
1372 | break; | 1264 | break; |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index fa1902dc81b8..2fa108245413 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
@@ -16,13 +16,6 @@ | |||
16 | #include <net/ip.h> | 16 | #include <net/ip.h> |
17 | #include <net/xfrm.h> | 17 | #include <net/xfrm.h> |
18 | 18 | ||
19 | int xfrm4_rcv(struct sk_buff *skb) | ||
20 | { | ||
21 | return xfrm4_rcv_encap(skb, 0); | ||
22 | } | ||
23 | |||
24 | EXPORT_SYMBOL(xfrm4_rcv); | ||
25 | |||
26 | static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) | 19 | static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq) |
27 | { | 20 | { |
28 | switch (nexthdr) { | 21 | switch (nexthdr) { |
@@ -53,7 +46,7 @@ drop: | |||
53 | } | 46 | } |
54 | #endif | 47 | #endif |
55 | 48 | ||
56 | int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | 49 | static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) |
57 | { | 50 | { |
58 | __be32 spi, seq; | 51 | __be32 spi, seq; |
59 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; | 52 | struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; |
@@ -167,3 +160,108 @@ drop: | |||
167 | kfree_skb(skb); | 160 | kfree_skb(skb); |
168 | return 0; | 161 | return 0; |
169 | } | 162 | } |
163 | |||
164 | /* If it's a keepalive packet, then just eat it. | ||
165 | * If it's an encapsulated packet, then pass it to the | ||
166 | * IPsec xfrm input. | ||
167 | * Returns 0 if skb passed to xfrm or was dropped. | ||
168 | * Returns >0 if skb should be passed to UDP. | ||
169 | * Returns <0 if skb should be resubmitted (-ret is protocol) | ||
170 | */ | ||
171 | int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) | ||
172 | { | ||
173 | struct udp_sock *up = udp_sk(sk); | ||
174 | struct udphdr *uh; | ||
175 | struct iphdr *iph; | ||
176 | int iphlen, len; | ||
177 | int ret; | ||
178 | |||
179 | __u8 *udpdata; | ||
180 | __be32 *udpdata32; | ||
181 | __u16 encap_type = up->encap_type; | ||
182 | |||
183 | /* if this is not encapsulated socket, then just return now */ | ||
184 | if (!encap_type) | ||
185 | return 1; | ||
186 | |||
187 | /* If this is a paged skb, make sure we pull up | ||
188 | * whatever data we need to look at. */ | ||
189 | len = skb->len - sizeof(struct udphdr); | ||
190 | if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8))) | ||
191 | return 1; | ||
192 | |||
193 | /* Now we can get the pointers */ | ||
194 | uh = udp_hdr(skb); | ||
195 | udpdata = (__u8 *)uh + sizeof(struct udphdr); | ||
196 | udpdata32 = (__be32 *)udpdata; | ||
197 | |||
198 | switch (encap_type) { | ||
199 | default: | ||
200 | case UDP_ENCAP_ESPINUDP: | ||
201 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
202 | if (len == 1 && udpdata[0] == 0xff) { | ||
203 | goto drop; | ||
204 | } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { | ||
205 | /* ESP Packet without Non-ESP header */ | ||
206 | len = sizeof(struct udphdr); | ||
207 | } else | ||
208 | /* Must be an IKE packet.. pass it through */ | ||
209 | return 1; | ||
210 | break; | ||
211 | case UDP_ENCAP_ESPINUDP_NON_IKE: | ||
212 | /* Check if this is a keepalive packet. If so, eat it. */ | ||
213 | if (len == 1 && udpdata[0] == 0xff) { | ||
214 | goto drop; | ||
215 | } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && | ||
216 | udpdata32[0] == 0 && udpdata32[1] == 0) { | ||
217 | |||
218 | /* ESP Packet with Non-IKE marker */ | ||
219 | len = sizeof(struct udphdr) + 2 * sizeof(u32); | ||
220 | } else | ||
221 | /* Must be an IKE packet.. pass it through */ | ||
222 | return 1; | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | /* At this point we are sure that this is an ESPinUDP packet, | ||
227 | * so we need to remove 'len' bytes from the packet (the UDP | ||
228 | * header and optional ESP marker bytes) and then modify the | ||
229 | * protocol to ESP, and then call into the transform receiver. | ||
230 | */ | ||
231 | if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | ||
232 | goto drop; | ||
233 | |||
234 | /* Now we can update and verify the packet length... */ | ||
235 | iph = ip_hdr(skb); | ||
236 | iphlen = iph->ihl << 2; | ||
237 | iph->tot_len = htons(ntohs(iph->tot_len) - len); | ||
238 | if (skb->len < iphlen + len) { | ||
239 | /* packet is too small!?! */ | ||
240 | goto drop; | ||
241 | } | ||
242 | |||
243 | /* pull the data buffer up to the ESP header and set the | ||
244 | * transport header to point to ESP. Keep UDP on the stack | ||
245 | * for later. | ||
246 | */ | ||
247 | __skb_pull(skb, len); | ||
248 | skb_reset_transport_header(skb); | ||
249 | |||
250 | /* modify the protocol (it's ESP!) */ | ||
251 | iph->protocol = IPPROTO_ESP; | ||
252 | |||
253 | /* process ESP */ | ||
254 | ret = xfrm4_rcv_encap(skb, encap_type); | ||
255 | return ret; | ||
256 | |||
257 | drop: | ||
258 | kfree_skb(skb); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | int xfrm4_rcv(struct sk_buff *skb) | ||
263 | { | ||
264 | return xfrm4_rcv_encap(skb, 0); | ||
265 | } | ||
266 | |||
267 | EXPORT_SYMBOL(xfrm4_rcv); | ||