* [PATCH net-next] af_packet: relax BUG statement in tpacket_destruct_skb
From: Daniel Borkmann @ 2012-08-09 16:39 UTC (permalink / raw)
To: davem; +Cc: netdev
Here's a quote of the comment about the BUG macro from asm-generic/bug.h:
Don't use BUG() or BUG_ON() unless there's really no way out; one
example might be detecting data structure corruption in the middle
of an operation that can't be backed out of. If the (sub)system
can somehow continue operating, perhaps with reduced functionality,
it's probably not BUG-worthy.
If you're tempted to BUG(), think again: is completely giving up
really the *only* solution? There are usually better options, where
users don't need to reboot ASAP and can mostly shut down cleanly.
In our case, the status flag of a ring buffer slot is managed from both sides,
the kernel space and the user space. This means that even though the kernel
side might work as expected, the user space screws up and changes this flag
right between the send(2) is triggered when the flag is changed to
TP_STATUS_SENDING and a given skb is destructed after some time. Then, this
will hit the BUG macro. Instead, we relax this condition with a WARN_ON_ONCE
macro, so that the user is aware of this situation. I've tested it and the
system still behaves /stable/, so in accordance with the above comment, we
should rather relax this behavior with a warning.
Signed-off-by: Daniel Borkmann <daniel.borkmann@tik.ee.ethz.ch>
---
net/packet/af_packet.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index ceaca7c..4def36f 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1936,7 +1936,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
if (likely(po->tx_ring.pg_vec)) {
ph = skb_shinfo(skb)->destructor_arg;
- BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING);
+ WARN_ON_ONCE(__packet_get_status(po, ph) != TP_STATUS_SENDING);
BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
atomic_dec(&po->tx_ring.pending);
__packet_set_status(po, ph, TP_STATUS_AVAILABLE);
^ permalink raw reply related
* Re: [PATCH] ipv4: tcp: security_sk_alloc() needed for unicast_sock
From: Eric Dumazet @ 2012-08-09 17:46 UTC (permalink / raw)
To: Eric Paris
Cc: Paul Moore, David Miller, Casey Schaufler, John Stultz,
Serge E. Hallyn, lkml, James Morris, selinux, john.johansen, LSM,
netdev
In-Reply-To: <CACLa4ptTfMzvhYk7_DaUJd-9u406FXf2CUHjn1mQrPDa4fFW4w@mail.gmail.com>
On Thu, 2012-08-09 at 12:05 -0400, Eric Paris wrote:
> On Thu, Aug 9, 2012 at 11:36 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > On Thu, 2012-08-09 at 11:07 -0400, Paul Moore wrote:
> >
> >> Is is possible to do the call to security_sk_alloc() in the ip_init() function
> >> or does the per-cpu nature of the socket make this a pain?
> >>
> >
> > Its a pain, if we want NUMA affinity.
> >
> > Here, each cpu should get memory from its closest node.
>
> I really really don't like it. I won't say NAK, but it is the first
> and only place in the kernel where I believe we allocate an object and
> don't allocate the security blob until some random later point in
> time.
...
> If it is such a performance issue to have the security blob in
> the same numa node, isn't adding a number of branches and putting this
> function call on every output at least as bad? Aren't we discouraged
> from GFP_ATOMIC? In __init we can use GFP_KERNEL.
What a big deal. Its done _once_ time per cpu, and this is so small blob
of memory you'll have to show us one single failure out of one million
boots.
If the security_sk_alloc() fails, we dont care. We are about sending a
RESET or ACK packet. They can be lost by the network, or even skb
allocation can fail. Nobody ever noticed and complained.
Every time we accept() a new socket (and call security_sk_alloc()), its
done under soft irq, thus GFP_ATOMIC, and you didn't complain yet, while
a socket needs about 2 Kbytes of memory...
>
> This still doesn't fix these sockets entirely. We now have the
> security blob allocated, but it was never set to something useful.
> Paul, are you looking into this? This is a bandaide, not a fix....
>
Please do so, on a followup patch, dont pretend I must fix all this
stuff.
^ permalink raw reply
* [PATCH net-next,1/1] hyperv: Add comments for the extended buffer after RNDIS message
From: Haiyang Zhang @ 2012-08-09 18:04 UTC (permalink / raw)
To: davem, netdev; +Cc: haiyangz, kys, olaf, linux-kernel, devel
Reported-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/net/hyperv/rndis_filter.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 1e88a10..06f8601 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -46,8 +46,14 @@ struct rndis_request {
/* Simplify allocation by having a netvsc packet inline */
struct hv_netvsc_packet pkt;
struct hv_page_buffer buf;
- /* FIXME: We assumed a fixed size request here. */
+
struct rndis_message request_msg;
+ /*
+ * The buffer for the extended info after the RNDIS message. It's
+ * referenced based on the data offset in the RNDIS message. Its size
+ * is enough for current needs, and should be sufficient for the near
+ * future.
+ */
u8 ext[100];
};
--
1.7.4.1
^ permalink raw reply related
* [net-next] bonding: don't allow the master to become its slave
From: Flavio Leitner @ 2012-08-09 18:30 UTC (permalink / raw)
To: netdev; +Cc: Jay Vosburgh, Andy Gospodarek, Leonardo Chiquitto, Flavio Leitner
It doesn't make any sense to allow the master to become
its slave. That creates a loop of events causing a crash.
Reported-by: Leonardo Chiquitto <lchiquitto@suse.com>
Signed-off-by: Flavio Leitner <fbl@redhat.com>
---
drivers/net/bonding/bond_main.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6fae5f3..5407b44 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1505,6 +1505,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
int link_reporting;
int res = 0;
+ if (bond_dev == slave_dev) {
+ pr_err("%s: Error: cannot enslave itself.\n", bond_dev->name);
+ return -EINVAL;
+ }
+
if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
slave_ops->ndo_do_ioctl == NULL) {
pr_warning("%s: Warning: no link monitoring support for %s\n",
--
1.7.11.2
^ permalink raw reply related
* Re: [PATCH] net: add new QCA alx ethernet driver
From: Ben Hutchings @ 2012-08-09 18:56 UTC (permalink / raw)
To: Steven Rostedt
Cc: Joe Perches, Ren, Cloud, David Miller, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, qca-linux-team, nic-devel,
Huang, Xiong, hao-ran.liu@canonical.com, Rodriguez, Luis
In-Reply-To: <1344526098.6935.44.camel@gandalf.stny.rr.com>
On Thu, 2012-08-09 at 11:28 -0400, Steven Rostedt wrote:
> On Thu, 2012-08-09 at 08:22 -0700, Joe Perches wrote:
>
> > Yes, I sent signed-off patches to their original RFC submission
> > (back last year?). To me, this single large patch is like a
> > snapshot of a git tree and not all contributors to that git
> > tree should be noted as signers of the entire thing.
>
> Ouch, that looks like we are losing all history.
>
> One large patch should not be submitted. If it was developed in steps,
> then it is best to show those steps when they are incorporated into the
> Linux repository.
>
> Sure, the patches may be reworked and folded together where appropriate,
> but when I read "this single large patch is like a snapshot of a git
> tree", that right there is a red flag.
I don't think this has ever been a requirement for new drivers.
The alterations to the description of atl1c ought to be broken out as a
separate patch, though.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [net-next] bonding: don't allow the master to become its slave
From: Ben Hutchings @ 2012-08-09 19:03 UTC (permalink / raw)
To: Flavio Leitner
Cc: netdev, Jay Vosburgh, Andy Gospodarek, Leonardo Chiquitto,
Jiri Pirko
In-Reply-To: <1344537049-11473-1-git-send-email-fbl@redhat.com>
On Thu, 2012-08-09 at 15:30 -0300, Flavio Leitner wrote:
> It doesn't make any sense to allow the master to become
> its slave. That creates a loop of events causing a crash.
What if there are other intermediate devices, e.g. the slave is a VLAN
sub-device of the bond? And doesn't team also have this problem?
I think a more general check for such loops might be required.
Ben.
> Reported-by: Leonardo Chiquitto <lchiquitto@suse.com>
> Signed-off-by: Flavio Leitner <fbl@redhat.com>
> ---
> drivers/net/bonding/bond_main.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 6fae5f3..5407b44 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -1505,6 +1505,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
> int link_reporting;
> int res = 0;
>
> + if (bond_dev == slave_dev) {
> + pr_err("%s: Error: cannot enslave itself.\n", bond_dev->name);
> + return -EINVAL;
> + }
> +
> if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
> slave_ops->ndo_do_ioctl == NULL) {
> pr_warning("%s: Warning: no link monitoring support for %s\n",
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [net-next] bonding: don't allow the master to become its slave
From: Leonardo Chiquitto @ 2012-08-09 18:45 UTC (permalink / raw)
To: Flavio Leitner, netdev; +Cc: Andy Gospodarek, Jay Vosburgh
In-Reply-To: <1344537049-11473-1-git-send-email-fbl@redhat.com>
>>> On 8/9/2012 at 03:30 PM, Flavio Leitner <fbl@redhat.com> wrote:
> It doesn't make any sense to allow the master to become
> its slave. That creates a loop of events causing a crash.
>
> Reported-by: Leonardo Chiquitto <lchiquitto@suse.com>
> Signed-off-by: Flavio Leitner <fbl@redhat.com>
> ---
> drivers/net/bonding/bond_main.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 6fae5f3..5407b44 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -1505,6 +1505,11 @@ int bond_enslave(struct net_device *bond_dev, struct
> net_device *slave_dev)
> int link_reporting;
> int res = 0;
>
> + if (bond_dev == slave_dev) {
> + pr_err("%s: Error: cannot enslave itself.\n", bond_dev->name);
> + return -EINVAL;
> + }
> +
> if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
> slave_ops->ndo_do_ioctl == NULL) {
> pr_warning("%s: Warning: no link monitoring support for %s\n",
I've tested it here and confirm it prevents the crash.
Tested-by: Leonardo Chiquitto <lchiquitto@suse.com>
Thanks,
Leonardo
^ permalink raw reply
* Re: [PATCH] net: add new QCA alx ethernet driver
From: Luis R. Rodriguez @ 2012-08-09 19:13 UTC (permalink / raw)
To: Steven Rostedt
Cc: Joe Perches, Ren, Cloud, David Miller, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, qca-linux-team, nic-devel,
Huang, Xiong, hao-ran.liu@canonical.com
In-Reply-To: <1344526098.6935.44.camel@gandalf.stny.rr.com>
On Thu, Aug 9, 2012 at 8:28 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Thu, 2012-08-09 at 08:22 -0700, Joe Perches wrote:
>
>> Yes, I sent signed-off patches to their original RFC submission
>> (back last year?).
And that is why your SOB was kept.
>> To me, this single large patch is like a
>> snapshot of a git tree and not all contributors to that git
>> tree should be noted as signers of the entire thing.
I am not sure we really ever addressed this technical difference and
from what I have seen we always run into this question on new driver
submissions.
Entity x goes on and posts driver joojoo-1, and we some folks in the
community may merge such patch onto their tree and edit the driver and
send some of their own changes and improvements to the developers /
mailing list. Typically if the patches sent had a SOB tag the right
thing to due given the legal implications of the Developer's
Certificate of Origin is to add those SOBs to the new driver
submission if company x goes on and posts joojoo-2.. but...
> Ouch, that looks like we are losing all history.
Agreed! It'd be best instead to have such changes as part of a linear
history somewhere so maybe what would be right prior to inclusion
upstream is for such patches to be merged on an external github tree
or wherever to be able to keep record of the submissions done during
development. Then upon submission to the Linux kernel again as
joojoo-2 instead of joojoo-1 company x would simply provide their own
SOB, and the record of the previous SOBs would be kept on the forked
git tree.
Whether or not it is required to have the SOB tog of previous patch
submitters is not clear but to me its not necessary if you have a
record somewhere that they were submitted and merged in some other
tree. The mailing list alone may serve as a good place holder for this
information as well so a separate tree may not be required.
So -- are we OK to *not* include SOBs of evolutions sent to developers
of joojoo-1 when company x submits joojoo-2 so long as those patches
were sent publicly or a record is kept somewhere ?
> One large patch should not be submitted. If it was developed in steps,
> then it is best to show those steps when they are incorporated into the
> Linux repository.
Sure, but at times some changes are asked after a submission of
joojoo-1, and at times this may be ongoing until maybe even joojoo-10,
before we are happy to merge it upstream.
Luis
^ permalink raw reply
* [iproute2][PATCH 1/2] tc: add ipset ematch
From: Florian Westphal @ 2012-08-09 19:18 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
example usage:
tc filter add dev $dev parent $id: basic match not ipset'(foobar src)' ..
also updates iproute2/ematch_map, else tc complains:
Error: Unable to find ematch "ipset" in /etc/iproute2/ematch_map
Please assign a unique ID to the ematch kind the suggested entry is:
8 ipset
when trying to use this ematch.
(text ematch (5) only exists in kernel, a vlan ematch (6) exists neither in
kernel nor userspace, but kernel headers define TCF_EM_VLAN == 6).
---
configure | 34 ++++++
etc/iproute2/ematch_map | 1 +
tc/Makefile | 4 +
tc/em_ipset.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 304 insertions(+), 0 deletions(-)
create mode 100644 tc/em_ipset.c
diff --git a/configure b/configure
index 0f4444f..a1916de 100755
--- a/configure
+++ b/configure
@@ -183,6 +183,37 @@ fi
rm -f $TMPDIR/setnstest.c $TMPDIR/setnstest
}
+check_ipset()
+{
+cat >$TMPDIR/ipsettest.c <<EOF
+#include <linux/netfilter/ipset/ip_set.h>
+#ifndef IP_SET_INVALID
+#define IPSET_DIM_MAX 3
+typedef unsigned short ip_set_id_t;
+#endif
+#include <linux/netfilter/xt_set.h>
+
+struct xt_set_info info;
+#if IPSET_PROTOCOL == 6
+int main(void)
+{
+ return IPSET_MAXNAMELEN;
+}
+#else
+#error unknown ipset version
+#endif
+EOF
+
+if gcc -I$INCLUDE -o $TMPDIR/ipsettest $TMPDIR/ipsettest.c >/dev/null 2>&1
+then
+ echo "TC_CONFIG_IPSET:=y" >>Config
+ echo "yes"
+else
+ echo "no"
+fi
+rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest
+}
+
echo "# Generated config based on" $INCLUDE >Config
echo "TC schedulers"
@@ -196,6 +227,9 @@ check_xt_old
check_xt_old_internal_h
check_ipt
+echo -n " IPSET "
+check_ipset
+
echo -n "iptables modules directory: "
check_ipt_lib_dir
diff --git a/etc/iproute2/ematch_map b/etc/iproute2/ematch_map
index 7c6a281..69b007d 100644
--- a/etc/iproute2/ematch_map
+++ b/etc/iproute2/ematch_map
@@ -3,3 +3,4 @@
2 nbyte
3 u32
4 meta
+8 ipset
diff --git a/tc/Makefile b/tc/Makefile
index 64d93ad..dfbfac5 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -50,6 +50,10 @@ TCMODULES += q_mqprio.o
TCMODULES += q_codel.o
TCMODULES += q_fq_codel.o
+ifeq ($(TC_CONFIG_IPSET), y)
+ TCMODULES += em_ipset.o
+endif
+
TCSO :=
ifeq ($(TC_CONFIG_ATM),y)
TCSO += q_atm.so
diff --git a/tc/em_ipset.c b/tc/em_ipset.c
new file mode 100644
index 0000000..a2d0d15
--- /dev/null
+++ b/tc/em_ipset.c
@@ -0,0 +1,265 @@
+/*
+ * em_ipset.c IPset Ematch
+ *
+ * (C) 2012 Florian Westphal <fw@strlen.de>
+ *
+ * Parts taken from iptables libxt_set.h:
+ * Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/ipset/ip_set.h>
+
+#ifndef IPSET_INVALID_ID
+typedef __u16 ip_set_id_t;
+
+enum ip_set_dim {
+ IPSET_DIM_ZERO = 0,
+ IPSET_DIM_ONE,
+ IPSET_DIM_TWO,
+ IPSET_DIM_THREE,
+ IPSET_DIM_MAX = 6,
+};
+#endif /* IPSET_INVALID_ID */
+
+#include <linux/netfilter/xt_set.h>
+#include "m_ematch.h"
+
+#ifndef IPSET_INVALID_ID
+#define IPSET_INVALID_ID 65535
+#define SO_IP_SET 83
+
+union ip_set_name_index {
+ char name[IPSET_MAXNAMELEN];
+ __u16 index;
+};
+
+#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
+struct ip_set_req_get_set {
+ unsigned op;
+ unsigned version;
+ union ip_set_name_index set;
+};
+
+#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
+/* Uses ip_set_req_get_set */
+
+#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
+struct ip_set_req_version {
+ unsigned op;
+ unsigned version;
+};
+#endif /* IPSET_INVALID_ID */
+
+extern struct ematch_util ipset_ematch_util;
+
+static int get_version(unsigned *version)
+{
+ int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ struct ip_set_req_version req_version;
+ socklen_t size = sizeof(req_version);
+
+ if (sockfd < 0) {
+ fputs("Can't open socket to ipset.\n", stderr);
+ return -1;
+ }
+
+ req_version.op = IP_SET_OP_VERSION;
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
+ if (res != 0) {
+ perror("xt_set getsockopt");
+ return -1;
+ }
+
+ *version = req_version.version;
+ return sockfd;
+}
+
+static int do_getsockopt(struct ip_set_req_get_set *req)
+{
+ int sockfd, res;
+ socklen_t size = sizeof(struct ip_set_req_get_set);
+ sockfd = get_version(&req->version);
+ if (sockfd < 0)
+ return -1;
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, req, &size);
+ if (res != 0)
+ perror("Problem when communicating with ipset");
+ close(sockfd);
+ if (res != 0)
+ return -1;
+
+ if (size != sizeof(struct ip_set_req_get_set)) {
+ fprintf(stderr,
+ "Incorrect return size from kernel during ipset lookup, "
+ "(want %zu, got %zu)\n",
+ sizeof(struct ip_set_req_get_set), (size_t)size);
+ return -1;
+ }
+
+ return res;
+}
+
+static int
+get_set_byid(char *setname, unsigned int idx)
+{
+ struct ip_set_req_get_set req;
+ int res;
+
+ req.op = IP_SET_OP_GET_BYINDEX;
+ req.set.index = idx;
+ res = do_getsockopt(&req);
+ if (res != 0)
+ return -1;
+ if (req.set.name[0] == '\0') {
+ fprintf(stderr,
+ "Set with index %i in kernel doesn't exist.\n", idx);
+ return -1;
+ }
+
+ strncpy(setname, req.set.name, IPSET_MAXNAMELEN);
+ return 0;
+}
+
+static int
+get_set_byname(const char *setname, struct xt_set_info *info)
+{
+ struct ip_set_req_get_set req;
+ int res;
+
+ req.op = IP_SET_OP_GET_BYNAME;
+ strncpy(req.set.name, setname, IPSET_MAXNAMELEN);
+ req.set.name[IPSET_MAXNAMELEN - 1] = '\0';
+ res = do_getsockopt(&req);
+ if (res != 0)
+ return -1;
+ if (req.set.index == IPSET_INVALID_ID)
+ return -1;
+ info->index = req.set.index;
+ return 0;
+}
+
+static int
+parse_dirs(const char *opt_arg, struct xt_set_info *info)
+{
+ char *saved = strdup(opt_arg);
+ char *ptr, *tmp = saved;
+
+ if (!tmp) {
+ perror("strdup");
+ return -1;
+ }
+
+ while (info->dim < IPSET_DIM_MAX && tmp != NULL) {
+ info->dim++;
+ ptr = strsep(&tmp, ",");
+ if (strncmp(ptr, "src", 3) == 0)
+ info->flags |= (1 << info->dim);
+ else if (strncmp(ptr, "dst", 3) != 0) {
+ fputs("You must specify (the comma separated list of) 'src' or 'dst'\n", stderr);
+ free(saved);
+ return -1;
+ }
+ }
+
+ if (tmp)
+ fprintf(stderr, "Can't be more src/dst options than %u", IPSET_DIM_MAX);
+ free(saved);
+ return tmp ? -1 : 0;
+}
+
+static void ipset_print_usage(FILE *fd)
+{
+ fprintf(fd,
+ "Usage: ipset(SETNAME FLAGS)\n" \
+ "where: SETNAME:= string\n" \
+ " FLAGS := { FLAG[,FLAGS] }\n" \
+ " FLAG := { src | dst }\n" \
+ "\n" \
+ "Example: 'ipset(bulk src,dst)'\n");
+}
+
+static int ipset_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
+ struct bstr *args)
+{
+ struct xt_set_info set_info;
+ int ret;
+
+ memset(&set_info, 0, sizeof(set_info));
+
+#define PARSE_ERR(CARG, FMT, ARGS...) \
+ em_parse_error(EINVAL, args, CARG, &ipset_ematch_util, FMT ,##ARGS)
+
+ if (args == NULL)
+ return PARSE_ERR(args, "ipset: missing set name");
+
+ if (args->len >= IPSET_MAXNAMELEN)
+ return PARSE_ERR(args, "ipset: set name too long (max %u)", IPSET_MAXNAMELEN - 1);
+ ret = get_set_byname(args->data, &set_info);
+ if (ret < 0)
+ return PARSE_ERR(args, "ipset: unknown set name '%s'", args->data);
+
+ if (args->next == NULL)
+ return PARSE_ERR(args, "ipset: missing set flags");
+
+ args = bstr_next(args);
+ if (parse_dirs(args->data, &set_info))
+ return PARSE_ERR(args, "ipset: error parsing set flags");
+
+ if (args->next) {
+ args = bstr_next(args);
+ return PARSE_ERR(args, "ipset: unknown parameter");
+ }
+
+ addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
+ addraw_l(n, MAX_MSG, &set_info, sizeof(set_info));
+
+#undef PARSE_ERR
+ return 0;
+}
+
+static int ipset_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
+ int data_len)
+{
+ int i;
+ char setname[IPSET_MAXNAMELEN];
+ const struct xt_set_info *set_info = data;
+
+ if (data_len != sizeof(*set_info)) {
+ fprintf(stderr, "xt_set_info struct size mismatch\n");
+ return -1;
+ }
+
+ if (get_set_byid(setname, set_info->index))
+ return -1;
+ fputs(setname, fd);
+ for (i = 1; i <= set_info->dim; i++) {
+ fprintf(fd, "%s%s", i == 1 ? " " : ",", set_info->flags & (1 << i) ? "src" : "dst");
+ }
+
+ return 0;
+}
+
+struct ematch_util ipset_ematch_util = {
+ .kind = "ipset",
+ .kind_num = TCF_EM_IPSET,
+ .parse_eopt = ipset_parse_eopt,
+ .print_eopt = ipset_print_eopt,
+ .print_usage = ipset_print_usage
+};
--
1.7.3.4
^ permalink raw reply related
* [iproute2][PATCH 2/2] add ematch man page
From: Florian Westphal @ 2012-08-09 19:18 UTC (permalink / raw)
To: netdev; +Cc: Florian Westphal
In-Reply-To: <1344539931-2653-1-git-send-email-fw@strlen.de>
---
could need more work, but a terse one is better than none.
man/man8/tc-ematch.8 | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++
man/man8/tc.8 | 1 +
2 files changed, 153 insertions(+), 0 deletions(-)
create mode 100644 man/man8/tc-ematch.8
diff --git a/man/man8/tc-ematch.8 b/man/man8/tc-ematch.8
new file mode 100644
index 0000000..53ae161
--- /dev/null
+++ b/man/man8/tc-ematch.8
@@ -0,0 +1,152 @@
+.TH filter ematch "6 August 2012" iproute2 Linux
+.
+.SH NAME
+ematch \- extended matches for use with "basic" or "flow" filters
+.
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B "tc filter add .. basic match"
+.RI EXPR
+.B .. flowid ..
+.sp
+
+.ti -8
+.IR EXPR " := " TERM " [ { "
+.B and | or
+}
+.IR EXPR
+]
+
+.ti -8
+.IR TERM " := [ " not " ] { " MATCH " | '(' " EXPR " ')' } "
+
+.ti -8
+.IR MATCH " := " module " '(' " ARGS " ')' "
+
+.ti -8
+.IR ARGS " := " ARG1 " " ARG2 " ..
+
+.SH MATCHES
+
+.SS cmp
+Simple comparison ematch: arithmetic compare of packet data to a given value.
+.ti
+.IR cmp "( " ALIGN " at " OFFSET " [ " ATTRS " ] { " eq " | " lt " | " gt " } " VALUE " )
+
+.ti
+.IR ALIGN " := { " u8 " | " u16 " | " u32 " } "
+
+.ti
+.IR ATTRS " := [ layer " LAYER " ] [ mask " MASK " ] [ " trans " ] "
+
+.ti
+.IR ALIGN " := { " u8 " | " u16 " | " u32 } "
+
+.ti
+.IR LAYER " := { " link " | " network " | " transport " | " 0..%d " }
+
+.SS meta
+Metadata ematch
+.ti
+.IR meta "( " OBJECT " { " eq " | " lt " |" gt " } " OBJECT " )
+
+.ti
+.IR OBJECT " := { " META_ID " | " VALUE " }
+
+.ti
+.IR META_ID " := id " [ shift " SHIFT " ] [ mask " MASK " ]
+
+.TP
+meta attributes:
+
+\fBrandom\fP 32 bit random value
+
+\fBloadavg_1\fP Load average in last 5 minutes
+
+\fBnf_mark\fP Netfilter mark
+
+\fBvlan\fP Vlan tag
+
+\fBsk_rcvbuf\fP Receive buffer size
+
+\fBsk_snd_queue\fP Send queue length
+
+.PP
+A full list of meta attributes can be obtained via
+
+# tc filter add dev eth1 basic match 'meta(list)'
+
+.SS nbyte
+match packet data byte sequence
+.ti
+.IR nbyte "( " NEEDLE " at " OFFSET " [ layer " LAYER " ] )
+
+.ti
+.IR NEEDLE " := { " string " | " c-escape-sequence " } "
+
+.ti
+.IR OFFSET " := " int
+
+.ti
+.IR LAYER " := { " link " | " network " | " transport " | " 0..%d " }
+
+.SS u32
+u32 ematch
+.ti
+.IR u32 "( " ALIGN VALUE MASK " at " [ nexthdr+ ] " OFFSET " )
+
+.ti
+.IR ALIGN " := " { " u8 " | " u16 " | " u32 " }
+
+.SS ipset
+test packet agains ipset membership
+.ti
+.IR ipset "( " SETNAME FLAGS )
+
+.ti
+.IR SETNAME " := " string
+
+.ti
+.IR FLAGS " := " { " FLAG " [, " FLAGS "] }
+
+The flag options are the same as those used by the iptables "set" match.
+
+When using the ipset ematch with the "ip_set_hash:net,iface" set type,
+the interface can be queried using "src,dst (source ip address, outgoing interface) or
+"src,src" (source ip address, incoming interface) syntax.
+
+.SH CAVEATS
+
+The ematch syntax uses '(' and ')' to group expressions. All braces need to be
+escaped properly to prevent shell commandline from interpreting these directly.
+
+When using the ipset ematch with the "ifb" device, the outgoing device will be the
+ifb device itself, e.g. "ifb0".
+The original interface (i.e. the device the packet arrived on) is treated as the incoming interface.
+
+.SH EXAMPLE & USAGE
+
+# tc filter add .. basic match ...
+
+# 'cmp(u16 at 3 layer 2 mask 0xff00 gt 20)'
+
+# 'meta(nfmark gt 24)' and 'meta(tcindex mask 0xf0 eq 0xf0)'
+
+# 'nbyte("ababa" at 12 layer 1)'
+
+# 'u32(u16 0x1122 0xffff at nexthdr+4)'
+
+Check if packet source ip address is member of set named \fBbulk\fP:
+
+# 'ipset(bulk src)'
+
+Check if packet source ip and the interface the packet arrived on is member of "hash:net,iface" set named \fBinteractive\fP:
+
+# 'ipset(interactive src,src)'
+
+.SH "AUTHOR"
+
+The extended match infrastructure was added by Thomas Graf.
diff --git a/man/man8/tc.8 b/man/man8/tc.8
index 95571a3..a285c49 100644
--- a/man/man8/tc.8
+++ b/man/man8/tc.8
@@ -374,6 +374,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2.
.BR tc-choke (8),
.BR tc-codel (8),
.BR tc-drr (8),
+.BR tc-ematch (8),
.BR tc-fq_codel (8),
.BR tc-hfsc (7),
.BR tc-hfsc (8),
--
1.7.3.4
^ permalink raw reply related
* Re: [net-next] bonding: don't allow the master to become its slave
From: Jay Vosburgh @ 2012-08-09 19:23 UTC (permalink / raw)
To: Ben Hutchings
Cc: Flavio Leitner, netdev, Andy Gospodarek, Leonardo Chiquitto,
Jiri Pirko
In-Reply-To: <1344539003.2593.7.camel@bwh-desktop.uk.solarflarecom.com>
Ben Hutchings <bhutchings@solarflare.com> wrote:
>On Thu, 2012-08-09 at 15:30 -0300, Flavio Leitner wrote:
>> It doesn't make any sense to allow the master to become
>> its slave. That creates a loop of events causing a crash.
>
>What if there are other intermediate devices, e.g. the slave is a VLAN
>sub-device of the bond? And doesn't team also have this problem?
>
>I think a more general check for such loops might be required.
I thought we had disallowed any nesting of bonds at all, but I
checked the netdev archives, and it appears we discussed it (and agreed
it didn't work), but it kind of petered out.
http://patchwork.ozlabs.org/patch/79705/
In any event, I think a patch like the following would get all
cases (double enslavement or enslavement of any bonding master) in one
place:
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6fae5f3..d14651c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1505,18 +1505,17 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
int link_reporting;
int res = 0;
+ if (slave_dev->priv_flags & IFF_BONDING) {
+ pr_debug("Error, Device was already enslaved\n");
+ return -EBUSY;
+ }
+
if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
slave_ops->ndo_do_ioctl == NULL) {
pr_warning("%s: Warning: no link monitoring support for %s\n",
bond_dev->name, slave_dev->name);
}
- /* already enslaved */
- if (slave_dev->flags & IFF_SLAVE) {
- pr_debug("Error, Device was already enslaved\n");
- return -EBUSY;
- }
-
/* vlan challenged mutual exclusion */
/* no need to lock since we're protected by rtnl_lock */
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
This is basically the same logic that Jiri Bohac originally
proposed in the discussion I mention above, although this patch moves
the test further up and combines the master and slave tests into one.
Comments? I haven't tested this at all, but I think the logic
is correct. I don't think having two separate tests to get special
"master" and "slave" error cases is worthwhile.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply related
* Re: [PATCH] net: add new QCA alx ethernet driver
From: Luis R. Rodriguez @ 2012-08-09 19:31 UTC (permalink / raw)
To: Steven Rostedt
Cc: Joe Perches, Ren, Cloud, David Miller, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, qca-linux-team, nic-devel,
Huang, Xiong, hao-ran.liu@canonical.com
In-Reply-To: <CAB=NE6X4JQmQgtgcy9is0hn0nNypTKJN-d2RHFR7vvg=vO_eHQ@mail.gmail.com>
On Thu, Aug 9, 2012 at 12:13 PM, Luis R. Rodriguez
<rodrigue@qca.qualcomm.com> wrote:
> So -- are we OK to *not* include SOBs of evolutions sent to developers
> of joojoo-1 when company x submits joojoo-2 so long as those patches
> were sent publicly or a record is kept somewhere ?
And lets be fair, some folks *may* want their SOB passed along to the
second joojoo-2, its hard to please everyone but so long as we can
decide on a method -- then great, we don't have to come back to this
again and then we can add this as documentation. I'm inclined to
prefer to not have the small patch submitters SOB tag if their patch
to joojoo-1 was public and in it they did have a SOB tag, given that
in practice *a few* secondary patch submitters tend to get surprised
when their SOB is added to a secondary patch submission if they only
contributed a few lines. To be clear the SOB does not have anything to
do with how many lines you contributed, its meaning is here:
http://gerrit.googlecode.com/svn-history/r1526/documentation/2.1.2/user-signedoffby.html
So even if those secondary patch submitters *think* it has to do with
volume of code, perhaps its best in practice to not include them so
long as we have a record of the original small patch submission
publicly and with a SOB tag.
Luis
^ permalink raw reply
* Re: [PATCH 07/14] bridge: add some comments for NETDEV_RELEASE
From: Stephen Hemminger @ 2012-08-09 19:44 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, David Miller, Stephen Hemminger
If you are going to add an explanation, then I would prefer a more complete one. Something like:
"Since more than one interface can be attached to a bridge, there still maybe an alternate path for netconsole to use; therefore there is no reason for a NETDEV_RELEASE event."
But my opinion it really isn't necessary to document what isn't done in the code, only what is done. The purpose of comments is to explain the wider impacts of the code.
^ permalink raw reply
* Re: [net-next] bonding: don't allow the master to become its slave
From: Flavio Leitner @ 2012-08-09 19:39 UTC (permalink / raw)
To: Ben Hutchings
Cc: netdev, Jay Vosburgh, Andy Gospodarek, Leonardo Chiquitto,
Jiri Pirko
In-Reply-To: <1344539003.2593.7.camel@bwh-desktop.uk.solarflarecom.com>
On Thu, 9 Aug 2012 20:03:23 +0100
Ben Hutchings <bhutchings@solarflare.com> wrote:
> On Thu, 2012-08-09 at 15:30 -0300, Flavio Leitner wrote:
> > It doesn't make any sense to allow the master to become
> > its slave. That creates a loop of events causing a crash.
>
> What if there are other intermediate devices, e.g. the slave is a VLAN
> sub-device of the bond? And doesn't team also have this problem?
>
> I think a more general check for such loops might be required.
Maybe patching netdev_set_master() to fail in the loop case is
the way to go. That would work for bonding, team and bridge.
What you think?
fbl
^ permalink raw reply
* Re: [net-next] bonding: don't allow the master to become its slave
From: Jiri Pirko @ 2012-08-09 19:54 UTC (permalink / raw)
To: Ben Hutchings
Cc: Flavio Leitner, netdev, Jay Vosburgh, Andy Gospodarek,
Leonardo Chiquitto
In-Reply-To: <1344539003.2593.7.camel@bwh-desktop.uk.solarflarecom.com>
Thu, Aug 09, 2012 at 09:03:23PM CEST, bhutchings@solarflare.com wrote:
>On Thu, 2012-08-09 at 15:30 -0300, Flavio Leitner wrote:
>> It doesn't make any sense to allow the master to become
>> its slave. That creates a loop of events causing a crash.
>
>What if there are other intermediate devices, e.g. the slave is a VLAN
>sub-device of the bond? And doesn't team also have this problem?
Yes, it does.
>
>I think a more general check for such loops might be required.
I agree.
>
>Ben.
>
>> Reported-by: Leonardo Chiquitto <lchiquitto@suse.com>
>> Signed-off-by: Flavio Leitner <fbl@redhat.com>
>> ---
>> drivers/net/bonding/bond_main.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>> index 6fae5f3..5407b44 100644
>> --- a/drivers/net/bonding/bond_main.c
>> +++ b/drivers/net/bonding/bond_main.c
>> @@ -1505,6 +1505,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
>> int link_reporting;
>> int res = 0;
>>
>> + if (bond_dev == slave_dev) {
>> + pr_err("%s: Error: cannot enslave itself.\n", bond_dev->name);
>> + return -EINVAL;
>> + }
>> +
>> if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
>> slave_ops->ndo_do_ioctl == NULL) {
>> pr_warning("%s: Warning: no link monitoring support for %s\n",
>
>--
>Ben Hutchings, Staff Engineer, Solarflare
>Not speaking for my employer; that's the marketing department's job.
>They asked us to note that Solarflare product names are trademarked.
>
^ permalink raw reply
* Re: [net-next] bonding: don't allow the master to become its slave
From: Jiri Pirko @ 2012-08-09 19:55 UTC (permalink / raw)
To: Flavio Leitner
Cc: Ben Hutchings, netdev, Jay Vosburgh, Andy Gospodarek,
Leonardo Chiquitto
In-Reply-To: <20120809163906.6dc0b6d4@obelix.rh>
Thu, Aug 09, 2012 at 09:39:06PM CEST, fbl@redhat.com wrote:
>On Thu, 9 Aug 2012 20:03:23 +0100
>Ben Hutchings <bhutchings@solarflare.com> wrote:
>
>> On Thu, 2012-08-09 at 15:30 -0300, Flavio Leitner wrote:
>> > It doesn't make any sense to allow the master to become
>> > its slave. That creates a loop of events causing a crash.
>>
>> What if there are other intermediate devices, e.g. the slave is a VLAN
>> sub-device of the bond? And doesn't team also have this problem?
>>
>> I think a more general check for such loops might be required.
>
>Maybe patching netdev_set_master() to fail in the loop case is
>the way to go. That would work for bonding, team and bridge.
>
>What you think?
How about other devices who do not use "->master" like vlan, macvlan?
>
>fbl
^ permalink raw reply
* Re: [PATCH] ipv4: tcp: security_sk_alloc() needed for unicast_sock
From: Eric Paris @ 2012-08-09 20:06 UTC (permalink / raw)
To: Eric Dumazet
Cc: Paul Moore, David Miller, Casey Schaufler, John Stultz,
Serge E. Hallyn, lkml, James Morris, selinux, john.johansen, LSM,
netdev
In-Reply-To: <1344523833.28967.996.camel@edumazet-glaptop>
[-- Attachment #1: Type: text/plain, Size: 8961 bytes --]
NAK.
I personally think commit be9f4a44e7d41cee should be reverted until it
is fixed. Let me explain what all I believe it broke and how.
Old callchain of the creation of the 'equivalent' socket previous to
the patch in question just for reference:
inet_ctl_sock_create
sock_create_kern
__sock_create
pf->create (inet_create)
sk_alloc
sk_prot_alloc
security_sk_alloc()
This WAS working properly. All of it. The equivalent struct sock was
being created and allocated in inet_create(), which called to
sk_alloc->sk_prot_alloc->security_sk_alloc(). We all agree that
failing to call security_sk_alloc() is the first regression
introduced.
The second regression was the labeling issue. There was a call to
security_socket_post_create (from __sock_create) which was properly
setting the labels on both the socket and sock. This new patch broke
that as well. We don't expose an equivalent
security_sock_post_create() interface in the LSM currently, and until
we do, this can't be fixed. It's why I say it should be reverted.
I have a patch I'm testing right now which takes care of the first
part the way I like (and yes, I'm doing the allocation on the correct
number node). It basically looks like so:
+ for_each_possible_cpu(cpu) {
+ sock = &per_cpu(unicast_sock, cpu);
+ rc = security_sk_alloc(&sock->sk, PF_INET, GFP_KERNEL,
cpu_to_node(cpu));
+ if (rc)
+ return rc;
+ }
I'm going to work right now on exposing the equivalent struct sock LSM
interface so we can call that as well. But it's going to take me a
bit. Attached is the patch just to (hopefully untested) shut up the
panic.
-Eric
On Thu, Aug 9, 2012 at 10:50 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> commit be9f4a44e7d41cee (ipv4: tcp: remove per net tcp_sock) added a
> selinux regression, reported and bisected by John Stultz
>
> selinux_ip_postroute_compat() expect to find a valid sk->sk_security
> pointer, but this field is NULL for unicast_sock
>
> Fix this by adding a new 'kernel' parameter to security_sk_alloc(),
> set to true if socket might already have a valid sk->sk_security
> pointer. ip_send_unicast_reply() uses a percpu fake socket, so the first
> call to security_sk_alloc() will populate sk->sk_security pointer,
> subsequent ones will reuse existing context.
>
> Reported-by: John Stultz <johnstul@us.ibm.com>
> Bisected-by: John Stultz <johnstul@us.ibm.com>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Paul Moore <paul@paul-moore.com>
> Cc: Eric Paris <eparis@parisplace.org>
> Cc: "Serge E. Hallyn" <serge@hallyn.com>
> ---
> include/linux/security.h | 6 +++---
> net/core/sock.c | 2 +-
> net/ipv4/ip_output.c | 4 +++-
> security/security.c | 4 ++--
> security/selinux/hooks.c | 5 ++++-
> security/smack/smack_lsm.c | 10 ++++++++--
> 6 files changed, 21 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 4e5a73c..4d8e454 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1601,7 +1601,7 @@ struct security_operations {
> int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb);
> int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
> int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
> - int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
> + int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority, bool kernel);
> void (*sk_free_security) (struct sock *sk);
> void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
> void (*sk_getsecid) (struct sock *sk, u32 *secid);
> @@ -2539,7 +2539,7 @@ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb);
> int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
> int __user *optlen, unsigned len);
> int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid);
> -int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
> +int security_sk_alloc(struct sock *sk, int family, gfp_t priority, bool kernel);
> void security_sk_free(struct sock *sk);
> void security_sk_clone(const struct sock *sk, struct sock *newsk);
> void security_sk_classify_flow(struct sock *sk, struct flowi *fl);
> @@ -2667,7 +2667,7 @@ static inline int security_socket_getpeersec_dgram(struct socket *sock, struct s
> return -ENOPROTOOPT;
> }
>
> -static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
> +static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority, bool kernel)
> {
> return 0;
> }
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 8f67ced..e00cadf 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1186,7 +1186,7 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
> if (sk != NULL) {
> kmemcheck_annotate_bitfield(sk, flags);
>
> - if (security_sk_alloc(sk, family, priority))
> + if (security_sk_alloc(sk, family, priority, false))
> goto out_free;
>
> if (!try_module_get(prot->owner))
> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> index 76dde25..b233d6e 100644
> --- a/net/ipv4/ip_output.c
> +++ b/net/ipv4/ip_output.c
> @@ -1524,6 +1524,8 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
> sk->sk_priority = skb->priority;
> sk->sk_protocol = ip_hdr(skb)->protocol;
> sk->sk_bound_dev_if = arg->bound_dev_if;
> + if (security_sk_alloc(sk, PF_INET, GFP_ATOMIC, true))
> + goto out;
> sock_net_set(sk, net);
> __skb_queue_head_init(&sk->sk_write_queue);
> sk->sk_sndbuf = sysctl_wmem_default;
> @@ -1539,7 +1541,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
> skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb));
> ip_push_pending_frames(sk, &fl4);
> }
> -
> +out:
> put_cpu_var(unicast_sock);
>
> ip_rt_put(rt);
> diff --git a/security/security.c b/security/security.c
> index 860aeb3..23cf297 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1146,9 +1146,9 @@ int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u
> }
> EXPORT_SYMBOL(security_socket_getpeersec_dgram);
>
> -int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
> +int security_sk_alloc(struct sock *sk, int family, gfp_t priority, bool kernel)
> {
> - return security_ops->sk_alloc_security(sk, family, priority);
> + return security_ops->sk_alloc_security(sk, family, priority, kernel);
> }
>
> void security_sk_free(struct sock *sk)
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 6c77f63..ccd4374 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4289,10 +4289,13 @@ out:
> return 0;
> }
>
> -static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
> +static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority, bool kernel)
> {
> struct sk_security_struct *sksec;
>
> + if (kernel && sk->sk_security)
> + return 0;
> +
> sksec = kzalloc(sizeof(*sksec), priority);
> if (!sksec)
> return -ENOMEM;
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 8221514..0b066d0 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -1749,20 +1749,26 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
> * @sk: the socket
> * @family: unused
> * @gfp_flags: memory allocation flags
> + * @kernel: true if we should check sk_security being already set
> *
> * Assign Smack pointers to current
> *
> * Returns 0 on success, -ENOMEM is there's no memory
> */
> -static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
> +static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags, bool kernel)
> {
> - char *csp = smk_of_current();
> + char *csp;
> struct socket_smack *ssp;
>
> + if (kernel && sk->sk_security)
> + return 0;
> +
> ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
> if (ssp == NULL)
> return -ENOMEM;
>
> + csp = kernel ? smack_net_ambient : smk_of_current();
> +
> ssp->smk_in = csp;
> ssp->smk_out = csp;
> ssp->smk_packet = NULL;
>
>
[-- Attachment #2: tmp.patch --]
[-- Type: application/octet-stream, Size: 12667 bytes --]
commit feaf4fe8a8e4509540286899d02cd88f09c0d343
Author: Eric Paris <eparis@redhat.com>
Date: Thu Aug 9 14:08:12 2012 -0400
Network/Security: allocate security data when we allocate unicast sockets
commit be9f4a44e7d41cee (ipv4: tcp: remove per net tcp_sock) added a
regression because it did not properly initialize the new per cpu sockets.
This was reported and bisected by John Stultz:
[ 69.272927] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
[ 69.273374] IP: [<ffffffff8132e7c4>] selinux_ip_postroute_compat+0xa4/0xe0
[ 69.273374] PGD 3a85b067 PUD 3f50b067 PMD 0
[ 69.273374] Oops: 0000 [#1] PREEMPT SMP
[ 69.273374] CPU 3
[ 69.273374] Pid: 2392, comm: hwclock Not tainted 3.6.0-rc1john+ #106 Bochs Bochs
[ 69.273374] RIP: 0010:[<ffffffff8132e7c4>] [<ffffffff8132e7c4>] selinux_ip_postroute_compat+0xa4/0xe0
[ 69.273374] RSP: 0018:ffff88003f003720 EFLAGS: 00010246
[ 69.273374] RAX: 0000000000000000 RBX: ffff88003f5fa9d8 RCX: 0000000000000006
[ 69.273374] RDX: ffff88003f003740 RSI: ffff88003c6b256c RDI: ffff88003f5fa9d8
[ OK ]
[ 69.273374] RBP: ffff88003f0037a0 R08: 0000000000000000 R09: ffff88003f1d0cc0
[ 69.273374] R10: 0000000000000003 R11: 0000000000000000 R12: 0000000000000000
[ 69.273374] R13: 0000000000000002 R14: ffff88003f0037c0 R15: 0000000000000004
[ 69.273374] FS: 00007fa398211700(0000) GS:ffff88003f000000(0000) knlGS:0000000000000000
[ 69.273374] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 69.273374] CR2: 0000000000000010 CR3: 000000003b52a000 CR4: 00000000000006e0
[ 69.273374] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 69.273374] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 69.273374] Process hwclock (pid: 2392, threadinfo ffff88003a0ee000, task ffff88003fa82b80)
[ 69.273374] Stack:
[ 69.273374] ffff88003c6b2558 0000000000000006 0000000000000000 0000160067d70002
[ 69.273374] 0f02000a0202000a 0000000000000000 0000000000000000 0000000000000000
[ 69.273374] ffff88003f003802 ffff88003f003728 ffff88003f1d42d0 ffff88003d6c3560
[ 69.273374] Call Trace:
[ 69.273374] <IRQ>
[ 69.273374] [<ffffffff8132eaab>] selinux_ip_postroute+0x2ab/0x3e0
[ 69.273374] [<ffffffff8132ec1c>] selinux_ipv4_postroute+0x1c/0x20
[ 69.273374] [<ffffffff8198265c>] nf_iterate+0xac/0x140
[ 69.273374] [<ffffffff819827a5>] nf_hook_slow+0xb5/0x210
[ 69.273374] [<ffffffff8199cbba>] ip_output+0xaa/0x150
[ 69.273374] [<ffffffff8199a9af>] ip_local_out+0x7f/0x110
[ 69.273374] [<ffffffff8199d82e>] ip_send_skb+0xe/0x40
[ 69.273374] [<ffffffff8199d88b>] ip_push_pending_frames+0x2b/0x30
[ 69.273374] [<ffffffff8199dc97>] ip_send_unicast_reply+0x2c7/0x3c0
[ 69.273374] [<ffffffff819bb215>] tcp_v4_send_reset+0x1f5/0x3f0
[ 69.273374] [<ffffffff819bf04b>] tcp_v4_rcv+0x2bb/0x1080
[ 69.273374] [<ffffffff81994d73>] ip_local_deliver_finish+0x133/0x4d0
[ 69.273374] [<ffffffff819953e0>] ip_local_deliver+0x90/0xa0
[ 69.273374] [<ffffffff819945b2>] ip_rcv_finish+0x262/0x8f0
[ 69.273374] [<ffffffff81995742>] ip_rcv+0x352/0x3a0
[ 69.323844] [<ffffffff81925244>] __netif_receive_skb+0xcb4/0x10e0
[ 69.323844] [<ffffffff8192ba5d>] netif_receive_skb+0x18d/0x230
[ 69.323844] [<ffffffff81746abc>] virtnet_poll+0x58c/0x7b0
[ 69.323844] [<ffffffff8192cf59>] net_rx_action+0x289/0x550
[ 69.323844] [<ffffffff8105846a>] __do_softirq+0x1da/0x560
[ 69.323844] [<ffffffff81b5c2bc>] call_softirq+0x1c/0x30
[ 69.323844] [<ffffffff81004d75>] do_softirq+0x105/0x1e0
[ 69.323844] [<ffffffff81058bbe>] irq_exit+0x9e/0x100
[ 69.323844] [<ffffffff81b5c9d3>] do_IRQ+0x63/0xd0
[ 69.323844] [<ffffffff81b5a56f>] common_interrupt+0x6f/0x6f
[ 69.323844] <EOI>
[ 69.323844] [<ffffffff810993ad>] __might_sleep+0x1cd/0x280
[ 69.323844] [<ffffffff81160e74>] might_fault+0x34/0xb0
[ 69.323844] [<ffffffff8105657e>] sys_gettimeofday+0xbe/0xf0
[ 69.323844] [<ffffffff81b5afe9>] system_call_fastpath+0x16/0x1b
[ 69.323844] Code: c0 45 31 c9 b1 01 ba 2a 00 00 00 e8 a7 89 ff ff 85 c0 b9 00 00 6f 00 74 0e 48 83 c4 70 89 c8 5b 41 5c 5d c3 0f 1f 00 0f b6 4d ef <41> 8b 7c 24 10 48 8d 55 c0 48 89 de e8 ab 6d 01 00 83 f8 01 19
[ 69.323844] RIP [<ffffffff8132e7c4>] selinux_ip_postroute_compat+0xa4/0xe0
[ 69.323844] RSP <ffff88003f003720>
[ 69.323844] CR2: 0000000000000010
[ 69.357489] ---[ end trace 0cd3e1a60dee6096 ]---
[ 69.358353] Kernel panic - not syncing: Fatal exception in interrupt
The reason for the regresion is because of how the new sock is created. The
old socket was created using inet_ctl_sock_create() which uses all generic
functions to establish the struct socket, struct sock, and do all of the
allocation and initialization of the socket and its appropriate security data.
aka:
inet_ctl_sock_create
sock_create_kern
__sock_create
pf->create (inet_create)
sk_alloc
sk_prot_alloc
sec_sk_alloc()
These new per_cpu skip all of that initialization and instead try to do it by
hand. Doing it by hand causes a second regression. The __sock_create()
function calls security_socket_post_create() which initializes the securty
state on both the socket and the sock. However here we don't set up the
security structure. I'd like to use security_socket_post_create() but it needs
the socket and in this case we skipped straight to the struct sock. Looks like
this custom hackary is going to require a second patch which exposes the inards
of security_socket_post_create() as security_sock_post_create() so we can do
the labeling of this created this way. But at least this one won't panic the
kernel.
Reported-by: John Stultz <johnstul@us.ibm.com>
Bisected-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
diff --git a/include/linux/security.h b/include/linux/security.h
index 4e5a73c..1e0c5a7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1601,7 +1601,7 @@ struct security_operations {
int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb);
int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
- int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
+ int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority, int numa_node);
void (*sk_free_security) (struct sock *sk);
void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
void (*sk_getsecid) (struct sock *sk, u32 *secid);
@@ -2539,7 +2539,7 @@ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb);
int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
int __user *optlen, unsigned len);
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid);
-int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
+int security_sk_alloc(struct sock *sk, int family, gfp_t priority, int numa_node);
void security_sk_free(struct sock *sk);
void security_sk_clone(const struct sock *sk, struct sock *newsk);
void security_sk_classify_flow(struct sock *sk, struct flowi *fl);
@@ -2667,7 +2667,7 @@ static inline int security_socket_getpeersec_dgram(struct socket *sock, struct s
return -ENOPROTOOPT;
}
-static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
+static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority, int numa_node)
{
return 0;
}
diff --git a/include/net/ip.h b/include/net/ip.h
index bd5e444..340905d 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -105,7 +105,7 @@ extern void ip_send_check(struct iphdr *ip);
extern int __ip_local_out(struct sk_buff *skb);
extern int ip_local_out(struct sk_buff *skb);
extern int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl);
-extern void ip_init(void);
+extern int ip_init(void);
extern int ip_append_data(struct sock *sk, struct flowi4 *fl4,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
diff --git a/net/core/sock.c b/net/core/sock.c
index 8f67ced8..2cab455 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1186,7 +1186,7 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
if (sk != NULL) {
kmemcheck_annotate_bitfield(sk, flags);
- if (security_sk_alloc(sk, family, priority))
+ if (security_sk_alloc(sk, family, priority, numa_node_id()))
goto out_free;
if (!try_module_get(prot->owner))
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 6681ccf..3f79f37 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1720,7 +1720,8 @@ static int __init inet_init(void)
* Set the IP module up
*/
- ip_init();
+ if (ip_init() < 0)
+ panic("Failed to initialize ip.\n");
tcp_v4_init();
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 76dde25..4a775b3 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1545,12 +1545,23 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
ip_rt_put(rt);
}
-void __init ip_init(void)
+int __init ip_init(void)
{
+ struct inet_sock *sock;
+ int rc, cpu;
+
ip_rt_init();
inet_initpeers();
#if defined(CONFIG_IP_MULTICAST) && defined(CONFIG_PROC_FS)
igmp_mc_proc_init();
#endif
+
+ for_each_possible_cpu(cpu) {
+ sock = &per_cpu(unicast_sock, cpu);
+ rc = security_sk_alloc(&sock->sk, PF_INET, GFP_KERNEL, cpu_to_node(cpu));
+ if (rc)
+ return rc;
+ }
+ return 0;
}
diff --git a/security/capability.c b/security/capability.c
index 61095df..0525d28 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -650,7 +650,7 @@ static int cap_socket_getpeersec_dgram(struct socket *sock,
return -ENOPROTOOPT;
}
-static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
+static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority, int numa_node)
{
return 0;
}
diff --git a/security/security.c b/security/security.c
index 860aeb3..02a7f76 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1146,9 +1146,9 @@ int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);
-int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
+int security_sk_alloc(struct sock *sk, int family, gfp_t priority, int numa_node)
{
- return security_ops->sk_alloc_security(sk, family, priority);
+ return security_ops->sk_alloc_security(sk, family, priority, numa_node);
}
void security_sk_free(struct sock *sk)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6c77f63..bdcfd0c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4289,11 +4289,12 @@ out:
return 0;
}
-static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
+static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority,
+ int numa_node)
{
struct sk_security_struct *sksec;
- sksec = kzalloc(sizeof(*sksec), priority);
+ sksec = kmalloc_node(sizeof(*sksec), priority | __GFP_ZERO, numa_node);
if (!sksec)
return -ENOMEM;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 8221514..b43ae5d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1754,12 +1754,14 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
*
* Returns 0 on success, -ENOMEM is there's no memory
*/
-static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
+static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags,
+ int numa_node)
{
char *csp = smk_of_current();
struct socket_smack *ssp;
- ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
+ ssp = kmalloc_node(sizeof(struct socket_smack), gfp_flags | __GFP_ZERO,
+ numa_node);
if (ssp == NULL)
return -ENOMEM;
^ permalink raw reply related
* [PATCH 03/19] netfilter: nf_nat_sip: fix via header translation with multiple parameters
From: kaber @ 2012-08-09 20:08 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Via-headers are parsed beginning at the first character after the Via-address.
When the address is translated first and its length decreases, the offset to
start parsing at is incorrect and header parameters might be missed.
Update the offset after translating the Via-address to fix this.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv4/netfilter/nf_nat_sip.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index eef8f29..4ad9cf1 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
hdr, NULL, &matchoff, &matchlen,
&addr, &port) > 0) {
- unsigned int matchend, poff, plen, buflen, n;
+ unsigned int olen, matchend, poff, plen, buflen, n;
char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
/* We're only interested in headers related to this
@@ -163,11 +163,12 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
goto next;
}
+ olen = *datalen;
if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
&addr, port))
return NF_DROP;
- matchend = matchoff + matchlen;
+ matchend = matchoff + matchlen + *datalen - olen;
/* The maddr= parameter (RFC 2361) specifies where to send
* the reply. */
--
1.7.1
^ permalink raw reply related
* [PATCH 10/19] netfilter: ipv6: expand skb head in ip6_route_me_harder after oif change
From: kaber @ 2012-08-09 20:08 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Expand the skb headroom if the oif changed due to rerouting similar to
how IPv4 packets are handled.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv6/netfilter.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index db31561..429089c 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -15,6 +15,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
{
struct net *net = dev_net(skb_dst(skb)->dev);
const struct ipv6hdr *iph = ipv6_hdr(skb);
+ unsigned int hh_len;
struct dst_entry *dst;
struct flowi6 fl6 = {
.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
@@ -47,6 +48,13 @@ int ip6_route_me_harder(struct sk_buff *skb)
}
#endif
+ /* Change in oif may mean change in hh_len. */
+ hh_len = skb_dst(skb)->dev->hard_header_len;
+ if (skb_headroom(skb) < hh_len &&
+ pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
+ 0, GFP_ATOMIC))
+ return -1;
+
return 0;
}
EXPORT_SYMBOL(ip6_route_me_harder);
--
1.7.1
^ permalink raw reply related
* [PATCH 16/19] netfilter: nf_nat: support IPv6 in FTP NAT helper
From: kaber @ 2012-08-09 20:09 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv4/netfilter/Kconfig | 5 -----
net/ipv4/netfilter/Makefile | 1 -
net/netfilter/Kconfig | 5 +++++
net/netfilter/Makefile | 3 +++
net/netfilter/nf_conntrack_ftp.c | 3 +--
net/{ipv4 => }/netfilter/nf_nat_ftp.c | 30 ++++++++++++++++++------------
6 files changed, 27 insertions(+), 20 deletions(-)
rename net/{ipv4 => }/netfilter/nf_nat_ftp.c (82%)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 33372a1..80272e7 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -220,11 +220,6 @@ config NF_NAT_PROTO_GRE
tristate
depends on NF_NAT_IPV4 && NF_CT_PROTO_GRE
-config NF_NAT_FTP
- tristate
- depends on NF_CONNTRACK && NF_NAT_IPV4
- default NF_NAT_IPV4 && NF_CONNTRACK_FTP
-
config NF_NAT_IRC
tristate
depends on NF_CONNTRACK && NF_NAT_IPV4
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 0ea3acc..4d8a4ad 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
# NAT helpers (nf_conntrack)
obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
-obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o
obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 91addda..3104494 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -380,6 +380,11 @@ config NF_NAT_PROTO_SCTP
depends on NF_NAT && NF_CT_PROTO_SCTP
select LIBCRC32C
+config NF_NAT_FTP
+ tristate
+ depends on NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_FTP
+
endif # NF_CONNTRACK
# transparent proxy support
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 09c9451..16592b1 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -54,6 +54,9 @@ obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
+# NAT helpers
+obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
+
# transparent proxy support
obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index c0f4a5b..f8cc26a 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -488,8 +488,7 @@ static int help(struct sk_buff *skb,
/* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */
nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
- if (nf_nat_ftp && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
- ct->status & IPS_NAT_MASK)
+ if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
protoff, matchoff, matchlen, exp);
else {
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/netfilter/nf_nat_ftp.c
similarity index 82%
rename from net/ipv4/netfilter/nf_nat_ftp.c
rename to net/netfilter/nf_nat_ftp.c
index dd5e387..e839b97 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/netfilter/nf_nat_ftp.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/ip.h>
+#include <linux/inet.h>
#include <linux/tcp.h>
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_nat.h>
@@ -26,22 +26,27 @@ MODULE_ALIAS("ip_nat_ftp");
/* FIXME: Time out? --RR */
-static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type,
+static int nf_nat_ftp_fmt_cmd(struct nf_conn *ct, enum nf_ct_ftp_type type,
char *buffer, size_t buflen,
- __be32 addr, u16 port)
+ union nf_inet_addr *addr, u16 port)
{
switch (type) {
case NF_CT_FTP_PORT:
case NF_CT_FTP_PASV:
return snprintf(buffer, buflen, "%u,%u,%u,%u,%u,%u",
- ((unsigned char *)&addr)[0],
- ((unsigned char *)&addr)[1],
- ((unsigned char *)&addr)[2],
- ((unsigned char *)&addr)[3],
+ ((unsigned char *)&addr->ip)[0],
+ ((unsigned char *)&addr->ip)[1],
+ ((unsigned char *)&addr->ip)[2],
+ ((unsigned char *)&addr->ip)[3],
port >> 8,
port & 0xFF);
case NF_CT_FTP_EPRT:
- return snprintf(buffer, buflen, "|1|%pI4|%u|", &addr, port);
+ if (nf_ct_l3num(ct) == NFPROTO_IPV4)
+ return snprintf(buffer, buflen, "|1|%pI4|%u|",
+ &addr->ip, port);
+ else
+ return snprintf(buffer, buflen, "|2|%pI6|%u|",
+ &addr->ip6, port);
case NF_CT_FTP_EPSV:
return snprintf(buffer, buflen, "|||%u|", port);
}
@@ -59,17 +64,17 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
unsigned int matchlen,
struct nf_conntrack_expect *exp)
{
- __be32 newip;
+ union nf_inet_addr newaddr;
u_int16_t port;
int dir = CTINFO2DIR(ctinfo);
struct nf_conn *ct = exp->master;
- char buffer[sizeof("|1|255.255.255.255|65535|")];
+ char buffer[sizeof("|1||65535|") + INET6_ADDRSTRLEN];
unsigned int buflen;
pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
/* Connection will come from wherever this packet goes, hence !dir */
- newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ newaddr = ct->tuplehash[!dir].tuple.dst.u3;
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
exp->dir = !dir;
@@ -94,7 +99,8 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
if (port == 0)
return NF_DROP;
- buflen = nf_nat_ftp_fmt_cmd(type, buffer, sizeof(buffer), newip, port);
+ buflen = nf_nat_ftp_fmt_cmd(ct, type, buffer, sizeof(buffer),
+ &newaddr, port);
if (!buflen)
goto out;
--
1.7.1
^ permalink raw reply related
* [PATCH 17/19] netfilter: nf_nat: support IPv6 in amanda NAT helper
From: kaber @ 2012-08-09 20:09 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv4/netfilter/Kconfig | 5 -----
net/ipv4/netfilter/Makefile | 1 -
net/netfilter/Kconfig | 5 +++++
net/netfilter/Makefile | 1 +
net/netfilter/nf_conntrack_amanda.c | 3 +--
net/{ipv4 => }/netfilter/nf_nat_amanda.c | 0
6 files changed, 7 insertions(+), 8 deletions(-)
rename net/{ipv4 => }/netfilter/nf_nat_amanda.c (100%)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 80272e7..df42031 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -230,11 +230,6 @@ config NF_NAT_TFTP
depends on NF_CONNTRACK && NF_NAT_IPV4
default NF_NAT_IPV4 && NF_CONNTRACK_TFTP
-config NF_NAT_AMANDA
- tristate
- depends on NF_CONNTRACK && NF_NAT_IPV4
- default NF_NAT_IPV4 && NF_CONNTRACK_AMANDA
-
config NF_NAT_PPTP
tristate
depends on NF_CONNTRACK && NF_NAT_IPV4
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 4d8a4ad..8baa496 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o
obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
# NAT helpers (nf_conntrack)
-obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o
obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3104494..2eee9f1 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -380,6 +380,11 @@ config NF_NAT_PROTO_SCTP
depends on NF_NAT && NF_CT_PROTO_SCTP
select LIBCRC32C
+config NF_NAT_AMANDA
+ tristate
+ depends on NF_CONNTRACK && NF_NAT
+ default NF_NAT && NF_CONNTRACK_AMANDA
+
config NF_NAT_FTP
tristate
depends on NF_CONNTRACK && NF_NAT
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 16592b1..7d6e1ea 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
# NAT helpers
+obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
# transparent proxy support
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index e0212b5..c514fe6 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -155,8 +155,7 @@ static int amanda_help(struct sk_buff *skb,
IPPROTO_TCP, NULL, &port);
nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
- if (nf_nat_amanda && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
- ct->status & IPS_NAT_MASK)
+ if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
ret = nf_nat_amanda(skb, ctinfo, protoff,
off - dataoff, len, exp);
else if (nf_ct_expect_related(exp) != 0)
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/netfilter/nf_nat_amanda.c
similarity index 100%
rename from net/ipv4/netfilter/nf_nat_amanda.c
rename to net/netfilter/nf_nat_amanda.c
--
1.7.1
^ permalink raw reply related
* [PATCH 19/19] netfilter: ip6tables: add stateless IPv6-to-IPv6 Network Prefix Translation target
From: kaber @ 2012-08-09 20:09 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/netfilter_ipv6/Kbuild | 1 +
include/linux/netfilter_ipv6/ip6t_NPT.h | 16 +++
net/ipv6/netfilter/Kconfig | 9 ++
net/ipv6/netfilter/Makefile | 1 +
net/ipv6/netfilter/ip6t_NPT.c | 165 +++++++++++++++++++++++++++++++
5 files changed, 192 insertions(+), 0 deletions(-)
create mode 100644 include/linux/netfilter_ipv6/ip6t_NPT.h
create mode 100644 net/ipv6/netfilter/ip6t_NPT.c
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild
index bd095bc..b88c005 100644
--- a/include/linux/netfilter_ipv6/Kbuild
+++ b/include/linux/netfilter_ipv6/Kbuild
@@ -1,6 +1,7 @@
header-y += ip6_tables.h
header-y += ip6t_HL.h
header-y += ip6t_LOG.h
+header-y += ip6t_NPT.h
header-y += ip6t_REJECT.h
header-y += ip6t_ah.h
header-y += ip6t_frag.h
diff --git a/include/linux/netfilter_ipv6/ip6t_NPT.h b/include/linux/netfilter_ipv6/ip6t_NPT.h
new file mode 100644
index 0000000..f763355
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_NPT.h
@@ -0,0 +1,16 @@
+#ifndef __NETFILTER_IP6T_NPT
+#define __NETFILTER_IP6T_NPT
+
+#include <linux/types.h>
+#include <linux/netfilter.h>
+
+struct ip6t_npt_tginfo {
+ union nf_inet_addr src_pfx;
+ union nf_inet_addr dst_pfx;
+ __u8 src_pfx_len;
+ __u8 dst_pfx_len;
+ /* Used internally by the kernel */
+ __sum16 adjustment;
+};
+
+#endif /* __NETFILTER_IP6T_NPT */
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 7bdf73b..44ae1bf 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -177,6 +177,15 @@ config IP6_NF_TARGET_REDIRECT
To compile it as a module, choose M here. If unsure, say N.
+config IP6_NF_TARGET_NPT
+ tristate "NPT (Network Prefix translation) target support"
+ depends on NETFILTER_ADVANCED
+ help
+ This option adda `SNPT' and `DNPT' target, which perform stateless
+ IPv6-to-IPv6 Network Prefix Translation (RFC 6296).
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP6_NF_FILTER
tristate "Packet filtering"
default m if NETFILTER_ADVANCED=n
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 0864ce6..5752132 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -36,5 +36,6 @@ obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
# targets
obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o
+obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o
obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o
obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c
new file mode 100644
index 0000000..e948691
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_NPT.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011, 2012 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_ipv6/ip6t_NPT.h>
+#include <linux/netfilter/x_tables.h>
+
+static __sum16 csum16_complement(__sum16 a)
+{
+ return (__force __sum16)(0xffff - (__force u16)a);
+}
+
+static __sum16 csum16_add(__sum16 a, __sum16 b)
+{
+ u16 sum;
+
+ sum = (__force u16)a + (__force u16)b;
+ sum += (__force u16)a < (__force u16)b;
+ return (__force __sum16)sum;
+}
+
+static __sum16 csum16_sub(__sum16 a, __sum16 b)
+{
+ return csum16_add(a, csum16_complement(b));
+}
+
+static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)
+{
+ struct ip6t_npt_tginfo *npt = par->targinfo;
+ __sum16 src_sum = 0, dst_sum = 0;
+ unsigned int i;
+
+ if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) {
+ src_sum = csum16_add(src_sum,
+ (__force __sum16)npt->src_pfx.in6.s6_addr16[i]);
+ dst_sum = csum16_add(dst_sum,
+ (__force __sum16)npt->dst_pfx.in6.s6_addr16[i]);
+ }
+
+ npt->adjustment = csum16_sub(src_sum, dst_sum);
+ return 0;
+}
+
+static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
+ struct in6_addr *addr)
+{
+ unsigned int pfx_len;
+ unsigned int i, idx;
+ __be32 mask;
+ __sum16 sum;
+
+ pfx_len = max(npt->src_pfx_len, npt->dst_pfx_len);
+ for (i = 0; i < pfx_len; i += 32) {
+ if (pfx_len - i >= 32)
+ mask = 0;
+ else
+ mask = htonl(~((1 << (pfx_len - i)) - 1));
+
+ idx = i / 32;
+ addr->s6_addr32[idx] &= mask;
+ addr->s6_addr32[idx] |= npt->dst_pfx.in6.s6_addr32[idx];
+ }
+
+ if (pfx_len <= 48)
+ idx = 3;
+ else {
+ for (idx = 4; idx < ARRAY_SIZE(addr->s6_addr16); idx++) {
+ if ((__force __sum16)addr->s6_addr16[idx] !=
+ CSUM_MANGLED_0)
+ break;
+ }
+ if (idx == ARRAY_SIZE(addr->s6_addr16))
+ return false;
+ }
+
+ sum = csum16_add((__force __sum16)addr->s6_addr16[idx],
+ npt->adjustment);
+ if (sum == CSUM_MANGLED_0)
+ sum = 0;
+ *(__force __sum16 *)&addr->s6_addr16[idx] = sum;
+
+ return true;
+}
+
+static unsigned int
+ip6t_snpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct ip6t_npt_tginfo *npt = par->targinfo;
+
+ if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->saddr)) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
+ offsetof(struct ipv6hdr, saddr));
+ return NF_DROP;
+ }
+ return XT_CONTINUE;
+}
+
+static unsigned int
+ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct ip6t_npt_tginfo *npt = par->targinfo;
+
+ if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->daddr)) {
+ icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
+ offsetof(struct ipv6hdr, daddr));
+ return NF_DROP;
+ }
+ return XT_CONTINUE;
+}
+
+static struct xt_target ip6t_npt_target_reg[] __read_mostly = {
+ {
+ .name = "SNPT",
+ .target = ip6t_snpt_tg,
+ .targetsize = sizeof(struct ip6t_npt_tginfo),
+ .checkentry = ip6t_npt_checkentry,
+ .family = NFPROTO_IPV6,
+ .hooks = (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_POST_ROUTING),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "DNPT",
+ .target = ip6t_dnpt_tg,
+ .targetsize = sizeof(struct ip6t_npt_tginfo),
+ .checkentry = ip6t_npt_checkentry,
+ .family = NFPROTO_IPV6,
+ .hooks = (1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_LOCAL_OUT),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init ip6t_npt_init(void)
+{
+ return xt_register_targets(ip6t_npt_target_reg,
+ ARRAY_SIZE(ip6t_npt_target_reg));
+}
+
+static void __exit ip6t_npt_exit(void)
+{
+ xt_unregister_targets(ip6t_npt_target_reg,
+ ARRAY_SIZE(ip6t_npt_target_reg));
+}
+
+module_init(ip6t_npt_init);
+module_exit(ip6t_npt_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IPv6-to-IPv6 Network Prefix Translation (RFC 6296)");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS("ip6t_SNPT");
+MODULE_ALIAS("ip6t_DNPT");
--
1.7.1
^ permalink raw reply related
* [PATCH 06/19] netfilter: nf_conntrack_ipv6: fix tracking of ICMPv6 error messages containing fragments
From: kaber @ 2012-08-09 20:08 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
ICMPv6 error messages are tracked by extracting the conntrack tuple of
the inner packet and looking up the corresponding conntrack entry. Tuple
extraction uses the ->get_l4proto() callback, which in case of fragments
returns NEXTHDR_FRAGMENT instead of the upper protocol, even for the
first fragment when the entire next header is present, resulting in a
failure to find the correct connection tracking entry.
This patch changes ipv6_get_l4proto() to use ipv6_skip_exthdr() instead
of nf_ct_ipv6_skip_exthdr() in order to skip fragment headers when the
fragment offset is zero.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 63 ++---------------------
1 files changed, 6 insertions(+), 57 deletions(-)
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 560d823..4d92ea6 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -64,82 +64,31 @@ static int ipv6_print_tuple(struct seq_file *s,
tuple->src.u3.ip6, tuple->dst.u3.ip6);
}
-/*
- * Based on ipv6_skip_exthdr() in net/ipv6/exthdr.c
- *
- * This function parses (probably truncated) exthdr set "hdr"
- * of length "len". "nexthdrp" initially points to some place,
- * where type of the first header can be found.
- *
- * It skips all well-known exthdrs, and returns pointer to the start
- * of unparsable area i.e. the first header with unknown type.
- * if success, *nexthdr is updated by type/protocol of this header.
- *
- * NOTES: - it may return pointer pointing beyond end of packet,
- * if the last recognized header is truncated in the middle.
- * - if packet is truncated, so that all parsed headers are skipped,
- * it returns -1.
- * - if packet is fragmented, return pointer of the fragment header.
- * - ESP is unparsable for now and considered like
- * normal payload protocol.
- * - Note also special handling of AUTH header. Thanks to IPsec wizards.
- */
-
-static int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
- u8 *nexthdrp, int len)
-{
- u8 nexthdr = *nexthdrp;
-
- while (ipv6_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr hdr;
- int hdrlen;
-
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return -1;
- if (nexthdr == NEXTHDR_NONE)
- break;
- if (nexthdr == NEXTHDR_FRAGMENT)
- break;
- if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
- BUG();
- if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr.hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(&hdr);
-
- nexthdr = hdr.nexthdr;
- len -= hdrlen;
- start += hdrlen;
- }
-
- *nexthdrp = nexthdr;
- return start;
-}
-
static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
unsigned int *dataoff, u_int8_t *protonum)
{
unsigned int extoff = nhoff + sizeof(struct ipv6hdr);
- unsigned char pnum;
+ __be16 frag_off;
int protoff;
+ u8 nexthdr;
if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr),
- &pnum, sizeof(pnum)) != 0) {
+ &nexthdr, sizeof(nexthdr)) != 0) {
pr_debug("ip6_conntrack_core: can't get nexthdr\n");
return -NF_ACCEPT;
}
- protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff);
+ protoff = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_off);
/*
* (protoff == skb->len) mean that the packet doesn't have no data
* except of IPv6 & ext headers. but it's tracked anyway. - YK
*/
- if ((protoff < 0) || (protoff > skb->len)) {
+ if (protoff < 0 || (frag_off & ntohs(~0x7)) != 0) {
pr_debug("ip6_conntrack_core: can't find proto in pkt\n");
return -NF_ACCEPT;
}
*dataoff = protoff;
- *protonum = pnum;
+ *protonum = nexthdr;
return NF_ACCEPT;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 13/19] netfilter: ip6tables: add MASQUERADE target
From: kaber @ 2012-08-09 20:08 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
In-Reply-To: <1344542943-11588-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/net/addrconf.h | 2 +-
net/ipv4/netfilter/ipt_MASQUERADE.c | 3 +-
net/ipv6/addrconf.c | 2 +-
net/ipv6/netfilter/Kconfig | 12 +++
net/ipv6/netfilter/Makefile | 1 +
net/ipv6/netfilter/ip6t_MASQUERADE.c | 135 ++++++++++++++++++++++++++++++++++
6 files changed, 152 insertions(+), 3 deletions(-)
create mode 100644 net/ipv6/netfilter/ip6t_MASQUERADE.c
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 089a09d..9e63e76 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -78,7 +78,7 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
int strict);
extern int ipv6_dev_get_saddr(struct net *net,
- struct net_device *dev,
+ const struct net_device *dev,
const struct in6_addr *daddr,
unsigned int srcprefs,
struct in6_addr *saddr);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 1c3aa28..5d5d4d1 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -99,7 +99,8 @@ device_cmp(struct nf_conn *i, void *ifindex)
if (!nat)
return 0;
-
+ if (nf_ct_l3num(i) != NFPROTO_IPV4)
+ return 0;
return nat->masq_index == (int)(long)ifindex;
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7918181..6536404 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1095,7 +1095,7 @@ out:
return ret;
}
-int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
+int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
const struct in6_addr *daddr, unsigned int prefs,
struct in6_addr *saddr)
{
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index b27e0ad..54a5032 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -144,6 +144,18 @@ config IP6_NF_TARGET_HL
(e.g. when running oldconfig). It selects
CONFIG_NETFILTER_XT_TARGET_HL.
+config IP6_NF_TARGET_MASQUERADE
+ tristate "MASQUERADE target support"
+ depends on NF_NAT_IPV6
+ help
+ Masquerading is a special case of NAT: all outgoing connections are
+ changed to seem to come from a particular interface's address, and
+ if the interface goes down, those connections are lost. This is
+ only useful for dialup accounts with dynamic IP address (ie. your IP
+ address will be different on next dialup).
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP6_NF_FILTER
tristate "Packet filtering"
default m if NETFILTER_ADVANCED=n
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 7677937..068bad1 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -34,4 +34,5 @@ obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
# targets
+obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c
new file mode 100644
index 0000000..60e9053
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on Rusty Russell's IPv6 MASQUERADE target. Development of IPv6
+ * NAT funded by Astaro.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ipv6.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/x_tables.h>
+#include <net/netfilter/nf_nat.h>
+#include <net/addrconf.h>
+#include <net/ipv6.h>
+
+static unsigned int
+masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct nf_nat_range *range = par->targinfo;
+ enum ip_conntrack_info ctinfo;
+ struct in6_addr src;
+ struct nf_conn *ct;
+ struct nf_nat_range newrange;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
+ ctinfo == IP_CT_RELATED_REPLY));
+
+ if (ipv6_dev_get_saddr(dev_net(par->out), par->out,
+ &ipv6_hdr(skb)->daddr, 0, &src) < 0)
+ return NF_DROP;
+
+ nfct_nat(ct)->masq_index = par->out->ifindex;
+
+ newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
+ newrange.min_addr.in6 = src;
+ newrange.max_addr.in6 = src;
+ newrange.min_proto = range->min_proto;
+ newrange.max_proto = range->max_proto;
+
+ return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
+}
+
+static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
+{
+ const struct nf_nat_range *range = par->targinfo;
+
+ if (range->flags & NF_NAT_RANGE_MAP_IPS)
+ return -EINVAL;
+ return 0;
+}
+
+static int device_cmp(struct nf_conn *ct, void *ifindex)
+{
+ const struct nf_conn_nat *nat = nfct_nat(ct);
+
+ if (!nat)
+ return 0;
+ if (nf_ct_l3num(ct) != NFPROTO_IPV6)
+ return 0;
+ return nat->masq_index == (int)(long)ifindex;
+}
+
+static int masq_device_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ const struct net_device *dev = ptr;
+ struct net *net = dev_net(dev);
+
+ if (event == NETDEV_DOWN)
+ nf_ct_iterate_cleanup(net, device_cmp,
+ (void *)(long)dev->ifindex);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block masq_dev_notifier = {
+ .notifier_call = masq_device_event,
+};
+
+static int masq_inet_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct inet6_ifaddr *ifa = ptr;
+
+ return masq_device_event(this, event, ifa->idev->dev);
+}
+
+static struct notifier_block masq_inet_notifier = {
+ .notifier_call = masq_inet_event,
+};
+
+static struct xt_target masquerade_tg6_reg __read_mostly = {
+ .name = "MASQUERADE",
+ .family = NFPROTO_IPV6,
+ .checkentry = masquerade_tg6_checkentry,
+ .target = masquerade_tg6,
+ .targetsize = sizeof(struct nf_nat_range),
+ .table = "nat",
+ .hooks = 1 << NF_INET_POST_ROUTING,
+ .me = THIS_MODULE,
+};
+
+static int __init masquerade_tg6_init(void)
+{
+ int err;
+
+ err = xt_register_target(&masquerade_tg6_reg);
+ if (err == 0) {
+ register_netdevice_notifier(&masq_dev_notifier);
+ register_inet6addr_notifier(&masq_inet_notifier);
+ }
+
+ return err;
+}
+static void __exit masquerade_tg6_exit(void)
+{
+ unregister_inet6addr_notifier(&masq_inet_notifier);
+ unregister_netdevice_notifier(&masq_dev_notifier);
+ xt_unregister_target(&masquerade_tg6_reg);
+}
+
+module_init(masquerade_tg6_init);
+module_exit(masquerade_tg6_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Xtables: automatic address SNAT");
--
1.7.1
^ permalink raw reply related
* [PATCH 00/19] netfilter: IPv6 NAT
From: kaber @ 2012-08-09 20:08 UTC (permalink / raw)
To: netfilter-devel; +Cc: netdev
The following patches contain an updated version of IPv6 NAT against
Linus' current tree.
The series is organized as follows:
- Patches 01-03 contain bugfixes for SIP helper bugs/regressions
present in the current kernel
- Patches 04-06 improve conntrack fragmentation handling, the IPv6
parts are also a precondition for IPv6 NAT
- Patches 07 and 08 prepare the current NAT code for conversion to
an address family independant core, but contain no functional
changes
- Patch 09 adds the address family independant NAT core and converts
the existing IPv4-only NAT code to an AF-specific module
- Patches 10 and 11 add some infrastructure for IPv6 NAT
- Patch 12 adds IPv6 NAT support
- Patches 13-15 add IPv6 specific NAT targets
- Patches 16-19 add some IPv6-capable ports of existing NAT helpers
- Patch 19 is independant of the IPv6 NAT code and adds support for
stateless IPv6 prefix translation, just to relieve my conscience ;)
Since the last posting numerous bugs have been fixed, I don't remember
all of them, the more important ones include:
- automatic NAT module loading in ctnetlink
- address selection when mapping to IPv6 ranges
- handling of IPv6 fragments
- NAT handling of ICMPv6 error messages
Besides implementing IPv6 NAT, there are no known bugs left. Userspace
patches will follow shortly.
The entire patchset is also available at
git://github.com/kaber/nf-nat-ipv6.git master
Comments, questions and test results welcome.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox