diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-07 19:18:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-07 19:18:50 -0400 |
commit | d3a5ea6e2188adeea028c410c83c90e6b6d9347c (patch) | |
tree | 7035d790158da6fad3c482afa545b3dba2e6b037 /net | |
parent | 8ce5c9f27d2e2ce415d903d916e848a356d4c0c0 (diff) | |
parent | 46ba5a25f521e3c50d7bb81b1abb977769047456 (diff) |
Merge branch 'master' of git://1984.lsi.us.es/nf-next
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 47 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 23 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 227 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 139 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_dccp.c | 56 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_generic.c | 45 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_gre.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_sctp.c | 65 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 74 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_udp.c | 66 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_udplite.c | 43 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 4 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 5 |
13 files changed, 540 insertions, 256 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 041923cb67ad..5241d997ab75 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -337,34 +337,62 @@ static struct ctl_table icmp_compat_sysctl_table[] = { | |||
337 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 337 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
338 | #endif /* CONFIG_SYSCTL */ | 338 | #endif /* CONFIG_SYSCTL */ |
339 | 339 | ||
340 | static int icmp_init_net(struct net *net) | 340 | static int icmp_kmemdup_sysctl_table(struct nf_proto_net *pn, |
341 | struct nf_icmp_net *in) | ||
341 | { | 342 | { |
342 | struct nf_icmp_net *in = icmp_pernet(net); | ||
343 | struct nf_proto_net *pn = (struct nf_proto_net *)in; | ||
344 | in->timeout = nf_ct_icmp_timeout; | ||
345 | |||
346 | #ifdef CONFIG_SYSCTL | 343 | #ifdef CONFIG_SYSCTL |
347 | pn->ctl_table = kmemdup(icmp_sysctl_table, | 344 | pn->ctl_table = kmemdup(icmp_sysctl_table, |
348 | sizeof(icmp_sysctl_table), | 345 | sizeof(icmp_sysctl_table), |
349 | GFP_KERNEL); | 346 | GFP_KERNEL); |
350 | if (!pn->ctl_table) | 347 | if (!pn->ctl_table) |
351 | return -ENOMEM; | 348 | return -ENOMEM; |
349 | |||
352 | pn->ctl_table[0].data = &in->timeout; | 350 | pn->ctl_table[0].data = &in->timeout; |
351 | #endif | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int icmp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, | ||
356 | struct nf_icmp_net *in) | ||
357 | { | ||
358 | #ifdef CONFIG_SYSCTL | ||
353 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 359 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
354 | pn->ctl_compat_table = kmemdup(icmp_compat_sysctl_table, | 360 | pn->ctl_compat_table = kmemdup(icmp_compat_sysctl_table, |
355 | sizeof(icmp_compat_sysctl_table), | 361 | sizeof(icmp_compat_sysctl_table), |
356 | GFP_KERNEL); | 362 | GFP_KERNEL); |
357 | if (!pn->ctl_compat_table) { | 363 | if (!pn->ctl_compat_table) |
358 | kfree(pn->ctl_table); | ||
359 | pn->ctl_table = NULL; | ||
360 | return -ENOMEM; | 364 | return -ENOMEM; |
361 | } | 365 | |
362 | pn->ctl_compat_table[0].data = &in->timeout; | 366 | pn->ctl_compat_table[0].data = &in->timeout; |
363 | #endif | 367 | #endif |
364 | #endif | 368 | #endif |
365 | return 0; | 369 | return 0; |
366 | } | 370 | } |
367 | 371 | ||
372 | static int icmp_init_net(struct net *net, u_int16_t proto) | ||
373 | { | ||
374 | int ret; | ||
375 | struct nf_icmp_net *in = icmp_pernet(net); | ||
376 | struct nf_proto_net *pn = &in->pn; | ||
377 | |||
378 | in->timeout = nf_ct_icmp_timeout; | ||
379 | |||
380 | ret = icmp_kmemdup_compat_sysctl_table(pn, in); | ||
381 | if (ret < 0) | ||
382 | return ret; | ||
383 | |||
384 | ret = icmp_kmemdup_sysctl_table(pn, in); | ||
385 | if (ret < 0) | ||
386 | nf_ct_kfree_compat_sysctl_table(pn); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | static struct nf_proto_net *icmp_get_net_proto(struct net *net) | ||
392 | { | ||
393 | return &net->ct.nf_ct_proto.icmp.pn; | ||
394 | } | ||
395 | |||
368 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | 396 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = |
369 | { | 397 | { |
370 | .l3proto = PF_INET, | 398 | .l3proto = PF_INET, |
@@ -395,4 +423,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | |||
395 | }, | 423 | }, |
396 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 424 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
397 | .init_net = icmp_init_net, | 425 | .init_net = icmp_init_net, |
426 | .get_net_proto = icmp_get_net_proto, | ||
398 | }; | 427 | }; |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 63ed0121836c..2d54b2061d68 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -333,22 +333,36 @@ static struct ctl_table icmpv6_sysctl_table[] = { | |||
333 | }; | 333 | }; |
334 | #endif /* CONFIG_SYSCTL */ | 334 | #endif /* CONFIG_SYSCTL */ |
335 | 335 | ||
336 | static int icmpv6_init_net(struct net *net) | 336 | static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn, |
337 | struct nf_icmp_net *in) | ||
337 | { | 338 | { |
338 | struct nf_icmp_net *in = icmpv6_pernet(net); | ||
339 | struct nf_proto_net *pn = (struct nf_proto_net *)in; | ||
340 | in->timeout = nf_ct_icmpv6_timeout; | ||
341 | #ifdef CONFIG_SYSCTL | 339 | #ifdef CONFIG_SYSCTL |
342 | pn->ctl_table = kmemdup(icmpv6_sysctl_table, | 340 | pn->ctl_table = kmemdup(icmpv6_sysctl_table, |
343 | sizeof(icmpv6_sysctl_table), | 341 | sizeof(icmpv6_sysctl_table), |
344 | GFP_KERNEL); | 342 | GFP_KERNEL); |
345 | if (!pn->ctl_table) | 343 | if (!pn->ctl_table) |
346 | return -ENOMEM; | 344 | return -ENOMEM; |
345 | |||
347 | pn->ctl_table[0].data = &in->timeout; | 346 | pn->ctl_table[0].data = &in->timeout; |
348 | #endif | 347 | #endif |
349 | return 0; | 348 | return 0; |
350 | } | 349 | } |
351 | 350 | ||
351 | static int icmpv6_init_net(struct net *net, u_int16_t proto) | ||
352 | { | ||
353 | struct nf_icmp_net *in = icmpv6_pernet(net); | ||
354 | struct nf_proto_net *pn = &in->pn; | ||
355 | |||
356 | in->timeout = nf_ct_icmpv6_timeout; | ||
357 | |||
358 | return icmpv6_kmemdup_sysctl_table(pn, in); | ||
359 | } | ||
360 | |||
361 | static struct nf_proto_net *icmpv6_get_net_proto(struct net *net) | ||
362 | { | ||
363 | return &net->ct.nf_ct_proto.icmpv6.pn; | ||
364 | } | ||
365 | |||
352 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = | 366 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = |
353 | { | 367 | { |
354 | .l3proto = PF_INET6, | 368 | .l3proto = PF_INET6, |
@@ -377,4 +391,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = | |||
377 | }, | 391 | }, |
378 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 392 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
379 | .init_net = icmpv6_init_net, | 393 | .init_net = icmpv6_init_net, |
394 | .get_net_proto = icmpv6_get_net_proto, | ||
380 | }; | 395 | }; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b9b8f4ac7a36..14f67a2cbcb5 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> | 4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> |
5 | * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> | 5 | * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> |
6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> | 6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> |
7 | * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org> | 7 | * (C) 2005-2012 by Pablo Neira Ayuso <pablo@netfilter.org> |
8 | * | 8 | * |
9 | * Initial connection tracking via netlink development funded and | 9 | * Initial connection tracking via netlink development funded and |
10 | * generally made possible by Network Robots, Inc. (www.networkrobots.com) | 10 | * generally made possible by Network Robots, Inc. (www.networkrobots.com) |
@@ -1627,6 +1627,155 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1627 | return err; | 1627 | return err; |
1628 | } | 1628 | } |
1629 | 1629 | ||
1630 | static int | ||
1631 | ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | ||
1632 | __u16 cpu, const struct ip_conntrack_stat *st) | ||
1633 | { | ||
1634 | struct nlmsghdr *nlh; | ||
1635 | struct nfgenmsg *nfmsg; | ||
1636 | unsigned int flags = pid ? NLM_F_MULTI : 0, event; | ||
1637 | |||
1638 | event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS_CPU); | ||
1639 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | ||
1640 | if (nlh == NULL) | ||
1641 | goto nlmsg_failure; | ||
1642 | |||
1643 | nfmsg = nlmsg_data(nlh); | ||
1644 | nfmsg->nfgen_family = AF_UNSPEC; | ||
1645 | nfmsg->version = NFNETLINK_V0; | ||
1646 | nfmsg->res_id = htons(cpu); | ||
1647 | |||
1648 | if (nla_put_be32(skb, CTA_STATS_SEARCHED, htonl(st->searched)) || | ||
1649 | nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) || | ||
1650 | nla_put_be32(skb, CTA_STATS_NEW, htonl(st->new)) || | ||
1651 | nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) || | ||
1652 | nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) || | ||
1653 | nla_put_be32(skb, CTA_STATS_DELETE, htonl(st->delete)) || | ||
1654 | nla_put_be32(skb, CTA_STATS_DELETE_LIST, htonl(st->delete_list)) || | ||
1655 | nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) || | ||
1656 | nla_put_be32(skb, CTA_STATS_INSERT_FAILED, | ||
1657 | htonl(st->insert_failed)) || | ||
1658 | nla_put_be32(skb, CTA_STATS_DROP, htonl(st->drop)) || | ||
1659 | nla_put_be32(skb, CTA_STATS_EARLY_DROP, htonl(st->early_drop)) || | ||
1660 | nla_put_be32(skb, CTA_STATS_ERROR, htonl(st->error)) || | ||
1661 | nla_put_be32(skb, CTA_STATS_SEARCH_RESTART, | ||
1662 | htonl(st->search_restart))) | ||
1663 | goto nla_put_failure; | ||
1664 | |||
1665 | nlmsg_end(skb, nlh); | ||
1666 | return skb->len; | ||
1667 | |||
1668 | nla_put_failure: | ||
1669 | nlmsg_failure: | ||
1670 | nlmsg_cancel(skb, nlh); | ||
1671 | return -1; | ||
1672 | } | ||
1673 | |||
1674 | static int | ||
1675 | ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
1676 | { | ||
1677 | int cpu; | ||
1678 | struct net *net = sock_net(skb->sk); | ||
1679 | |||
1680 | if (cb->args[0] == nr_cpu_ids) | ||
1681 | return 0; | ||
1682 | |||
1683 | for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { | ||
1684 | const struct ip_conntrack_stat *st; | ||
1685 | |||
1686 | if (!cpu_possible(cpu)) | ||
1687 | continue; | ||
1688 | |||
1689 | st = per_cpu_ptr(net->ct.stat, cpu); | ||
1690 | if (ctnetlink_ct_stat_cpu_fill_info(skb, | ||
1691 | NETLINK_CB(cb->skb).pid, | ||
1692 | cb->nlh->nlmsg_seq, | ||
1693 | cpu, st) < 0) | ||
1694 | break; | ||
1695 | } | ||
1696 | cb->args[0] = cpu; | ||
1697 | |||
1698 | return skb->len; | ||
1699 | } | ||
1700 | |||
1701 | static int | ||
1702 | ctnetlink_stat_ct_cpu(struct sock *ctnl, struct sk_buff *skb, | ||
1703 | const struct nlmsghdr *nlh, | ||
1704 | const struct nlattr * const cda[]) | ||
1705 | { | ||
1706 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | ||
1707 | struct netlink_dump_control c = { | ||
1708 | .dump = ctnetlink_ct_stat_cpu_dump, | ||
1709 | }; | ||
1710 | return netlink_dump_start(ctnl, skb, nlh, &c); | ||
1711 | } | ||
1712 | |||
1713 | return 0; | ||
1714 | } | ||
1715 | |||
1716 | static int | ||
1717 | ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | ||
1718 | struct net *net) | ||
1719 | { | ||
1720 | struct nlmsghdr *nlh; | ||
1721 | struct nfgenmsg *nfmsg; | ||
1722 | unsigned int flags = pid ? NLM_F_MULTI : 0, event; | ||
1723 | unsigned int nr_conntracks = atomic_read(&net->ct.count); | ||
1724 | |||
1725 | event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET_STATS); | ||
1726 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | ||
1727 | if (nlh == NULL) | ||
1728 | goto nlmsg_failure; | ||
1729 | |||
1730 | nfmsg = nlmsg_data(nlh); | ||
1731 | nfmsg->nfgen_family = AF_UNSPEC; | ||
1732 | nfmsg->version = NFNETLINK_V0; | ||
1733 | nfmsg->res_id = 0; | ||
1734 | |||
1735 | if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks))) | ||
1736 | goto nla_put_failure; | ||
1737 | |||
1738 | nlmsg_end(skb, nlh); | ||
1739 | return skb->len; | ||
1740 | |||
1741 | nla_put_failure: | ||
1742 | nlmsg_failure: | ||
1743 | nlmsg_cancel(skb, nlh); | ||
1744 | return -1; | ||
1745 | } | ||
1746 | |||
1747 | static int | ||
1748 | ctnetlink_stat_ct(struct sock *ctnl, struct sk_buff *skb, | ||
1749 | const struct nlmsghdr *nlh, | ||
1750 | const struct nlattr * const cda[]) | ||
1751 | { | ||
1752 | struct sk_buff *skb2; | ||
1753 | int err; | ||
1754 | |||
1755 | skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1756 | if (skb2 == NULL) | ||
1757 | return -ENOMEM; | ||
1758 | |||
1759 | err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).pid, | ||
1760 | nlh->nlmsg_seq, | ||
1761 | NFNL_MSG_TYPE(nlh->nlmsg_type), | ||
1762 | sock_net(skb->sk)); | ||
1763 | if (err <= 0) | ||
1764 | goto free; | ||
1765 | |||
1766 | err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); | ||
1767 | if (err < 0) | ||
1768 | goto out; | ||
1769 | |||
1770 | return 0; | ||
1771 | |||
1772 | free: | ||
1773 | kfree_skb(skb2); | ||
1774 | out: | ||
1775 | /* this avoids a loop in nfnetlink. */ | ||
1776 | return err == -EAGAIN ? -ENOBUFS : err; | ||
1777 | } | ||
1778 | |||
1630 | #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT | 1779 | #ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT |
1631 | static size_t | 1780 | static size_t |
1632 | ctnetlink_nfqueue_build_size(const struct nf_conn *ct) | 1781 | ctnetlink_nfqueue_build_size(const struct nf_conn *ct) |
@@ -2440,6 +2589,79 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
2440 | return err; | 2589 | return err; |
2441 | } | 2590 | } |
2442 | 2591 | ||
2592 | static int | ||
2593 | ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int cpu, | ||
2594 | const struct ip_conntrack_stat *st) | ||
2595 | { | ||
2596 | struct nlmsghdr *nlh; | ||
2597 | struct nfgenmsg *nfmsg; | ||
2598 | unsigned int flags = pid ? NLM_F_MULTI : 0, event; | ||
2599 | |||
2600 | event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_EXP_GET_STATS_CPU); | ||
2601 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | ||
2602 | if (nlh == NULL) | ||
2603 | goto nlmsg_failure; | ||
2604 | |||
2605 | nfmsg = nlmsg_data(nlh); | ||
2606 | nfmsg->nfgen_family = AF_UNSPEC; | ||
2607 | nfmsg->version = NFNETLINK_V0; | ||
2608 | nfmsg->res_id = htons(cpu); | ||
2609 | |||
2610 | if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) || | ||
2611 | nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) || | ||
2612 | nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete))) | ||
2613 | goto nla_put_failure; | ||
2614 | |||
2615 | nlmsg_end(skb, nlh); | ||
2616 | return skb->len; | ||
2617 | |||
2618 | nla_put_failure: | ||
2619 | nlmsg_failure: | ||
2620 | nlmsg_cancel(skb, nlh); | ||
2621 | return -1; | ||
2622 | } | ||
2623 | |||
2624 | static int | ||
2625 | ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
2626 | { | ||
2627 | int cpu; | ||
2628 | struct net *net = sock_net(skb->sk); | ||
2629 | |||
2630 | if (cb->args[0] == nr_cpu_ids) | ||
2631 | return 0; | ||
2632 | |||
2633 | for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { | ||
2634 | const struct ip_conntrack_stat *st; | ||
2635 | |||
2636 | if (!cpu_possible(cpu)) | ||
2637 | continue; | ||
2638 | |||
2639 | st = per_cpu_ptr(net->ct.stat, cpu); | ||
2640 | if (ctnetlink_exp_stat_fill_info(skb, NETLINK_CB(cb->skb).pid, | ||
2641 | cb->nlh->nlmsg_seq, | ||
2642 | cpu, st) < 0) | ||
2643 | break; | ||
2644 | } | ||
2645 | cb->args[0] = cpu; | ||
2646 | |||
2647 | return skb->len; | ||
2648 | } | ||
2649 | |||
2650 | static int | ||
2651 | ctnetlink_stat_exp_cpu(struct sock *ctnl, struct sk_buff *skb, | ||
2652 | const struct nlmsghdr *nlh, | ||
2653 | const struct nlattr * const cda[]) | ||
2654 | { | ||
2655 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | ||
2656 | struct netlink_dump_control c = { | ||
2657 | .dump = ctnetlink_exp_stat_cpu_dump, | ||
2658 | }; | ||
2659 | return netlink_dump_start(ctnl, skb, nlh, &c); | ||
2660 | } | ||
2661 | |||
2662 | return 0; | ||
2663 | } | ||
2664 | |||
2443 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 2665 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
2444 | static struct nf_ct_event_notifier ctnl_notifier = { | 2666 | static struct nf_ct_event_notifier ctnl_notifier = { |
2445 | .fcn = ctnetlink_conntrack_event, | 2667 | .fcn = ctnetlink_conntrack_event, |
@@ -2463,6 +2685,8 @@ static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { | |||
2463 | [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, | 2685 | [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, |
2464 | .attr_count = CTA_MAX, | 2686 | .attr_count = CTA_MAX, |
2465 | .policy = ct_nla_policy }, | 2687 | .policy = ct_nla_policy }, |
2688 | [IPCTNL_MSG_CT_GET_STATS_CPU] = { .call = ctnetlink_stat_ct_cpu }, | ||
2689 | [IPCTNL_MSG_CT_GET_STATS] = { .call = ctnetlink_stat_ct }, | ||
2466 | }; | 2690 | }; |
2467 | 2691 | ||
2468 | static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { | 2692 | static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { |
@@ -2475,6 +2699,7 @@ static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { | |||
2475 | [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, | 2699 | [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, |
2476 | .attr_count = CTA_EXPECT_MAX, | 2700 | .attr_count = CTA_EXPECT_MAX, |
2477 | .policy = exp_nla_policy }, | 2701 | .policy = exp_nla_policy }, |
2702 | [IPCTNL_MSG_EXP_GET_STATS_CPU] = { .call = ctnetlink_stat_exp_cpu }, | ||
2478 | }; | 2703 | }; |
2479 | 2704 | ||
2480 | static const struct nfnetlink_subsystem ctnl_subsys = { | 2705 | static const struct nfnetlink_subsystem ctnl_subsys = { |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 1ea919450fc3..0dc63854390f 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -39,16 +39,13 @@ static int | |||
39 | nf_ct_register_sysctl(struct net *net, | 39 | nf_ct_register_sysctl(struct net *net, |
40 | struct ctl_table_header **header, | 40 | struct ctl_table_header **header, |
41 | const char *path, | 41 | const char *path, |
42 | struct ctl_table *table, | 42 | struct ctl_table *table) |
43 | unsigned int *users) | ||
44 | { | 43 | { |
45 | if (*header == NULL) { | 44 | if (*header == NULL) { |
46 | *header = register_net_sysctl(net, path, table); | 45 | *header = register_net_sysctl(net, path, table); |
47 | if (*header == NULL) | 46 | if (*header == NULL) |
48 | return -ENOMEM; | 47 | return -ENOMEM; |
49 | } | 48 | } |
50 | if (users != NULL) | ||
51 | (*users)++; | ||
52 | 49 | ||
53 | return 0; | 50 | return 0; |
54 | } | 51 | } |
@@ -56,9 +53,9 @@ nf_ct_register_sysctl(struct net *net, | |||
56 | static void | 53 | static void |
57 | nf_ct_unregister_sysctl(struct ctl_table_header **header, | 54 | nf_ct_unregister_sysctl(struct ctl_table_header **header, |
58 | struct ctl_table **table, | 55 | struct ctl_table **table, |
59 | unsigned int *users) | 56 | unsigned int users) |
60 | { | 57 | { |
61 | if (users != NULL && --*users > 0) | 58 | if (users > 0) |
62 | return; | 59 | return; |
63 | 60 | ||
64 | unregister_net_sysctl_table(*header); | 61 | unregister_net_sysctl_table(*header); |
@@ -191,8 +188,7 @@ static int nf_ct_l3proto_register_sysctl(struct net *net, | |||
191 | err = nf_ct_register_sysctl(net, | 188 | err = nf_ct_register_sysctl(net, |
192 | &in->ctl_table_header, | 189 | &in->ctl_table_header, |
193 | l3proto->ctl_table_path, | 190 | l3proto->ctl_table_path, |
194 | in->ctl_table, | 191 | in->ctl_table); |
195 | NULL); | ||
196 | if (err < 0) { | 192 | if (err < 0) { |
197 | kfree(in->ctl_table); | 193 | kfree(in->ctl_table); |
198 | in->ctl_table = NULL; | 194 | in->ctl_table = NULL; |
@@ -213,7 +209,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct net *net, | |||
213 | if (in->ctl_table_header != NULL) | 209 | if (in->ctl_table_header != NULL) |
214 | nf_ct_unregister_sysctl(&in->ctl_table_header, | 210 | nf_ct_unregister_sysctl(&in->ctl_table_header, |
215 | &in->ctl_table, | 211 | &in->ctl_table, |
216 | NULL); | 212 | 0); |
217 | #endif | 213 | #endif |
218 | } | 214 | } |
219 | 215 | ||
@@ -253,18 +249,23 @@ int nf_conntrack_l3proto_register(struct net *net, | |||
253 | { | 249 | { |
254 | int ret = 0; | 250 | int ret = 0; |
255 | 251 | ||
256 | if (net == &init_net) | 252 | if (proto->init_net) { |
257 | ret = nf_conntrack_l3proto_register_net(proto); | 253 | ret = proto->init_net(net); |
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | } | ||
258 | 257 | ||
258 | ret = nf_ct_l3proto_register_sysctl(net, proto); | ||
259 | if (ret < 0) | 259 | if (ret < 0) |
260 | return ret; | 260 | return ret; |
261 | 261 | ||
262 | if (proto->init_net) { | 262 | if (net == &init_net) { |
263 | ret = proto->init_net(net); | 263 | ret = nf_conntrack_l3proto_register_net(proto); |
264 | if (ret < 0) | 264 | if (ret < 0) |
265 | return ret; | 265 | nf_ct_l3proto_unregister_sysctl(net, proto); |
266 | } | 266 | } |
267 | return nf_ct_l3proto_register_sysctl(net, proto); | 267 | |
268 | return ret; | ||
268 | } | 269 | } |
269 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register); | 270 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_register); |
270 | 271 | ||
@@ -302,93 +303,77 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); | |||
302 | static struct nf_proto_net *nf_ct_l4proto_net(struct net *net, | 303 | static struct nf_proto_net *nf_ct_l4proto_net(struct net *net, |
303 | struct nf_conntrack_l4proto *l4proto) | 304 | struct nf_conntrack_l4proto *l4proto) |
304 | { | 305 | { |
305 | switch (l4proto->l4proto) { | 306 | if (l4proto->get_net_proto) { |
306 | case IPPROTO_TCP: | 307 | /* statically built-in protocols use static per-net */ |
307 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.tcp; | 308 | return l4proto->get_net_proto(net); |
308 | case IPPROTO_UDP: | 309 | } else if (l4proto->net_id) { |
309 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.udp; | 310 | /* ... and loadable protocols use dynamic per-net */ |
310 | case IPPROTO_ICMP: | 311 | return net_generic(net, *l4proto->net_id); |
311 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.icmp; | ||
312 | case IPPROTO_ICMPV6: | ||
313 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.icmpv6; | ||
314 | case 255: /* l4proto_generic */ | ||
315 | return (struct nf_proto_net *)&net->ct.nf_ct_proto.generic; | ||
316 | default: | ||
317 | if (l4proto->net_id) | ||
318 | return net_generic(net, *l4proto->net_id); | ||
319 | else | ||
320 | return NULL; | ||
321 | } | 312 | } |
322 | return NULL; | 313 | return NULL; |
323 | } | 314 | } |
324 | 315 | ||
325 | static | 316 | static |
326 | int nf_ct_l4proto_register_sysctl(struct net *net, | 317 | int nf_ct_l4proto_register_sysctl(struct net *net, |
318 | struct nf_proto_net *pn, | ||
327 | struct nf_conntrack_l4proto *l4proto) | 319 | struct nf_conntrack_l4proto *l4proto) |
328 | { | 320 | { |
329 | int err = 0; | 321 | int err = 0; |
330 | struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto); | ||
331 | if (pn == NULL) | ||
332 | return 0; | ||
333 | 322 | ||
334 | #ifdef CONFIG_SYSCTL | 323 | #ifdef CONFIG_SYSCTL |
335 | if (pn->ctl_table != NULL) { | 324 | if (pn->ctl_table != NULL) { |
336 | err = nf_ct_register_sysctl(net, | 325 | err = nf_ct_register_sysctl(net, |
337 | &pn->ctl_table_header, | 326 | &pn->ctl_table_header, |
338 | "net/netfilter", | 327 | "net/netfilter", |
339 | pn->ctl_table, | 328 | pn->ctl_table); |
340 | &pn->users); | ||
341 | if (err < 0) { | 329 | if (err < 0) { |
342 | if (!pn->users) { | 330 | if (!pn->users) { |
343 | kfree(pn->ctl_table); | 331 | kfree(pn->ctl_table); |
344 | pn->ctl_table = NULL; | 332 | pn->ctl_table = NULL; |
345 | } | 333 | } |
346 | goto out; | ||
347 | } | 334 | } |
348 | } | 335 | } |
349 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 336 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
350 | if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_table != NULL) { | 337 | if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_table != NULL) { |
338 | if (err < 0) { | ||
339 | nf_ct_kfree_compat_sysctl_table(pn); | ||
340 | goto out; | ||
341 | } | ||
351 | err = nf_ct_register_sysctl(net, | 342 | err = nf_ct_register_sysctl(net, |
352 | &pn->ctl_compat_header, | 343 | &pn->ctl_compat_header, |
353 | "net/ipv4/netfilter", | 344 | "net/ipv4/netfilter", |
354 | pn->ctl_compat_table, | 345 | pn->ctl_compat_table); |
355 | NULL); | ||
356 | if (err == 0) | 346 | if (err == 0) |
357 | goto out; | 347 | goto out; |
358 | 348 | ||
359 | kfree(pn->ctl_compat_table); | 349 | nf_ct_kfree_compat_sysctl_table(pn); |
360 | pn->ctl_compat_table = NULL; | ||
361 | nf_ct_unregister_sysctl(&pn->ctl_table_header, | 350 | nf_ct_unregister_sysctl(&pn->ctl_table_header, |
362 | &pn->ctl_table, | 351 | &pn->ctl_table, |
363 | &pn->users); | 352 | pn->users); |
364 | } | 353 | } |
365 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | ||
366 | out: | 354 | out: |
355 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | ||
367 | #endif /* CONFIG_SYSCTL */ | 356 | #endif /* CONFIG_SYSCTL */ |
368 | return err; | 357 | return err; |
369 | } | 358 | } |
370 | 359 | ||
371 | static | 360 | static |
372 | void nf_ct_l4proto_unregister_sysctl(struct net *net, | 361 | void nf_ct_l4proto_unregister_sysctl(struct net *net, |
362 | struct nf_proto_net *pn, | ||
373 | struct nf_conntrack_l4proto *l4proto) | 363 | struct nf_conntrack_l4proto *l4proto) |
374 | { | 364 | { |
375 | struct nf_proto_net *pn = nf_ct_l4proto_net(net, l4proto); | ||
376 | if (pn == NULL) | ||
377 | return; | ||
378 | #ifdef CONFIG_SYSCTL | 365 | #ifdef CONFIG_SYSCTL |
379 | if (pn->ctl_table_header != NULL) | 366 | if (pn->ctl_table_header != NULL) |
380 | nf_ct_unregister_sysctl(&pn->ctl_table_header, | 367 | nf_ct_unregister_sysctl(&pn->ctl_table_header, |
381 | &pn->ctl_table, | 368 | &pn->ctl_table, |
382 | &pn->users); | 369 | pn->users); |
383 | 370 | ||
384 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 371 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
385 | if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_header != NULL) | 372 | if (l4proto->l3proto != AF_INET6 && pn->ctl_compat_header != NULL) |
386 | nf_ct_unregister_sysctl(&pn->ctl_compat_header, | 373 | nf_ct_unregister_sysctl(&pn->ctl_compat_header, |
387 | &pn->ctl_compat_table, | 374 | &pn->ctl_compat_table, |
388 | NULL); | 375 | 0); |
389 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 376 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
390 | #else | ||
391 | pn->users--; | ||
392 | #endif /* CONFIG_SYSCTL */ | 377 | #endif /* CONFIG_SYSCTL */ |
393 | } | 378 | } |
394 | 379 | ||
@@ -454,19 +439,33 @@ int nf_conntrack_l4proto_register(struct net *net, | |||
454 | struct nf_conntrack_l4proto *l4proto) | 439 | struct nf_conntrack_l4proto *l4proto) |
455 | { | 440 | { |
456 | int ret = 0; | 441 | int ret = 0; |
457 | if (net == &init_net) | 442 | struct nf_proto_net *pn = NULL; |
458 | ret = nf_conntrack_l4proto_register_net(l4proto); | ||
459 | 443 | ||
460 | if (ret < 0) | 444 | if (l4proto->init_net) { |
461 | return ret; | 445 | ret = l4proto->init_net(net, l4proto->l3proto); |
446 | if (ret < 0) | ||
447 | goto out; | ||
448 | } | ||
462 | 449 | ||
463 | if (l4proto->init_net) | 450 | pn = nf_ct_l4proto_net(net, l4proto); |
464 | ret = l4proto->init_net(net); | 451 | if (pn == NULL) |
452 | goto out; | ||
465 | 453 | ||
454 | ret = nf_ct_l4proto_register_sysctl(net, pn, l4proto); | ||
466 | if (ret < 0) | 455 | if (ret < 0) |
467 | return ret; | 456 | goto out; |
468 | 457 | ||
469 | return nf_ct_l4proto_register_sysctl(net, l4proto); | 458 | if (net == &init_net) { |
459 | ret = nf_conntrack_l4proto_register_net(l4proto); | ||
460 | if (ret < 0) { | ||
461 | nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); | ||
462 | goto out; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | pn->users++; | ||
467 | out: | ||
468 | return ret; | ||
470 | } | 469 | } |
471 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register); | 470 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_register); |
472 | 471 | ||
@@ -490,10 +489,18 @@ nf_conntrack_l4proto_unregister_net(struct nf_conntrack_l4proto *l4proto) | |||
490 | void nf_conntrack_l4proto_unregister(struct net *net, | 489 | void nf_conntrack_l4proto_unregister(struct net *net, |
491 | struct nf_conntrack_l4proto *l4proto) | 490 | struct nf_conntrack_l4proto *l4proto) |
492 | { | 491 | { |
492 | struct nf_proto_net *pn = NULL; | ||
493 | |||
493 | if (net == &init_net) | 494 | if (net == &init_net) |
494 | nf_conntrack_l4proto_unregister_net(l4proto); | 495 | nf_conntrack_l4proto_unregister_net(l4proto); |
495 | 496 | ||
496 | nf_ct_l4proto_unregister_sysctl(net, l4proto); | 497 | pn = nf_ct_l4proto_net(net, l4proto); |
498 | if (pn == NULL) | ||
499 | return; | ||
500 | |||
501 | pn->users--; | ||
502 | nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); | ||
503 | |||
497 | /* Remove all contrack entries for this protocol */ | 504 | /* Remove all contrack entries for this protocol */ |
498 | rtnl_lock(); | 505 | rtnl_lock(); |
499 | nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); | 506 | nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); |
@@ -505,10 +512,15 @@ int nf_conntrack_proto_init(struct net *net) | |||
505 | { | 512 | { |
506 | unsigned int i; | 513 | unsigned int i; |
507 | int err; | 514 | int err; |
508 | err = nf_conntrack_l4proto_generic.init_net(net); | 515 | struct nf_proto_net *pn = nf_ct_l4proto_net(net, |
516 | &nf_conntrack_l4proto_generic); | ||
517 | |||
518 | err = nf_conntrack_l4proto_generic.init_net(net, | ||
519 | nf_conntrack_l4proto_generic.l3proto); | ||
509 | if (err < 0) | 520 | if (err < 0) |
510 | return err; | 521 | return err; |
511 | err = nf_ct_l4proto_register_sysctl(net, | 522 | err = nf_ct_l4proto_register_sysctl(net, |
523 | pn, | ||
512 | &nf_conntrack_l4proto_generic); | 524 | &nf_conntrack_l4proto_generic); |
513 | if (err < 0) | 525 | if (err < 0) |
514 | return err; | 526 | return err; |
@@ -518,13 +530,20 @@ int nf_conntrack_proto_init(struct net *net) | |||
518 | rcu_assign_pointer(nf_ct_l3protos[i], | 530 | rcu_assign_pointer(nf_ct_l3protos[i], |
519 | &nf_conntrack_l3proto_generic); | 531 | &nf_conntrack_l3proto_generic); |
520 | } | 532 | } |
533 | |||
534 | pn->users++; | ||
521 | return 0; | 535 | return 0; |
522 | } | 536 | } |
523 | 537 | ||
524 | void nf_conntrack_proto_fini(struct net *net) | 538 | void nf_conntrack_proto_fini(struct net *net) |
525 | { | 539 | { |
526 | unsigned int i; | 540 | unsigned int i; |
541 | struct nf_proto_net *pn = nf_ct_l4proto_net(net, | ||
542 | &nf_conntrack_l4proto_generic); | ||
543 | |||
544 | pn->users--; | ||
527 | nf_ct_l4proto_unregister_sysctl(net, | 545 | nf_ct_l4proto_unregister_sysctl(net, |
546 | pn, | ||
528 | &nf_conntrack_l4proto_generic); | 547 | &nf_conntrack_l4proto_generic); |
529 | if (net == &init_net) { | 548 | if (net == &init_net) { |
530 | /* free l3proto protocol tables */ | 549 | /* free l3proto protocol tables */ |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index c33f76af913f..6535326cf07c 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -387,7 +387,7 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = | |||
387 | /* this module per-net specifics */ | 387 | /* this module per-net specifics */ |
388 | static int dccp_net_id __read_mostly; | 388 | static int dccp_net_id __read_mostly; |
389 | struct dccp_net { | 389 | struct dccp_net { |
390 | struct nf_proto_net np; | 390 | struct nf_proto_net pn; |
391 | int dccp_loose; | 391 | int dccp_loose; |
392 | unsigned int dccp_timeout[CT_DCCP_MAX + 1]; | 392 | unsigned int dccp_timeout[CT_DCCP_MAX + 1]; |
393 | }; | 393 | }; |
@@ -815,16 +815,37 @@ static struct ctl_table dccp_sysctl_table[] = { | |||
815 | }; | 815 | }; |
816 | #endif /* CONFIG_SYSCTL */ | 816 | #endif /* CONFIG_SYSCTL */ |
817 | 817 | ||
818 | static int dccp_init_net(struct net *net) | 818 | static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn, |
819 | struct dccp_net *dn) | ||
819 | { | 820 | { |
820 | struct dccp_net *dn = dccp_pernet(net); | ||
821 | struct nf_proto_net *pn = (struct nf_proto_net *)dn; | ||
822 | |||
823 | #ifdef CONFIG_SYSCTL | 821 | #ifdef CONFIG_SYSCTL |
824 | if (!pn->ctl_table) { | 822 | if (pn->ctl_table) |
825 | #else | 823 | return 0; |
826 | if (!pn->users++) { | 824 | |
825 | pn->ctl_table = kmemdup(dccp_sysctl_table, | ||
826 | sizeof(dccp_sysctl_table), | ||
827 | GFP_KERNEL); | ||
828 | if (!pn->ctl_table) | ||
829 | return -ENOMEM; | ||
830 | |||
831 | pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST]; | ||
832 | pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND]; | ||
833 | pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN]; | ||
834 | pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN]; | ||
835 | pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ]; | ||
836 | pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING]; | ||
837 | pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; | ||
838 | pn->ctl_table[7].data = &dn->dccp_loose; | ||
827 | #endif | 839 | #endif |
840 | return 0; | ||
841 | } | ||
842 | |||
843 | static int dccp_init_net(struct net *net, u_int16_t proto) | ||
844 | { | ||
845 | struct dccp_net *dn = dccp_pernet(net); | ||
846 | struct nf_proto_net *pn = &dn->pn; | ||
847 | |||
848 | if (!pn->users) { | ||
828 | /* default values */ | 849 | /* default values */ |
829 | dn->dccp_loose = 1; | 850 | dn->dccp_loose = 1; |
830 | dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; | 851 | dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; |
@@ -834,24 +855,9 @@ static int dccp_init_net(struct net *net) | |||
834 | dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ; | 855 | dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ; |
835 | dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ; | 856 | dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ; |
836 | dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL; | 857 | dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL; |
837 | #ifdef CONFIG_SYSCTL | ||
838 | pn->ctl_table = kmemdup(dccp_sysctl_table, | ||
839 | sizeof(dccp_sysctl_table), | ||
840 | GFP_KERNEL); | ||
841 | if (!pn->ctl_table) | ||
842 | return -ENOMEM; | ||
843 | |||
844 | pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST]; | ||
845 | pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND]; | ||
846 | pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN]; | ||
847 | pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN]; | ||
848 | pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ]; | ||
849 | pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING]; | ||
850 | pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; | ||
851 | pn->ctl_table[7].data = &dn->dccp_loose; | ||
852 | #endif | ||
853 | } | 858 | } |
854 | return 0; | 859 | |
860 | return dccp_kmemdup_sysctl_table(pn, dn); | ||
855 | } | 861 | } |
856 | 862 | ||
857 | static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { | 863 | static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { |
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index bb0e74fe0fae..d25f29377648 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c | |||
@@ -135,34 +135,62 @@ static struct ctl_table generic_compat_sysctl_table[] = { | |||
135 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 135 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
136 | #endif /* CONFIG_SYSCTL */ | 136 | #endif /* CONFIG_SYSCTL */ |
137 | 137 | ||
138 | static int generic_init_net(struct net *net) | 138 | static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn, |
139 | struct nf_generic_net *gn) | ||
139 | { | 140 | { |
140 | struct nf_generic_net *gn = generic_pernet(net); | ||
141 | struct nf_proto_net *pn = (struct nf_proto_net *)gn; | ||
142 | gn->timeout = nf_ct_generic_timeout; | ||
143 | #ifdef CONFIG_SYSCTL | 141 | #ifdef CONFIG_SYSCTL |
144 | pn->ctl_table = kmemdup(generic_sysctl_table, | 142 | pn->ctl_table = kmemdup(generic_sysctl_table, |
145 | sizeof(generic_sysctl_table), | 143 | sizeof(generic_sysctl_table), |
146 | GFP_KERNEL); | 144 | GFP_KERNEL); |
147 | if (!pn->ctl_table) | 145 | if (!pn->ctl_table) |
148 | return -ENOMEM; | 146 | return -ENOMEM; |
147 | |||
149 | pn->ctl_table[0].data = &gn->timeout; | 148 | pn->ctl_table[0].data = &gn->timeout; |
149 | #endif | ||
150 | return 0; | ||
151 | } | ||
150 | 152 | ||
153 | static int generic_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, | ||
154 | struct nf_generic_net *gn) | ||
155 | { | ||
156 | #ifdef CONFIG_SYSCTL | ||
151 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 157 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
152 | pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table, | 158 | pn->ctl_compat_table = kmemdup(generic_compat_sysctl_table, |
153 | sizeof(generic_compat_sysctl_table), | 159 | sizeof(generic_compat_sysctl_table), |
154 | GFP_KERNEL); | 160 | GFP_KERNEL); |
155 | if (!pn->ctl_compat_table) { | 161 | if (!pn->ctl_compat_table) |
156 | kfree(pn->ctl_table); | ||
157 | pn->ctl_table = NULL; | ||
158 | return -ENOMEM; | 162 | return -ENOMEM; |
159 | } | 163 | |
160 | pn->ctl_compat_table[0].data = &gn->timeout; | 164 | pn->ctl_compat_table[0].data = &gn->timeout; |
161 | #endif | 165 | #endif |
162 | #endif | 166 | #endif |
163 | return 0; | 167 | return 0; |
164 | } | 168 | } |
165 | 169 | ||
170 | static int generic_init_net(struct net *net, u_int16_t proto) | ||
171 | { | ||
172 | int ret; | ||
173 | struct nf_generic_net *gn = generic_pernet(net); | ||
174 | struct nf_proto_net *pn = &gn->pn; | ||
175 | |||
176 | gn->timeout = nf_ct_generic_timeout; | ||
177 | |||
178 | ret = generic_kmemdup_compat_sysctl_table(pn, gn); | ||
179 | if (ret < 0) | ||
180 | return ret; | ||
181 | |||
182 | ret = generic_kmemdup_sysctl_table(pn, gn); | ||
183 | if (ret < 0) | ||
184 | nf_ct_kfree_compat_sysctl_table(pn); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | static struct nf_proto_net *generic_get_net_proto(struct net *net) | ||
190 | { | ||
191 | return &net->ct.nf_ct_proto.generic.pn; | ||
192 | } | ||
193 | |||
166 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = | 194 | struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = |
167 | { | 195 | { |
168 | .l3proto = PF_UNSPEC, | 196 | .l3proto = PF_UNSPEC, |
@@ -184,4 +212,5 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = | |||
184 | }, | 212 | }, |
185 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 213 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
186 | .init_net = generic_init_net, | 214 | .init_net = generic_init_net, |
215 | .get_net_proto = generic_get_net_proto, | ||
187 | }; | 216 | }; |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 5cac41c2fa09..b09b7af7f6f8 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
@@ -348,7 +348,7 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = { | |||
348 | }; | 348 | }; |
349 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 349 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
350 | 350 | ||
351 | static int gre_init_net(struct net *net) | 351 | static int gre_init_net(struct net *net, u_int16_t proto) |
352 | { | 352 | { |
353 | struct netns_proto_gre *net_gre = gre_pernet(net); | 353 | struct netns_proto_gre *net_gre = gre_pernet(net); |
354 | int i; | 354 | int i; |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 8fb0582ad397..c746d61f83ed 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -707,23 +707,10 @@ static struct ctl_table sctp_compat_sysctl_table[] = { | |||
707 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 707 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
708 | #endif | 708 | #endif |
709 | 709 | ||
710 | static void sctp_init_net_data(struct sctp_net *sn) | 710 | static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn, |
711 | { | 711 | struct sctp_net *sn) |
712 | int i; | ||
713 | #ifdef CONFIG_SYSCTL | ||
714 | if (!sn->pn.ctl_table) { | ||
715 | #else | ||
716 | if (!sn->pn.users++) { | ||
717 | #endif | ||
718 | for (i = 0; i < SCTP_CONNTRACK_MAX; i++) | ||
719 | sn->timeouts[i] = sctp_timeouts[i]; | ||
720 | } | ||
721 | } | ||
722 | |||
723 | static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn) | ||
724 | { | 712 | { |
725 | #ifdef CONFIG_SYSCTL | 713 | #ifdef CONFIG_SYSCTL |
726 | struct sctp_net *sn = (struct sctp_net *)pn; | ||
727 | if (pn->ctl_table) | 714 | if (pn->ctl_table) |
728 | return 0; | 715 | return 0; |
729 | 716 | ||
@@ -744,11 +731,11 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn) | |||
744 | return 0; | 731 | return 0; |
745 | } | 732 | } |
746 | 733 | ||
747 | static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | 734 | static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, |
735 | struct sctp_net *sn) | ||
748 | { | 736 | { |
749 | #ifdef CONFIG_SYSCTL | 737 | #ifdef CONFIG_SYSCTL |
750 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 738 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
751 | struct sctp_net *sn = (struct sctp_net *)pn; | ||
752 | pn->ctl_compat_table = kmemdup(sctp_compat_sysctl_table, | 739 | pn->ctl_compat_table = kmemdup(sctp_compat_sysctl_table, |
753 | sizeof(sctp_compat_sysctl_table), | 740 | sizeof(sctp_compat_sysctl_table), |
754 | GFP_KERNEL); | 741 | GFP_KERNEL); |
@@ -767,41 +754,33 @@ static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | |||
767 | return 0; | 754 | return 0; |
768 | } | 755 | } |
769 | 756 | ||
770 | static int sctpv4_init_net(struct net *net) | 757 | static int sctp_init_net(struct net *net, u_int16_t proto) |
771 | { | 758 | { |
772 | int ret; | 759 | int ret; |
773 | struct sctp_net *sn = sctp_pernet(net); | 760 | struct sctp_net *sn = sctp_pernet(net); |
774 | struct nf_proto_net *pn = (struct nf_proto_net *)sn; | 761 | struct nf_proto_net *pn = &sn->pn; |
775 | 762 | ||
776 | sctp_init_net_data(sn); | 763 | if (!pn->users) { |
764 | int i; | ||
777 | 765 | ||
778 | ret = sctp_kmemdup_compat_sysctl_table(pn); | 766 | for (i = 0; i < SCTP_CONNTRACK_MAX; i++) |
779 | if (ret < 0) | 767 | sn->timeouts[i] = sctp_timeouts[i]; |
780 | return ret; | 768 | } |
781 | 769 | ||
782 | ret = sctp_kmemdup_sysctl_table(pn); | 770 | if (proto == AF_INET) { |
771 | ret = sctp_kmemdup_compat_sysctl_table(pn, sn); | ||
772 | if (ret < 0) | ||
773 | return ret; | ||
783 | 774 | ||
784 | #ifdef CONFIG_SYSCTL | 775 | ret = sctp_kmemdup_sysctl_table(pn, sn); |
785 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 776 | if (ret < 0) |
786 | if (ret < 0) { | 777 | nf_ct_kfree_compat_sysctl_table(pn); |
778 | } else | ||
779 | ret = sctp_kmemdup_sysctl_table(pn, sn); | ||
787 | 780 | ||
788 | kfree(pn->ctl_compat_table); | ||
789 | pn->ctl_compat_table = NULL; | ||
790 | } | ||
791 | #endif | ||
792 | #endif | ||
793 | return ret; | 781 | return ret; |
794 | } | 782 | } |
795 | 783 | ||
796 | static int sctpv6_init_net(struct net *net) | ||
797 | { | ||
798 | struct sctp_net *sn = sctp_pernet(net); | ||
799 | struct nf_proto_net *pn = (struct nf_proto_net *)sn; | ||
800 | |||
801 | sctp_init_net_data(sn); | ||
802 | return sctp_kmemdup_sysctl_table(pn); | ||
803 | } | ||
804 | |||
805 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { | 784 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { |
806 | .l3proto = PF_INET, | 785 | .l3proto = PF_INET, |
807 | .l4proto = IPPROTO_SCTP, | 786 | .l4proto = IPPROTO_SCTP, |
@@ -833,7 +812,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { | |||
833 | }, | 812 | }, |
834 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 813 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
835 | .net_id = &sctp_net_id, | 814 | .net_id = &sctp_net_id, |
836 | .init_net = sctpv4_init_net, | 815 | .init_net = sctp_init_net, |
837 | }; | 816 | }; |
838 | 817 | ||
839 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { | 818 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { |
@@ -867,7 +846,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { | |||
867 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 846 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
868 | #endif | 847 | #endif |
869 | .net_id = &sctp_net_id, | 848 | .net_id = &sctp_net_id, |
870 | .init_net = sctpv6_init_net, | 849 | .init_net = sctp_init_net, |
871 | }; | 850 | }; |
872 | 851 | ||
873 | static int sctp_net_init(struct net *net) | 852 | static int sctp_net_init(struct net *net) |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 99caa1304477..a5ac11ebef33 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -821,7 +821,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, | |||
821 | 821 | ||
822 | static unsigned int *tcp_get_timeouts(struct net *net) | 822 | static unsigned int *tcp_get_timeouts(struct net *net) |
823 | { | 823 | { |
824 | return tcp_timeouts; | 824 | return tcp_pernet(net)->timeouts; |
825 | } | 825 | } |
826 | 826 | ||
827 | /* Returns verdict for packet, or -1 for invalid. */ | 827 | /* Returns verdict for packet, or -1 for invalid. */ |
@@ -1533,11 +1533,10 @@ static struct ctl_table tcp_compat_sysctl_table[] = { | |||
1533 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 1533 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
1534 | #endif /* CONFIG_SYSCTL */ | 1534 | #endif /* CONFIG_SYSCTL */ |
1535 | 1535 | ||
1536 | static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn) | 1536 | static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn, |
1537 | struct nf_tcp_net *tn) | ||
1537 | { | 1538 | { |
1538 | #ifdef CONFIG_SYSCTL | 1539 | #ifdef CONFIG_SYSCTL |
1539 | struct nf_tcp_net *tn = (struct nf_tcp_net *)pn; | ||
1540 | |||
1541 | if (pn->ctl_table) | 1540 | if (pn->ctl_table) |
1542 | return 0; | 1541 | return 0; |
1543 | 1542 | ||
@@ -1564,11 +1563,11 @@ static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn) | |||
1564 | return 0; | 1563 | return 0; |
1565 | } | 1564 | } |
1566 | 1565 | ||
1567 | static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | 1566 | static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, |
1567 | struct nf_tcp_net *tn) | ||
1568 | { | 1568 | { |
1569 | #ifdef CONFIG_SYSCTL | 1569 | #ifdef CONFIG_SYSCTL |
1570 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 1570 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
1571 | struct nf_tcp_net *tn = (struct nf_tcp_net *)pn; | ||
1572 | pn->ctl_compat_table = kmemdup(tcp_compat_sysctl_table, | 1571 | pn->ctl_compat_table = kmemdup(tcp_compat_sysctl_table, |
1573 | sizeof(tcp_compat_sysctl_table), | 1572 | sizeof(tcp_compat_sysctl_table), |
1574 | GFP_KERNEL); | 1573 | GFP_KERNEL); |
@@ -1593,18 +1592,15 @@ static int tcp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | |||
1593 | return 0; | 1592 | return 0; |
1594 | } | 1593 | } |
1595 | 1594 | ||
1596 | static int tcpv4_init_net(struct net *net) | 1595 | static int tcp_init_net(struct net *net, u_int16_t proto) |
1597 | { | 1596 | { |
1598 | int i; | 1597 | int ret; |
1599 | int ret = 0; | ||
1600 | struct nf_tcp_net *tn = tcp_pernet(net); | 1598 | struct nf_tcp_net *tn = tcp_pernet(net); |
1601 | struct nf_proto_net *pn = (struct nf_proto_net *)tn; | 1599 | struct nf_proto_net *pn = &tn->pn; |
1600 | |||
1601 | if (!pn->users) { | ||
1602 | int i; | ||
1602 | 1603 | ||
1603 | #ifdef CONFIG_SYSCTL | ||
1604 | if (!pn->ctl_table) { | ||
1605 | #else | ||
1606 | if (!pn->users++) { | ||
1607 | #endif | ||
1608 | for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++) | 1604 | for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++) |
1609 | tn->timeouts[i] = tcp_timeouts[i]; | 1605 | tn->timeouts[i] = tcp_timeouts[i]; |
1610 | 1606 | ||
@@ -1613,43 +1609,23 @@ static int tcpv4_init_net(struct net *net) | |||
1613 | tn->tcp_max_retrans = nf_ct_tcp_max_retrans; | 1609 | tn->tcp_max_retrans = nf_ct_tcp_max_retrans; |
1614 | } | 1610 | } |
1615 | 1611 | ||
1616 | ret = tcp_kmemdup_compat_sysctl_table(pn); | 1612 | if (proto == AF_INET) { |
1617 | 1613 | ret = tcp_kmemdup_compat_sysctl_table(pn, tn); | |
1618 | if (ret < 0) | 1614 | if (ret < 0) |
1619 | return ret; | 1615 | return ret; |
1620 | 1616 | ||
1621 | ret = tcp_kmemdup_sysctl_table(pn); | 1617 | ret = tcp_kmemdup_sysctl_table(pn, tn); |
1618 | if (ret < 0) | ||
1619 | nf_ct_kfree_compat_sysctl_table(pn); | ||
1620 | } else | ||
1621 | ret = tcp_kmemdup_sysctl_table(pn, tn); | ||
1622 | 1622 | ||
1623 | #ifdef CONFIG_SYSCTL | ||
1624 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | ||
1625 | if (ret < 0) { | ||
1626 | kfree(pn->ctl_compat_table); | ||
1627 | pn->ctl_compat_table = NULL; | ||
1628 | } | ||
1629 | #endif | ||
1630 | #endif | ||
1631 | return ret; | 1623 | return ret; |
1632 | } | 1624 | } |
1633 | 1625 | ||
1634 | static int tcpv6_init_net(struct net *net) | 1626 | static struct nf_proto_net *tcp_get_net_proto(struct net *net) |
1635 | { | 1627 | { |
1636 | int i; | 1628 | return &net->ct.nf_ct_proto.tcp.pn; |
1637 | struct nf_tcp_net *tn = tcp_pernet(net); | ||
1638 | struct nf_proto_net *pn = (struct nf_proto_net *)tn; | ||
1639 | |||
1640 | #ifdef CONFIG_SYSCTL | ||
1641 | if (!pn->ctl_table) { | ||
1642 | #else | ||
1643 | if (!pn->users++) { | ||
1644 | #endif | ||
1645 | for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++) | ||
1646 | tn->timeouts[i] = tcp_timeouts[i]; | ||
1647 | tn->tcp_loose = nf_ct_tcp_loose; | ||
1648 | tn->tcp_be_liberal = nf_ct_tcp_be_liberal; | ||
1649 | tn->tcp_max_retrans = nf_ct_tcp_max_retrans; | ||
1650 | } | ||
1651 | |||
1652 | return tcp_kmemdup_sysctl_table(pn); | ||
1653 | } | 1629 | } |
1654 | 1630 | ||
1655 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = | 1631 | struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = |
@@ -1684,7 +1660,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = | |||
1684 | .nla_policy = tcp_timeout_nla_policy, | 1660 | .nla_policy = tcp_timeout_nla_policy, |
1685 | }, | 1661 | }, |
1686 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 1662 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
1687 | .init_net = tcpv4_init_net, | 1663 | .init_net = tcp_init_net, |
1664 | .get_net_proto = tcp_get_net_proto, | ||
1688 | }; | 1665 | }; |
1689 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); | 1666 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4); |
1690 | 1667 | ||
@@ -1720,6 +1697,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = | |||
1720 | .nla_policy = tcp_timeout_nla_policy, | 1697 | .nla_policy = tcp_timeout_nla_policy, |
1721 | }, | 1698 | }, |
1722 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 1699 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
1723 | .init_net = tcpv6_init_net, | 1700 | .init_net = tcp_init_net, |
1701 | .get_net_proto = tcp_get_net_proto, | ||
1724 | }; | 1702 | }; |
1725 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6); | 1703 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp6); |
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index a83cf93545cd..59623cc56e8d 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c | |||
@@ -235,10 +235,10 @@ static struct ctl_table udp_compat_sysctl_table[] = { | |||
235 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ | 235 | #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */ |
236 | #endif /* CONFIG_SYSCTL */ | 236 | #endif /* CONFIG_SYSCTL */ |
237 | 237 | ||
238 | static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn) | 238 | static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn, |
239 | struct nf_udp_net *un) | ||
239 | { | 240 | { |
240 | #ifdef CONFIG_SYSCTL | 241 | #ifdef CONFIG_SYSCTL |
241 | struct nf_udp_net *un = (struct nf_udp_net *)pn; | ||
242 | if (pn->ctl_table) | 242 | if (pn->ctl_table) |
243 | return 0; | 243 | return 0; |
244 | pn->ctl_table = kmemdup(udp_sysctl_table, | 244 | pn->ctl_table = kmemdup(udp_sysctl_table, |
@@ -252,11 +252,11 @@ static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn) | |||
252 | return 0; | 252 | return 0; |
253 | } | 253 | } |
254 | 254 | ||
255 | static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | 255 | static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn, |
256 | struct nf_udp_net *un) | ||
256 | { | 257 | { |
257 | #ifdef CONFIG_SYSCTL | 258 | #ifdef CONFIG_SYSCTL |
258 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | 259 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT |
259 | struct nf_udp_net *un = (struct nf_udp_net *)pn; | ||
260 | pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table, | 260 | pn->ctl_compat_table = kmemdup(udp_compat_sysctl_table, |
261 | sizeof(udp_compat_sysctl_table), | 261 | sizeof(udp_compat_sysctl_table), |
262 | GFP_KERNEL); | 262 | GFP_KERNEL); |
@@ -270,50 +270,36 @@ static int udp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn) | |||
270 | return 0; | 270 | return 0; |
271 | } | 271 | } |
272 | 272 | ||
273 | static void udp_init_net_data(struct nf_udp_net *un) | 273 | static int udp_init_net(struct net *net, u_int16_t proto) |
274 | { | 274 | { |
275 | int i; | 275 | int ret; |
276 | #ifdef CONFIG_SYSCTL | 276 | struct nf_udp_net *un = udp_pernet(net); |
277 | if (!un->pn.ctl_table) { | 277 | struct nf_proto_net *pn = &un->pn; |
278 | #else | 278 | |
279 | if (!un->pn.users++) { | 279 | if (!pn->users) { |
280 | #endif | 280 | int i; |
281 | |||
281 | for (i = 0; i < UDP_CT_MAX; i++) | 282 | for (i = 0; i < UDP_CT_MAX; i++) |
282 | un->timeouts[i] = udp_timeouts[i]; | 283 | un->timeouts[i] = udp_timeouts[i]; |
283 | } | 284 | } |
284 | } | ||
285 | |||
286 | static int udpv4_init_net(struct net *net) | ||
287 | { | ||
288 | int ret; | ||
289 | struct nf_udp_net *un = udp_pernet(net); | ||
290 | struct nf_proto_net *pn = (struct nf_proto_net *)un; | ||
291 | 285 | ||
292 | udp_init_net_data(un); | 286 | if (proto == AF_INET) { |
287 | ret = udp_kmemdup_compat_sysctl_table(pn, un); | ||
288 | if (ret < 0) | ||
289 | return ret; | ||
293 | 290 | ||
294 | ret = udp_kmemdup_compat_sysctl_table(pn); | 291 | ret = udp_kmemdup_sysctl_table(pn, un); |
295 | if (ret < 0) | 292 | if (ret < 0) |
296 | return ret; | 293 | nf_ct_kfree_compat_sysctl_table(pn); |
294 | } else | ||
295 | ret = udp_kmemdup_sysctl_table(pn, un); | ||
297 | 296 | ||
298 | ret = udp_kmemdup_sysctl_table(pn); | ||
299 | #ifdef CONFIG_SYSCTL | ||
300 | #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT | ||
301 | if (ret < 0) { | ||
302 | kfree(pn->ctl_compat_table); | ||
303 | pn->ctl_compat_table = NULL; | ||
304 | } | ||
305 | #endif | ||
306 | #endif | ||
307 | return ret; | 297 | return ret; |
308 | } | 298 | } |
309 | 299 | ||
310 | static int udpv6_init_net(struct net *net) | 300 | static struct nf_proto_net *udp_get_net_proto(struct net *net) |
311 | { | 301 | { |
312 | struct nf_udp_net *un = udp_pernet(net); | 302 | return &net->ct.nf_ct_proto.udp.pn; |
313 | struct nf_proto_net *pn = (struct nf_proto_net *)un; | ||
314 | |||
315 | udp_init_net_data(un); | ||
316 | return udp_kmemdup_sysctl_table(pn); | ||
317 | } | 303 | } |
318 | 304 | ||
319 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = | 305 | struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = |
@@ -343,7 +329,8 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = | |||
343 | .nla_policy = udp_timeout_nla_policy, | 329 | .nla_policy = udp_timeout_nla_policy, |
344 | }, | 330 | }, |
345 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 331 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
346 | .init_net = udpv4_init_net, | 332 | .init_net = udp_init_net, |
333 | .get_net_proto = udp_get_net_proto, | ||
347 | }; | 334 | }; |
348 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); | 335 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4); |
349 | 336 | ||
@@ -374,6 +361,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = | |||
374 | .nla_policy = udp_timeout_nla_policy, | 361 | .nla_policy = udp_timeout_nla_policy, |
375 | }, | 362 | }, |
376 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | 363 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ |
377 | .init_net = udpv6_init_net, | 364 | .init_net = udp_init_net, |
365 | .get_net_proto = udp_get_net_proto, | ||
378 | }; | 366 | }; |
379 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6); | 367 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp6); |
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index b32e700f8dde..4b66df209286 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c | |||
@@ -234,29 +234,38 @@ static struct ctl_table udplite_sysctl_table[] = { | |||
234 | }; | 234 | }; |
235 | #endif /* CONFIG_SYSCTL */ | 235 | #endif /* CONFIG_SYSCTL */ |
236 | 236 | ||
237 | static int udplite_init_net(struct net *net) | 237 | static int udplite_kmemdup_sysctl_table(struct nf_proto_net *pn, |
238 | struct udplite_net *un) | ||
238 | { | 239 | { |
239 | int i; | ||
240 | struct udplite_net *un = udplite_pernet(net); | ||
241 | struct nf_proto_net *pn = (struct nf_proto_net *)un; | ||
242 | #ifdef CONFIG_SYSCTL | 240 | #ifdef CONFIG_SYSCTL |
243 | if (!pn->ctl_table) { | 241 | if (pn->ctl_table) |
244 | #else | 242 | return 0; |
245 | if (!pn->users++) { | 243 | |
244 | pn->ctl_table = kmemdup(udplite_sysctl_table, | ||
245 | sizeof(udplite_sysctl_table), | ||
246 | GFP_KERNEL); | ||
247 | if (!pn->ctl_table) | ||
248 | return -ENOMEM; | ||
249 | |||
250 | pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED]; | ||
251 | pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED]; | ||
246 | #endif | 252 | #endif |
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static int udplite_init_net(struct net *net, u_int16_t proto) | ||
257 | { | ||
258 | struct udplite_net *un = udplite_pernet(net); | ||
259 | struct nf_proto_net *pn = &un->pn; | ||
260 | |||
261 | if (!pn->users) { | ||
262 | int i; | ||
263 | |||
247 | for (i = 0 ; i < UDPLITE_CT_MAX; i++) | 264 | for (i = 0 ; i < UDPLITE_CT_MAX; i++) |
248 | un->timeouts[i] = udplite_timeouts[i]; | 265 | un->timeouts[i] = udplite_timeouts[i]; |
249 | #ifdef CONFIG_SYSCTL | ||
250 | pn->ctl_table = kmemdup(udplite_sysctl_table, | ||
251 | sizeof(udplite_sysctl_table), | ||
252 | GFP_KERNEL); | ||
253 | if (!pn->ctl_table) | ||
254 | return -ENOMEM; | ||
255 | pn->ctl_table[0].data = &un->timeouts[UDPLITE_CT_UNREPLIED]; | ||
256 | pn->ctl_table[1].data = &un->timeouts[UDPLITE_CT_REPLIED]; | ||
257 | #endif | ||
258 | } | 266 | } |
259 | return 0; | 267 | |
268 | return udplite_kmemdup_sysctl_table(pn, un); | ||
260 | } | 269 | } |
261 | 270 | ||
262 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = | 271 | static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 465539d43a0a..a26503342e71 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -195,9 +195,11 @@ replay: | |||
195 | lockdep_is_held(&nfnl_mutex)) != ss || | 195 | lockdep_is_held(&nfnl_mutex)) != ss || |
196 | nfnetlink_find_client(type, ss) != nc) | 196 | nfnetlink_find_client(type, ss) != nc) |
197 | err = -EAGAIN; | 197 | err = -EAGAIN; |
198 | else | 198 | else if (nc->call) |
199 | err = nc->call(net->nfnl, skb, nlh, | 199 | err = nc->call(net->nfnl, skb, nlh, |
200 | (const struct nlattr **)cda); | 200 | (const struct nlattr **)cda); |
201 | else | ||
202 | err = -EINVAL; | ||
201 | nfnl_unlock(); | 203 | nfnl_unlock(); |
202 | } | 204 | } |
203 | if (err == -EAGAIN) | 205 | if (err == -EAGAIN) |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index a0b64920039d..c0496a55ad0c 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -910,6 +910,11 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
910 | flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS])); | 910 | flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS])); |
911 | mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK])); | 911 | mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK])); |
912 | 912 | ||
913 | if (flags >= NFQA_CFG_F_MAX) { | ||
914 | ret = -EOPNOTSUPP; | ||
915 | goto err_out_unlock; | ||
916 | } | ||
917 | |||
913 | spin_lock_bh(&queue->lock); | 918 | spin_lock_bh(&queue->lock); |
914 | queue->flags &= ~mask; | 919 | queue->flags &= ~mask; |
915 | queue->flags |= flags & mask; | 920 | queue->flags |= flags & mask; |