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

Commit 49e8a279 authored by Denis V. Lunev's avatar Denis V. Lunev Committed by David S. Miller
Browse files

[NETNS]: Process ARP in the context of the correct namespace.



Get namespace from a device and pass it to the routing engine. Enable
ARP packet processing and device notifiers after that.

Signed-off-by: default avatarDenis V. Lunev <den@openvz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2feb27db
Loading
Loading
Loading
Loading
+9 −14
Original line number Original line Diff line number Diff line
@@ -242,7 +242,7 @@ static int arp_constructor(struct neighbour *neigh)
		return -EINVAL;
		return -EINVAL;
	}
	}


	neigh->type = inet_addr_type(&init_net, addr);
	neigh->type = inet_addr_type(dev->nd_net, addr);


	parms = in_dev->arp_parms;
	parms = in_dev->arp_parms;
	__neigh_parms_put(neigh->parms);
	__neigh_parms_put(neigh->parms);
@@ -341,14 +341,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
	default:
	default:
	case 0:		/* By default announce any local IP */
	case 0:		/* By default announce any local IP */
		if (skb && inet_addr_type(&init_net, ip_hdr(skb)->saddr) == RTN_LOCAL)
		if (skb && inet_addr_type(dev->nd_net, ip_hdr(skb)->saddr) == RTN_LOCAL)
			saddr = ip_hdr(skb)->saddr;
			saddr = ip_hdr(skb)->saddr;
		break;
		break;
	case 1:		/* Restrict announcements of saddr in same subnet */
	case 1:		/* Restrict announcements of saddr in same subnet */
		if (!skb)
		if (!skb)
			break;
			break;
		saddr = ip_hdr(skb)->saddr;
		saddr = ip_hdr(skb)->saddr;
		if (inet_addr_type(&init_net, saddr) == RTN_LOCAL) {
		if (inet_addr_type(dev->nd_net, saddr) == RTN_LOCAL) {
			/* saddr should be known to target */
			/* saddr should be known to target */
			if (inet_addr_onlink(in_dev, target, saddr))
			if (inet_addr_onlink(in_dev, target, saddr))
				break;
				break;
@@ -424,7 +424,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
	int flag = 0;
	int flag = 0;
	/*unsigned long now; */
	/*unsigned long now; */


	if (ip_route_output_key(&init_net, &rt, &fl) < 0)
	if (ip_route_output_key(dev->nd_net, &rt, &fl) < 0)
		return 1;
		return 1;
	if (rt->u.dst.dev != dev) {
	if (rt->u.dst.dev != dev) {
		NET_INC_STATS_BH(LINUX_MIB_ARPFILTER);
		NET_INC_STATS_BH(LINUX_MIB_ARPFILTER);
@@ -477,7 +477,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)


	paddr = skb->rtable->rt_gateway;
	paddr = skb->rtable->rt_gateway;


	if (arp_set_predefined(inet_addr_type(&init_net, paddr), haddr, paddr, dev))
	if (arp_set_predefined(inet_addr_type(dev->nd_net, paddr), haddr, paddr, dev))
		return 0;
		return 0;


	n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
	n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
@@ -709,6 +709,7 @@ static int arp_process(struct sk_buff *skb)
	u16 dev_type = dev->type;
	u16 dev_type = dev->type;
	int addr_type;
	int addr_type;
	struct neighbour *n;
	struct neighbour *n;
	struct net *net = dev->nd_net;


	/* arp_rcv below verifies the ARP header and verifies the device
	/* arp_rcv below verifies the ARP header and verifies the device
	 * is ARP'able.
	 * is ARP'able.
@@ -804,7 +805,7 @@ static int arp_process(struct sk_buff *skb)
	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
	if (sip == 0) {
	if (sip == 0) {
		if (arp->ar_op == htons(ARPOP_REQUEST) &&
		if (arp->ar_op == htons(ARPOP_REQUEST) &&
		    inet_addr_type(&init_net, tip) == RTN_LOCAL &&
		    inet_addr_type(net, tip) == RTN_LOCAL &&
		    !arp_ignore(in_dev, sip, tip))
		    !arp_ignore(in_dev, sip, tip))
			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
				 dev->dev_addr, sha);
				 dev->dev_addr, sha);
@@ -834,7 +835,7 @@ static int arp_process(struct sk_buff *skb)
			goto out;
			goto out;
		} else if (IN_DEV_FORWARD(in_dev)) {
		} else if (IN_DEV_FORWARD(in_dev)) {
			    if (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
			    if (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
			     (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &init_net, &tip, dev, 0))) {
			     (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
				if (n)
				if (n)
					neigh_release(n);
					neigh_release(n);
@@ -864,7 +865,7 @@ static int arp_process(struct sk_buff *skb)
		 */
		 */
		if (n == NULL &&
		if (n == NULL &&
		    arp->ar_op == htons(ARPOP_REPLY) &&
		    arp->ar_op == htons(ARPOP_REPLY) &&
		    inet_addr_type(&init_net, sip) == RTN_UNICAST)
		    inet_addr_type(net, sip) == RTN_UNICAST)
			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
			n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
	}
	}


@@ -911,9 +912,6 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
{
{
	struct arphdr *arp;
	struct arphdr *arp;


	if (dev->nd_net != &init_net)
		goto freeskb;

	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
		goto freeskb;
		goto freeskb;
@@ -1198,9 +1196,6 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo
{
{
	struct net_device *dev = ptr;
	struct net_device *dev = ptr;


	if (dev->nd_net != &init_net)
		return NOTIFY_DONE;

	switch (event) {
	switch (event) {
	case NETDEV_CHANGEADDR:
	case NETDEV_CHANGEADDR:
		neigh_changeaddr(&arp_tbl, dev);
		neigh_changeaddr(&arp_tbl, dev);