|
@@ -3,7 +3,7 @@
|
|
|
*
|
|
|
* (C) 2001 by Jay Schulist <jschlst@samba.org>,
|
|
|
* (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
|
|
|
- * (C) 2005,2007 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
|
+ * (C) 2005-2017 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
|
*
|
|
|
* Initial netfilter messages via netlink development funded and
|
|
|
* generally made possible by Network Robots, Inc. (www.networkrobots.com)
|
|
@@ -273,7 +273,7 @@ enum {
|
|
|
};
|
|
|
|
|
|
static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
|
- u16 subsys_id)
|
|
|
+ u16 subsys_id, u32 genid)
|
|
|
{
|
|
|
struct sk_buff *oskb = skb;
|
|
|
struct net *net = sock_net(skb->sk);
|
|
@@ -315,6 +315,12 @@ replay:
|
|
|
return kfree_skb(skb);
|
|
|
}
|
|
|
|
|
|
+ if (genid && ss->valid_genid && !ss->valid_genid(net, genid)) {
|
|
|
+ nfnl_unlock(subsys_id);
|
|
|
+ netlink_ack(oskb, nlh, -ERESTART);
|
|
|
+ return kfree_skb(skb);
|
|
|
+ }
|
|
|
+
|
|
|
while (skb->len >= nlmsg_total_size(0)) {
|
|
|
int msglen, type;
|
|
|
|
|
@@ -436,11 +442,20 @@ done:
|
|
|
kfree_skb(skb);
|
|
|
}
|
|
|
|
|
|
+static const struct nla_policy nfnl_batch_policy[NFNL_BATCH_MAX + 1] = {
|
|
|
+ [NFNL_BATCH_GENID] = { .type = NLA_U32 },
|
|
|
+};
|
|
|
+
|
|
|
static void nfnetlink_rcv_skb_batch(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
|
{
|
|
|
+ int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
|
|
|
+ struct nlattr *attr = (void *)nlh + min_len;
|
|
|
+ struct nlattr *cda[NFNL_BATCH_MAX + 1];
|
|
|
+ int attrlen = nlh->nlmsg_len - min_len;
|
|
|
struct nfgenmsg *nfgenmsg;
|
|
|
+ int msglen, err;
|
|
|
+ u32 gen_id = 0;
|
|
|
u16 res_id;
|
|
|
- int msglen;
|
|
|
|
|
|
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
|
|
|
if (msglen > skb->len)
|
|
@@ -450,6 +465,14 @@ static void nfnetlink_rcv_skb_batch(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
|
skb->len < NLMSG_HDRLEN + sizeof(struct nfgenmsg))
|
|
|
return;
|
|
|
|
|
|
+ err = nla_parse(cda, NFNL_BATCH_MAX, attr, attrlen, nfnl_batch_policy);
|
|
|
+ if (err < 0) {
|
|
|
+ netlink_ack(skb, nlh, err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (cda[NFNL_BATCH_GENID])
|
|
|
+ gen_id = ntohl(nla_get_be32(cda[NFNL_BATCH_GENID]));
|
|
|
+
|
|
|
nfgenmsg = nlmsg_data(nlh);
|
|
|
skb_pull(skb, msglen);
|
|
|
/* Work around old nft using host byte order */
|
|
@@ -458,7 +481,7 @@ static void nfnetlink_rcv_skb_batch(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
|
else
|
|
|
res_id = ntohs(nfgenmsg->res_id);
|
|
|
|
|
|
- nfnetlink_rcv_batch(skb, nlh, res_id);
|
|
|
+ nfnetlink_rcv_batch(skb, nlh, res_id, gen_id);
|
|
|
}
|
|
|
|
|
|
static void nfnetlink_rcv(struct sk_buff *skb)
|