Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter/IPVS updates for your net-next
tree. Basically, a new extension for ip6tables, simplification work of
nf_tables that saves us 500 LoC, allow raw table registration before
defragmentation, conversion of the SNMP helper to use the ASN.1 code
generator, unique 64-bit handle for all nf_tables objects and fixes to
address fallout from previous nf-next batch.  More specifically, they
are:

1) Seven patches to remove family abstraction layer (struct nft_af_info)
   in nf_tables, this simplifies our codebase and it saves us 64 bytes per
   net namespace.

2) Add IPv6 segment routing header matching for ip6tables, from Ahmed
   Abdelsalam.

3) Allow to register iptable_raw table before defragmentation, some
   people do not want to waste cycles on defragmenting traffic that is
   going to be dropped, hence add a new module parameter to enable this
   behaviour in iptables and ip6tables. From Subash Abhinov
   Kasiviswanathan. This patch needed a couple of follow up patches to
   get things tidy from Arnd Bergmann.

4) SNMP helper uses the ASN.1 code generator, from Taehee Yoo. Several
   patches for this helper to prepare this change are also part of this
   patch series.

5) Add 64-bit handles to uniquely objects in nf_tables, from Harsha
   Sharma.

6) Remove log message that several netfilter subsystems print at
   boot/load time.

7) Restore x_tables module autoloading, that got broken in a previous
   patch to allow singleton NAT hook callback registration per hook
   spot, from Florian Westphal. Moreover, return EBUSY to report that
   the singleton NAT hook slot is already in instead.

8) Several fixes for the new nf_tables flowtable representation,
   including incorrect error check after nf_tables_flowtable_lookup(),
   missing Kconfig dependencies that lead to build breakage and missing
   initialization of priority and hooknum in flowtable object.

9) Missing NETFILTER_FAMILY_ARP dependency in Kconfig for the clusterip
   target. This is due to recent updates in the core to shrink the hook
   array size and compile it out if no specific family is enabled via
   .config file. Patch from Florian Westphal.

10) Remove duplicated include header files, from Wei Yongjun.

11) Sparse warning fix for the NFPROTO_INET handling from the core
    due to missing static function definition, also from Wei Yongjun.

12) Restore ICMPv6 Parameter Problem error reporting when
    defragmentation fails, from Subash Abhinov Kasiviswanathan.

13) Remove obsolete owner field initialization from struct
    file_operations, patch from Alexey Dobriyan.

14) Use boolean datatype where needed in the Netfilter codebase, from
    Gustavo A. R. Silva.

15) Remove double semicolon in dynset nf_tables expression, from
    Luis de Bethencourt.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2018-01-21 11:35:34 -05:00
62 changed files with 1239 additions and 2224 deletions

View File

@@ -72,8 +72,9 @@ endif # NF_TABLES_IPV6
endif # NF_TABLES
config NF_FLOW_TABLE_IPV6
select NF_FLOW_TABLE
tristate "Netfilter flow table IPv6 module"
depends on NF_CONNTRACK && NF_TABLES
select NF_FLOW_TABLE
help
This option adds the flow table IPv6 support.
@@ -240,6 +241,15 @@ config IP6_NF_MATCH_RT
To compile it as a module, choose M here. If unsure, say N.
config IP6_NF_MATCH_SRH
tristate '"srh" Segment Routing header match support'
depends on NETFILTER_ADVANCED
help
srh matching allows you to match packets based on the segment
routing header of the packet.
To compile it as a module, choose M here. If unsure, say N.
# The targets
config IP6_NF_TARGET_HL
tristate '"HL" hoplimit target support'

View File

@@ -57,6 +57,7 @@ obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
obj-$(CONFIG_IP6_NF_MATCH_SRH) += ip6t_srh.o
# targets
obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o

View File

@@ -1952,7 +1952,6 @@ static int __init ip6_tables_init(void)
if (ret < 0)
goto err5;
pr_info("(C) 2000-2006 Netfilter Core Team\n");
return 0;
err5:

View File

@@ -0,0 +1,161 @@
/* Kernel module to match Segment Routing Header (SRH) parameters. */
/* Author:
* Ahmed Abdelsalam <amsalam20@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <net/ipv6.h>
#include <net/seg6.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv6/ip6t_srh.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
/* Test a struct->mt_invflags and a boolean for inequality */
#define NF_SRH_INVF(ptr, flag, boolean) \
((boolean) ^ !!((ptr)->mt_invflags & (flag)))
static bool srh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct ip6t_srh *srhinfo = par->matchinfo;
struct ipv6_sr_hdr *srh;
struct ipv6_sr_hdr _srh;
int hdrlen, srhoff = 0;
if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
return false;
srh = skb_header_pointer(skb, srhoff, sizeof(_srh), &_srh);
if (!srh)
return false;
hdrlen = ipv6_optlen(srh);
if (skb->len - srhoff < hdrlen)
return false;
if (srh->type != IPV6_SRCRT_TYPE_4)
return false;
if (srh->segments_left > srh->first_segment)
return false;
/* Next Header matching */
if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_NEXTHDR,
!(srh->nexthdr == srhinfo->next_hdr)))
return false;
/* Header Extension Length matching */
if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_EQ,
!(srh->hdrlen == srhinfo->hdr_len)))
return false;
if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_GT,
!(srh->hdrlen > srhinfo->hdr_len)))
return false;
if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LEN_LT,
!(srh->hdrlen < srhinfo->hdr_len)))
return false;
/* Segments Left matching */
if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_EQ,
!(srh->segments_left == srhinfo->segs_left)))
return false;
if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_GT,
!(srh->segments_left > srhinfo->segs_left)))
return false;
if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_SEGS_LT,
!(srh->segments_left < srhinfo->segs_left)))
return false;
/**
* Last Entry matching
* Last_Entry field was introduced in revision 6 of the SRH draft.
* It was called First_Segment in the previous revision
*/
if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_EQ,
!(srh->first_segment == srhinfo->last_entry)))
return false;
if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_GT,
!(srh->first_segment > srhinfo->last_entry)))
return false;
if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_LAST_LT,
!(srh->first_segment < srhinfo->last_entry)))
return false;
/**
* Tag matchig
* Tag field was introduced in revision 6 of the SRH draft.
*/
if (srhinfo->mt_flags & IP6T_SRH_TAG)
if (NF_SRH_INVF(srhinfo, IP6T_SRH_INV_TAG,
!(srh->tag == srhinfo->tag)))
return false;
return true;
}
static int srh_mt6_check(const struct xt_mtchk_param *par)
{
const struct ip6t_srh *srhinfo = par->matchinfo;
if (srhinfo->mt_flags & ~IP6T_SRH_MASK) {
pr_err("unknown srh match flags %X\n", srhinfo->mt_flags);
return -EINVAL;
}
if (srhinfo->mt_invflags & ~IP6T_SRH_INV_MASK) {
pr_err("unknown srh invflags %X\n", srhinfo->mt_invflags);
return -EINVAL;
}
return 0;
}
static struct xt_match srh_mt6_reg __read_mostly = {
.name = "srh",
.family = NFPROTO_IPV6,
.match = srh_mt6,
.matchsize = sizeof(struct ip6t_srh),
.checkentry = srh_mt6_check,
.me = THIS_MODULE,
};
static int __init srh_mt6_init(void)
{
return xt_register_match(&srh_mt6_reg);
}
static void __exit srh_mt6_exit(void)
{
xt_unregister_match(&srh_mt6_reg);
}
module_init(srh_mt6_init);
module_exit(srh_mt6_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Xtables: IPv6 Segment Routing Header match");
MODULE_AUTHOR("Ahmed Abdelsalam <amsalam20@gmail.com>");

View File

@@ -3,6 +3,7 @@
*
* Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/slab.h>
@@ -11,6 +12,10 @@
static int __net_init ip6table_raw_table_init(struct net *net);
static bool raw_before_defrag __read_mostly;
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
module_param(raw_before_defrag, bool, 0000);
static const struct xt_table packet_raw = {
.name = "raw",
.valid_hooks = RAW_VALID_HOOKS,
@@ -20,6 +25,15 @@ static const struct xt_table packet_raw = {
.table_init = ip6table_raw_table_init,
};
static const struct xt_table packet_raw_before_defrag = {
.name = "raw",
.valid_hooks = RAW_VALID_HOOKS,
.me = THIS_MODULE,
.af = NFPROTO_IPV6,
.priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG,
.table_init = ip6table_raw_table_init,
};
/* The work comes in here from netfilter.c. */
static unsigned int
ip6table_raw_hook(void *priv, struct sk_buff *skb,
@@ -33,15 +47,19 @@ static struct nf_hook_ops *rawtable_ops __read_mostly;
static int __net_init ip6table_raw_table_init(struct net *net)
{
struct ip6t_replace *repl;
const struct xt_table *table = &packet_raw;
int ret;
if (raw_before_defrag)
table = &packet_raw_before_defrag;
if (net->ipv6.ip6table_raw)
return 0;
repl = ip6t_alloc_initial_table(&packet_raw);
repl = ip6t_alloc_initial_table(table);
if (repl == NULL)
return -ENOMEM;
ret = ip6t_register_table(net, &packet_raw, repl, rawtable_ops,
ret = ip6t_register_table(net, table, repl, rawtable_ops,
&net->ipv6.ip6table_raw);
kfree(repl);
return ret;
@@ -62,9 +80,16 @@ static struct pernet_operations ip6table_raw_net_ops = {
static int __init ip6table_raw_init(void)
{
int ret;
const struct xt_table *table = &packet_raw;
if (raw_before_defrag) {
table = &packet_raw_before_defrag;
pr_info("Enabling raw table before defrag\n");
}
/* Register hooks */
rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook);
rawtable_ops = xt_hook_ops_alloc(table, ip6table_raw_hook);
if (IS_ERR(rawtable_ops))
return PTR_ERR(rawtable_ops);

View File

@@ -231,7 +231,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb,
if ((unsigned int)end > IPV6_MAXPLEN) {
pr_debug("offset is too large.\n");
return -1;
return -EINVAL;
}
ecn = ip6_frag_ecn(ipv6_hdr(skb));
@@ -264,7 +264,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb,
* this case. -DaveM
*/
pr_debug("end of fragment not rounded to 8 bytes.\n");
return -1;
return -EPROTO;
}
if (end > fq->q.len) {
/* Some bits beyond end -> corruption. */
@@ -358,7 +358,7 @@ found:
discard_fq:
inet_frag_kill(&fq->q, &nf_frags);
err:
return -1;
return -EINVAL;
}
/*
@@ -567,6 +567,7 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
{
u16 savethdr = skb->transport_header;
struct net_device *dev = skb->dev;
int fhoff, nhoff, ret;
struct frag_hdr *fhdr;
@@ -600,8 +601,12 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
spin_lock_bh(&fq->q.lock);
if (nf_ct_frag6_queue(fq, skb, fhdr, nhoff) < 0) {
ret = -EINVAL;
ret = nf_ct_frag6_queue(fq, skb, fhdr, nhoff);
if (ret < 0) {
if (ret == -EPROTO) {
skb->transport_header = savethdr;
ret = 0;
}
goto out_unlock;
}

View File

@@ -63,6 +63,9 @@ static unsigned int ipv6_defrag(void *priv,
/* Previously seen (loopback)? */
if (skb_nfct(skb) && !nf_ct_is_template((struct nf_conn *)skb_nfct(skb)))
return NF_ACCEPT;
if (skb->_nfct == IP_CT_UNTRACKED)
return NF_ACCEPT;
#endif
err = nf_ct_frag6_gather(state->net, skb,

View File

@@ -5,7 +5,6 @@
#include <linux/rhashtable.h>
#include <linux/ipv6.h>
#include <linux/netdevice.h>
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
#include <net/neighbour.h>

View File

@@ -28,40 +28,6 @@ static unsigned int nft_do_chain_ipv6(void *priv,
return nft_do_chain(&pkt, priv);
}
static struct nft_af_info nft_af_ipv6 __read_mostly = {
.family = NFPROTO_IPV6,
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
};
static int nf_tables_ipv6_init_net(struct net *net)
{
net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
if (net->nft.ipv6 == NULL)
return -ENOMEM;
memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));
if (nft_register_afinfo(net, net->nft.ipv6) < 0)
goto err;
return 0;
err:
kfree(net->nft.ipv6);
return -ENOMEM;
}
static void nf_tables_ipv6_exit_net(struct net *net)
{
nft_unregister_afinfo(net, net->nft.ipv6);
kfree(net->nft.ipv6);
}
static struct pernet_operations nf_tables_ipv6_net_ops = {
.init = nf_tables_ipv6_init_net,
.exit = nf_tables_ipv6_exit_net,
};
static const struct nf_chain_type filter_ipv6 = {
.name = "filter",
.type = NFT_CHAIN_T_DEFAULT,
@@ -83,22 +49,11 @@ static const struct nf_chain_type filter_ipv6 = {
static int __init nf_tables_ipv6_init(void)
{
int ret;
ret = nft_register_chain_type(&filter_ipv6);
if (ret < 0)
return ret;
ret = register_pernet_subsys(&nf_tables_ipv6_net_ops);
if (ret < 0)
nft_unregister_chain_type(&filter_ipv6);
return ret;
return nft_register_chain_type(&filter_ipv6);
}
static void __exit nf_tables_ipv6_exit(void)
{
unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
nft_unregister_chain_type(&filter_ipv6);
}
@@ -107,4 +62,4 @@ module_exit(nf_tables_ipv6_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_ALIAS_NFT_FAMILY(AF_INET6);
MODULE_ALIAS_NFT_CHAIN(AF_INET6, "filter");