]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add chain netlink messages to the batch
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 19 May 2014 10:21:23 +0000 (12:21 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 19 May 2014 10:21:25 +0000 (12:21 +0200)
This patch moves the chain netlink messages to the big netlink
batch that is sent to kernel-space.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/mnl.h
src/mnl.c
src/netlink.c

index f25dd533c237e5ff87e8fbbfee175008f4bd7bf7..a86da069bc2357a912c9dc7fa044c22acfcb0d54 100644 (file)
@@ -35,8 +35,12 @@ struct nft_rule_list *mnl_nft_rule_dump(struct mnl_socket *nf_sock,
 
 int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
                      unsigned int flags);
+int mnl_nft_chain_batch_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+                           unsigned int flags, uint32_t seq);
 int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
                          unsigned int flags);
+int mnl_nft_chain_batch_del(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+                           unsigned int flags, uint32_t seq);
 struct nft_chain_list *mnl_nft_chain_dump(struct mnl_socket *nf_sock,
                                          int family);
 int mnl_nft_chain_get(struct mnl_socket *nf_sock, struct nft_chain *nlc,
index 873d442c3d1ecdfebd004fd0e8828b7a90ae7df8..fc360a4bae0ccdedbf8e13855c08eb34de2dc269 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -420,6 +420,24 @@ int mnl_nft_chain_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
        return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
 }
 
+int mnl_nft_chain_batch_add(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+                           unsigned int flags, uint32_t seqnum)
+
+{
+       struct nlmsghdr *nlh;
+
+       nlh = nft_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
+                       NFT_MSG_NEWCHAIN,
+                       nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
+                       NLM_F_CREATE | flags, seqnum);
+       nft_chain_nlmsg_build_payload(nlh, nlc);
+
+       if (!mnl_nlmsg_batch_next(batch))
+               mnl_batch_page_add();
+
+       return 0;
+}
+
 int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
                         unsigned int flags)
 {
@@ -434,6 +452,23 @@ int mnl_nft_chain_delete(struct mnl_socket *nf_sock, struct nft_chain *nlc,
        return nft_mnl_talk(nf_sock, nlh, nlh->nlmsg_len, NULL, NULL);
 }
 
+int mnl_nft_chain_batch_del(struct mnl_socket *nf_sock, struct nft_chain *nlc,
+                           unsigned int flags, uint32_t seqnum)
+{
+       struct nlmsghdr *nlh;
+
+       nlh = nft_chain_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
+                       NFT_MSG_DELCHAIN,
+                       nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
+                       NLM_F_ACK, seqnum);
+       nft_chain_nlmsg_build_payload(nlh, nlc);
+
+       if (!mnl_nlmsg_batch_next(batch))
+               mnl_batch_page_add();
+
+       return 0;
+}
+
 static int chain_cb(const struct nlmsghdr *nlh, void *data)
 {
        struct nft_chain_list *nlc_list = data;
index f4c512cca54bf778df5d61952ea8007872c9826b..10a00fa8346b3b5e114230310238df562896f75c 100644 (file)
@@ -472,9 +472,10 @@ void netlink_dump_chain(struct nft_chain *nlc)
 #endif
 }
 
-int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
-                     const struct location *loc, const struct chain *chain,
-                     bool excl)
+static int netlink_add_chain_compat(struct netlink_ctx *ctx,
+                                   const struct handle *h,
+                                   const struct location *loc,
+                                   const struct chain *chain, bool excl)
 {
        struct nft_chain *nlc;
        int err;
@@ -498,8 +499,53 @@ int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
        return err;
 }
 
-int netlink_rename_chain(struct netlink_ctx *ctx, const struct handle *h,
-                        const struct location *loc, const char *name)
+static int netlink_add_chain_batch(struct netlink_ctx *ctx,
+                                  const struct handle *h,
+                                  const struct location *loc,
+                                  const struct chain *chain, bool excl)
+{
+       struct nft_chain *nlc;
+       int err;
+
+       nlc = alloc_nft_chain(h);
+       if (chain != NULL && chain->flags & CHAIN_F_BASECHAIN) {
+               nft_chain_attr_set_u32(nlc, NFT_CHAIN_ATTR_HOOKNUM,
+                                      chain->hooknum);
+               nft_chain_attr_set_u32(nlc, NFT_CHAIN_ATTR_PRIO,
+                                      chain->priority);
+               nft_chain_attr_set_str(nlc, NFT_CHAIN_ATTR_TYPE,
+                                      chain->type);
+       }
+       netlink_dump_chain(nlc);
+       err = mnl_nft_chain_batch_add(nf_sock, nlc, excl ? NLM_F_EXCL : 0,
+                                     ctx->seqnum);
+       nft_chain_free(nlc);
+
+       if (err < 0) {
+               netlink_io_error(ctx, loc, "Could not add chain: %s",
+                                strerror(errno));
+       }
+       return err;
+}
+
+int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
+                     const struct location *loc, const struct chain *chain,
+                     bool excl)
+{
+       int ret;
+
+       if (ctx->batch_supported)
+               ret = netlink_add_chain_batch(ctx, h, loc, chain, excl);
+       else
+               ret = netlink_add_chain_compat(ctx, h, loc, chain, excl);
+
+       return ret;
+}
+
+static int netlink_rename_chain_compat(struct netlink_ctx *ctx,
+                                      const struct handle *h,
+                                      const struct location *loc,
+                                      const char *name)
 {
        struct nft_chain *nlc;
        int err;
@@ -516,8 +562,43 @@ int netlink_rename_chain(struct netlink_ctx *ctx, const struct handle *h,
        return err;
 }
 
-int netlink_delete_chain(struct netlink_ctx *ctx, const struct handle *h,
-                        const struct location *loc)
+static int netlink_rename_chain_batch(struct netlink_ctx *ctx,
+                                     const struct handle *h,
+                                     const struct location *loc,
+                                     const char *name)
+{
+       struct nft_chain *nlc;
+       int err;
+
+       nlc = alloc_nft_chain(h);
+       nft_chain_attr_set_str(nlc, NFT_CHAIN_ATTR_NAME, name);
+       netlink_dump_chain(nlc);
+       err = mnl_nft_chain_batch_add(nf_sock, nlc, 0, ctx->seqnum);
+       nft_chain_free(nlc);
+
+       if (err < 0) {
+               netlink_io_error(ctx, loc, "Could not rename chain: %s",
+                                strerror(errno));
+       }
+       return err;
+}
+
+int netlink_rename_chain(struct netlink_ctx *ctx, const struct handle *h,
+                        const struct location *loc, const char *name)
+{
+       int ret;
+
+       if (ctx->batch_supported)
+               ret = netlink_rename_chain_batch(ctx, h, loc, name);
+       else
+               ret = netlink_rename_chain_compat(ctx, h, loc, name);
+
+       return ret;
+}
+
+static int netlink_del_chain_compat(struct netlink_ctx *ctx,
+                                   const struct handle *h,
+                                   const struct location *loc)
 {
        struct nft_chain *nlc;
        int err;
@@ -527,12 +608,45 @@ int netlink_delete_chain(struct netlink_ctx *ctx, const struct handle *h,
        err = mnl_nft_chain_delete(nf_sock, nlc, 0);
        nft_chain_free(nlc);
 
-       if (err < 0)
+       if (err < 0) {
+               netlink_io_error(ctx, loc, "Could not delete chain: %s",
+                                strerror(errno));
+       }
+       return err;
+}
+
+static int netlink_del_chain_batch(struct netlink_ctx *ctx,
+                                  const struct handle *h,
+                                  const struct location *loc)
+{
+       struct nft_chain *nlc;
+       int err;
+
+       nlc = alloc_nft_chain(h);
+       netlink_dump_chain(nlc);
+       err = mnl_nft_chain_batch_del(nf_sock, nlc, 0, ctx->seqnum);
+       nft_chain_free(nlc);
+
+       if (err < 0) {
                netlink_io_error(ctx, loc, "Could not delete chain: %s",
                                 strerror(errno));
+       }
        return err;
 }
 
+int netlink_delete_chain(struct netlink_ctx *ctx, const struct handle *h,
+                        const struct location *loc)
+{
+       int ret;
+
+       if (ctx->batch_supported)
+               ret = netlink_del_chain_batch(ctx, h, loc);
+       else
+               ret = netlink_del_chain_compat(ctx, h, loc);
+
+       return ret;
+}
+
 static struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
                                               struct nft_chain *nlc)
 {