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: Vivek Venkatraman <vivek@cumulusnetworks.com> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7ada7ca562
commit
7b8f7a402d
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 @@ out:
|
|||
}
|
||||
|
||||
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 @@ out:
|
|||
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 @@ nla_put_failure:
|
|||
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 @@ errout:
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue