diff mbox

[RFC] Allow ipv6 proxies and arp proxies be shown with ip

Message ID 1327484698-344265-1-git-send-email-antonz@parallels.com
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Tony Zelenoff Jan. 25, 2012, 9:44 a.m. UTC
When i trying to add neighbour proxy with ip and then show it -
nothing happens but the proxy really added and work inside kernel.
$ ip neigh add proxy 2001::1 dev eth0
$ ip -6 neigh show
$

This is intended, as was written here
http://www.uwsg.iu.edu/hypermail/linux/kernel/0110.2/index.html#523
But, ~11 years were passed and this command is still alive and useful.
Also ipv6 protocol bring new feature: ND proxy which i want to use.
It described in RFC 4389 Neighbor Discovery Proxies. So, from my
point of view, the ip utility must show all neighbour proxies added to it.
Arp proxies is discussable, but better to show them too.

To do it - the additional storage of neighbour proxies should be processed
and dumped to requestor same way as neighbour tables.

Unfortunately proper filling of proxy neighbour info is not possible in
case of compatibility with ip itself. Returning structure field which
store state of record is reached its 8 bits limit and new flag showing
proxy can't be added. And at this point i'm stucked a bit. The ip utility
must show that exact address is not just neighbour, but is a proxy. Can
somebody advice me how to do it? Or maybe the whole idea is not good at all,
if so - please tell me why.

Signed-off-by: Tony Zelenoff <antonz@parallels.com>
CC: davem@davemloft.net
CC: kuznet@ms2.inr.ac.ru
CC: netdev@vger.kernel.org
CC: xemul@parallels.com

---
 net/core/neighbour.c |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 79 insertions(+), 0 deletions(-)

Comments

Alexey Kuznetsov Jan. 25, 2012, 10:59 p.m. UTC | #1
On Wed, Jan 25, 2012 at 01:44:58PM +0400, Tony Zelenoff wrote:
> But, ~11 years were passed and this command is still alive and useful.

Indeed. :-)


> Unfortunately proper filling of proxy neighbour info is not possible in
> case of compatibility with ip itself. Returning structure field which
> store state of record is reached its 8 bits limit and new flag showing
> proxy can't be added.

It is not necessary, there exists flag NTF_PROXY in ndm_flags.



>		 And at this point i'm stucked a bit. The ip utility
> must show that exact address is not just neighbour, but is a proxy. Can
> somebody advice me how to do it? Or maybe the whole idea is not good at all,
> if so - please tell me why.

Apparently, ip utility requires some modifications as well.


However, it is necessary to preserve compatibility with older ip utility,
which could be confused seeing proxy entries in the same stream.


I see two variants:

1. On request to list proxy entries, ip utility could send request containing
   full ndmsg with NTF_PROXY set in ndm_flags. When kernel sees request without NTF_PROXY,
   it dumps normal neighbor table. When it sees NTF_PROXY, it dumps proxy table instead.

   From user viewpoint, "ip neigh list ..." works as usual, "ip neigh list proxy ..." will list
   proxy entries.

2. Adding RTM_*PNEIGH and the whole new set of "ip pneigh ..." commands.
   Logically, I would prefer this solution and, unless I was lazy 10 years ago, I would
   go this way. Unfortunately, this will break compatibility with existing
   "ip neigh add/del proxy ...", so that the kludge to intercept NTF_PROXY command in RTM_*NEIGH
   is still required and the solution loses half of its beauty.

So, seems #1 looks better.

Alexey
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller Jan. 26, 2012, 2:40 a.m. UTC | #2
From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Date: Thu, 26 Jan 2012 02:59:31 +0400

> I see two variants:
> 
> 1. On request to list proxy entries, ip utility could send request containing
>    full ndmsg with NTF_PROXY set in ndm_flags. When kernel sees request without NTF_PROXY,
>    it dumps normal neighbor table. When it sees NTF_PROXY, it dumps proxy table instead.
> 
>    From user viewpoint, "ip neigh list ..." works as usual, "ip neigh list proxy ..." will list
>    proxy entries.
> 
> 2. Adding RTM_*PNEIGH and the whole new set of "ip pneigh ..." commands.
>    Logically, I would prefer this solution and, unless I was lazy 10 years ago, I would
>    go this way. Unfortunately, this will break compatibility with existing
>    "ip neigh add/del proxy ...", so that the kludge to intercept NTF_PROXY command in RTM_*NEIGH
>    is still required and the solution loses half of its beauty.
> 
> So, seems #1 looks better.

Agreed.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 5ac07d3..73ea97e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2134,6 +2134,38 @@  nla_put_failure:
 	return -EMSGSIZE;
 }
 
+static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
+			    u32 pid, u32 seq, int type, unsigned int flags,
+			    struct neigh_table *tbl)
+{
+	struct nlmsghdr *nlh;
+	struct ndmsg *ndm;
+
+	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
+	if (nlh == NULL)
+		return -EMSGSIZE;
+
+	ndm = nlmsg_data(nlh);
+	ndm->ndm_family	 = tbl->family;
+	ndm->ndm_pad1    = 0;
+	ndm->ndm_pad2    = 0;
+	ndm->ndm_flags	 = pn->flags;
+	ndm->ndm_type	 = NDA_DST;
+	ndm->ndm_ifindex = pn->dev->ifindex;
+	/* Let proxy neighbour be disaplayed as permanent entry.
+	 * The problem: there is no space in u8 struct member
+	 * to create and set new flag like NUD_PROXY. */
+	ndm->ndm_state	 = NUD_PERMANENT;
+
+	NLA_PUT(skb, NDA_DST, tbl->key_len, pn->key);
+
+	return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
+}
+
 static void neigh_update_notify(struct neighbour *neigh)
 {
 	call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
@@ -2183,6 +2215,50 @@  out:
 	return rc;
 }
 
+static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
+			     struct netlink_callback *cb)
+{
+	struct pneigh_entry *n;
+	struct net *net = sock_net(skb->sk);
+	int rc, h, s_h = cb->args[3];
+	int idx, s_idx = idx = cb->args[4];
+
+	read_lock_bh(&tbl->lock);
+
+	for (h = 0; h <= PNEIGH_HASHMASK; h++) {
+		if (h < s_h)
+			continue;
+		if (h > s_h)
+			s_idx = 0;
+		for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
+			if (dev_net(n->dev) != net)
+				continue;
+			if (idx < s_idx)
+				goto next;
+
+			if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
+					    cb->nlh->nlmsg_seq,
+					    RTM_NEWNEIGH,
+					    NLM_F_MULTI, tbl) <= 0) {
+				read_unlock_bh(&tbl->lock);
+				rc = -1;
+				goto out;
+			}
+
+		next:
+			idx++;
+		}
+	}
+
+	read_unlock_bh(&tbl->lock);
+	rc = skb->len;
+out:
+	cb->args[3] = h;
+	cb->args[4] = idx;
+	return rc;
+
+}
+
 static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct neigh_table *tbl;
@@ -2200,6 +2276,9 @@  static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 						sizeof(cb->args[0]));
 		if (neigh_dump_table(tbl, skb, cb) < 0)
 			break;
+
+		if (pneigh_dump_table(tbl, skb, cb) < 0)
+			break;
 	}
 	read_unlock(&neigh_tbl_lock);