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

Commit ca860fb3 authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller
Browse files

[NEIGH]: Convert neighbour table dumping to new netlink api



Also fixes skipping of already dumped neighbours.

Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6b3f8674
Loading
Loading
Loading
Loading
+74 −67
Original line number Diff line number Diff line
@@ -1597,56 +1597,59 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)

static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
{
	struct rtattr *nest = NULL;
	struct nlattr *nest;

	nest = RTA_NEST(skb, NDTA_PARMS);
	nest = nla_nest_start(skb, NDTA_PARMS);
	if (nest == NULL)
		return -ENOBUFS;

	if (parms->dev)
		RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);

	RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
	RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
	RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
	RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
	RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
	RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
	RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
	RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
		NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);

	NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
	NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
	NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
	NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
	NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
	NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
	NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
	NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
		      parms->base_reachable_time);
	RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
	RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
	RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
	RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
	RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
	RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
	NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
	NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
	NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
	NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
	NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
	NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);

	return RTA_NEST_END(skb, nest);
	return nla_nest_end(skb, nest);

rtattr_failure:
	return RTA_NEST_CANCEL(skb, nest);
nla_put_failure:
	return nla_nest_cancel(skb, nest);
}

static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
			      struct netlink_callback *cb)
static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
			      u32 pid, u32 seq, int type, int flags)
{
	struct nlmsghdr *nlh;
	struct ndtmsg *ndtmsg;

	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
			       NLM_F_MULTI);
	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
	if (nlh == NULL)
		return -ENOBUFS;

	ndtmsg = NLMSG_DATA(nlh);
	ndtmsg = nlmsg_data(nlh);

	read_lock_bh(&tbl->lock);
	ndtmsg->ndtm_family = tbl->family;
	ndtmsg->ndtm_pad1   = 0;
	ndtmsg->ndtm_pad2   = 0;

	RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
	RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
	RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
	RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
	RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
	NLA_PUT_STRING(skb, NDTA_NAME, tbl->id);
	NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
	NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
	NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
	NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);

	{
		unsigned long now = jiffies;
@@ -1665,7 +1668,7 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
			.ndtc_proxy_qlen	= tbl->proxy_queue.qlen,
		};

		RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
		NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
	}

	{
@@ -1690,55 +1693,50 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
			ndst.ndts_forced_gc_runs	+= st->forced_gc_runs;
		}

		RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
		NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
	}

	BUG_ON(tbl->parms.dev);
	if (neightbl_fill_parms(skb, &tbl->parms) < 0)
		goto rtattr_failure;
		goto nla_put_failure;

	read_unlock_bh(&tbl->lock);
	return NLMSG_END(skb, nlh);
	return nlmsg_end(skb, nlh);

rtattr_failure:
nla_put_failure:
	read_unlock_bh(&tbl->lock);
	return NLMSG_CANCEL(skb, nlh);
 
nlmsg_failure:
	return -1;
	return nlmsg_cancel(skb, nlh);
}

static int neightbl_fill_param_info(struct neigh_table *tbl,
static int neightbl_fill_param_info(struct sk_buff *skb,
				    struct neigh_table *tbl,
				    struct neigh_parms *parms,
				    struct sk_buff *skb,
				    struct netlink_callback *cb)
				    u32 pid, u32 seq, int type,
				    unsigned int flags)
{
	struct ndtmsg *ndtmsg;
	struct nlmsghdr *nlh;

	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
			       NLM_F_MULTI);
	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
	if (nlh == NULL)
		return -ENOBUFS;

	ndtmsg = NLMSG_DATA(nlh);
	ndtmsg = nlmsg_data(nlh);

	read_lock_bh(&tbl->lock);
	ndtmsg->ndtm_family = tbl->family;
	ndtmsg->ndtm_pad1   = 0;
	ndtmsg->ndtm_pad2   = 0;
	RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);

	if (neightbl_fill_parms(skb, parms) < 0)
		goto rtattr_failure;
	if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
	    neightbl_fill_parms(skb, parms) < 0)
		goto errout;

	read_unlock_bh(&tbl->lock);
	return NLMSG_END(skb, nlh);

rtattr_failure:
	return nlmsg_end(skb, nlh);
errout:
	read_unlock_bh(&tbl->lock);
	return NLMSG_CANCEL(skb, nlh);

nlmsg_failure:
	return -1;
	return nlmsg_cancel(skb, nlh);
}
 
static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
@@ -1905,34 +1903,43 @@ int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)

int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
{
	int idx, family;
	int s_idx = cb->args[0];
	int family, tidx, nidx = 0;
	int tbl_skip = cb->args[0];
	int neigh_skip = cb->args[1];
	struct neigh_table *tbl;

	family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
	family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;

	read_lock(&neigh_tbl_lock);
	for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) {
	for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
		struct neigh_parms *p;

		if (idx < s_idx || (family && tbl->family != family))
		if (tidx < tbl_skip || (family && tbl->family != family))
			continue;

		if (neightbl_fill_info(tbl, skb, cb) <= 0)
		if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).pid,
				       cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
				       NLM_F_MULTI) <= 0)
			break;

		for (++idx, p = tbl->parms.next; p; p = p->next, idx++) {
			if (idx < s_idx)
		for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) {
			if (nidx < neigh_skip)
				continue;

			if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0)
			if (neightbl_fill_param_info(skb, tbl, p,
						     NETLINK_CB(cb->skb).pid,
						     cb->nlh->nlmsg_seq,
						     RTM_NEWNEIGHTBL,
						     NLM_F_MULTI) <= 0)
				goto out;
		}

		neigh_skip = 0;
	}
out:
	read_unlock(&neigh_tbl_lock);
	cb->args[0] = idx;
	cb->args[0] = tidx;
	cb->args[1] = nidx;

	return skb->len;
}