diff options
-rw-r--r-- | include/uapi/linux/netfilter/xt_socket.h | 7 | ||||
-rw-r--r-- | net/netfilter/xt_socket.c | 70 |
2 files changed, 69 insertions, 8 deletions
diff --git a/include/uapi/linux/netfilter/xt_socket.h b/include/uapi/linux/netfilter/xt_socket.h index 26d7217bd4f1..6315e2ac3474 100644 --- a/include/uapi/linux/netfilter/xt_socket.h +++ b/include/uapi/linux/netfilter/xt_socket.h | |||
@@ -5,10 +5,17 @@ | |||
5 | 5 | ||
6 | enum { | 6 | enum { |
7 | XT_SOCKET_TRANSPARENT = 1 << 0, | 7 | XT_SOCKET_TRANSPARENT = 1 << 0, |
8 | XT_SOCKET_NOWILDCARD = 1 << 1, | ||
8 | }; | 9 | }; |
9 | 10 | ||
10 | struct xt_socket_mtinfo1 { | 11 | struct xt_socket_mtinfo1 { |
11 | __u8 flags; | 12 | __u8 flags; |
12 | }; | 13 | }; |
14 | #define XT_SOCKET_FLAGS_V1 XT_SOCKET_TRANSPARENT | ||
15 | |||
16 | struct xt_socket_mtinfo2 { | ||
17 | __u8 flags; | ||
18 | }; | ||
19 | #define XT_SOCKET_FLAGS_V2 (XT_SOCKET_TRANSPARENT | XT_SOCKET_NOWILDCARD) | ||
13 | 20 | ||
14 | #endif /* _XT_SOCKET_H */ | 21 | #endif /* _XT_SOCKET_H */ |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 02704245710e..f8b71911037a 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -163,8 +163,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, | |||
163 | bool wildcard; | 163 | bool wildcard; |
164 | bool transparent = true; | 164 | bool transparent = true; |
165 | 165 | ||
166 | /* Ignore sockets listening on INADDR_ANY */ | 166 | /* Ignore sockets listening on INADDR_ANY, |
167 | wildcard = (sk->sk_state != TCP_TIME_WAIT && | 167 | * unless XT_SOCKET_NOWILDCARD is set |
168 | */ | ||
169 | wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) && | ||
170 | sk->sk_state != TCP_TIME_WAIT && | ||
168 | inet_sk(sk)->inet_rcv_saddr == 0); | 171 | inet_sk(sk)->inet_rcv_saddr == 0); |
169 | 172 | ||
170 | /* Ignore non-transparent sockets, | 173 | /* Ignore non-transparent sockets, |
@@ -197,7 +200,7 @@ socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par) | |||
197 | } | 200 | } |
198 | 201 | ||
199 | static bool | 202 | static bool |
200 | socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par) | 203 | socket_mt4_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) |
201 | { | 204 | { |
202 | return socket_match(skb, par, par->matchinfo); | 205 | return socket_match(skb, par, par->matchinfo); |
203 | } | 206 | } |
@@ -259,7 +262,7 @@ extract_icmp6_fields(const struct sk_buff *skb, | |||
259 | } | 262 | } |
260 | 263 | ||
261 | static bool | 264 | static bool |
262 | socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | 265 | socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) |
263 | { | 266 | { |
264 | struct ipv6hdr *iph = ipv6_hdr(skb); | 267 | struct ipv6hdr *iph = ipv6_hdr(skb); |
265 | struct udphdr _hdr, *hp = NULL; | 268 | struct udphdr _hdr, *hp = NULL; |
@@ -302,8 +305,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
302 | bool wildcard; | 305 | bool wildcard; |
303 | bool transparent = true; | 306 | bool transparent = true; |
304 | 307 | ||
305 | /* Ignore sockets listening on INADDR_ANY */ | 308 | /* Ignore sockets listening on INADDR_ANY |
306 | wildcard = (sk->sk_state != TCP_TIME_WAIT && | 309 | * unless XT_SOCKET_NOWILDCARD is set |
310 | */ | ||
311 | wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) && | ||
312 | sk->sk_state != TCP_TIME_WAIT && | ||
307 | ipv6_addr_any(&inet6_sk(sk)->rcv_saddr)); | 313 | ipv6_addr_any(&inet6_sk(sk)->rcv_saddr)); |
308 | 314 | ||
309 | /* Ignore non-transparent sockets, | 315 | /* Ignore non-transparent sockets, |
@@ -331,6 +337,28 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
331 | } | 337 | } |
332 | #endif | 338 | #endif |
333 | 339 | ||
340 | static int socket_mt_v1_check(const struct xt_mtchk_param *par) | ||
341 | { | ||
342 | const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; | ||
343 | |||
344 | if (info->flags & ~XT_SOCKET_FLAGS_V1) { | ||
345 | pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static int socket_mt_v2_check(const struct xt_mtchk_param *par) | ||
352 | { | ||
353 | const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo; | ||
354 | |||
355 | if (info->flags & ~XT_SOCKET_FLAGS_V2) { | ||
356 | pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | return 0; | ||
360 | } | ||
361 | |||
334 | static struct xt_match socket_mt_reg[] __read_mostly = { | 362 | static struct xt_match socket_mt_reg[] __read_mostly = { |
335 | { | 363 | { |
336 | .name = "socket", | 364 | .name = "socket", |
@@ -345,7 +373,8 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
345 | .name = "socket", | 373 | .name = "socket", |
346 | .revision = 1, | 374 | .revision = 1, |
347 | .family = NFPROTO_IPV4, | 375 | .family = NFPROTO_IPV4, |
348 | .match = socket_mt4_v1, | 376 | .match = socket_mt4_v1_v2, |
377 | .checkentry = socket_mt_v1_check, | ||
349 | .matchsize = sizeof(struct xt_socket_mtinfo1), | 378 | .matchsize = sizeof(struct xt_socket_mtinfo1), |
350 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 379 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
351 | (1 << NF_INET_LOCAL_IN), | 380 | (1 << NF_INET_LOCAL_IN), |
@@ -356,7 +385,32 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
356 | .name = "socket", | 385 | .name = "socket", |
357 | .revision = 1, | 386 | .revision = 1, |
358 | .family = NFPROTO_IPV6, | 387 | .family = NFPROTO_IPV6, |
359 | .match = socket_mt6_v1, | 388 | .match = socket_mt6_v1_v2, |
389 | .checkentry = socket_mt_v1_check, | ||
390 | .matchsize = sizeof(struct xt_socket_mtinfo1), | ||
391 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
392 | (1 << NF_INET_LOCAL_IN), | ||
393 | .me = THIS_MODULE, | ||
394 | }, | ||
395 | #endif | ||
396 | { | ||
397 | .name = "socket", | ||
398 | .revision = 2, | ||
399 | .family = NFPROTO_IPV4, | ||
400 | .match = socket_mt4_v1_v2, | ||
401 | .checkentry = socket_mt_v2_check, | ||
402 | .matchsize = sizeof(struct xt_socket_mtinfo1), | ||
403 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
404 | (1 << NF_INET_LOCAL_IN), | ||
405 | .me = THIS_MODULE, | ||
406 | }, | ||
407 | #ifdef XT_SOCKET_HAVE_IPV6 | ||
408 | { | ||
409 | .name = "socket", | ||
410 | .revision = 2, | ||
411 | .family = NFPROTO_IPV6, | ||
412 | .match = socket_mt6_v1_v2, | ||
413 | .checkentry = socket_mt_v2_check, | ||
360 | .matchsize = sizeof(struct xt_socket_mtinfo1), | 414 | .matchsize = sizeof(struct xt_socket_mtinfo1), |
361 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 415 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
362 | (1 << NF_INET_LOCAL_IN), | 416 | (1 << NF_INET_LOCAL_IN), |