aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/netfilter/xt_socket.h7
-rw-r--r--net/netfilter/xt_socket.c70
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
6enum { 6enum {
7 XT_SOCKET_TRANSPARENT = 1 << 0, 7 XT_SOCKET_TRANSPARENT = 1 << 0,
8 XT_SOCKET_NOWILDCARD = 1 << 1,
8}; 9};
9 10
10struct xt_socket_mtinfo1 { 11struct xt_socket_mtinfo1 {
11 __u8 flags; 12 __u8 flags;
12}; 13};
14#define XT_SOCKET_FLAGS_V1 XT_SOCKET_TRANSPARENT
15
16struct 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
199static bool 202static bool
200socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par) 203socket_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
261static bool 264static bool
262socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) 265socket_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
340static 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
351static 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
334static struct xt_match socket_mt_reg[] __read_mostly = { 362static 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),