Commit b6544c0b authored by Jamal Hadi Salim's avatar Jamal Hadi Salim Committed by David S. Miller
Browse files

[NETLINK]: Correctly set NLM_F_MULTI without checking the pid



This patch rectifies some rtnetlink message builders that derive the
flags from the pid. It is now explicit like the other cases
which get it right. Also fixes half a dozen dumpers which did not
set NLM_F_MULTI at all.

Signed-off-by: default avatarJamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1797754e
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -1859,18 +1859,17 @@ out:
}

static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
			   u32 pid, u32 seq, int event)
			   u32 pid, u32 seq, int event, unsigned int flags)
{
	unsigned long now = jiffies;
	unsigned char *b = skb->tail;
	struct nda_cacheinfo ci;
	int locked = 0;
	u32 probes;
	struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, event,
					 sizeof(struct ndmsg));
	struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event,
					 sizeof(struct ndmsg), flags);
	struct ndmsg *ndm = NLMSG_DATA(nlh);

	nlh->nlmsg_flags = pid ? NLM_F_MULTI : 0;
	ndm->ndm_family	 = n->ops->family;
	ndm->ndm_flags	 = n->flags;
	ndm->ndm_type	 = n->type;
@@ -1920,7 +1919,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
				continue;
			if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
					    cb->nlh->nlmsg_seq,
					    RTM_NEWNEIGH) <= 0) {
					    RTM_NEWNEIGH,
					    NLM_F_MULTI) <= 0) {
				read_unlock_bh(&tbl->lock);
				rc = -1;
				goto out;
@@ -2329,7 +2329,7 @@ void neigh_app_ns(struct neighbour *n)
	if (!skb)
		return;

	if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH) < 0) {
	if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) {
		kfree_skb(skb);
		return;
	}
@@ -2348,7 +2348,7 @@ static void neigh_app_notify(struct neighbour *n)
	if (!skb)
		return;

	if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH) < 0) {
	if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) {
		kfree_skb(skb);
		return;
	}
+8 −5
Original line number Diff line number Diff line
@@ -178,14 +178,14 @@ rtattr_failure:


static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
				 int type, u32 pid, u32 seq, u32 change)
				 int type, u32 pid, u32 seq, u32 change, 
				 unsigned int flags)
{
	struct ifinfomsg *r;
	struct nlmsghdr  *nlh;
	unsigned char	 *b = skb->tail;

	nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
	nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
	r = NLMSG_DATA(nlh);
	r->ifi_family = AF_UNSPEC;
	r->ifi_type = dev->type;
@@ -275,7 +275,10 @@ static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *c
	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
		if (idx < s_idx)
			continue;
		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
					  NETLINK_CB(cb->skb).pid,
					  cb->nlh->nlmsg_seq, 0,
					  NLM_F_MULTI) <= 0)
			break;
	}
	read_unlock(&dev_base_lock);
@@ -449,7 +452,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
	if (!skb)
		return;

	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) {
	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) {
		kfree_skb(skb);
		return;
	}
+5 −4
Original line number Diff line number Diff line
@@ -716,13 +716,13 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
}

static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
				u32 pid, u32 seq, int event)
				u32 pid, u32 seq, int event, unsigned int flags)
{
	struct ifaddrmsg *ifm;
	struct nlmsghdr *nlh;
	unsigned char *b = skb->tail;

	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
	ifm = NLMSG_DATA(nlh);

	ifm->ifa_family = AF_DECnet;
@@ -755,7 +755,7 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
		netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
		return;
	}
	if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
	if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
		kfree_skb(skb);
		netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
		return;
@@ -790,7 +790,8 @@ static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
			if (dn_dev_fill_ifaddr(skb, ifa,
					       NETLINK_CB(cb->skb).pid,
					       cb->nlh->nlmsg_seq,
					       RTM_NEWADDR) <= 0)
					       RTM_NEWADDR,
					       NLM_F_MULTI) <= 0)
				goto done;
		}
	}
+6 −5
Original line number Diff line number Diff line
@@ -1465,7 +1465,8 @@ int dn_route_input(struct sk_buff *skb)
	return dn_route_input_slow(skb);
}

static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
			   int event, int nowait, unsigned int flags)
{
	struct dn_route *rt = (struct dn_route *)skb->dst;
	struct rtmsg *r;
@@ -1473,9 +1474,8 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int
	unsigned char *b = skb->tail;
	struct rta_cacheinfo ci;

	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
	r = NLMSG_DATA(nlh);
	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
	r->rtm_family = AF_DECnet;
	r->rtm_dst_len = 16;
	r->rtm_src_len = 0;
@@ -1596,7 +1596,7 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)

	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

	err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
	err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);

	if (err == 0)
		goto out_free;
@@ -1644,7 +1644,8 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
				continue;
			skb->dst = dst_clone(&rt->u.dst);
			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 
					1, NLM_F_MULTI) <= 0) {
				dst_release(xchg(&skb->dst, NULL));
				rcu_read_unlock_bh();
				goto done;
+4 −3
Original line number Diff line number Diff line
@@ -342,14 +342,15 @@ static struct notifier_block dn_fib_rules_notifier = {
	.notifier_call =	dn_fib_rules_event,
};

static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r, struct netlink_callback *cb)
static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r,
			    struct netlink_callback *cb, unsigned int flags)
{
	struct rtmsg *rtm;
	struct nlmsghdr *nlh;
	unsigned char *b = skb->tail;


	nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
	rtm = NLMSG_DATA(nlh);
	rtm->rtm_family = AF_DECnet;
	rtm->rtm_dst_len = r->r_dst_len;
@@ -394,7 +395,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
	for(r = dn_fib_rules, idx = 0; r; r = r->r_next, idx++) {
		if (idx < s_idx)
			continue;
		if (dn_fib_fill_rule(skb, r, cb) < 0)
		if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
			break;
	}
	read_unlock(&dn_fib_rules_lock);
Loading