From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Jan Engelhardt <jengelh@medozas.de>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [PATCH 3/7] netfilter: xtables2: chain creation and deletion
Date: Tue, 14 Feb 2012 12:07:12 +0100 [thread overview]
Message-ID: <20120214110712.GA27221@1984> (raw)
In-Reply-To: <1326990381-14534-4-git-send-email-jengelh@medozas.de>
On Thu, Jan 19, 2012 at 05:26:17PM +0100, Jan Engelhardt wrote:
[...]
> diff --git a/net/netfilter/xt2_nfnetlink.c b/net/netfilter/xt2_nfnetlink.c
> index 3dc241f..b50e468d 100644
> --- a/net/netfilter/xt2_nfnetlink.c
> +++ b/net/netfilter/xt2_nfnetlink.c
> @@ -17,6 +17,7 @@
> #include <linux/netfilter/nfnetlink.h>
> #include <linux/netfilter/nfnetlink_xtables.h>
> #include <net/netlink.h>
> +#include <net/sock.h>
> #include <net/netfilter/x_tables2.h>
>
> MODULE_DESCRIPTION("Xtables2 nfnetlink interface");
> @@ -69,6 +70,66 @@ xtnetlink_fill(struct sk_buff *skb, const struct xtnetlink_pktref *old,
> }
>
> /**
> + * @ref: skb/nl pointers that will be filled in (secondary return values)
> + * @old: pointers to the original incoming skb/nl headers
> + *
> + * xtnetlink_fill can be used when the outgoing skb already exists (e.g. in
> + * case of a dump operation), but for non-dump responses, we have to create it
> + * ourselves.
> + */
> +static int
> +xtnetlink_new_fill(struct xtnetlink_pktref *ref,
> + const struct xtnetlink_pktref *old)
> +{
> + ref->skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
> + if (ref->skb == NULL)
> + return -ENOMEM;
> + ref->msg = xtnetlink_fill(ref->skb, old, 0);
> + if (IS_ERR(ref->msg)) {
> + kfree_skb(ref->skb);
> + return PTR_ERR(ref->msg);
> + }
> + return 0;
> +}
> +
> +/**
> + * @xtnl: socket to send the error packet out on
> + * @old: pointers to the original incoming skb/nl headers
> + * @errcode: last error code
> + *
> + * Create and send out an NFXT error packet. If @errcode is < 0, it indicates
> + * a system-level error (such as %-ENOMEM), reported back using %NFXTA_ERRNO.
> + * If @errcode is >= 0, it indicates an NFXT-specific error codes (%NFXTE_*),
> + * which is more fine grained than the dreaded %EINVAL, and which is reported
> + * back using %NFXTA_XTERRNO.
> + */
> +static int
> +xtnetlink_error(struct sock *xtnl, const struct xtnetlink_pktref *old,
> + int errcode)
> +{
> + struct xtnetlink_pktref ref;
> + int ret;
> +
> + ret = xtnetlink_new_fill(&ref, old);
> + if (ret < 0)
> + return ret;
> + if (errcode < 0)
> + /* Prefer positive numbers on the wire */
> + NLA_PUT_U32(ref.skb, NFXTA_ERRNO, -errcode);
> + else
> + NLA_PUT_U32(ref.skb, NFXTA_XTERRNO, errcode);
> + nlmsg_end(ref.skb, ref.msg);
> + ret = netlink_unicast(xtnl, ref.skb, NETLINK_CB(old->skb).pid,
> + MSG_DONTWAIT);
> + if (ret < 0)
> + return ret;
> + /* ret is skb->len, but values >0 mean error to the caller -.- */
> + return 0;
> + nla_put_failure:
> + return -ENOBUFS;
> +}
You seem to be using some similar approach that ipset uses for error
handling. I like the idea of having fine grain error handling indeed,
but I think we can extend the Netlink framework to integrate as part
of NLMSG_ERR message types.
My idea is to attach the specific error at the end of the NLMSG_ERR,
IIRC we need to allow passing one callback to netlink_ack to add the
specific error message after the generic netlink error message.
I think this will be also backward compatible with existing netlink
library since they will ignore the trailing part of the error message
that they don't know how to interpret.
> +static int
> +xtnetlink_chain_new(struct sock *xtnl, struct sk_buff *iskb,
> + const struct nlmsghdr *imsg, const struct nlattr *const *ad)
> +{
> + struct xt2_pernet_data *pnet = xtables2_pernet(sock_net(xtnl));
> + struct xtnetlink_pktref ref = {.c_skb = iskb, .c_msg = imsg};
> + const struct nlattr *attr;
> + struct xt2_table *table;
> + struct xt2_chain *chain;
> + const char *name;
> + int ret = 0;
> +
> + attr = nlmsg_find_attr(imsg, sizeof(struct nfgenmsg), NFXTA_NAME);
> + if (attr == NULL)
> + return xtnetlink_error(xtnl, &ref, NFXTE_ATTRSET_INCOMPLETE);
> + name = nla_data(attr);
> + if (*name == '\0')
I think you may better identify this special chains with some flags?
You end up defining flags for objects sooner or later instead of using
this special name.
> + /* Anonymous chains are internal. */
> + return xtnetlink_error(xtnl, &ref, NFXTE_CHAIN_INVALID_NAME);
> + /*
> + * The table needs to stay, but note that rcu_read_lock cannot be used,
> + * since we might sleep.
> + */
> + mutex_lock(&pnet->master_lock);
> + table = pnet->master;
> + mutex_lock(&table->lock);
> + if (xt2_chain_lookup(table, name) != NULL) {
> + ret = xtnetlink_error(xtnl, &ref, NFXTE_CHAIN_EXISTS);
> + } else {
> + chain = xt2_chain_new(table, name);
> + if (IS_ERR(chain))
> + ret = PTR_ERR(chain);
> + /* Use NFXTE error codes whenever possible. */
> + if (ret == -ENAMETOOLONG)
> + ret = NFXTE_CHAIN_NAMETOOLONG;
> + ret = xtnetlink_error(xtnl, &ref, ret);
> + }
> + mutex_unlock(&table->lock);
> + mutex_unlock(&pnet->master_lock);
> + return ret;
> +}
> +
> +/**
> + * Act on a %NFXTM_CHAIN_DEL message.
> + */
> +static int
> +xtnetlink_chain_del(struct sock *xtnl, struct sk_buff *iskb,
> + const struct nlmsghdr *imsg,
> + const struct nlattr *const *ad)
> +{
> + struct xt2_pernet_data *pnet = xtables2_pernet(sock_net(xtnl));
> + struct xtnetlink_pktref ref = {.c_skb = iskb, .c_msg = imsg};
> + const struct nlattr *name_attr;
> + struct xt2_table *table;
> + struct xt2_chain *chain;
> + const char *name;
> + int ret = 0;
> +
> + name_attr = nlmsg_find_attr(imsg, sizeof(struct nfgenmsg), NFXTA_NAME);
> + if (name_attr == NULL)
> + return xtnetlink_error(xtnl, &ref, NFXTE_ATTRSET_INCOMPLETE);
> + name = nla_data(name_attr);
> + if (*name == '\0')
> + return xtnetlink_error(xtnl, &ref, NFXTE_CHAIN_NOENT);
> +
> + mutex_lock(&pnet->master_lock);
> + table = pnet->master;
> + mutex_lock(&table->lock);
> + chain = xt2_chain_lookup(table, name);
> + if (chain != NULL)
> + xt2_chain_free(chain);
> + else
> + ret = NFXTE_CHAIN_NOENT;
> + ret = xtnetlink_error(xtnl, &ref, ret);
> + mutex_unlock(&table->lock);
> + mutex_unlock(&pnet->master_lock);
> + return ret;
> +}
> +
> static const struct nla_policy xtnetlink_policy[] = {
> [NFXTA_NAME] = {.type = NLA_NUL_STRING},
> + [NFXTA_ERRNO] = {.type = NLA_U32},
> + [NFXTA_XTERRNO] = {.type = NLA_U32},
> };
>
> /*
> * Use the same policy for all messages. I do not want to see EINVAL anytime
> * soon again just because I forgot sending an attribute from userspace.
> - * (If such occurs, it will be dealt with %NFXTE_ATTRSET_INCOMPLETE, tbd.)
> + * (If such occurs, it will be dealt with %NFXTE_ATTRSET_INCOMPLETE.)
> */
> #define pol \
> .policy = xtnetlink_policy, \
> @@ -128,6 +270,8 @@ static const struct nla_policy xtnetlink_policy[] = {
> static const struct nfnl_callback xtnetlink_callback[] = {
> [0] = {.call = xtnetlink_ignore},
> [NFXTM_IDENTIFY] = {.call = xtnetlink_identify, pol},
> + [NFXTM_CHAIN_NEW] = {.call = xtnetlink_chain_new, pol},
> + [NFXTM_CHAIN_DEL] = {.call = xtnetlink_chain_del, pol},
> };
> #undef pol
>
> --
> 1.7.7
>
next prev parent reply other threads:[~2012-02-14 11:07 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-19 16:26 xtables2 a8, netlink interface Jan Engelhardt
2012-01-19 16:26 ` [PATCH 1/7] netfilter: xtables2: initial table skeletal functions Jan Engelhardt
2012-01-20 0:23 ` Pablo Neira Ayuso
2012-01-20 9:23 ` Jan Engelhardt
2012-01-19 16:26 ` [PATCH 2/7] netfilter: xtables2: initial Netlink interface Jan Engelhardt
2012-02-14 10:47 ` Pablo Neira Ayuso
2012-02-14 15:56 ` Jan Engelhardt
2012-02-14 19:53 ` Pablo Neira Ayuso
2012-01-19 16:26 ` [PATCH 3/7] netfilter: xtables2: chain creation and deletion Jan Engelhardt
2012-02-14 11:07 ` Pablo Neira Ayuso [this message]
2012-01-19 16:26 ` [PATCH 4/7] netfilter: xtables2: chain renaming support Jan Engelhardt
2012-01-19 16:26 ` [PATCH 5/7] netfilter: xtables2: initial table replace support Jan Engelhardt
2012-01-19 16:26 ` [PATCH 6/7] netfilter: xtables2: transaction abort support Jan Engelhardt
2012-01-19 16:26 ` [PATCH 7/7] netfilter: xtables2: redirect writes into transaction buffer Jan Engelhardt
2012-01-20 0:56 ` xtables2 a8, netlink interface Stephen Hemminger
2012-01-20 8:33 ` Jan Engelhardt
2012-01-20 9:23 ` Dave Taht
2012-01-20 16:50 ` Stephen Hemminger
2012-01-21 14:10 ` Jozsef Kadlecsik
2012-01-21 15:53 ` Jan Engelhardt
2012-01-21 20:21 ` Jozsef Kadlecsik
2012-01-23 15:42 ` Jan Engelhardt
2012-01-23 19:48 ` Jozsef Kadlecsik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120214110712.GA27221@1984 \
--to=pablo@netfilter.org \
--cc=jengelh@medozas.de \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).