*
* (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)
};
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);
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;
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)
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 */
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)