Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b8f7a40 authored by Roopa Prabhu's avatar Roopa Prabhu Committed by David S. Miller
Browse files

neighbour: fix nlmsg_pid in notifications



neigh notifications today carry pid 0 for nlmsg_pid
in all cases. This patch fixes it to carry calling process
pid when available. Applications (eg. quagga) rely on
nlmsg_pid to ignore notifications generated by their own
netlink operations. This patch follows the routing subsystem
which already sets this correctly.

Reported-by: default avatarVivek Venkatraman <vivek@cumulusnetworks.com>
Signed-off-by: default avatarRoopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7ada7ca5
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -314,7 +314,8 @@ static inline struct neighbour *neigh_create(struct neigh_table *tbl,
}
void neigh_destroy(struct neighbour *neigh);
int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags);
int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags,
		 u32 nlmsg_pid);
void __neigh_set_probe_once(struct neighbour *neigh);
void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
+2 −2
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
			entry->expires = jiffies - 1;
			/* force resolution or expiration */
			error = neigh_update(entry->neigh, NULL, NUD_NONE,
					     NEIGH_UPDATE_F_ADMIN);
					     NEIGH_UPDATE_F_ADMIN, 0);
			if (error)
				pr_crit("neigh_update failed with %d\n", error);
			goto out;
@@ -481,7 +481,7 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
		link_vcc(clip_vcc, entry);
	}
	error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
			     NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
			     NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN, 0);
	neigh_release(neigh);
	return error;
}
+18 −14
Original line number Diff line number Diff line
@@ -52,8 +52,9 @@ do { \
#define PNEIGH_HASHMASK		0xF

static void neigh_timer_handler(unsigned long arg);
static void __neigh_notify(struct neighbour *n, int type, int flags);
static void neigh_update_notify(struct neighbour *neigh);
static void __neigh_notify(struct neighbour *n, int type, int flags,
			   u32 pid);
static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid);
static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);

#ifdef CONFIG_PROC_FS
@@ -99,7 +100,7 @@ static void neigh_cleanup_and_release(struct neighbour *neigh)
	if (neigh->parms->neigh_cleanup)
		neigh->parms->neigh_cleanup(neigh);

	__neigh_notify(neigh, RTM_DELNEIGH, 0);
	__neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
	call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
	neigh_release(neigh);
}
@@ -948,7 +949,7 @@ static void neigh_timer_handler(unsigned long arg)
	}

	if (notify)
		neigh_update_notify(neigh);
		neigh_update_notify(neigh, 0);

	neigh_release(neigh);
}
@@ -1072,7 +1073,7 @@ static void neigh_update_hhs(struct neighbour *neigh)
 */

int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
		 u32 flags)
		 u32 flags, u32 nlmsg_pid)
{
	u8 old;
	int err;
@@ -1229,7 +1230,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
	write_unlock_bh(&neigh->lock);

	if (notify)
		neigh_update_notify(neigh);
		neigh_update_notify(neigh, nlmsg_pid);

	return err;
}
@@ -1260,7 +1261,7 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
						 lladdr || !dev->addr_len);
	if (neigh)
		neigh_update(neigh, lladdr, NUD_STALE,
			     NEIGH_UPDATE_F_OVERRIDE);
			     NEIGH_UPDATE_F_OVERRIDE, 0);
	return neigh;
}
EXPORT_SYMBOL(neigh_event_ns);
@@ -1638,7 +1639,8 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)

	err = neigh_update(neigh, NULL, NUD_FAILED,
			   NEIGH_UPDATE_F_OVERRIDE |
			   NEIGH_UPDATE_F_ADMIN);
			   NEIGH_UPDATE_F_ADMIN,
			   NETLINK_CB(skb).portid);
	neigh_release(neigh);

out:
@@ -1729,7 +1731,8 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
		neigh_event_send(neigh, NULL);
		err = 0;
	} else
		err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
		err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
				   NETLINK_CB(skb).portid);
	neigh_release(neigh);

out:
@@ -2229,10 +2232,10 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
	return -EMSGSIZE;
}

static void neigh_update_notify(struct neighbour *neigh)
static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
{
	call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
	__neigh_notify(neigh, RTM_NEWNEIGH, 0);
	__neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
}

static bool neigh_master_filtered(struct net_device *dev, int master_idx)
@@ -2830,7 +2833,8 @@ static inline size_t neigh_nlmsg_size(void)
	       + nla_total_size(4); /* NDA_PROBES */
}

static void __neigh_notify(struct neighbour *n, int type, int flags)
static void __neigh_notify(struct neighbour *n, int type, int flags,
			   u32 pid)
{
	struct net *net = dev_net(n->dev);
	struct sk_buff *skb;
@@ -2840,7 +2844,7 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
	if (skb == NULL)
		goto errout;

	err = neigh_fill_info(skb, n, 0, 0, type, flags);
	err = neigh_fill_info(skb, n, pid, 0, type, flags);
	if (err < 0) {
		/* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
		WARN_ON(err == -EMSGSIZE);
@@ -2856,7 +2860,7 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)

void neigh_app_ns(struct neighbour *n)
{
	__neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
	__neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
}
EXPORT_SYMBOL(neigh_app_ns);

+3 −3
Original line number Diff line number Diff line
@@ -872,7 +872,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
		    skb->pkt_type != PACKET_HOST)
			state = NUD_STALE;
		neigh_update(n, sha, state,
			     override ? NEIGH_UPDATE_F_OVERRIDE : 0);
			     override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
		neigh_release(n);
	}

@@ -1033,7 +1033,7 @@ static int arp_req_set(struct net *net, struct arpreq *r,
		err = neigh_update(neigh, (r->arp_flags & ATF_COM) ?
				   r->arp_ha.sa_data : NULL, state,
				   NEIGH_UPDATE_F_OVERRIDE |
				   NEIGH_UPDATE_F_ADMIN);
				   NEIGH_UPDATE_F_ADMIN, 0);
		neigh_release(neigh);
	}
	return err;
@@ -1084,7 +1084,7 @@ static int arp_invalidate(struct net_device *dev, __be32 ip)
		if (neigh->nud_state & ~NUD_NOARP)
			err = neigh_update(neigh, NULL, NUD_FAILED,
					   NEIGH_UPDATE_F_OVERRIDE|
					   NEIGH_UPDATE_F_ADMIN);
					   NEIGH_UPDATE_F_ADMIN, 0);
		neigh_release(neigh);
	}

+1 −1
Original line number Diff line number Diff line
@@ -732,7 +732,7 @@ void ndisc_update(const struct net_device *dev, struct neighbour *neigh,
		  const u8 *lladdr, u8 new, u32 flags, u8 icmp6_type,
		  struct ndisc_options *ndopts)
{
	neigh_update(neigh, lladdr, new, flags);
	neigh_update(neigh, lladdr, new, flags, 0);
	/* report ndisc ops about neighbour update */
	ndisc_ops_update(dev, neigh, flags, icmp6_type, ndopts);
}