nft: adapt chain rename to recent Patrick's updates

This patch gets existing code in sync with Patrick's chain
renaming new approach.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 837bab3..bdab3f2 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -73,11 +73,12 @@
 enum nft_chain_attributes {
 	NFTA_CHAIN_UNSPEC,
 	NFTA_CHAIN_TABLE,
+	NFTA_CHAIN_HANDLE,
 	NFTA_CHAIN_NAME,
 	NFTA_CHAIN_HOOK,
 	NFTA_CHAIN_POLICY,
 	NFTA_CHAIN_USE,
-	NFTA_CHAIN_NEW_NAME,
+	NFTA_CHAIN_TYPE,
 	__NFTA_CHAIN_MAX
 };
 #define NFTA_CHAIN_MAX		(__NFTA_CHAIN_MAX - 1)
diff --git a/iptables/nft.c b/iptables/nft.c
index 1f5ecb7..46c8c94 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1686,17 +1686,66 @@
 	return ret == 0 ? 1 : 0;
 }
 
+static struct nft_chain *
+nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
+{
+	struct nft_chain_list *list;
+	struct nft_chain_list_iter *iter;
+	struct nft_chain *c;
+
+	list = nft_chain_list_get(h);
+	if (list == NULL) {
+		DEBUGP("cannot allocate chain list\n");
+		return NULL;
+	}
+
+	iter = nft_chain_list_iter_create(list);
+	if (iter == NULL) {
+		DEBUGP("cannot allocate rule list iterator\n");
+		return NULL;
+	}
+
+	c = nft_chain_list_iter_next(iter);
+	while (c != NULL) {
+		const char *table_name =
+			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE);
+		const char *chain_name =
+			nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME);
+
+		if (strcmp(table, table_name) != 0)
+			goto next;
+
+		if (strcmp(chain, chain_name) != 0)
+			goto next;
+
+		return c;
+next:
+		c = nft_chain_list_iter_next(iter);
+	}
+	return NULL;
+}
+
 int nft_chain_user_rename(struct nft_handle *h,const char *chain,
 			  const char *table, const char *newname)
 {
 	char buf[MNL_SOCKET_BUFFER_SIZE];
 	struct nlmsghdr *nlh;
 	struct nft_chain *c;
+	uint64_t handle;
 	int ret;
 
 	/* If built-in chains don't exist for this table, create them */
 	nft_chain_builtin_init(h, table, NULL, NF_ACCEPT);
 
+	/* Find the old chain to be renamed */
+	c = nft_chain_find(h, table, chain);
+	if (c == NULL) {
+		errno = ENOENT;
+		return -1;
+	}
+	handle = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_HANDLE);
+
+	/* Now prepare the new name for the chain */
 	c = nft_chain_alloc();
 	if (c == NULL) {
 		DEBUGP("cannot allocate chain\n");
@@ -1704,11 +1753,11 @@
 	}
 
 	nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
-	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
-	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NEW_NAME, (char *)newname);
+	nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
+	nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
 
 	nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
-					NLM_F_ACK|NLM_F_REPLACE, h->seq);
+					NLM_F_ACK, h->seq);
 	nft_chain_nlmsg_build_payload(nlh, c);
 	nft_chain_free(c);