aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-05-09 18:07:44 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-09 18:07:44 -0400
commita49d1a905ed96c7a790d9535e2bc62d3f2f55a05 (patch)
tree709bdaab23aa7ef98aad0cdfd4d8ecd8324650cc
parent2e7d21c54adbab6d10481eddc685328f89bb6389 (diff)
parent0197dee7d3182bb6b6a21955860dfa14fa022d84 (diff)
Merge git://1984.lsi.us.es/net-next
-rw-r--r--include/linux/netfilter/xt_HMARK.h45
-rw-r--r--include/linux/netfilter/xt_hashlimit.h10
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h7
-rw-r--r--net/ipv6/netfilter/ip6_tables.c36
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c4
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c4
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c4
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c4
-rw-r--r--net/netfilter/Kconfig15
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/xt_HMARK.c362
-rw-r--r--net/netfilter/xt_TPROXY.c4
-rw-r--r--net/netfilter/xt_hashlimit.c129
-rw-r--r--net/netfilter/xt_limit.c5
-rw-r--r--net/netfilter/xt_socket.c4
15 files changed, 588 insertions, 46 deletions
diff --git a/include/linux/netfilter/xt_HMARK.h b/include/linux/netfilter/xt_HMARK.h
new file mode 100644
index 000000000000..abb1650940d2
--- /dev/null
+++ b/include/linux/netfilter/xt_HMARK.h
@@ -0,0 +1,45 @@
1#ifndef XT_HMARK_H_
2#define XT_HMARK_H_
3
4#include <linux/types.h>
5
6enum {
7 XT_HMARK_SADDR_MASK,
8 XT_HMARK_DADDR_MASK,
9 XT_HMARK_SPI,
10 XT_HMARK_SPI_MASK,
11 XT_HMARK_SPORT,
12 XT_HMARK_DPORT,
13 XT_HMARK_SPORT_MASK,
14 XT_HMARK_DPORT_MASK,
15 XT_HMARK_PROTO_MASK,
16 XT_HMARK_RND,
17 XT_HMARK_MODULUS,
18 XT_HMARK_OFFSET,
19 XT_HMARK_CT,
20 XT_HMARK_METHOD_L3,
21 XT_HMARK_METHOD_L3_4,
22};
23#define XT_HMARK_FLAG(flag) (1 << flag)
24
25union hmark_ports {
26 struct {
27 __u16 src;
28 __u16 dst;
29 } p16;
30 __u32 v32;
31};
32
33struct xt_hmark_info {
34 union nf_inet_addr src_mask;
35 union nf_inet_addr dst_mask;
36 union hmark_ports port_mask;
37 union hmark_ports port_set;
38 __u32 flags;
39 __u16 proto_mask;
40 __u32 hashrnd;
41 __u32 hmodulus;
42 __u32 hoffset; /* Mark offset to start from */
43};
44
45#endif /* XT_HMARK_H_ */
diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h
index b1925b5925e9..05fe7993dd76 100644
--- a/include/linux/netfilter/xt_hashlimit.h
+++ b/include/linux/netfilter/xt_hashlimit.h
@@ -6,7 +6,11 @@
6/* timings are in milliseconds. */ 6/* timings are in milliseconds. */
7#define XT_HASHLIMIT_SCALE 10000 7#define XT_HASHLIMIT_SCALE 10000
8/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 8/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
9 seconds, or one every 59 hours. */ 9 * seconds, or one packet every 59 hours.
10 */
11
12/* packet length accounting is done in 16-byte steps */
13#define XT_HASHLIMIT_BYTE_SHIFT 4
10 14
11/* details of this structure hidden by the implementation */ 15/* details of this structure hidden by the implementation */
12struct xt_hashlimit_htable; 16struct xt_hashlimit_htable;
@@ -17,6 +21,10 @@ enum {
17 XT_HASHLIMIT_HASH_SIP = 1 << 2, 21 XT_HASHLIMIT_HASH_SIP = 1 << 2,
18 XT_HASHLIMIT_HASH_SPT = 1 << 3, 22 XT_HASHLIMIT_HASH_SPT = 1 << 3,
19 XT_HASHLIMIT_INVERT = 1 << 4, 23 XT_HASHLIMIT_INVERT = 1 << 4,
24 XT_HASHLIMIT_BYTES = 1 << 5,
25#ifdef __KERNEL__
26 XT_HASHLIMIT_MAX = 1 << 6,
27#endif
20}; 28};
21 29
22struct hashlimit_cfg { 30struct hashlimit_cfg {
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 1bc898b14a80..08c2cbbaa32b 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -298,9 +298,14 @@ ip6t_ext_hdr(u8 nexthdr)
298 (nexthdr == IPPROTO_DSTOPTS); 298 (nexthdr == IPPROTO_DSTOPTS);
299} 299}
300 300
301enum {
302 IP6T_FH_F_FRAG = (1 << 0),
303 IP6T_FH_F_AUTH = (1 << 1),
304};
305
301/* find specified header and get offset to it */ 306/* find specified header and get offset to it */
302extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, 307extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
303 int target, unsigned short *fragoff); 308 int target, unsigned short *fragoff, int *fragflg);
304 309
305#ifdef CONFIG_COMPAT 310#ifdef CONFIG_COMPAT
306#include <net/compat.h> 311#include <net/compat.h>
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index d4e350f72bbb..308bdd651230 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -133,7 +133,7 @@ ip6_packet_match(const struct sk_buff *skb,
133 int protohdr; 133 int protohdr;
134 unsigned short _frag_off; 134 unsigned short _frag_off;
135 135
136 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off); 136 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off, NULL);
137 if (protohdr < 0) { 137 if (protohdr < 0) {
138 if (_frag_off == 0) 138 if (_frag_off == 0)
139 *hotdrop = true; 139 *hotdrop = true;
@@ -362,6 +362,7 @@ ip6t_do_table(struct sk_buff *skb,
362 const struct xt_entry_match *ematch; 362 const struct xt_entry_match *ematch;
363 363
364 IP_NF_ASSERT(e); 364 IP_NF_ASSERT(e);
365 acpar.thoff = 0;
365 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, 366 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
366 &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) { 367 &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
367 no_match: 368 no_match:
@@ -2278,6 +2279,10 @@ static void __exit ip6_tables_fini(void)
2278 * if target < 0. "last header" is transport protocol header, ESP, or 2279 * if target < 0. "last header" is transport protocol header, ESP, or
2279 * "No next header". 2280 * "No next header".
2280 * 2281 *
2282 * Note that *offset is used as input/output parameter. an if it is not zero,
2283 * then it must be a valid offset to an inner IPv6 header. This can be used
2284 * to explore inner IPv6 header, eg. ICMPv6 error messages.
2285 *
2281 * If target header is found, its offset is set in *offset and return protocol 2286 * If target header is found, its offset is set in *offset and return protocol
2282 * number. Otherwise, return -1. 2287 * number. Otherwise, return -1.
2283 * 2288 *
@@ -2289,17 +2294,33 @@ static void __exit ip6_tables_fini(void)
2289 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff 2294 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
2290 * isn't NULL. 2295 * isn't NULL.
2291 * 2296 *
2297 * if flags is not NULL and it's a fragment, then the frag flag IP6T_FH_F_FRAG
2298 * will be set. If it's an AH header, the IP6T_FH_F_AUTH flag is set and
2299 * target < 0, then this function will stop at the AH header.
2292 */ 2300 */
2293int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, 2301int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2294 int target, unsigned short *fragoff) 2302 int target, unsigned short *fragoff, int *flags)
2295{ 2303{
2296 unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr); 2304 unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
2297 u8 nexthdr = ipv6_hdr(skb)->nexthdr; 2305 u8 nexthdr = ipv6_hdr(skb)->nexthdr;
2298 unsigned int len = skb->len - start; 2306 unsigned int len;
2299 2307
2300 if (fragoff) 2308 if (fragoff)
2301 *fragoff = 0; 2309 *fragoff = 0;
2302 2310
2311 if (*offset) {
2312 struct ipv6hdr _ip6, *ip6;
2313
2314 ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
2315 if (!ip6 || (ip6->version != 6)) {
2316 printk(KERN_ERR "IPv6 header not found\n");
2317 return -EBADMSG;
2318 }
2319 start = *offset + sizeof(struct ipv6hdr);
2320 nexthdr = ip6->nexthdr;
2321 }
2322 len = skb->len - start;
2323
2303 while (nexthdr != target) { 2324 while (nexthdr != target) {
2304 struct ipv6_opt_hdr _hdr, *hp; 2325 struct ipv6_opt_hdr _hdr, *hp;
2305 unsigned int hdrlen; 2326 unsigned int hdrlen;
@@ -2316,6 +2337,9 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2316 if (nexthdr == NEXTHDR_FRAGMENT) { 2337 if (nexthdr == NEXTHDR_FRAGMENT) {
2317 unsigned short _frag_off; 2338 unsigned short _frag_off;
2318 __be16 *fp; 2339 __be16 *fp;
2340
2341 if (flags) /* Indicate that this is a fragment */
2342 *flags |= IP6T_FH_F_FRAG;
2319 fp = skb_header_pointer(skb, 2343 fp = skb_header_pointer(skb,
2320 start+offsetof(struct frag_hdr, 2344 start+offsetof(struct frag_hdr,
2321 frag_off), 2345 frag_off),
@@ -2336,9 +2360,11 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
2336 return -ENOENT; 2360 return -ENOENT;
2337 } 2361 }
2338 hdrlen = 8; 2362 hdrlen = 8;
2339 } else if (nexthdr == NEXTHDR_AUTH) 2363 } else if (nexthdr == NEXTHDR_AUTH) {
2364 if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
2365 break;
2340 hdrlen = (hp->hdrlen + 2) << 2; 2366 hdrlen = (hp->hdrlen + 2) << 2;
2341 else 2367 } else
2342 hdrlen = ipv6_optlen(hp); 2368 hdrlen = ipv6_optlen(hp);
2343 2369
2344 nexthdr = hp->nexthdr; 2370 nexthdr = hp->nexthdr;
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index 89cccc5a9c92..04099ab7d2e3 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -41,11 +41,11 @@ static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par)
41 struct ip_auth_hdr _ah; 41 struct ip_auth_hdr _ah;
42 const struct ip_auth_hdr *ah; 42 const struct ip_auth_hdr *ah;
43 const struct ip6t_ah *ahinfo = par->matchinfo; 43 const struct ip6t_ah *ahinfo = par->matchinfo;
44 unsigned int ptr; 44 unsigned int ptr = 0;
45 unsigned int hdrlen = 0; 45 unsigned int hdrlen = 0;
46 int err; 46 int err;
47 47
48 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); 48 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL, NULL);
49 if (err < 0) { 49 if (err < 0) {
50 if (err != -ENOENT) 50 if (err != -ENOENT)
51 par->hotdrop = true; 51 par->hotdrop = true;
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index eda898fda6ca..3b5735e56bfe 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -40,10 +40,10 @@ frag_mt6(const struct sk_buff *skb, struct xt_action_param *par)
40 struct frag_hdr _frag; 40 struct frag_hdr _frag;
41 const struct frag_hdr *fh; 41 const struct frag_hdr *fh;
42 const struct ip6t_frag *fraginfo = par->matchinfo; 42 const struct ip6t_frag *fraginfo = par->matchinfo;
43 unsigned int ptr; 43 unsigned int ptr = 0;
44 int err; 44 int err;
45 45
46 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); 46 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL, NULL);
47 if (err < 0) { 47 if (err < 0) {
48 if (err != -ENOENT) 48 if (err != -ENOENT)
49 par->hotdrop = true; 49 par->hotdrop = true;
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 59df051eaef6..01df142bb027 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -50,7 +50,7 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
50 const struct ipv6_opt_hdr *oh; 50 const struct ipv6_opt_hdr *oh;
51 const struct ip6t_opts *optinfo = par->matchinfo; 51 const struct ip6t_opts *optinfo = par->matchinfo;
52 unsigned int temp; 52 unsigned int temp;
53 unsigned int ptr; 53 unsigned int ptr = 0;
54 unsigned int hdrlen = 0; 54 unsigned int hdrlen = 0;
55 bool ret = false; 55 bool ret = false;
56 u8 _opttype; 56 u8 _opttype;
@@ -62,7 +62,7 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
62 62
63 err = ipv6_find_hdr(skb, &ptr, 63 err = ipv6_find_hdr(skb, &ptr,
64 (par->match == &hbh_mt6_reg[0]) ? 64 (par->match == &hbh_mt6_reg[0]) ?
65 NEXTHDR_HOP : NEXTHDR_DEST, NULL); 65 NEXTHDR_HOP : NEXTHDR_DEST, NULL, NULL);
66 if (err < 0) { 66 if (err < 0) {
67 if (err != -ENOENT) 67 if (err != -ENOENT)
68 par->hotdrop = true; 68 par->hotdrop = true;
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index d8488c50a8e0..2c99b94eeca3 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -42,14 +42,14 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par)
42 const struct ipv6_rt_hdr *rh; 42 const struct ipv6_rt_hdr *rh;
43 const struct ip6t_rt *rtinfo = par->matchinfo; 43 const struct ip6t_rt *rtinfo = par->matchinfo;
44 unsigned int temp; 44 unsigned int temp;
45 unsigned int ptr; 45 unsigned int ptr = 0;
46 unsigned int hdrlen = 0; 46 unsigned int hdrlen = 0;
47 bool ret = false; 47 bool ret = false;
48 struct in6_addr _addr; 48 struct in6_addr _addr;
49 const struct in6_addr *ap; 49 const struct in6_addr *ap;
50 int err; 50 int err;
51 51
52 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); 52 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL, NULL);
53 if (err < 0) { 53 if (err < 0) {
54 if (err != -ENOENT) 54 if (err != -ENOENT)
55 par->hotdrop = true; 55 par->hotdrop = true;
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 0c6f67e8f2e5..209c1ed43368 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -509,6 +509,21 @@ config NETFILTER_XT_TARGET_HL
509 since you can easily create immortal packets that loop 509 since you can easily create immortal packets that loop
510 forever on the network. 510 forever on the network.
511 511
512config NETFILTER_XT_TARGET_HMARK
513 tristate '"HMARK" target support'
514 depends on (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
515 depends on NETFILTER_ADVANCED
516 ---help---
517 This option adds the "HMARK" target.
518
519 The target allows you to create rules in the "raw" and "mangle" tables
520 which set the skbuff mark by means of hash calculation within a given
521 range. The nfmark can influence the routing method (see "Use netfilter
522 MARK value as routing key") and can also be used by other subsystems to
523 change their behaviour.
524
525 To compile it as a module, choose M here. If unsure, say N.
526
512config NETFILTER_XT_TARGET_IDLETIMER 527config NETFILTER_XT_TARGET_IDLETIMER
513 tristate "IDLETIMER target support" 528 tristate "IDLETIMER target support"
514 depends on NETFILTER_ADVANCED 529 depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index ca3676586f51..4e7960cc7b97 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
59obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o 59obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
60obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 60obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
61obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o 61obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
62obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o
62obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o 63obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
63obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o 64obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
64obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 65obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
diff --git a/net/netfilter/xt_HMARK.c b/net/netfilter/xt_HMARK.c
new file mode 100644
index 000000000000..32fbd735d02b
--- /dev/null
+++ b/net/netfilter/xt_HMARK.c
@@ -0,0 +1,362 @@
1/*
2 * xt_HMARK - Netfilter module to set mark by means of hashing
3 *
4 * (C) 2012 by Hans Schillstrom <hans.schillstrom@ericsson.com>
5 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/icmp.h>
15
16#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_HMARK.h>
18
19#include <net/ip.h>
20#if IS_ENABLED(CONFIG_NF_CONNTRACK)
21#include <net/netfilter/nf_conntrack.h>
22#endif
23#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
24#include <net/ipv6.h>
25#include <linux/netfilter_ipv6/ip6_tables.h>
26#endif
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Hans Schillstrom <hans.schillstrom@ericsson.com>");
30MODULE_DESCRIPTION("Xtables: packet marking using hash calculation");
31MODULE_ALIAS("ipt_HMARK");
32MODULE_ALIAS("ip6t_HMARK");
33
34struct hmark_tuple {
35 u32 src;
36 u32 dst;
37 union hmark_ports uports;
38 uint8_t proto;
39};
40
41static inline u32 hmark_addr6_mask(const __u32 *addr32, const __u32 *mask)
42{
43 return (addr32[0] & mask[0]) ^
44 (addr32[1] & mask[1]) ^
45 (addr32[2] & mask[2]) ^
46 (addr32[3] & mask[3]);
47}
48
49static inline u32
50hmark_addr_mask(int l3num, const __u32 *addr32, const __u32 *mask)
51{
52 switch (l3num) {
53 case AF_INET:
54 return *addr32 & *mask;
55 case AF_INET6:
56 return hmark_addr6_mask(addr32, mask);
57 }
58 return 0;
59}
60
61static int
62hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t,
63 const struct xt_hmark_info *info)
64{
65#if IS_ENABLED(CONFIG_NF_CONNTRACK)
66 enum ip_conntrack_info ctinfo;
67 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
68 struct nf_conntrack_tuple *otuple;
69 struct nf_conntrack_tuple *rtuple;
70
71 if (ct == NULL || nf_ct_is_untracked(ct))
72 return -1;
73
74 otuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
75 rtuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
76
77 t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.all,
78 info->src_mask.all);
79 t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.all,
80 info->dst_mask.all);
81
82 if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3))
83 return 0;
84
85 t->proto = nf_ct_protonum(ct);
86 if (t->proto != IPPROTO_ICMP) {
87 t->uports.p16.src = otuple->src.u.all;
88 t->uports.p16.dst = rtuple->src.u.all;
89 t->uports.v32 = (t->uports.v32 & info->port_mask.v32) |
90 info->port_set.v32;
91 if (t->uports.p16.dst < t->uports.p16.src)
92 swap(t->uports.p16.dst, t->uports.p16.src);
93 }
94
95 return 0;
96#else
97 return -1;
98#endif
99}
100
101static inline u32
102hmark_hash(struct hmark_tuple *t, const struct xt_hmark_info *info)
103{
104 u32 hash;
105
106 if (t->dst < t->src)
107 swap(t->src, t->dst);
108
109 hash = jhash_3words(t->src, t->dst, t->uports.v32, info->hashrnd);
110 hash = hash ^ (t->proto & info->proto_mask);
111
112 return (hash % info->hmodulus) + info->hoffset;
113}
114
115static void
116hmark_set_tuple_ports(const struct sk_buff *skb, unsigned int nhoff,
117 struct hmark_tuple *t, const struct xt_hmark_info *info)
118{
119 int protoff;
120
121 protoff = proto_ports_offset(t->proto);
122 if (protoff < 0)
123 return;
124
125 nhoff += protoff;
126 if (skb_copy_bits(skb, nhoff, &t->uports, sizeof(t->uports)) < 0)
127 return;
128
129 t->uports.v32 = (t->uports.v32 & info->port_mask.v32) |
130 info->port_set.v32;
131
132 if (t->uports.p16.dst < t->uports.p16.src)
133 swap(t->uports.p16.dst, t->uports.p16.src);
134}
135
136#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
137static int get_inner6_hdr(const struct sk_buff *skb, int *offset)
138{
139 struct icmp6hdr *icmp6h, _ih6;
140
141 icmp6h = skb_header_pointer(skb, *offset, sizeof(_ih6), &_ih6);
142 if (icmp6h == NULL)
143 return 0;
144
145 if (icmp6h->icmp6_type && icmp6h->icmp6_type < 128) {
146 *offset += sizeof(struct icmp6hdr);
147 return 1;
148 }
149 return 0;
150}
151
152static int
153hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
154 const struct xt_hmark_info *info)
155{
156 struct ipv6hdr *ip6, _ip6;
157 int flag = IP6T_FH_F_AUTH;
158 unsigned int nhoff = 0;
159 u16 fragoff = 0;
160 int nexthdr;
161
162 ip6 = (struct ipv6hdr *) (skb->data + skb_network_offset(skb));
163 nexthdr = ipv6_find_hdr(skb, &nhoff, -1, &fragoff, &flag);
164 if (nexthdr < 0)
165 return 0;
166 /* No need to check for icmp errors on fragments */
167 if ((flag & IP6T_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
168 goto noicmp;
169 /* Use inner header in case of ICMP errors */
170 if (get_inner6_hdr(skb, &nhoff)) {
171 ip6 = skb_header_pointer(skb, nhoff, sizeof(_ip6), &_ip6);
172 if (ip6 == NULL)
173 return -1;
174 /* If AH present, use SPI like in ESP. */
175 flag = IP6T_FH_F_AUTH;
176 nexthdr = ipv6_find_hdr(skb, &nhoff, -1, &fragoff, &flag);
177 if (nexthdr < 0)
178 return -1;
179 }
180noicmp:
181 t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.all);
182 t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.all);
183
184 if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3))
185 return 0;
186
187 t->proto = nexthdr;
188 if (t->proto == IPPROTO_ICMPV6)
189 return 0;
190
191 if (flag & IP6T_FH_F_FRAG)
192 return 0;
193
194 hmark_set_tuple_ports(skb, nhoff, t, info);
195 return 0;
196}
197
198static unsigned int
199hmark_tg_v6(struct sk_buff *skb, const struct xt_action_param *par)
200{
201 const struct xt_hmark_info *info = par->targinfo;
202 struct hmark_tuple t;
203
204 memset(&t, 0, sizeof(struct hmark_tuple));
205
206 if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT)) {
207 if (hmark_ct_set_htuple(skb, &t, info) < 0)
208 return XT_CONTINUE;
209 } else {
210 if (hmark_pkt_set_htuple_ipv6(skb, &t, info) < 0)
211 return XT_CONTINUE;
212 }
213
214 skb->mark = hmark_hash(&t, info);
215 return XT_CONTINUE;
216}
217#endif
218
219static int get_inner_hdr(const struct sk_buff *skb, int iphsz, int *nhoff)
220{
221 const struct icmphdr *icmph;
222 struct icmphdr _ih;
223
224 /* Not enough header? */
225 icmph = skb_header_pointer(skb, *nhoff + iphsz, sizeof(_ih), &_ih);
226 if (icmph == NULL && icmph->type > NR_ICMP_TYPES)
227 return 0;
228
229 /* Error message? */
230 if (icmph->type != ICMP_DEST_UNREACH &&
231 icmph->type != ICMP_SOURCE_QUENCH &&
232 icmph->type != ICMP_TIME_EXCEEDED &&
233 icmph->type != ICMP_PARAMETERPROB &&
234 icmph->type != ICMP_REDIRECT)
235 return 0;
236
237 *nhoff += iphsz + sizeof(_ih);
238 return 1;
239}
240
241static int
242hmark_pkt_set_htuple_ipv4(const struct sk_buff *skb, struct hmark_tuple *t,
243 const struct xt_hmark_info *info)
244{
245 struct iphdr *ip, _ip;
246 int nhoff = skb_network_offset(skb);
247
248 ip = (struct iphdr *) (skb->data + nhoff);
249 if (ip->protocol == IPPROTO_ICMP) {
250 /* Use inner header in case of ICMP errors */
251 if (get_inner_hdr(skb, ip->ihl * 4, &nhoff)) {
252 ip = skb_header_pointer(skb, nhoff, sizeof(_ip), &_ip);
253 if (ip == NULL)
254 return -1;
255 }
256 }
257
258 t->src = (__force u32) ip->saddr;
259 t->dst = (__force u32) ip->daddr;
260
261 t->src &= info->src_mask.ip;
262 t->dst &= info->dst_mask.ip;
263
264 if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3))
265 return 0;
266
267 t->proto = ip->protocol;
268
269 /* ICMP has no ports, skip */
270 if (t->proto == IPPROTO_ICMP)
271 return 0;
272
273 /* follow-up fragments don't contain ports, skip all fragments */
274 if (ip->frag_off & htons(IP_MF | IP_OFFSET))
275 return 0;
276
277 hmark_set_tuple_ports(skb, (ip->ihl * 4) + nhoff, t, info);
278
279 return 0;
280}
281
282static unsigned int
283hmark_tg_v4(struct sk_buff *skb, const struct xt_action_param *par)
284{
285 const struct xt_hmark_info *info = par->targinfo;
286 struct hmark_tuple t;
287
288 memset(&t, 0, sizeof(struct hmark_tuple));
289
290 if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT)) {
291 if (hmark_ct_set_htuple(skb, &t, info) < 0)
292 return XT_CONTINUE;
293 } else {
294 if (hmark_pkt_set_htuple_ipv4(skb, &t, info) < 0)
295 return XT_CONTINUE;
296 }
297
298 skb->mark = hmark_hash(&t, info);
299 return XT_CONTINUE;
300}
301
302static int hmark_tg_check(const struct xt_tgchk_param *par)
303{
304 const struct xt_hmark_info *info = par->targinfo;
305
306 if (!info->hmodulus) {
307 pr_info("xt_HMARK: hash modulus can't be zero\n");
308 return -EINVAL;
309 }
310 if (info->proto_mask &&
311 (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3))) {
312 pr_info("xt_HMARK: proto mask must be zero with L3 mode\n");
313 return -EINVAL;
314 }
315 if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK) &&
316 (info->flags & (XT_HMARK_FLAG(XT_HMARK_SPORT_MASK) |
317 XT_HMARK_FLAG(XT_HMARK_DPORT_MASK)))) {
318 pr_info("xt_HMARK: spi-mask and port-mask can't be combined\n");
319 return -EINVAL;
320 }
321 if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI) &&
322 (info->flags & (XT_HMARK_FLAG(XT_HMARK_SPORT) |
323 XT_HMARK_FLAG(XT_HMARK_DPORT)))) {
324 pr_info("xt_HMARK: spi-set and port-set can't be combined\n");
325 return -EINVAL;
326 }
327 return 0;
328}
329
330static struct xt_target hmark_tg_reg[] __read_mostly = {
331 {
332 .name = "HMARK",
333 .family = NFPROTO_IPV4,
334 .target = hmark_tg_v4,
335 .targetsize = sizeof(struct xt_hmark_info),
336 .checkentry = hmark_tg_check,
337 .me = THIS_MODULE,
338 },
339#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
340 {
341 .name = "HMARK",
342 .family = NFPROTO_IPV6,
343 .target = hmark_tg_v6,
344 .targetsize = sizeof(struct xt_hmark_info),
345 .checkentry = hmark_tg_check,
346 .me = THIS_MODULE,
347 },
348#endif
349};
350
351static int __init hmark_tg_init(void)
352{
353 return xt_register_targets(hmark_tg_reg, ARRAY_SIZE(hmark_tg_reg));
354}
355
356static void __exit hmark_tg_exit(void)
357{
358 xt_unregister_targets(hmark_tg_reg, ARRAY_SIZE(hmark_tg_reg));
359}
360
361module_init(hmark_tg_init);
362module_exit(hmark_tg_exit);
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 35a959a096e0..146033a86de8 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -282,10 +282,10 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par)
282 struct sock *sk; 282 struct sock *sk;
283 const struct in6_addr *laddr; 283 const struct in6_addr *laddr;
284 __be16 lport; 284 __be16 lport;
285 int thoff; 285 int thoff = 0;
286 int tproto; 286 int tproto;
287 287
288 tproto = ipv6_find_hdr(skb, &thoff, -1, NULL); 288 tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
289 if (tproto < 0) { 289 if (tproto < 0) {
290 pr_debug("unable to find transport header in IPv6 packet, dropping\n"); 290 pr_debug("unable to find transport header in IPv6 packet, dropping\n");
291 return NF_DROP; 291 return NF_DROP;
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d95f9c963cde..d0424f9621f2 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -388,9 +388,20 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
388 388
389#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) 389#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
390 390
391/* in byte mode, the lowest possible rate is one packet/second.
392 * credit_cap is used as a counter that tells us how many times we can
393 * refill the "credits available" counter when it becomes empty.
394 */
395#define MAX_CPJ_BYTES (0xFFFFFFFF / HZ)
396#define CREDITS_PER_JIFFY_BYTES POW2_BELOW32(MAX_CPJ_BYTES)
397
398static u32 xt_hashlimit_len_to_chunks(u32 len)
399{
400 return (len >> XT_HASHLIMIT_BYTE_SHIFT) + 1;
401}
402
391/* Precision saver. */ 403/* Precision saver. */
392static inline u_int32_t 404static u32 user2credits(u32 user)
393user2credits(u_int32_t user)
394{ 405{
395 /* If multiplying would overflow... */ 406 /* If multiplying would overflow... */
396 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) 407 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
@@ -400,12 +411,53 @@ user2credits(u_int32_t user)
400 return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE; 411 return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE;
401} 412}
402 413
403static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) 414static u32 user2credits_byte(u32 user)
404{ 415{
405 dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY; 416 u64 us = user;
406 if (dh->rateinfo.credit > dh->rateinfo.credit_cap) 417 us *= HZ * CREDITS_PER_JIFFY_BYTES;
407 dh->rateinfo.credit = dh->rateinfo.credit_cap; 418 return (u32) (us >> 32);
419}
420
421static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now, u32 mode)
422{
423 unsigned long delta = now - dh->rateinfo.prev;
424 u32 cap;
425
426 if (delta == 0)
427 return;
428
408 dh->rateinfo.prev = now; 429 dh->rateinfo.prev = now;
430
431 if (mode & XT_HASHLIMIT_BYTES) {
432 u32 tmp = dh->rateinfo.credit;
433 dh->rateinfo.credit += CREDITS_PER_JIFFY_BYTES * delta;
434 cap = CREDITS_PER_JIFFY_BYTES * HZ;
435 if (tmp >= dh->rateinfo.credit) {/* overflow */
436 dh->rateinfo.credit = cap;
437 return;
438 }
439 } else {
440 dh->rateinfo.credit += delta * CREDITS_PER_JIFFY;
441 cap = dh->rateinfo.credit_cap;
442 }
443 if (dh->rateinfo.credit > cap)
444 dh->rateinfo.credit = cap;
445}
446
447static void rateinfo_init(struct dsthash_ent *dh,
448 struct xt_hashlimit_htable *hinfo)
449{
450 dh->rateinfo.prev = jiffies;
451 if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) {
452 dh->rateinfo.credit = CREDITS_PER_JIFFY_BYTES * HZ;
453 dh->rateinfo.cost = user2credits_byte(hinfo->cfg.avg);
454 dh->rateinfo.credit_cap = hinfo->cfg.burst;
455 } else {
456 dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
457 hinfo->cfg.burst);
458 dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
459 dh->rateinfo.credit_cap = dh->rateinfo.credit;
460 }
409} 461}
410 462
411static inline __be32 maskl(__be32 a, unsigned int l) 463static inline __be32 maskl(__be32 a, unsigned int l)
@@ -511,6 +563,21 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
511 return 0; 563 return 0;
512} 564}
513 565
566static u32 hashlimit_byte_cost(unsigned int len, struct dsthash_ent *dh)
567{
568 u64 tmp = xt_hashlimit_len_to_chunks(len);
569 tmp = tmp * dh->rateinfo.cost;
570
571 if (unlikely(tmp > CREDITS_PER_JIFFY_BYTES * HZ))
572 tmp = CREDITS_PER_JIFFY_BYTES * HZ;
573
574 if (dh->rateinfo.credit < tmp && dh->rateinfo.credit_cap) {
575 dh->rateinfo.credit_cap--;
576 dh->rateinfo.credit = CREDITS_PER_JIFFY_BYTES * HZ;
577 }
578 return (u32) tmp;
579}
580
514static bool 581static bool
515hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) 582hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
516{ 583{
@@ -519,6 +586,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
519 unsigned long now = jiffies; 586 unsigned long now = jiffies;
520 struct dsthash_ent *dh; 587 struct dsthash_ent *dh;
521 struct dsthash_dst dst; 588 struct dsthash_dst dst;
589 u32 cost;
522 590
523 if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0) 591 if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
524 goto hotdrop; 592 goto hotdrop;
@@ -532,21 +600,21 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
532 goto hotdrop; 600 goto hotdrop;
533 } 601 }
534 dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); 602 dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
535 dh->rateinfo.prev = jiffies; 603 rateinfo_init(dh, hinfo);
536 dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
537 hinfo->cfg.burst);
538 dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
539 hinfo->cfg.burst);
540 dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
541 } else { 604 } else {
542 /* update expiration timeout */ 605 /* update expiration timeout */
543 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); 606 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
544 rateinfo_recalc(dh, now); 607 rateinfo_recalc(dh, now, hinfo->cfg.mode);
545 } 608 }
546 609
547 if (dh->rateinfo.credit >= dh->rateinfo.cost) { 610 if (info->cfg.mode & XT_HASHLIMIT_BYTES)
611 cost = hashlimit_byte_cost(skb->len, dh);
612 else
613 cost = dh->rateinfo.cost;
614
615 if (dh->rateinfo.credit >= cost) {
548 /* below the limit */ 616 /* below the limit */
549 dh->rateinfo.credit -= dh->rateinfo.cost; 617 dh->rateinfo.credit -= cost;
550 spin_unlock(&dh->lock); 618 spin_unlock(&dh->lock);
551 rcu_read_unlock_bh(); 619 rcu_read_unlock_bh();
552 return !(info->cfg.mode & XT_HASHLIMIT_INVERT); 620 return !(info->cfg.mode & XT_HASHLIMIT_INVERT);
@@ -568,14 +636,6 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
568 struct xt_hashlimit_mtinfo1 *info = par->matchinfo; 636 struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
569 int ret; 637 int ret;
570 638
571 /* Check for overflow. */
572 if (info->cfg.burst == 0 ||
573 user2credits(info->cfg.avg * info->cfg.burst) <
574 user2credits(info->cfg.avg)) {
575 pr_info("overflow, try lower: %u/%u\n",
576 info->cfg.avg, info->cfg.burst);
577 return -ERANGE;
578 }
579 if (info->cfg.gc_interval == 0 || info->cfg.expire == 0) 639 if (info->cfg.gc_interval == 0 || info->cfg.expire == 0)
580 return -EINVAL; 640 return -EINVAL;
581 if (info->name[sizeof(info->name)-1] != '\0') 641 if (info->name[sizeof(info->name)-1] != '\0')
@@ -588,6 +648,26 @@ static int hashlimit_mt_check(const struct xt_mtchk_param *par)
588 return -EINVAL; 648 return -EINVAL;
589 } 649 }
590 650
651 if (info->cfg.mode >= XT_HASHLIMIT_MAX) {
652 pr_info("Unknown mode mask %X, kernel too old?\n",
653 info->cfg.mode);
654 return -EINVAL;
655 }
656
657 /* Check for overflow. */
658 if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
659 if (user2credits_byte(info->cfg.avg) == 0) {
660 pr_info("overflow, rate too high: %u\n", info->cfg.avg);
661 return -EINVAL;
662 }
663 } else if (info->cfg.burst == 0 ||
664 user2credits(info->cfg.avg * info->cfg.burst) <
665 user2credits(info->cfg.avg)) {
666 pr_info("overflow, try lower: %u/%u\n",
667 info->cfg.avg, info->cfg.burst);
668 return -ERANGE;
669 }
670
591 mutex_lock(&hashlimit_mutex); 671 mutex_lock(&hashlimit_mutex);
592 info->hinfo = htable_find_get(net, info->name, par->family); 672 info->hinfo = htable_find_get(net, info->name, par->family);
593 if (info->hinfo == NULL) { 673 if (info->hinfo == NULL) {
@@ -680,10 +760,11 @@ static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family,
680 struct seq_file *s) 760 struct seq_file *s)
681{ 761{
682 int res; 762 int res;
763 const struct xt_hashlimit_htable *ht = s->private;
683 764
684 spin_lock(&ent->lock); 765 spin_lock(&ent->lock);
685 /* recalculate to show accurate numbers */ 766 /* recalculate to show accurate numbers */
686 rateinfo_recalc(ent, jiffies); 767 rateinfo_recalc(ent, jiffies, ht->cfg.mode);
687 768
688 switch (family) { 769 switch (family) {
689 case NFPROTO_IPV4: 770 case NFPROTO_IPV4:
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 32b7a579a032..5c22ce8ab309 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -88,8 +88,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
88} 88}
89 89
90/* Precision saver. */ 90/* Precision saver. */
91static u_int32_t 91static u32 user2credits(u32 user)
92user2credits(u_int32_t user)
93{ 92{
94 /* If multiplying would overflow... */ 93 /* If multiplying would overflow... */
95 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) 94 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
@@ -123,7 +122,7 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
123 128. */ 122 128. */
124 priv->prev = jiffies; 123 priv->prev = jiffies;
125 priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ 124 priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
126 r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ 125 r->credit_cap = priv->credit; /* Credits full. */
127 r->cost = user2credits(r->avg); 126 r->cost = user2credits(r->avg);
128 } 127 }
129 return 0; 128 return 0;
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 72bb07f57f97..9ea482d08cf7 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -263,10 +263,10 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
263 struct sock *sk; 263 struct sock *sk;
264 struct in6_addr *daddr, *saddr; 264 struct in6_addr *daddr, *saddr;
265 __be16 dport, sport; 265 __be16 dport, sport;
266 int thoff, tproto; 266 int thoff = 0, tproto;
267 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; 267 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
268 268
269 tproto = ipv6_find_hdr(skb, &thoff, -1, NULL); 269 tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
270 if (tproto < 0) { 270 if (tproto < 0) {
271 pr_debug("unable to find transport header in IPv6 packet, dropping\n"); 271 pr_debug("unable to find transport header in IPv6 packet, dropping\n");
272 return NF_DROP; 272 return NF_DROP;