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

Commit 2b4743bd authored by YOSHIFUJI Hideaki's avatar YOSHIFUJI Hideaki Committed by David S. Miller
Browse files

ipv6 sit: Avoid extra need for compat layer in PRL management.



We've introduced extra need of compat layer for ip_tunnel_prl{}
for PRL (Potential Router List) management.  Though compat_ioctl
is still missing in ipv4/ipv6, let's make the interface more
straight-forward and eliminate extra need for nasty compat layer
anyway since the interface is new for 2.6.26.

Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 47083fc0
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -41,7 +41,7 @@ struct ip_tunnel_prl {
	__u16			__reserved;
	__u16			__reserved;
	__u32			datalen;
	__u32			datalen;
	__u32			__reserved2;
	__u32			__reserved2;
	void __user		*data;
	/* data follows */
};
};


/* PRL flags */
/* PRL flags */
+24 −20
Original line number Original line Diff line number Diff line
@@ -222,15 +222,18 @@ __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)


}
}


static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
				struct ip_tunnel_prl __user *a)
{
{
	struct ip_tunnel_prl *kp;
	struct ip_tunnel_prl kprl, *kp;
	struct ip_tunnel_prl_entry *prl;
	struct ip_tunnel_prl_entry *prl;
	unsigned int cmax, c = 0, ca, len;
	unsigned int cmax, c = 0, ca, len;
	int ret = 0;
	int ret = 0;


	cmax = a->datalen / sizeof(*a);
	if (copy_from_user(&kprl, a, sizeof(kprl)))
	if (cmax > 1 && a->addr != htonl(INADDR_ANY))
		return -EFAULT;
	cmax = kprl.datalen / sizeof(kprl);
	if (cmax > 1 && kprl.addr != htonl(INADDR_ANY))
		cmax = 1;
		cmax = 1;


	/* For simple GET or for root users,
	/* For simple GET or for root users,
@@ -261,26 +264,25 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
	for (prl = t->prl; prl; prl = prl->next) {
	for (prl = t->prl; prl; prl = prl->next) {
		if (c > cmax)
		if (c > cmax)
			break;
			break;
		if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr)
		if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr)
			continue;
			continue;
		kp[c].addr = prl->addr;
		kp[c].addr = prl->addr;
		kp[c].flags = prl->flags;
		kp[c].flags = prl->flags;
		c++;
		c++;
		if (a->addr != htonl(INADDR_ANY))
		if (kprl.addr != htonl(INADDR_ANY))
			break;
			break;
	}
	}
out:
out:
	read_unlock(&ipip6_lock);
	read_unlock(&ipip6_lock);


	len = sizeof(*kp) * c;
	len = sizeof(*kp) * c;
	ret = len ? copy_to_user(a->data, kp, len) : 0;
	ret = 0;
	if ((len && copy_to_user(a + 1, kp, len)) || put_user(len, &a->datalen))
		ret = -EFAULT;


	kfree(kp);
	kfree(kp);
	if (ret)
		return -EFAULT;


	a->datalen = len;
	return ret;
	return 0;
}
}


static int
static int
@@ -873,11 +875,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
		break;
		break;


	case SIOCGETPRL:
	case SIOCGETPRL:
		err = -EINVAL;
		if (dev == sitn->fb_tunnel_dev)
			goto done;
		err = -ENOENT;
		if (!(t = netdev_priv(dev)))
			goto done;
		err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data);
		break;

	case SIOCADDPRL:
	case SIOCADDPRL:
	case SIOCDELPRL:
	case SIOCDELPRL:
	case SIOCCHGPRL:
	case SIOCCHGPRL:
		err = -EPERM;
		err = -EPERM;
		if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN))
		if (!capable(CAP_NET_ADMIN))
			goto done;
			goto done;
		err = -EINVAL;
		err = -EINVAL;
		if (dev == sitn->fb_tunnel_dev)
		if (dev == sitn->fb_tunnel_dev)
@@ -890,12 +901,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
			goto done;
			goto done;


		switch (cmd) {
		switch (cmd) {
		case SIOCGETPRL:
			err = ipip6_tunnel_get_prl(t, &prl);
			if (!err && copy_to_user(ifr->ifr_ifru.ifru_data,
						 &prl, sizeof(prl)))
				err = -EFAULT;
			break;
		case SIOCDELPRL:
		case SIOCDELPRL:
			err = ipip6_tunnel_del_prl(t, &prl);
			err = ipip6_tunnel_del_prl(t, &prl);
			break;
			break;
@@ -904,7 +909,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
			err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
			err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
			break;
			break;
		}
		}
		if (cmd != SIOCGETPRL)
		netdev_state_change(dev);
		netdev_state_change(dev);
		break;
		break;