Commit 67da2552 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://1984.lsi.us.es/net-next

parents 7b34ca2a 2597a834
...@@ -414,21 +414,6 @@ Who: Jean Delvare <khali@linux-fr.org> ...@@ -414,21 +414,6 @@ Who: Jean Delvare <khali@linux-fr.org>
---------------------------- ----------------------------
What: xt_connlimit rev 0
When: 2012
Who: Jan Engelhardt <jengelh@medozas.de>
Files: net/netfilter/xt_connlimit.c
----------------------------
What: ipt_addrtype match include file
When: 2012
Why: superseded by xt_addrtype
Who: Florian Westphal <fw@strlen.de>
Files: include/linux/netfilter_ipv4/ipt_addrtype.h
----------------------------
What: i2c_driver.attach_adapter What: i2c_driver.attach_adapter
i2c_driver.detach_adapter i2c_driver.detach_adapter
When: September 2011 When: September 2011
...@@ -589,6 +574,13 @@ Why: Remount currently allows changing bound subsystems and ...@@ -589,6 +574,13 @@ Why: Remount currently allows changing bound subsystems and
---------------------------- ----------------------------
What: xt_recent rev 0
When: 2013
Who: Pablo Neira Ayuso <pablo@netfilter.org>
Files: net/netfilter/xt_recent.c
----------------------------
What: KVM debugfs statistics What: KVM debugfs statistics
When: 2013 When: 2013
Why: KVM tracepoints provide mostly equivalent information in a much more Why: KVM tracepoints provide mostly equivalent information in a much more
......
...@@ -94,6 +94,16 @@ static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1, ...@@ -94,6 +94,16 @@ static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
a1->all[3] == a2->all[3]; a1->all[3] == a2->all[3];
} }
static inline void nf_inet_addr_mask(const union nf_inet_addr *a1,
union nf_inet_addr *result,
const union nf_inet_addr *mask)
{
result->all[0] = a1->all[0] & mask->all[0];
result->all[1] = a1->all[1] & mask->all[1];
result->all[2] = a1->all[2] & mask->all[2];
result->all[3] = a1->all[3] & mask->all[3];
}
extern void netfilter_init(void); extern void netfilter_init(void);
/* Largest hook number + 1 */ /* Largest hook number + 1 */
......
...@@ -84,8 +84,13 @@ enum nfqnl_attr_config { ...@@ -84,8 +84,13 @@ enum nfqnl_attr_config {
NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */ NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */ NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
NFQA_CFG_QUEUE_MAXLEN, /* __u32 */ NFQA_CFG_QUEUE_MAXLEN, /* __u32 */
NFQA_CFG_MASK, /* identify which flags to change */
NFQA_CFG_FLAGS, /* value of these flags (__u32) */
__NFQA_CFG_MAX __NFQA_CFG_MAX
}; };
#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1) #define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
/* Flags for NFQA_CFG_FLAGS */
#define NFQA_CFG_F_FAIL_OPEN (1 << 0)
#endif /* _NFNETLINK_QUEUE_H */ #endif /* _NFNETLINK_QUEUE_H */
...@@ -22,13 +22,8 @@ struct xt_connlimit_info { ...@@ -22,13 +22,8 @@ struct xt_connlimit_info {
#endif #endif
}; };
unsigned int limit; unsigned int limit;
union { /* revision 1 */
/* revision 0 */ __u32 flags;
unsigned int inverse;
/* revision 1 */
__u32 flags;
};
/* Used internally by the kernel */ /* Used internally by the kernel */
struct xt_connlimit_data *data __attribute__((aligned(8))); struct xt_connlimit_data *data __attribute__((aligned(8)));
......
...@@ -32,4 +32,14 @@ struct xt_recent_mtinfo { ...@@ -32,4 +32,14 @@ struct xt_recent_mtinfo {
__u8 side; __u8 side;
}; };
struct xt_recent_mtinfo_v1 {
__u32 seconds;
__u32 hit_count;
__u8 check_set;
__u8 invert;
char name[XT_RECENT_NAME_LEN];
__u8 side;
union nf_inet_addr mask;
};
#endif /* _LINUX_NETFILTER_XT_RECENT_H */ #endif /* _LINUX_NETFILTER_XT_RECENT_H */
...@@ -5,7 +5,6 @@ header-y += ipt_LOG.h ...@@ -5,7 +5,6 @@ header-y += ipt_LOG.h
header-y += ipt_REJECT.h header-y += ipt_REJECT.h
header-y += ipt_TTL.h header-y += ipt_TTL.h
header-y += ipt_ULOG.h header-y += ipt_ULOG.h
header-y += ipt_addrtype.h
header-y += ipt_ah.h header-y += ipt_ah.h
header-y += ipt_ecn.h header-y += ipt_ecn.h
header-y += ipt_ttl.h header-y += ipt_ttl.h
#ifndef _IPT_ADDRTYPE_H
#define _IPT_ADDRTYPE_H
#include <linux/types.h>
enum {
IPT_ADDRTYPE_INVERT_SOURCE = 0x0001,
IPT_ADDRTYPE_INVERT_DEST = 0x0002,
IPT_ADDRTYPE_LIMIT_IFACE_IN = 0x0004,
IPT_ADDRTYPE_LIMIT_IFACE_OUT = 0x0008,
};
struct ipt_addrtype_info_v1 {
__u16 source; /* source-type mask */
__u16 dest; /* dest-type mask */
__u32 flags;
};
/* revision 0 */
struct ipt_addrtype_info {
__u16 source; /* source-type mask */
__u16 dest; /* dest-type mask */
__u32 invert_source;
__u32 invert_dest;
};
#endif
...@@ -28,8 +28,8 @@ extern unsigned int nf_conntrack_in(struct net *net, ...@@ -28,8 +28,8 @@ extern unsigned int nf_conntrack_in(struct net *net,
extern int nf_conntrack_init(struct net *net); extern int nf_conntrack_init(struct net *net);
extern void nf_conntrack_cleanup(struct net *net); extern void nf_conntrack_cleanup(struct net *net);
extern int nf_conntrack_proto_init(void); extern int nf_conntrack_proto_init(struct net *net);
extern void nf_conntrack_proto_fini(void); extern void nf_conntrack_proto_fini(struct net *net);
extern bool extern bool
nf_ct_get_tuple(const struct sk_buff *skb, nf_ct_get_tuple(const struct sk_buff *skb,
......
...@@ -64,11 +64,12 @@ struct nf_conntrack_l3proto { ...@@ -64,11 +64,12 @@ struct nf_conntrack_l3proto {
size_t nla_size; size_t nla_size;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct ctl_table_header *ctl_table_header;
const char *ctl_table_path; const char *ctl_table_path;
struct ctl_table *ctl_table;
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
/* Init l3proto pernet data */
int (*init_net)(struct net *net);
/* Module (if any) which this is connected to. */ /* Module (if any) which this is connected to. */
struct module *me; struct module *me;
}; };
...@@ -76,8 +77,10 @@ struct nf_conntrack_l3proto { ...@@ -76,8 +77,10 @@ struct nf_conntrack_l3proto {
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX]; extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
/* Protocol registration. */ /* Protocol registration. */
extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); extern int nf_conntrack_l3proto_register(struct net *net,
extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); struct nf_conntrack_l3proto *proto);
extern void nf_conntrack_l3proto_unregister(struct net *net,
struct nf_conntrack_l3proto *proto);
extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto); extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netns/generic.h>
struct seq_file; struct seq_file;
...@@ -86,23 +87,18 @@ struct nf_conntrack_l4proto { ...@@ -86,23 +87,18 @@ struct nf_conntrack_l4proto {
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
struct { struct {
size_t obj_size; size_t obj_size;
int (*nlattr_to_obj)(struct nlattr *tb[], void *data); int (*nlattr_to_obj)(struct nlattr *tb[],
struct net *net, void *data);
int (*obj_to_nlattr)(struct sk_buff *skb, const void *data); int (*obj_to_nlattr)(struct sk_buff *skb, const void *data);
unsigned int nlattr_max; unsigned int nlattr_max;
const struct nla_policy *nla_policy; const struct nla_policy *nla_policy;
} ctnl_timeout; } ctnl_timeout;
#endif #endif
int *net_id;
/* Init l4proto pernet data */
int (*init_net)(struct net *net);
#ifdef CONFIG_SYSCTL
struct ctl_table_header **ctl_table_header;
struct ctl_table *ctl_table;
unsigned int *ctl_table_users;
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
struct ctl_table_header *ctl_compat_table_header;
struct ctl_table *ctl_compat_table;
#endif
#endif
/* Protocol name */ /* Protocol name */
const char *name; const char *name;
...@@ -123,8 +119,10 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto); ...@@ -123,8 +119,10 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
/* Protocol registration. */ /* Protocol registration. */
extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); extern int nf_conntrack_l4proto_register(struct net *net,
extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); struct nf_conntrack_l4proto *proto);
extern void nf_conntrack_l4proto_unregister(struct net *net,
struct nf_conntrack_l4proto *proto);
/* Generic netlink helpers */ /* Generic netlink helpers */
extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
......
...@@ -4,10 +4,64 @@ ...@@ -4,10 +4,64 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/list_nulls.h> #include <linux/list_nulls.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/netfilter/nf_conntrack_tcp.h>
struct ctl_table_header; struct ctl_table_header;
struct nf_conntrack_ecache; struct nf_conntrack_ecache;
struct nf_proto_net {
#ifdef CONFIG_SYSCTL
struct ctl_table_header *ctl_table_header;
struct ctl_table *ctl_table;
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
struct ctl_table_header *ctl_compat_header;
struct ctl_table *ctl_compat_table;
#endif
#endif
unsigned int users;
};
struct nf_generic_net {
struct nf_proto_net pn;
unsigned int timeout;
};
struct nf_tcp_net {
struct nf_proto_net pn;
unsigned int timeouts[TCP_CONNTRACK_TIMEOUT_MAX];
unsigned int tcp_loose;
unsigned int tcp_be_liberal;
unsigned int tcp_max_retrans;
};
enum udp_conntrack {
UDP_CT_UNREPLIED,
UDP_CT_REPLIED,
UDP_CT_MAX
};
struct nf_udp_net {
struct nf_proto_net pn;
unsigned int timeouts[UDP_CT_MAX];
};
struct nf_icmp_net {
struct nf_proto_net pn;
unsigned int timeout;
};
struct nf_ip_net {
struct nf_generic_net generic;
struct nf_tcp_net tcp;
struct nf_udp_net udp;
struct nf_icmp_net icmp;
struct nf_icmp_net icmpv6;
#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
struct ctl_table_header *ctl_table_header;
struct ctl_table *ctl_table;
#endif
};
struct netns_ct { struct netns_ct {
atomic_t count; atomic_t count;
unsigned int expect_count; unsigned int expect_count;
...@@ -28,6 +82,7 @@ struct netns_ct { ...@@ -28,6 +82,7 @@ struct netns_ct {
unsigned int sysctl_log_invalid; /* Log invalid packets */ unsigned int sysctl_log_invalid; /* Log invalid packets */
int sysctl_auto_assign_helper; int sysctl_auto_assign_helper;
bool auto_assign_helper_warned; bool auto_assign_helper_warned;
struct nf_ip_net nf_ct_proto;
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_header; struct ctl_table_header *sysctl_header;
struct ctl_table_header *acct_sysctl_header; struct ctl_table_header *acct_sysctl_header;
......
...@@ -764,9 +764,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, ...@@ -764,9 +764,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
return NF_DROP; return NF_DROP;
if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb)) if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb))
pf = PF_INET; pf = NFPROTO_IPV4;
else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb))
pf = PF_INET6; pf = NFPROTO_IPV6;
else else
return NF_ACCEPT; return NF_ACCEPT;
...@@ -778,13 +778,13 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, ...@@ -778,13 +778,13 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
nf_bridge->mask |= BRNF_PKT_TYPE; nf_bridge->mask |= BRNF_PKT_TYPE;
} }
if (pf == PF_INET && br_parse_ip_options(skb)) if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb))
return NF_DROP; return NF_DROP;
/* The physdev module checks on this */ /* The physdev module checks on this */
nf_bridge->mask |= BRNF_BRIDGED; nf_bridge->mask |= BRNF_BRIDGED;
nf_bridge->physoutdev = skb->dev; nf_bridge->physoutdev = skb->dev;
if (pf == PF_INET) if (pf == NFPROTO_IPV4)
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
else else
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
...@@ -871,9 +871,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, ...@@ -871,9 +871,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb,
return NF_DROP; return NF_DROP;
if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb)) if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb))
pf = PF_INET; pf = NFPROTO_IPV4;
else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb))
pf = PF_INET6; pf = NFPROTO_IPV6;
else else
return NF_ACCEPT; return NF_ACCEPT;
...@@ -886,7 +886,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, ...@@ -886,7 +886,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb,
nf_bridge_pull_encap_header(skb); nf_bridge_pull_encap_header(skb);
nf_bridge_save_header(skb); nf_bridge_save_header(skb);
if (pf == PF_INET) if (pf == NFPROTO_IPV4)
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
else else
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
...@@ -919,49 +919,49 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { ...@@ -919,49 +919,49 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = {
{ {
.hook = br_nf_pre_routing, .hook = br_nf_pre_routing,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_BRIDGE, .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_PRE_ROUTING, .hooknum = NF_BR_PRE_ROUTING,
.priority = NF_BR_PRI_BRNF, .priority = NF_BR_PRI_BRNF,
}, },
{ {
.hook = br_nf_local_in, .hook = br_nf_local_in,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_BRIDGE, .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_LOCAL_IN, .hooknum = NF_BR_LOCAL_IN,
.priority = NF_BR_PRI_BRNF, .priority = NF_BR_PRI_BRNF,
}, },
{ {
.hook = br_nf_forward_ip, .hook = br_nf_forward_ip,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_BRIDGE, .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_FORWARD, .hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_BRNF - 1, .priority = NF_BR_PRI_BRNF - 1,
}, },
{ {
.hook = br_nf_forward_arp, .hook = br_nf_forward_arp,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_BRIDGE, .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_FORWARD, .hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_BRNF, .priority = NF_BR_PRI_BRNF,
}, },
{ {
.hook = br_nf_post_routing, .hook = br_nf_post_routing,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_BRIDGE, .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_POST_ROUTING, .hooknum = NF_BR_POST_ROUTING,
.priority = NF_BR_PRI_LAST, .priority = NF_BR_PRI_LAST,
}, },
{ {
.hook = ip_sabotage_in, .hook = ip_sabotage_in,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING, .hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST, .priority = NF_IP_PRI_FIRST,
}, },
{ {
.hook = ip_sabotage_in, .hook = ip_sabotage_in,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_PRE_ROUTING, .hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP6_PRI_FIRST, .priority = NF_IP6_PRI_FIRST,
}, },
......
...@@ -117,7 +117,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) ...@@ -117,7 +117,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
static struct nf_hook_ops dnrmg_ops __read_mostly = { static struct nf_hook_ops dnrmg_ops __read_mostly = {
.hook = dnrmg_hook, .hook = dnrmg_hook,
.pf = PF_DECnet, .pf = NFPROTO_DECNET,
.hooknum = NF_DN_ROUTE, .hooknum = NF_DN_ROUTE,
.priority = NF_DN_PRI_DNRTMSG, .priority = NF_DN_PRI_DNRTMSG,
}; };
......
...@@ -207,35 +207,30 @@ static int log_invalid_proto_max = 255; ...@@ -207,35 +207,30 @@ static int log_invalid_proto_max = 255;
static ctl_table ip_ct_sysctl_table[] = { static ctl_table ip_ct_sysctl_table[] = {
{ {
.procname = "ip_conntrack_max", .procname = "ip_conntrack_max",
.data = &nf_conntrack_max,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{ {
.procname = "ip_conntrack_count", .procname = "ip_conntrack_count",
.data = &init_net.ct.count,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0444, .mode = 0444,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{ {
.procname = "ip_conntrack_buckets", .procname = "ip_conntrack_buckets",
.data = &init_net.ct.htable_size,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0444, .mode = 0444,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{ {
.procname = "ip_conntrack_checksum", .procname = "ip_conntrack_checksum",
.data = &init_net.ct.sysctl_checksum,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{ {
.procname = "ip_conntrack_log_invalid", .procname = "ip_conntrack_log_invalid",
.data = &init_net.ct.sysctl_log_invalid,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_minmax, .proc_handler = proc_dointvec_minmax,
...@@ -351,6 +346,25 @@ static struct nf_sockopt_ops so_getorigdst = { ...@@ -351,6 +346,25 @@ static struct nf_sockopt_ops so_getorigdst = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int ipv4_init_net(struct net *net)
{
#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
struct nf_ip_net *in = &net->ct.nf_ct_proto;
in->ctl_table = kmemdup(ip_ct_sysctl_table,
sizeof(ip_ct_sysctl_table),
GFP_KERNEL);
if (!in->ctl_table)
return -ENOMEM;
in->ctl_table[0].data = &nf_conntrack_max;
in->ctl_table[1].data = &net->ct.count;
in->ctl_table[2].data = &net->ct.htable_size;
in->ctl_table[3].data = &net->ct.sysctl_checksum;
in->ctl_table[4].data = &net->ct.sysctl_log_invalid;
#endif
return 0;
}
struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
.l3proto = PF_INET, .l3proto = PF_INET,
.name = "ipv4", .name = "ipv4",
...@@ -366,8 +380,8 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { ...@@ -366,8 +380,8 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
#endif #endif
#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) #if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
.ctl_table_path = "net/ipv4/netfilter", .ctl_table_path = "net/ipv4/netfilter",
.ctl_table = ip_ct_sysctl_table,
#endif #endif
.init_net = ipv4_init_net,
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
...@@ -378,6 +392,65 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); ...@@ -378,6 +392,65 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_ALIAS("ip_conntrack"); MODULE_ALIAS("ip_conntrack");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int ipv4_net_init(struct net *net)
{
int ret = 0;
ret = nf_conntrack_l4proto_register(net,
&nf_conntrack_l4proto_tcp4);
if (ret < 0) {
pr_err("nf_conntrack_l4proto_tcp4 :protocol register failed\n");
goto out_tcp;
}
ret = nf_conntrack_l4proto_register(net,
&nf_conntrack_l4proto_udp4);
if (ret < 0) {
pr_err("nf_conntrack_l4proto_udp4 :protocol register failed\n");
goto out_udp;
}
ret = nf_conntrack_l4proto_register(net,
&nf_conntrack_l4proto_icmp);
if (ret < 0) {
pr_err("nf_conntrack_l4proto_icmp4 :protocol register failed\n");
goto out_icmp;
}
ret = nf_conntrack_l3proto_register(net,
&nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_l3proto_ipv4 :protocol register failed\n");
goto out_ipv4;
}
return 0;
out_ipv4:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_icmp);
out_icmp:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_udp4);
out_udp:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_tcp4);
out_tcp:
return ret;
}
static void ipv4_net_exit(struct net *net)
{
nf_conntrack_l3proto_unregister(net,
&nf_conntrack_l3proto_ipv4);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_icmp);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_udp4);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_tcp4);
}
static struct pernet_operations ipv4_net_ops = {
.init = ipv4_net_init,
.exit = ipv4_net_exit,
};
static int __init nf_conntrack_l3proto_ipv4_init(void) static int __init nf_conntrack_l3proto_ipv4_init(void)
{ {
int ret = 0; int ret = 0;
...@@ -391,35 +464,17 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) ...@@ -391,35 +464,17 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
return ret; return ret;
} }
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4); ret = register_pernet_subsys(&ipv4_net_ops);
if (ret < 0) { if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register tcp.\n"); pr_err("nf_conntrack_ipv4: can't register pernet ops\n");
goto cleanup_sockopt; goto cleanup_sockopt;
} }
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register udp.\n");
goto cleanup_tcp;
}
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register icmp.\n");
goto cleanup_udp;
}
ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register ipv4\n");
goto cleanup_icmp;
}
ret = nf_register_hooks(ipv4_conntrack_ops, ret = nf_register_hooks(ipv4_conntrack_ops,
ARRAY_SIZE(ipv4_conntrack_ops)); ARRAY_SIZE(ipv4_conntrack_ops));
if (ret < 0) { if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register hooks.\n"); pr_err("nf_conntrack_ipv4: can't register hooks.\n");
goto cleanup_ipv4; goto cleanup_pernet;
} }
#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) #if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
ret = nf_conntrack_ipv4_compat_init(); ret = nf_conntrack_ipv4_compat_init();
...@@ -431,14 +486,8 @@ static int __init nf_conntrack_l3proto_ipv4_init(void) ...@@ -431,14 +486,8 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
cleanup_hooks: cleanup_hooks:
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
#endif #endif
cleanup_ipv4: cleanup_pernet:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); unregister_pernet_subsys(&ipv4_net_ops);
cleanup_icmp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
cleanup_udp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
cleanup_tcp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
cleanup_sockopt: cleanup_sockopt:
nf_unregister_sockopt(&so_getorigdst); nf_unregister_sockopt(&so_getorigdst);
return ret; return ret;
...@@ -451,10 +500,7 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void) ...@@ -451,10 +500,7 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
nf_conntrack_ipv4_compat_fini(); nf_conntrack_ipv4_compat_fini();
#endif #endif
nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); unregister_pernet_subsys(&ipv4_net_ops);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
nf_unregister_sockopt(&so_getorigdst); nf_unregister_sockopt(&so_getorigdst);
} }
......
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ;
static inline struct nf_icmp_net *icmp_pernet(struct net *net)
{
return &net->ct.nf_ct_proto.icmp;
}
static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
{ {
...@@ -77,7 +82,7 @@ static int icmp_print_tuple(struct seq_file *s, ...@@ -77,7 +82,7 @@ static int icmp_print_tuple(struct seq_file *s,
static unsigned int *icmp_get_timeouts(struct net *net) static unsigned int *icmp_get_timeouts(struct net *net)
{ {
return &nf_ct_icmp_timeout; return &icmp_pernet(net)->timeout;
} }
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
...@@ -274,16 +279,18 @@ static int icmp_nlattr_tuple_size(void) ...@@ -274,16 +279,18 @@ static int icmp_nlattr_tuple_size(void)
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
unsigned int *timeout = data; unsigned int *timeout = data;
struct nf_icmp_net *in = icmp_pernet(net);
if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) { if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) {
*timeout = *timeout =
ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ; ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ;
} else { } else {
/* Set default ICMP timeout. */ /* Set default ICMP timeout. */
*timeout = nf_ct_icmp_timeout; *timeout = in->timeout;
} }
return 0; return 0;
} }
...@@ -308,11 +315,9 @@ icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = { ...@@ -308,11 +315,9 @@ icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static struct ctl_table_header *icmp_sysctl_header;
static struct ctl_table icmp_sysctl_table[] = { static struct ctl_table icmp_sysctl_table[] = {
{ {
.procname = "nf_conntrack_icmp_timeout", .procname = "nf_conntrack_icmp_timeout",
.data = &nf_ct_icmp_timeout,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -323,7 +328,6 @@ static struct ctl_table icmp_sysctl_table[] = { ...@@ -323,7 +328,6 @@ static struct ctl_table icmp_sysctl_table[] = {
static struct ctl_table icmp_compat_sysctl_table[] = { static struct ctl_table icmp_compat_sysctl_table[] = {
{ {
.procname = "ip_conntrack_icmp_timeout", .procname = "ip_conntrack_icmp_timeout",
.data = &nf_ct_icmp_timeout,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -333,6 +337,34 @@ static struct ctl_table icmp_compat_sysctl_table[] = { ...@@ -333,6 +337,34 @@ static struct ctl_table icmp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
static int icmp_init_net(struct net *net)
{
struct nf_icmp_net *in = icmp_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)in;
in->timeout = nf_ct_icmp_timeout;
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(icmp_sysctl_table,
sizeof(icmp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &in->timeout;
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
pn->ctl_compat_table = kmemdup(icmp_compat_sysctl_table,
sizeof(icmp_compat_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_compat_table) {
kfree(pn->ctl_table);
pn->ctl_table = NULL;
return -ENOMEM;
}
pn->ctl_compat_table[0].data = &in->timeout;
#endif
#endif
return 0;
}
struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
{ {
.l3proto = PF_INET, .l3proto = PF_INET,
...@@ -362,11 +394,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = ...@@ -362,11 +394,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
.nla_policy = icmp_timeout_nla_policy, .nla_policy = icmp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .init_net = icmp_init_net,
.ctl_table_header = &icmp_sysctl_header,
.ctl_table = icmp_sysctl_table,
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
.ctl_compat_table = icmp_compat_sysctl_table,
#endif
#endif
}; };
...@@ -94,14 +94,14 @@ static struct nf_hook_ops ipv4_defrag_ops[] = { ...@@ -94,14 +94,14 @@ static struct nf_hook_ops ipv4_defrag_ops[] = {
{ {
.hook = ipv4_conntrack_defrag, .hook = ipv4_conntrack_defrag,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING, .hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG, .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
}, },
{ {
.hook = ipv4_conntrack_defrag, .hook = ipv4_conntrack_defrag,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT, .hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG, .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
}, },
......
...@@ -333,37 +333,75 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); ...@@ -333,37 +333,75 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
static int __init nf_conntrack_l3proto_ipv6_init(void) static int ipv6_net_init(struct net *net)
{ {
int ret = 0; int ret = 0;
need_conntrack(); ret = nf_conntrack_l4proto_register(net,
nf_defrag_ipv6_enable(); &nf_conntrack_l4proto_tcp6);
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6);
if (ret < 0) { if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register tcp.\n"); printk(KERN_ERR "nf_conntrack_l4proto_tcp6: protocol register failed\n");
return ret; goto out;
} }
ret = nf_conntrack_l4proto_register(net,
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); &nf_conntrack_l4proto_udp6);
if (ret < 0) { if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register udp.\n"); printk(KERN_ERR "nf_conntrack_l4proto_udp6: protocol register failed\n");
goto cleanup_tcp; goto cleanup_tcp6;
} }
ret = nf_conntrack_l4proto_register(net,
ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); &nf_conntrack_l4proto_icmpv6);
if (ret < 0) { if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register icmpv6.\n"); printk(KERN_ERR "nf_conntrack_l4proto_icmp6: protocol register failed\n");
goto cleanup_udp; goto cleanup_udp6;
} }
ret = nf_conntrack_l3proto_register(net,
ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6); &nf_conntrack_l3proto_ipv6);
if (ret < 0) { if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register ipv6\n"); printk(KERN_ERR "nf_conntrack_l3proto_ipv6: protocol register failed\n");
goto cleanup_icmpv6; goto cleanup_icmpv6;
} }
return 0;
cleanup_icmpv6:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_icmpv6);
cleanup_udp6:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_udp6);
cleanup_tcp6:
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_tcp6);
out:
return ret;
}
static void ipv6_net_exit(struct net *net)
{
nf_conntrack_l3proto_unregister(net,
&nf_conntrack_l3proto_ipv6);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_icmpv6);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_udp6);
nf_conntrack_l4proto_unregister(net,
&nf_conntrack_l4proto_tcp6);
}
static struct pernet_operations ipv6_net_ops = {
.init = ipv6_net_init,
.exit = ipv6_net_exit,
};
static int __init nf_conntrack_l3proto_ipv6_init(void)
{
int ret = 0;
need_conntrack();
nf_defrag_ipv6_enable();
ret = register_pernet_subsys(&ipv6_net_ops);
if (ret < 0)
goto cleanup_pernet;
ret = nf_register_hooks(ipv6_conntrack_ops, ret = nf_register_hooks(ipv6_conntrack_ops,
ARRAY_SIZE(ipv6_conntrack_ops)); ARRAY_SIZE(ipv6_conntrack_ops));
if (ret < 0) { if (ret < 0) {
...@@ -374,13 +412,8 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) ...@@ -374,13 +412,8 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
return ret; return ret;
cleanup_ipv6: cleanup_ipv6:
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); unregister_pernet_subsys(&ipv6_net_ops);
cleanup_icmpv6: cleanup_pernet:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
cleanup_udp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
cleanup_tcp:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
return ret; return ret;
} }
...@@ -388,10 +421,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void) ...@@ -388,10 +421,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
{ {
synchronize_net(); synchronize_net();
nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); unregister_pernet_subsys(&ipv6_net_ops);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
} }
module_init(nf_conntrack_l3proto_ipv6_init); module_init(nf_conntrack_l3proto_ipv6_init);
......
...@@ -29,6 +29,11 @@ ...@@ -29,6 +29,11 @@
static unsigned int nf_ct_icmpv6_timeout __read_mostly = 30*HZ; static unsigned int nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
static inline struct nf_icmp_net *icmpv6_pernet(struct net *net)
{
return &net->ct.nf_ct_proto.icmpv6;
}
static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
...@@ -90,7 +95,7 @@ static int icmpv6_print_tuple(struct seq_file *s, ...@@ -90,7 +95,7 @@ static int icmpv6_print_tuple(struct seq_file *s,
static unsigned int *icmpv6_get_timeouts(struct net *net) static unsigned int *icmpv6_get_timeouts(struct net *net)
{ {
return &nf_ct_icmpv6_timeout; return &icmpv6_pernet(net)->timeout;
} }
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
...@@ -281,16 +286,18 @@ static int icmpv6_nlattr_tuple_size(void) ...@@ -281,16 +286,18 @@ static int icmpv6_nlattr_tuple_size(void)
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
unsigned int *timeout = data; unsigned int *timeout = data;
struct nf_icmp_net *in = icmpv6_pernet(net);
if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) { if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) {
*timeout = *timeout =
ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ; ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ;
} else { } else {
/* Set default ICMPv6 timeout. */ /* Set default ICMPv6 timeout. */
*timeout = nf_ct_icmpv6_timeout; *timeout = in->timeout;
} }
return 0; return 0;
} }
...@@ -315,11 +322,9 @@ icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = { ...@@ -315,11 +322,9 @@ icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static struct ctl_table_header *icmpv6_sysctl_header;
static struct ctl_table icmpv6_sysctl_table[] = { static struct ctl_table icmpv6_sysctl_table[] = {
{ {
.procname = "nf_conntrack_icmpv6_timeout", .procname = "nf_conntrack_icmpv6_timeout",
.data = &nf_ct_icmpv6_timeout,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -328,6 +333,22 @@ static struct ctl_table icmpv6_sysctl_table[] = { ...@@ -328,6 +333,22 @@ static struct ctl_table icmpv6_sysctl_table[] = {
}; };
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
static int icmpv6_init_net(struct net *net)
{
struct nf_icmp_net *in = icmpv6_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)in;
in->timeout = nf_ct_icmpv6_timeout;
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(icmpv6_sysctl_table,
sizeof(icmpv6_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &in->timeout;
#endif
return 0;
}
struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
{ {
.l3proto = PF_INET6, .l3proto = PF_INET6,
...@@ -355,8 +376,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = ...@@ -355,8 +376,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
.nla_policy = icmpv6_timeout_nla_policy, .nla_policy = icmpv6_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .init_net = icmpv6_init_net,
.ctl_table_header = &icmpv6_sysctl_header,
.ctl_table = icmpv6_sysctl_table,
#endif
}; };
...@@ -1742,7 +1742,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1742,7 +1742,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_reply4, .hook = ip_vs_reply4,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN, .hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC - 2, .priority = NF_IP_PRI_NAT_SRC - 2,
}, },
...@@ -1752,7 +1752,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1752,7 +1752,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_remote_request4, .hook = ip_vs_remote_request4,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN, .hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC - 1, .priority = NF_IP_PRI_NAT_SRC - 1,
}, },
...@@ -1760,7 +1760,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1760,7 +1760,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_local_reply4, .hook = ip_vs_local_reply4,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT, .hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST + 1, .priority = NF_IP_PRI_NAT_DST + 1,
}, },
...@@ -1768,7 +1768,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1768,7 +1768,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_local_request4, .hook = ip_vs_local_request4,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT, .hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST + 2, .priority = NF_IP_PRI_NAT_DST + 2,
}, },
...@@ -1777,7 +1777,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1777,7 +1777,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_forward_icmp, .hook = ip_vs_forward_icmp,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD, .hooknum = NF_INET_FORWARD,
.priority = 99, .priority = 99,
}, },
...@@ -1785,7 +1785,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1785,7 +1785,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_reply4, .hook = ip_vs_reply4,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD, .hooknum = NF_INET_FORWARD,
.priority = 100, .priority = 100,
}, },
...@@ -1794,7 +1794,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1794,7 +1794,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_reply6, .hook = ip_vs_reply6,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN, .hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP6_PRI_NAT_SRC - 2, .priority = NF_IP6_PRI_NAT_SRC - 2,
}, },
...@@ -1804,7 +1804,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1804,7 +1804,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_remote_request6, .hook = ip_vs_remote_request6,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN, .hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP6_PRI_NAT_SRC - 1, .priority = NF_IP6_PRI_NAT_SRC - 1,
}, },
...@@ -1812,7 +1812,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1812,7 +1812,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_local_reply6, .hook = ip_vs_local_reply6,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT, .hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP6_PRI_NAT_DST + 1, .priority = NF_IP6_PRI_NAT_DST + 1,
}, },
...@@ -1820,7 +1820,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1820,7 +1820,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_local_request6, .hook = ip_vs_local_request6,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_OUT, .hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP6_PRI_NAT_DST + 2, .priority = NF_IP6_PRI_NAT_DST + 2,
}, },
...@@ -1829,7 +1829,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1829,7 +1829,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_forward_icmp_v6, .hook = ip_vs_forward_icmp_v6,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD, .hooknum = NF_INET_FORWARD,
.priority = 99, .priority = 99,
}, },
...@@ -1837,7 +1837,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { ...@@ -1837,7 +1837,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
{ {
.hook = ip_vs_reply6, .hook = ip_vs_reply6,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD, .hooknum = NF_INET_FORWARD,
.priority = 100, .priority = 100,
}, },
......
...@@ -1333,7 +1333,6 @@ static void nf_conntrack_cleanup_init_net(void) ...@@ -1333,7 +1333,6 @@ static void nf_conntrack_cleanup_init_net(void)
while (untrack_refs() > 0) while (untrack_refs() > 0)
schedule(); schedule();
nf_conntrack_proto_fini();
#ifdef CONFIG_NF_CONNTRACK_ZONES #ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend); nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif #endif
...@@ -1372,7 +1371,7 @@ void nf_conntrack_cleanup(struct net *net) ...@@ -1372,7 +1371,7 @@ void nf_conntrack_cleanup(struct net *net)
netfilter framework. Roll on, two-stage module netfilter framework. Roll on, two-stage module
delete... */ delete... */
synchronize_net(); synchronize_net();
nf_conntrack_proto_fini(net);
nf_conntrack_cleanup_net(net); nf_conntrack_cleanup_net(net);
if (net_eq(net, &init_net)) { if (net_eq(net, &init_net)) {
...@@ -1496,11 +1495,6 @@ static int nf_conntrack_init_init_net(void) ...@@ -1496,11 +1495,6 @@ static int nf_conntrack_init_init_net(void)
printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n", printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n",
NF_CONNTRACK_VERSION, nf_conntrack_htable_size, NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
nf_conntrack_max); nf_conntrack_max);
ret = nf_conntrack_proto_init();
if (ret < 0)
goto err_proto;
#ifdef CONFIG_NF_CONNTRACK_ZONES #ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend); ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0) if (ret < 0)
...@@ -1518,9 +1512,7 @@ static int nf_conntrack_init_init_net(void) ...@@ -1518,9 +1512,7 @@ static int nf_conntrack_init_init_net(void)
#ifdef CONFIG_NF_CONNTRACK_ZONES #ifdef CONFIG_NF_CONNTRACK_ZONES
err_extend: err_extend:
nf_conntrack_proto_fini();
#endif #endif
err_proto:
return ret; return ret;
} }
...@@ -1583,9 +1575,7 @@ static int nf_conntrack_init_net(struct net *net) ...@@ -1583,9 +1575,7 @@ static int nf_conntrack_init_net(struct net *net)
ret = nf_conntrack_helper_init(net); ret = nf_conntrack_helper_init(net);
if (ret < 0) if (ret < 0)
goto err_helper; goto err_helper;
return 0; return 0;
err_helper: err_helper:
nf_conntrack_timeout_fini(net); nf_conntrack_timeout_fini(net);
err_timeout: err_timeout:
...@@ -1622,6 +1612,9 @@ int nf_conntrack_init(struct net *net) ...@@ -1622,6 +1612,9 @@ int nf_conntrack_init(struct net *net)
if (ret < 0) if (ret < 0)
goto out_init_net; goto out_init_net;
} }
ret = nf_conntrack_proto_init(net);
if (ret < 0)
goto out_proto;
ret = nf_conntrack_init_net(net); ret = nf_conntrack_init_net(net);
if (ret < 0) if (ret < 0)
goto out_net; goto out_net;
...@@ -1637,6 +1630,8 @@ int nf_conntrack_init(struct net *net) ...@@ -1637,6 +1630,8 @@ int nf_conntrack_init(struct net *net)
return 0; return 0;
out_net: out_net:
nf_conntrack_proto_fini(net);
out_proto:
if (net_eq(net, &init_net)) if (net_eq(net, &init_net))
nf_conntrack_cleanup_init_net(); nf_conntrack_cleanup_init_net();
out_init_net: out_init_net:
......
This diff is collapsed.
...@@ -387,12 +387,9 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = ...@@ -387,12 +387,9 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] =
/* this module per-net specifics */ /* this module per-net specifics */
static int dccp_net_id __read_mostly; static int dccp_net_id __read_mostly;
struct dccp_net { struct dccp_net {
struct nf_proto_net np;
int dccp_loose; int dccp_loose;
unsigned int dccp_timeout[CT_DCCP_MAX + 1]; unsigned int dccp_timeout[CT_DCCP_MAX + 1];
#ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_header;
struct ctl_table *sysctl_table;
#endif
}; };
static inline struct dccp_net *dccp_pernet(struct net *net) static inline struct dccp_net *dccp_pernet(struct net *net)
...@@ -715,9 +712,10 @@ static int dccp_nlattr_size(void) ...@@ -715,9 +712,10 @@ static int dccp_nlattr_size(void)
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
struct dccp_net *dn = dccp_pernet(&init_net); struct dccp_net *dn = dccp_pernet(net);
unsigned int *timeouts = data; unsigned int *timeouts = data;
int i; int i;
...@@ -817,6 +815,45 @@ static struct ctl_table dccp_sysctl_table[] = { ...@@ -817,6 +815,45 @@ static struct ctl_table dccp_sysctl_table[] = {
}; };
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
static int dccp_init_net(struct net *net)
{
struct dccp_net *dn = dccp_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)dn;
#ifdef CONFIG_SYSCTL
if (!pn->ctl_table) {
#else
if (!pn->users++) {
#endif
/* default values */
dn->dccp_loose = 1;
dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL;
dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL;
dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ;
dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ;
dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(dccp_sysctl_table,
sizeof(dccp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
pn->ctl_table[7].data = &dn->dccp_loose;
#endif
}
return 0;
}
static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
.l3proto = AF_INET, .l3proto = AF_INET,
.l4proto = IPPROTO_DCCP, .l4proto = IPPROTO_DCCP,
...@@ -847,6 +884,8 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { ...@@ -847,6 +884,8 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
.nla_policy = dccp_timeout_nla_policy, .nla_policy = dccp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
.net_id = &dccp_net_id,
.init_net = dccp_init_net,
}; };
static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
...@@ -879,55 +918,39 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { ...@@ -879,55 +918,39 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
.nla_policy = dccp_timeout_nla_policy, .nla_policy = dccp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
.net_id = &dccp_net_id,
.init_net = dccp_init_net,
}; };
static __net_init int dccp_net_init(struct net *net) static __net_init int dccp_net_init(struct net *net)
{ {
struct dccp_net *dn = dccp_pernet(net); int ret = 0;
ret = nf_conntrack_l4proto_register(net,
/* default values */ &dccp_proto4);
dn->dccp_loose = 1; if (ret < 0) {
dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; pr_err("nf_conntrack_l4proto_dccp4 :protocol register failed.\n");
dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL; goto out;
dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL; }
dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ; ret = nf_conntrack_l4proto_register(net,
dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ; &dccp_proto6);
dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ; if (ret < 0) {
dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL; pr_err("nf_conntrack_l4proto_dccp6 :protocol register failed.\n");
goto cleanup_dccp4;
#ifdef CONFIG_SYSCTL
dn->sysctl_table = kmemdup(dccp_sysctl_table,
sizeof(dccp_sysctl_table), GFP_KERNEL);
if (!dn->sysctl_table)
return -ENOMEM;
dn->sysctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
dn->sysctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
dn->sysctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
dn->sysctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
dn->sysctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
dn->sysctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
dn->sysctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
dn->sysctl_table[7].data = &dn->dccp_loose;
dn->sysctl_header = register_net_sysctl(net, "net/netfilter",
dn->sysctl_table);
if (!dn->sysctl_header) {
kfree(dn->sysctl_table);
return -ENOMEM;
} }
#endif
return 0; return 0;
cleanup_dccp4:
nf_conntrack_l4proto_unregister(net,
&dccp_proto4);
out:
return ret;
} }
static __net_exit void dccp_net_exit(struct net *net) static __net_exit void dccp_net_exit(struct net *net)
{ {
struct dccp_net *dn = dccp_pernet(net); nf_conntrack_l4proto_unregister(net,
#ifdef CONFIG_SYSCTL &dccp_proto6);
unregister_net_sysctl_table(dn->sysctl_header); nf_conntrack_l4proto_unregister(net,
kfree(dn->sysctl_table); &dccp_proto4);
#endif
} }
static struct pernet_operations dccp_net_ops = { static struct pernet_operations dccp_net_ops = {
...@@ -939,34 +962,12 @@ static struct pernet_operations dccp_net_ops = { ...@@ -939,34 +962,12 @@ static struct pernet_operations dccp_net_ops = {
static int __init nf_conntrack_proto_dccp_init(void) static int __init nf_conntrack_proto_dccp_init(void)
{ {
int err; return register_pernet_subsys(&dccp_net_ops);
err = register_pernet_subsys(&dccp_net_ops);
if (err < 0)
goto err1;
err = nf_conntrack_l4proto_register(&dccp_proto4);
if (err < 0)
goto err2;
err = nf_conntrack_l4proto_register(&dccp_proto6);
if (err < 0)
goto err3;
return 0;
err3:
nf_conntrack_l4proto_unregister(&dccp_proto4);
err2:
unregister_pernet_subsys(&dccp_net_ops);
err1:
return err;
} }
static void __exit nf_conntrack_proto_dccp_fini(void) static void __exit nf_conntrack_proto_dccp_fini(void)
{ {
unregister_pernet_subsys(&dccp_net_ops); unregister_pernet_subsys(&dccp_net_ops);
nf_conntrack_l4proto_unregister(&dccp_proto6);
nf_conntrack_l4proto_unregister(&dccp_proto4);
} }
module_init(nf_conntrack_proto_dccp_init); module_init(nf_conntrack_proto_dccp_init);
......
...@@ -14,6 +14,11 @@ ...@@ -14,6 +14,11 @@
static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
static inline struct nf_generic_net *generic_pernet(struct net *net)
{
return &net->ct.nf_ct_proto.generic;
}
static bool generic_pkt_to_tuple(const struct sk_buff *skb, static bool generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
...@@ -42,7 +47,7 @@ static int generic_print_tuple(struct seq_file *s, ...@@ -42,7 +47,7 @@ static int generic_print_tuple(struct seq_file *s,
static unsigned int *generic_get_timeouts(struct net *net) static unsigned int *generic_get_timeouts(struct net *net)
{ {
return &nf_ct_generic_timeout; return &(generic_pernet(net)->timeout);
} }
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
...@@ -70,16 +75,18 @@ static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, ...@@ -70,16 +75,18 @@ static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int generic_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int generic_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
unsigned int *timeout = data; unsigned int *timeout = data;
struct nf_generic_net *gn = generic_pernet(net);
if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT]) if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT])
*timeout = *timeout =
ntohl(nla_get_be32(tb[CTA_TIMEOUT_GENERIC_TIMEOUT])) * HZ; ntohl(nla_get_be32(tb[CTA_TIMEOUT_GENERIC_TIMEOUT])) * HZ;
else { else {
/* Set default generic timeout. */ /* Set default generic timeout. */
*timeout = nf_ct_generic_timeout; *timeout = gn->timeout;
} }
return 0; return 0;
...@@ -106,11 +113,9 @@ generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = { ...@@ -106,11 +113,9 @@ generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static struct ctl_table_header *generic_sysctl_header;
static struct ctl_table generic_sysctl_table[] = { static struct ctl_table generic_sysctl_table[] = {
{ {
.procname = "nf_conntrack_generic_timeout", .procname = "nf_conntrack_generic_timeout",
.data = &nf_ct_generic_timeout,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -121,7 +126,6 @@ static struct ctl_table generic_sysctl_table[] = { ...@@ -121,7 +126,6 @@ static struct ctl_table generic_sysctl_table[] = {
static struct ctl_table generic_compat_sysctl_table[] = { static struct ctl_table generic_compat_sysctl_table[] = {
{ {
.procname = "ip_conntrack_generic_timeout", .procname = "ip_conntrack_generic_timeout",
.data = &nf_ct_generic_timeout,
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -131,6 +135,34 @@ static struct ctl_table generic_compat_sysctl_table[] = { ...@@ -131,6 +135,34 @@ static struct ctl_table generic_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
static int generic_init_net(struct net *net)
{
struct nf_generic_net *gn = generic_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)gn;
gn->timeout = nf_ct_generic_timeout;
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(generic_sysctl_table,
sizeof(generic_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &gn->timeout;
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table,
sizeof(generic_compat_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_compat_table) {
kfree(pn->ctl_table);
pn->ctl_table = NULL;
return -ENOMEM;
}
pn->ctl_compat_table[0].data = &gn->timeout;
#endif
#endif
return 0;
}
struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
{ {
.l3proto = PF_UNSPEC, .l3proto = PF_UNSPEC,
...@@ -151,11 +183,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = ...@@ -151,11 +183,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
.nla_policy = generic_timeout_nla_policy, .nla_policy = generic_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .init_net = generic_init_net,
.ctl_table_header = &generic_sysctl_header,
.ctl_table = generic_sysctl_table,
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
.ctl_compat_table = generic_compat_sysctl_table,
#endif
#endif
}; };
...@@ -54,13 +54,20 @@ static unsigned int gre_timeouts[GRE_CT_MAX] = { ...@@ -54,13 +54,20 @@ static unsigned int gre_timeouts[GRE_CT_MAX] = {
static int proto_gre_net_id __read_mostly; static int proto_gre_net_id __read_mostly;
struct netns_proto_gre { struct netns_proto_gre {
struct nf_proto_net nf;
rwlock_t keymap_lock; rwlock_t keymap_lock;
struct list_head keymap_list; struct list_head keymap_list;
unsigned int gre_timeouts[GRE_CT_MAX];
}; };
static inline struct netns_proto_gre *gre_pernet(struct net *net)
{
return net_generic(net, proto_gre_net_id);
}
void nf_ct_gre_keymap_flush(struct net *net) void nf_ct_gre_keymap_flush(struct net *net)
{ {
struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id); struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_ct_gre_keymap *km, *tmp; struct nf_ct_gre_keymap *km, *tmp;
write_lock_bh(&net_gre->keymap_lock); write_lock_bh(&net_gre->keymap_lock);
...@@ -85,7 +92,7 @@ static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, ...@@ -85,7 +92,7 @@ static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
/* look up the source key for a given tuple */ /* look up the source key for a given tuple */
static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t) static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t)
{ {
struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id); struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_ct_gre_keymap *km; struct nf_ct_gre_keymap *km;
__be16 key = 0; __be16 key = 0;
...@@ -109,7 +116,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, ...@@ -109,7 +116,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conntrack_tuple *t) struct nf_conntrack_tuple *t)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id); struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_conn_help *help = nfct_help(ct); struct nf_conn_help *help = nfct_help(ct);
struct nf_ct_gre_keymap **kmp, *km; struct nf_ct_gre_keymap **kmp, *km;
...@@ -150,7 +157,7 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add); ...@@ -150,7 +157,7 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add);
void nf_ct_gre_keymap_destroy(struct nf_conn *ct) void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id); struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_conn_help *help = nfct_help(ct); struct nf_conn_help *help = nfct_help(ct);
enum ip_conntrack_dir dir; enum ip_conntrack_dir dir;
...@@ -237,7 +244,7 @@ static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct) ...@@ -237,7 +244,7 @@ static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct)
static unsigned int *gre_get_timeouts(struct net *net) static unsigned int *gre_get_timeouts(struct net *net)
{ {
return gre_timeouts; return gre_pernet(net)->gre_timeouts;
} }
/* Returns verdict for packet, and may modify conntrack */ /* Returns verdict for packet, and may modify conntrack */
...@@ -297,13 +304,15 @@ static void gre_destroy(struct nf_conn *ct) ...@@ -297,13 +304,15 @@ static void gre_destroy(struct nf_conn *ct)
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int gre_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int gre_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
unsigned int *timeouts = data; unsigned int *timeouts = data;
struct netns_proto_gre *net_gre = gre_pernet(net);
/* set default timeouts for GRE. */ /* set default timeouts for GRE. */
timeouts[GRE_CT_UNREPLIED] = gre_timeouts[GRE_CT_UNREPLIED]; timeouts[GRE_CT_UNREPLIED] = net_gre->gre_timeouts[GRE_CT_UNREPLIED];
timeouts[GRE_CT_REPLIED] = gre_timeouts[GRE_CT_REPLIED]; timeouts[GRE_CT_REPLIED] = net_gre->gre_timeouts[GRE_CT_REPLIED];
if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) { if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) {
timeouts[GRE_CT_UNREPLIED] = timeouts[GRE_CT_UNREPLIED] =
...@@ -339,6 +348,19 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = { ...@@ -339,6 +348,19 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = {
}; };
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
static int gre_init_net(struct net *net)
{
struct netns_proto_gre *net_gre = gre_pernet(net);
int i;
rwlock_init(&net_gre->keymap_lock);
INIT_LIST_HEAD(&net_gre->keymap_list);
for (i = 0; i < GRE_CT_MAX; i++)
net_gre->gre_timeouts[i] = gre_timeouts[i];
return 0;
}
/* protocol helper struct */ /* protocol helper struct */
static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
.l3proto = AF_INET, .l3proto = AF_INET,
...@@ -368,20 +390,22 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { ...@@ -368,20 +390,22 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
.nla_policy = gre_timeout_nla_policy, .nla_policy = gre_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
.net_id = &proto_gre_net_id,
.init_net = gre_init_net,
}; };
static int proto_gre_net_init(struct net *net) static int proto_gre_net_init(struct net *net)
{ {
struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id); int ret = 0;
ret = nf_conntrack_l4proto_register(net, &nf_conntrack_l4proto_gre4);
rwlock_init(&net_gre->keymap_lock); if (ret < 0)
INIT_LIST_HEAD(&net_gre->keymap_list); pr_err("nf_conntrack_l4proto_gre4 :protocol register failed.\n");
return ret;
return 0;
} }
static void proto_gre_net_exit(struct net *net) static void proto_gre_net_exit(struct net *net)
{ {
nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_gre4);
nf_ct_gre_keymap_flush(net); nf_ct_gre_keymap_flush(net);
} }
...@@ -394,20 +418,11 @@ static struct pernet_operations proto_gre_net_ops = { ...@@ -394,20 +418,11 @@ static struct pernet_operations proto_gre_net_ops = {
static int __init nf_ct_proto_gre_init(void) static int __init nf_ct_proto_gre_init(void)
{ {
int rv; return register_pernet_subsys(&proto_gre_net_ops);
rv = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
if (rv < 0)
return rv;
rv = register_pernet_subsys(&proto_gre_net_ops);
if (rv < 0)
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
return rv;
} }
static void __exit nf_ct_proto_gre_fini(void) static void __exit nf_ct_proto_gre_fini(void)
{ {
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
unregister_pernet_subsys(&proto_gre_net_ops); unregister_pernet_subsys(&proto_gre_net_ops);
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,17 +25,16 @@ ...@@ -25,17 +25,16 @@
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
enum udp_conntrack {
UDP_CT_UNREPLIED,
UDP_CT_REPLIED,
UDP_CT_MAX
};
static unsigned int udp_timeouts[UDP_CT_MAX] = { static unsigned int udp_timeouts[UDP_CT_MAX] = {
[UDP_CT_UNREPLIED] = 30*HZ, [UDP_CT_UNREPLIED] = 30*HZ,
[UDP_CT_REPLIED] = 180*HZ, [UDP_CT_REPLIED] = 180*HZ,
}; };
static inline struct nf_udp_net *udp_pernet(struct net *net)
{
return &net->ct.nf_ct_proto.udp;
}
static bool udp_pkt_to_tuple(const struct sk_buff *skb, static bool udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
...@@ -73,7 +72,7 @@ static int udp_print_tuple(struct seq_file *s, ...@@ -73,7 +72,7 @@ static int udp_print_tuple(struct seq_file *s,
static unsigned int *udp_get_timeouts(struct net *net) static unsigned int *udp_get_timeouts(struct net *net)
{ {
return udp_timeouts; return udp_pernet(net)->timeouts;
} }
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
...@@ -157,13 +156,15 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, ...@@ -157,13 +156,15 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int udp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int udp_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
unsigned int *timeouts = data; unsigned int *timeouts = data;
struct nf_udp_net *un = udp_pernet(net);
/* set default timeouts for UDP. */ /* set default timeouts for UDP. */
timeouts[UDP_CT_UNREPLIED] = udp_timeouts[UDP_CT_UNREPLIED]; timeouts[UDP_CT_UNREPLIED] = un->timeouts[UDP_CT_UNREPLIED];
timeouts[UDP_CT_REPLIED] = udp_timeouts[UDP_CT_REPLIED]; timeouts[UDP_CT_REPLIED] = un->timeouts[UDP_CT_REPLIED];
if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) { if (tb[CTA_TIMEOUT_UDP_UNREPLIED]) {
timeouts[UDP_CT_UNREPLIED] = timeouts[UDP_CT_UNREPLIED] =
...@@ -200,19 +201,15 @@ udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = { ...@@ -200,19 +201,15 @@ udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static unsigned int udp_sysctl_table_users;
static struct ctl_table_header *udp_sysctl_header;
static struct ctl_table udp_sysctl_table[] = { static struct ctl_table udp_sysctl_table[] = {
{ {
.procname = "nf_conntrack_udp_timeout", .procname = "nf_conntrack_udp_timeout",
.data = &udp_timeouts[UDP_CT_UNREPLIED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_udp_timeout_stream", .procname = "nf_conntrack_udp_timeout_stream",
.data = &udp_timeouts[UDP_CT_REPLIED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -223,14 +220,12 @@ static struct ctl_table udp_sysctl_table[] = { ...@@ -223,14 +220,12 @@ static struct ctl_table udp_sysctl_table[] = {
static struct ctl_table udp_compat_sysctl_table[] = { static struct ctl_table udp_compat_sysctl_table[] = {
{ {
.procname = "ip_conntrack_udp_timeout", .procname = "ip_conntrack_udp_timeout",
.data = &udp_timeouts[UDP_CT_UNREPLIED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "ip_conntrack_udp_timeout_stream", .procname = "ip_conntrack_udp_timeout_stream",
.data = &udp_timeouts[UDP_CT_REPLIED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -240,6 +235,87 @@ static struct ctl_table udp_compat_sysctl_table[] = { ...@@ -240,6 +235,87 @@ static struct ctl_table udp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn)
{
#ifdef CONFIG_SYSCTL
struct nf_udp_net *un = (struct nf_udp_net *)pn;
if (pn->ctl_table)
return 0;
pn->ctl_table = kmemdup(udp_sysctl_table,
sizeof(udp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
pn->ctl_table[1].data = &un->timeouts[UDP_CT_REPLIED];
#endif
return 0;
}
static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn)
{
#ifdef CONFIG_SYSCTL
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
struct nf_udp_net *un = (struct nf_udp_net *)pn;
pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table,
sizeof(udp_compat_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_compat_table)
return -ENOMEM;
pn->ctl_compat_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
pn->ctl_compat_table[1].data = &un->timeouts[UDP_CT_REPLIED];
#endif
#endif
return 0;
}
static void udp_init_net_data(struct nf_udp_net *un)
{
int i;
#ifdef CONFIG_SYSCTL
if (!un->pn.ctl_table) {
#else
if (!un->pn.user++) {
#endif
for (i = 0; i < UDP_CT_MAX; i++)
un->timeouts[i] = udp_timeouts[i];
}
}
static int udpv4_init_net(struct net *net)
{
int ret;
struct nf_udp_net *un = udp_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)un;
udp_init_net_data(un);
ret = udp_kmemdup_compat_sysctl_table(pn);
if (ret < 0)
return ret;
ret = udp_kmemdup_sysctl_table(pn);
#ifdef CONFIG_SYSCTL
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
if (ret < 0) {
kfree(pn->ctl_compat_table);
pn->ctl_compat_table = NULL;
}
#endif
#endif
return ret;
}
static int udpv6_init_net(struct net *net)
{
struct nf_udp_net *un = udp_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)un;
udp_init_net_data(un);
return udp_kmemdup_sysctl_table(pn);
}
struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
{ {
.l3proto = PF_INET, .l3proto = PF_INET,
...@@ -267,14 +343,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = ...@@ -267,14 +343,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
.nla_policy = udp_timeout_nla_policy, .nla_policy = udp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .init_net = udpv4_init_net,
.ctl_table_users = &udp_sysctl_table_users,
.ctl_table_header = &udp_sysctl_header,
.ctl_table = udp_sysctl_table,
#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
.ctl_compat_table = udp_compat_sysctl_table,
#endif
#endif
}; };
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
...@@ -305,10 +374,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = ...@@ -305,10 +374,6 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
.nla_policy = udp_timeout_nla_policy, .nla_policy = udp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .init_net = udpv6_init_net,
.ctl_table_users = &udp_sysctl_table_users,
.ctl_table_header = &udp_sysctl_header,
.ctl_table = udp_sysctl_table,
#endif
}; };
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6); EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6);
...@@ -35,6 +35,17 @@ static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = { ...@@ -35,6 +35,17 @@ static unsigned int udplite_timeouts[UDPLITE_CT_MAX] = {
[UDPLITE_CT_REPLIED] = 180*HZ, [UDPLITE_CT_REPLIED] = 180*HZ,
}; };
static int udplite_net_id __read_mostly;
struct udplite_net {
struct nf_proto_net pn;
unsigned int timeouts[UDPLITE_CT_MAX];
};
static inline struct udplite_net *udplite_pernet(struct net *net)
{
return net_generic(net, udplite_net_id);
}
static bool udplite_pkt_to_tuple(const struct sk_buff *skb, static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
...@@ -70,7 +81,7 @@ static int udplite_print_tuple(struct seq_file *s, ...@@ -70,7 +81,7 @@ static int udplite_print_tuple(struct seq_file *s,
static unsigned int *udplite_get_timeouts(struct net *net) static unsigned int *udplite_get_timeouts(struct net *net)
{ {
return udplite_timeouts; return udplite_pernet(net)->timeouts;
} }
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
...@@ -161,13 +172,15 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, ...@@ -161,13 +172,15 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl,
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h> #include <linux/netfilter/nfnetlink_cttimeout.h>
static int udplite_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) static int udplite_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data)
{ {
unsigned int *timeouts = data; unsigned int *timeouts = data;
struct udplite_net *un = udplite_pernet(net);
/* set default timeouts for UDPlite. */ /* set default timeouts for UDPlite. */
timeouts[UDPLITE_CT_UNREPLIED] = udplite_timeouts[UDPLITE_CT_UNREPLIED]; timeouts[UDPLITE_CT_UNREPLIED] = un->timeouts[UDPLITE_CT_UNREPLIED];
timeouts[UDPLITE_CT_REPLIED] = udplite_timeouts[UDPLITE_CT_REPLIED]; timeouts[UDPLITE_CT_REPLIED] = un->timeouts[UDPLITE_CT_REPLIED];
if (tb[CTA_TIMEOUT_UDPLITE_UNREPLIED]) { if (tb[CTA_TIMEOUT_UDPLITE_UNREPLIED]) {
timeouts[UDPLITE_CT_UNREPLIED] = timeouts[UDPLITE_CT_UNREPLIED] =
...@@ -204,19 +217,15 @@ udplite_timeout_nla_policy[CTA_TIMEOUT_UDPLITE_MAX+1] = { ...@@ -204,19 +217,15 @@ udplite_timeout_nla_policy[CTA_TIMEOUT_UDPLITE_MAX+1] = {
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static unsigned int udplite_sysctl_table_users;
static struct ctl_table_header *udplite_sysctl_header;
static struct ctl_table udplite_sysctl_table[] = { static struct ctl_table udplite_sysctl_table[] = {
{ {
.procname = "nf_conntrack_udplite_timeout", .procname = "nf_conntrack_udplite_timeout",
.data = &udplite_timeouts[UDPLITE_CT_UNREPLIED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{ {
.procname = "nf_conntrack_udplite_timeout_stream", .procname = "nf_conntrack_udplite_timeout_stream",
.data = &udplite_timeouts[UDPLITE_CT_REPLIED],
.maxlen = sizeof(unsigned int), .maxlen = sizeof(unsigned int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
...@@ -225,6 +234,31 @@ static struct ctl_table udplite_sysctl_table[] = { ...@@ -225,6 +234,31 @@ static struct ctl_table udplite_sysctl_table[] = {
}; };
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
static int udplite_init_net(struct net *net)
{
int i;
struct udplite_net *un = udplite_pernet(net);
struct nf_proto_net *pn = (struct nf_proto_net *)un;
#ifdef CONFIG_SYSCTL
if (!pn->ctl_table) {
#else
if (!pn->users++) {
#endif
for (i = 0 ; i < UDPLITE_CT_MAX; i++)
un->timeouts[i] = udplite_timeouts[i];
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(udplite_sysctl_table,
sizeof(udplite_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED];
pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED];
#endif
}
return 0;
}
static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
{ {
.l3proto = PF_INET, .l3proto = PF_INET,
...@@ -253,11 +287,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = ...@@ -253,11 +287,8 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
.nla_policy = udplite_timeout_nla_policy, .nla_policy = udplite_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .net_id = &udplite_net_id,
.ctl_table_users = &udplite_sysctl_table_users, .init_net = udplite_init_net,
.ctl_table_header = &udplite_sysctl_header,
.ctl_table = udplite_sysctl_table,
#endif
}; };
static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
...@@ -288,34 +319,55 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = ...@@ -288,34 +319,55 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.nla_policy = udplite_timeout_nla_policy, .nla_policy = udplite_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
#ifdef CONFIG_SYSCTL .net_id = &udplite_net_id,
.ctl_table_users = &udplite_sysctl_table_users, .init_net = udplite_init_net,
.ctl_table_header = &udplite_sysctl_header,
.ctl_table = udplite_sysctl_table,
#endif
}; };
static int __init nf_conntrack_proto_udplite_init(void) static int udplite_net_init(struct net *net)
{ {
int err; int ret = 0;
err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4); ret = nf_conntrack_l4proto_register(net,
if (err < 0) &nf_conntrack_l4proto_udplite4);
goto err1; if (ret < 0) {
err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6); pr_err("nf_conntrack_l4proto_udplite4 :protocol register failed.\n");
if (err < 0) goto out;
goto err2; }
ret = nf_conntrack_l4proto_register(net,
&nf_conntrack_l4proto_udplite6);
if (ret < 0) {
pr_err("nf_conntrack_l4proto_udplite4 :protocol register failed.\n");
goto cleanup_udplite4;
}
return 0; return 0;
err2:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4); cleanup_udplite4:
err1: nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_udplite4);
return err; out:
return ret;
}
static void udplite_net_exit(struct net *net)
{
nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_udplite6);
nf_conntrack_l4proto_unregister(net, &nf_conntrack_l4proto_udplite4);
}
static struct pernet_operations udplite_net_ops = {
.init = udplite_net_init,
.exit = udplite_net_exit,
.id = &udplite_net_id,
.size = sizeof(struct udplite_net),
};
static int __init nf_conntrack_proto_udplite_init(void)
{
return register_pernet_subsys(&udplite_net_ops);
} }
static void __exit nf_conntrack_proto_udplite_exit(void) static void __exit nf_conntrack_proto_udplite_exit(void)
{ {
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6); unregister_pernet_subsys(&udplite_net_ops);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
} }
module_init(nf_conntrack_proto_udplite_init); module_init(nf_conntrack_proto_udplite_init);
......
...@@ -49,8 +49,9 @@ static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { ...@@ -49,8 +49,9 @@ static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
static int static int
ctnl_timeout_parse_policy(struct ctnl_timeout *timeout, ctnl_timeout_parse_policy(struct ctnl_timeout *timeout,
struct nf_conntrack_l4proto *l4proto, struct nf_conntrack_l4proto *l4proto,
const struct nlattr *attr) struct net *net,
const struct nlattr *attr)
{ {
int ret = 0; int ret = 0;
...@@ -60,7 +61,8 @@ ctnl_timeout_parse_policy(struct ctnl_timeout *timeout, ...@@ -60,7 +61,8 @@ ctnl_timeout_parse_policy(struct ctnl_timeout *timeout,
nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
attr, l4proto->ctnl_timeout.nla_policy); attr, l4proto->ctnl_timeout.nla_policy);
ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, &timeout->data); ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net,
&timeout->data);
} }
return ret; return ret;
} }
...@@ -74,6 +76,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, ...@@ -74,6 +76,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
__u8 l4num; __u8 l4num;
struct nf_conntrack_l4proto *l4proto; struct nf_conntrack_l4proto *l4proto;
struct ctnl_timeout *timeout, *matching = NULL; struct ctnl_timeout *timeout, *matching = NULL;
struct net *net = sock_net(skb->sk);
char *name; char *name;
int ret; int ret;
...@@ -117,7 +120,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, ...@@ -117,7 +120,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
goto err_proto_put; goto err_proto_put;
} }
ret = ctnl_timeout_parse_policy(matching, l4proto, ret = ctnl_timeout_parse_policy(matching, l4proto, net,
cda[CTA_TIMEOUT_DATA]); cda[CTA_TIMEOUT_DATA]);
return ret; return ret;
} }
...@@ -132,7 +135,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, ...@@ -132,7 +135,7 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
goto err_proto_put; goto err_proto_put;
} }
ret = ctnl_timeout_parse_policy(timeout, l4proto, ret = ctnl_timeout_parse_policy(timeout, l4proto, net,
cda[CTA_TIMEOUT_DATA]); cda[CTA_TIMEOUT_DATA]);
if (ret < 0) if (ret < 0)
goto err; goto err;
......
...@@ -52,6 +52,7 @@ struct nfqnl_instance { ...@@ -52,6 +52,7 @@ struct nfqnl_instance {
u_int16_t queue_num; /* number of this queue */ u_int16_t queue_num; /* number of this queue */
u_int8_t copy_mode; u_int8_t copy_mode;
u_int32_t flags; /* Set using NFQA_CFG_FLAGS */
/* /*
* Following fields are dirtied for each queued packet, * Following fields are dirtied for each queued packet,
* keep them in same cache line if possible. * keep them in same cache line if possible.
...@@ -406,6 +407,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) ...@@ -406,6 +407,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
struct nfqnl_instance *queue; struct nfqnl_instance *queue;
int err = -ENOBUFS; int err = -ENOBUFS;
__be32 *packet_id_ptr; __be32 *packet_id_ptr;
int failopen = 0;
/* rcu_read_lock()ed by nf_hook_slow() */ /* rcu_read_lock()ed by nf_hook_slow() */
queue = instance_lookup(queuenum); queue = instance_lookup(queuenum);
...@@ -431,9 +433,14 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) ...@@ -431,9 +433,14 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
goto err_out_free_nskb; goto err_out_free_nskb;
} }
if (queue->queue_total >= queue->queue_maxlen) { if (queue->queue_total >= queue->queue_maxlen) {
queue->queue_dropped++; if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
net_warn_ratelimited("nf_queue: full at %d entries, dropping packets(s)\n", failopen = 1;
queue->queue_total); err = 0;
} else {
queue->queue_dropped++;
net_warn_ratelimited("nf_queue: full at %d entries, dropping packets(s)\n",
queue->queue_total);
}
goto err_out_free_nskb; goto err_out_free_nskb;
} }
entry->id = ++queue->id_sequence; entry->id = ++queue->id_sequence;
...@@ -455,6 +462,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) ...@@ -455,6 +462,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
kfree_skb(nskb); kfree_skb(nskb);
err_out_unlock: err_out_unlock:
spin_unlock_bh(&queue->lock); spin_unlock_bh(&queue->lock);
if (failopen)
nf_reinject(entry, NF_ACCEPT);
err_out: err_out:
return err; return err;
} }
...@@ -858,6 +867,31 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ...@@ -858,6 +867,31 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
spin_unlock_bh(&queue->lock); spin_unlock_bh(&queue->lock);
} }
if (nfqa[NFQA_CFG_FLAGS]) {
__u32 flags, mask;
if (!queue) {
ret = -ENODEV;
goto err_out_unlock;
}
if (!nfqa[NFQA_CFG_MASK]) {
/* A mask is needed to specify which flags are being
* changed.
*/
ret = -EINVAL;
goto err_out_unlock;
}
flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS]));
mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK]));
spin_lock_bh(&queue->lock);
queue->flags &= ~mask;
queue->flags |= flags & mask;
spin_unlock_bh(&queue->lock);
}
err_out_unlock: err_out_unlock:
rcu_read_unlock(); rcu_read_unlock();
return ret; return ret;
......
...@@ -41,26 +41,36 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -41,26 +41,36 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
static u32 hash_v4(const struct sk_buff *skb) static u32 hash_v4(const struct sk_buff *skb)
{ {
const struct iphdr *iph = ip_hdr(skb); const struct iphdr *iph = ip_hdr(skb);
__be32 ipaddr;
/* packets in either direction go into same queue */ /* packets in either direction go into same queue */
ipaddr = iph->saddr ^ iph->daddr; if (iph->saddr < iph->daddr)
return jhash_3words((__force u32)iph->saddr,
(__force u32)iph->daddr, iph->protocol, jhash_initval);
return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval); return jhash_3words((__force u32)iph->daddr,
(__force u32)iph->saddr, iph->protocol, jhash_initval);
} }
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
static u32 hash_v6(const struct sk_buff *skb) static u32 hash_v6(const struct sk_buff *skb)
{ {
const struct ipv6hdr *ip6h = ipv6_hdr(skb); const struct ipv6hdr *ip6h = ipv6_hdr(skb);
__be32 addr[4]; u32 a, b, c;
if (ip6h->saddr.s6_addr32[3] < ip6h->daddr.s6_addr32[3]) {
a = (__force u32) ip6h->saddr.s6_addr32[3];
b = (__force u32) ip6h->daddr.s6_addr32[3];
} else {
b = (__force u32) ip6h->saddr.s6_addr32[3];
a = (__force u32) ip6h->daddr.s6_addr32[3];
}
addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0]; if (ip6h->saddr.s6_addr32[1] < ip6h->daddr.s6_addr32[1])
addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1]; c = (__force u32) ip6h->saddr.s6_addr32[1];
addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2]; else
addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3]; c = (__force u32) ip6h->daddr.s6_addr32[1];
return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval); return jhash_3words(a, b, c, jhash_initval);
} }
#endif #endif
......
...@@ -274,38 +274,25 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) ...@@ -274,38 +274,25 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
kfree(info->data); kfree(info->data);
} }
static struct xt_match connlimit_mt_reg[] __read_mostly = { static struct xt_match connlimit_mt_reg __read_mostly = {
{ .name = "connlimit",
.name = "connlimit", .revision = 1,
.revision = 0, .family = NFPROTO_UNSPEC,
.family = NFPROTO_UNSPEC, .checkentry = connlimit_mt_check,
.checkentry = connlimit_mt_check, .match = connlimit_mt,
.match = connlimit_mt, .matchsize = sizeof(struct xt_connlimit_info),
.matchsize = sizeof(struct xt_connlimit_info), .destroy = connlimit_mt_destroy,
.destroy = connlimit_mt_destroy, .me = THIS_MODULE,
.me = THIS_MODULE,
},
{
.name = "connlimit",
.revision = 1,
.family = NFPROTO_UNSPEC,
.checkentry = connlimit_mt_check,
.match = connlimit_mt,
.matchsize = sizeof(struct xt_connlimit_info),
.destroy = connlimit_mt_destroy,
.me = THIS_MODULE,
},
}; };
static int __init connlimit_mt_init(void) static int __init connlimit_mt_init(void)
{ {
return xt_register_matches(connlimit_mt_reg, return xt_register_match(&connlimit_mt_reg);
ARRAY_SIZE(connlimit_mt_reg));
} }
static void __exit connlimit_mt_exit(void) static void __exit connlimit_mt_exit(void)
{ {
xt_unregister_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg)); xt_unregister_match(&connlimit_mt_reg);
} }
module_init(connlimit_mt_init); module_init(connlimit_mt_init);
......
...@@ -75,6 +75,7 @@ struct recent_entry { ...@@ -75,6 +75,7 @@ struct recent_entry {
struct recent_table { struct recent_table {
struct list_head list; struct list_head list;
char name[XT_RECENT_NAME_LEN]; char name[XT_RECENT_NAME_LEN];
union nf_inet_addr mask;
unsigned int refcnt; unsigned int refcnt;
unsigned int entries; unsigned int entries;
struct list_head lru_list; struct list_head lru_list;
...@@ -228,10 +229,10 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -228,10 +229,10 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
{ {
struct net *net = dev_net(par->in ? par->in : par->out); struct net *net = dev_net(par->in ? par->in : par->out);
struct recent_net *recent_net = recent_pernet(net); struct recent_net *recent_net = recent_pernet(net);
const struct xt_recent_mtinfo *info = par->matchinfo; const struct xt_recent_mtinfo_v1 *info = par->matchinfo;
struct recent_table *t; struct recent_table *t;
struct recent_entry *e; struct recent_entry *e;
union nf_inet_addr addr = {}; union nf_inet_addr addr = {}, addr_mask;
u_int8_t ttl; u_int8_t ttl;
bool ret = info->invert; bool ret = info->invert;
...@@ -261,12 +262,15 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -261,12 +262,15 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
spin_lock_bh(&recent_lock); spin_lock_bh(&recent_lock);
t = recent_table_lookup(recent_net, info->name); t = recent_table_lookup(recent_net, info->name);
e = recent_entry_lookup(t, &addr, par->family,
nf_inet_addr_mask(&addr, &addr_mask, &t->mask);
e = recent_entry_lookup(t, &addr_mask, par->family,
(info->check_set & XT_RECENT_TTL) ? ttl : 0); (info->check_set & XT_RECENT_TTL) ? ttl : 0);
if (e == NULL) { if (e == NULL) {
if (!(info->check_set & XT_RECENT_SET)) if (!(info->check_set & XT_RECENT_SET))
goto out; goto out;
e = recent_entry_init(t, &addr, par->family, ttl); e = recent_entry_init(t, &addr_mask, par->family, ttl);
if (e == NULL) if (e == NULL)
par->hotdrop = true; par->hotdrop = true;
ret = !ret; ret = !ret;
...@@ -306,10 +310,10 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -306,10 +310,10 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par)
return ret; return ret;
} }
static int recent_mt_check(const struct xt_mtchk_param *par) static int recent_mt_check(const struct xt_mtchk_param *par,
const struct xt_recent_mtinfo_v1 *info)
{ {
struct recent_net *recent_net = recent_pernet(par->net); struct recent_net *recent_net = recent_pernet(par->net);
const struct xt_recent_mtinfo *info = par->matchinfo;
struct recent_table *t; struct recent_table *t;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct proc_dir_entry *pde; struct proc_dir_entry *pde;
...@@ -361,6 +365,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par) ...@@ -361,6 +365,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par)
goto out; goto out;
} }
t->refcnt = 1; t->refcnt = 1;
memcpy(&t->mask, &info->mask, sizeof(t->mask));
strcpy(t->name, info->name); strcpy(t->name, info->name);
INIT_LIST_HEAD(&t->lru_list); INIT_LIST_HEAD(&t->lru_list);
for (i = 0; i < ip_list_hash_size; i++) for (i = 0; i < ip_list_hash_size; i++)
...@@ -385,10 +391,28 @@ static int recent_mt_check(const struct xt_mtchk_param *par) ...@@ -385,10 +391,28 @@ static int recent_mt_check(const struct xt_mtchk_param *par)
return ret; return ret;
} }
static int recent_mt_check_v0(const struct xt_mtchk_param *par)
{
const struct xt_recent_mtinfo_v0 *info_v0 = par->matchinfo;
struct xt_recent_mtinfo_v1 info_v1;
/* Copy revision 0 structure to revision 1 */
memcpy(&info_v1, info_v0, sizeof(struct xt_recent_mtinfo));
/* Set default mask to ensure backward compatible behaviour */
memset(info_v1.mask.all, 0xFF, sizeof(info_v1.mask.all));
return recent_mt_check(par, &info_v1);
}
static int recent_mt_check_v1(const struct xt_mtchk_param *par)
{
return recent_mt_check(par, par->matchinfo);
}
static void recent_mt_destroy(const struct xt_mtdtor_param *par) static void recent_mt_destroy(const struct xt_mtdtor_param *par)
{ {
struct recent_net *recent_net = recent_pernet(par->net); struct recent_net *recent_net = recent_pernet(par->net);
const struct xt_recent_mtinfo *info = par->matchinfo; const struct xt_recent_mtinfo_v1 *info = par->matchinfo;
struct recent_table *t; struct recent_table *t;
mutex_lock(&recent_mutex); mutex_lock(&recent_mutex);
...@@ -625,7 +649,7 @@ static struct xt_match recent_mt_reg[] __read_mostly = { ...@@ -625,7 +649,7 @@ static struct xt_match recent_mt_reg[] __read_mostly = {
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
.match = recent_mt, .match = recent_mt,
.matchsize = sizeof(struct xt_recent_mtinfo), .matchsize = sizeof(struct xt_recent_mtinfo),
.checkentry = recent_mt_check, .checkentry = recent_mt_check_v0,
.destroy = recent_mt_destroy, .destroy = recent_mt_destroy,
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
...@@ -635,10 +659,30 @@ static struct xt_match recent_mt_reg[] __read_mostly = { ...@@ -635,10 +659,30 @@ static struct xt_match recent_mt_reg[] __read_mostly = {
.family = NFPROTO_IPV6, .family = NFPROTO_IPV6,
.match = recent_mt, .match = recent_mt,
.matchsize = sizeof(struct xt_recent_mtinfo), .matchsize = sizeof(struct xt_recent_mtinfo),
.checkentry = recent_mt_check, .checkentry = recent_mt_check_v0,
.destroy = recent_mt_destroy,
.me = THIS_MODULE,
},
{
.name = "recent",
.revision = 1,
.family = NFPROTO_IPV4,
.match = recent_mt,
.matchsize = sizeof(struct xt_recent_mtinfo_v1),
.checkentry = recent_mt_check_v1,
.destroy = recent_mt_destroy, .destroy = recent_mt_destroy,
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
{
.name = "recent",
.revision = 1,
.family = NFPROTO_IPV6,
.match = recent_mt,
.matchsize = sizeof(struct xt_recent_mtinfo_v1),
.checkentry = recent_mt_check_v1,
.destroy = recent_mt_destroy,
.me = THIS_MODULE,
}
}; };
static int __init recent_mt_init(void) static int __init recent_mt_init(void)
......
...@@ -5763,21 +5763,21 @@ static struct nf_hook_ops selinux_ipv4_ops[] = { ...@@ -5763,21 +5763,21 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
{ {
.hook = selinux_ipv4_postroute, .hook = selinux_ipv4_postroute,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_POST_ROUTING, .hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP_PRI_SELINUX_LAST, .priority = NF_IP_PRI_SELINUX_LAST,
}, },
{ {
.hook = selinux_ipv4_forward, .hook = selinux_ipv4_forward,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD, .hooknum = NF_INET_FORWARD,
.priority = NF_IP_PRI_SELINUX_FIRST, .priority = NF_IP_PRI_SELINUX_FIRST,
}, },
{ {
.hook = selinux_ipv4_output, .hook = selinux_ipv4_output,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET, .pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT, .hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_SELINUX_FIRST, .priority = NF_IP_PRI_SELINUX_FIRST,
} }
...@@ -5789,14 +5789,14 @@ static struct nf_hook_ops selinux_ipv6_ops[] = { ...@@ -5789,14 +5789,14 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
{ {
.hook = selinux_ipv6_postroute, .hook = selinux_ipv6_postroute,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_POST_ROUTING, .hooknum = NF_INET_POST_ROUTING,
.priority = NF_IP6_PRI_SELINUX_LAST, .priority = NF_IP6_PRI_SELINUX_LAST,
}, },
{ {
.hook = selinux_ipv6_forward, .hook = selinux_ipv6_forward,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pf = PF_INET6, .pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD, .hooknum = NF_INET_FORWARD,
.priority = NF_IP6_PRI_SELINUX_FIRST, .priority = NF_IP6_PRI_SELINUX_FIRST,
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment