[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: ipv6 on sparc / 6in4



On Fri, Aug 02, 2002 at 03:31:48PM -0400, Tom 'spot' Callaway wrote:
> None of the tunneling works on sparc/sparc64. The ioctls are not
> implemented at all. I looked into fixing this a while back and decided
> it was low priority.

I fixed this one - There is still the unsolved problem of backward
compatibility of the userspace app but when you apply the attached
patch and recompile your "iproute" against the new kernel headers
you will get tunnels to work (Only sit tunnels tried). 

BTW: On sparc they should work just happy - On sparc64 you have the
problem of needing wrappers for the 32bit userspace -> 64 bit kernel
pointer arithmetic. The problem is that the SIOCADDTUNNEL and friends
are SIOCDEVPRIVATE ioctls which can't get a wrapper attached. I solved
that by making them their own non private ioctls.

diff -Nur -X /home/flo/.dontdiff linux-2.4.19/arch/sparc64/kernel/ioctl32.c linux-2.4.19.flo/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.19/arch/sparc64/kernel/ioctl32.c	Sat Aug  3 02:39:43 2002
+++ linux-2.4.19.flo/arch/sparc64/kernel/ioctl32.c	Tue Aug  6 15:29:09 2002
@@ -33,6 +33,7 @@
 #include <linux/if_ppp.h>
 #include <linux/if_pppox.h>
 #include <linux/if_tun.h>
+#include <linux/if_tunnel.h>
 #include <linux/mtio.h>
 #include <linux/cdrom.h>
 #include <linux/loop.h>
@@ -3881,6 +3882,63 @@
 	return ((0 == ret) ? 0 : -EFAULT);
 }	
 
+static int tunnel_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct	ifreq	ifr;
+	mm_segment_t	old_fs = get_fs();
+	int		err=-EFAULT;
+	u32		data;
+
+	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+
+	ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
+
+	if (!ifr.ifr_data)
+		return -EAGAIN;
+
+	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+	if (copy_from_user(ifr.ifr_data, (char *)A(data), sizeof(struct ip_tunnel_parm))) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+
+	if (err)
+		goto out;
+
+	switch(cmd) {
+	case SIOCGETTUNNEL:
+	case SIOCADDTUNNEL:
+	case SIOCCHGTUNNEL:
+		err=-EFAULT;
+
+		/* copy ifr64 back to the ifr32 in userspace and be  */
+		/* careful not to touch the ifr_data pointer which   */
+		/* we assume to be the last in the struct            */
+		if (copy_to_user((struct ifreq32 *)arg, &ifr,
+				sizeof(struct ifreq32) - sizeof(__kernel_caddr_t32)))
+			goto out;
+
+		if (copy_to_user((char *)A(data), ifr.ifr_data,
+				sizeof(struct ip_tunnel_parm)))
+			goto out;
+
+		err=0;
+
+		break;
+	}
+
+out:
+	free_page((unsigned long) ifr.ifr_data);
+	return err;
+}
+
+
 struct ioctl_trans {
 	unsigned int cmd;
 	unsigned int handler;
@@ -4654,6 +4712,10 @@
 HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl)
 HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
 HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
+HANDLE_IOCTL(SIOCADDTUNNEL, tunnel_ioctl) 
+HANDLE_IOCTL(SIOCCHGTUNNEL, tunnel_ioctl) 
+HANDLE_IOCTL(SIOCDELTUNNEL, tunnel_ioctl) 
+HANDLE_IOCTL(SIOCGETTUNNEL, tunnel_ioctl) 
 /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
diff -Nur -X /home/flo/.dontdiff linux-2.4.19/include/linux/if_tunnel.h linux-2.4.19.flo/include/linux/if_tunnel.h
--- linux-2.4.19/include/linux/if_tunnel.h	Sun Nov 30 23:00:38 1997
+++ linux-2.4.19.flo/include/linux/if_tunnel.h	Tue Aug  6 10:17:25 2002
@@ -1,10 +1,10 @@
 #ifndef _IF_TUNNEL_H_
 #define _IF_TUNNEL_H_
 
-#define SIOCGETTUNNEL   (SIOCDEVPRIVATE + 0)
-#define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)
-#define SIOCDELTUNNEL   (SIOCDEVPRIVATE + 2)
-#define SIOCCHGTUNNEL   (SIOCDEVPRIVATE + 3)
+#define SIOCGETTUNNEL_PRIV	(SIOCDEVPRIVATE + 0)
+#define SIOCADDTUNNEL_PRIV	(SIOCDEVPRIVATE + 1)
+#define SIOCDELTUNNEL_PRIV	(SIOCDEVPRIVATE + 2)
+#define SIOCCHGTUNNEL_PRIV	(SIOCDEVPRIVATE + 3)
 
 #define GRE_CSUM	__constant_htons(0x8000)
 #define GRE_ROUTING	__constant_htons(0x4000)
diff -Nur -X /home/flo/.dontdiff linux-2.4.19/include/linux/sockios.h linux-2.4.19.flo/include/linux/sockios.h
--- linux-2.4.19/include/linux/sockios.h	Wed Nov  7 23:39:36 2001
+++ linux-2.4.19.flo/include/linux/sockios.h	Tue Aug  6 10:17:25 2002
@@ -113,6 +113,13 @@
 #define SIOCBONDSLAVEINFOQUERY 0x8993   /* rtn info about slave state   */
 #define SIOCBONDINFOQUERY      0x8994	/* rtn info about bond state    */
 #define SIOCBONDCHANGEACTIVE   0x8995   /* update to a new active slave */
+
+/* tunnel calls */
+
+#define SIOCGETTUNNEL	0x8996
+#define SIOCADDTUNNEL	0x8997
+#define SIOCCHGTUNNEL	0x8998
+#define SIOCDELTUNNEL	0x8999
 			
 /* Device private ioctl calls */
 
diff -Nur -X /home/flo/.dontdiff linux-2.4.19/net/core/dev.c linux-2.4.19.flo/net/core/dev.c
--- linux-2.4.19/net/core/dev.c	Sat Aug  3 02:39:46 2002
+++ linux-2.4.19.flo/net/core/dev.c	Tue Aug  6 11:02:31 2002
@@ -2110,7 +2110,11 @@
 			    cmd == SIOCETHTOOL ||
 			    cmd == SIOCGMIIPHY ||
 			    cmd == SIOCGMIIREG ||
-			    cmd == SIOCSMIIREG) {
+			    cmd == SIOCSMIIREG ||
+			    cmd == SIOCGETTUNNEL ||
+			    cmd == SIOCADDTUNNEL ||
+			    cmd == SIOCCHGTUNNEL ||
+			    cmd == SIOCDELTUNNEL) {
 				if (dev->do_ioctl) {
 					if (!netif_device_present(dev))
 						return -ENODEV;
@@ -2181,7 +2185,8 @@
 		 *	- atomic and do not require locking.
 		 *	- return a value
 		 */
-		 
+
+		case SIOCGETTUNNEL:
 		case SIOCGIFFLAGS:
 		case SIOCGIFMETRIC:
 		case SIOCGIFMTU:
@@ -2209,6 +2214,8 @@
 		 *	- return a value
 		 */
 		 
+		case SIOCADDTUNNEL:
+		case SIOCCHGTUNNEL:
 		case SIOCETHTOOL:
 		case SIOCGMIIPHY:
 		case SIOCGMIIREG:
@@ -2235,6 +2242,7 @@
 		 *	- do not return a value
 		 */
 		 
+		case SIOCDELTUNNEL:
 		case SIOCSIFFLAGS:
 		case SIOCSIFMETRIC:
 		case SIOCSIFMTU:
diff -Nur -X /home/flo/.dontdiff linux-2.4.19/net/ipv4/ip_gre.c linux-2.4.19.flo/net/ipv4/ip_gre.c
--- linux-2.4.19/net/ipv4/ip_gre.c	Sat Aug  3 02:39:46 2002
+++ linux-2.4.19.flo/net/ipv4/ip_gre.c	Tue Aug  6 10:17:25 2002
@@ -908,6 +908,7 @@
 	MOD_INC_USE_COUNT;
 
 	switch (cmd) {
+	case SIOCGETTUNNEL_PRIV:
 	case SIOCGETTUNNEL:
 		t = NULL;
 		if (dev == &ipgre_fb_tunnel_dev) {
@@ -924,6 +925,8 @@
 			err = -EFAULT;
 		break;
 
+	case SIOCADDTUNNEL_PRIV:
+	case SIOCCHGTUNNEL_PRIV:
 	case SIOCADDTUNNEL:
 	case SIOCCHGTUNNEL:
 		err = -EPERM;
@@ -947,9 +950,11 @@
 		if (!(p.o_flags&GRE_KEY))
 			p.o_key = 0;
 
-		t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
+		t = ipgre_tunnel_locate(&p, (cmd == SIOCADDTUNNEL ||
+					cmd == SIOCADDTUNNEL_PRIV));
 
-		if (dev != &ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
+		if (dev != &ipgre_fb_tunnel_dev &&
+			(cmd == SIOCCHGTUNNEL || cmd == SIOCCHGTUNNEL_PRIV) &&
 		    t != &ipgre_fb_tunnel) {
 			if (t != NULL) {
 				if (t->dev != dev) {
@@ -984,7 +989,7 @@
 
 		if (t) {
 			err = 0;
-			if (cmd == SIOCCHGTUNNEL) {
+			if (cmd == SIOCCHGTUNNEL || cmd == SIOCCHGTUNNEL_PRIV) {
 				t->parms.iph.ttl = p.iph.ttl;
 				t->parms.iph.tos = p.iph.tos;
 				t->parms.iph.frag_off = p.iph.frag_off;
@@ -992,9 +997,11 @@
 			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
 				err = -EFAULT;
 		} else
-			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+			err = ((cmd == SIOCADDTUNNEL || cmd == SIOCADDTUNNEL_PRIV)
+					? -ENOBUFS : -ENOENT);
 		break;
 
+	case SIOCDELTUNNEL_PRIV:
 	case SIOCDELTUNNEL:
 		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
diff -Nur -X /home/flo/.dontdiff linux-2.4.19/net/ipv4/ipip.c linux-2.4.19.flo/net/ipv4/ipip.c
--- linux-2.4.19/net/ipv4/ipip.c	Sat Aug  3 02:39:46 2002
+++ linux-2.4.19.flo/net/ipv4/ipip.c	Tue Aug  6 11:06:14 2002
@@ -675,6 +675,7 @@
 	MOD_INC_USE_COUNT;
 
 	switch (cmd) {
+	case SIOCGETTUNNEL_PRIV:
 	case SIOCGETTUNNEL:
 		t = NULL;
 		if (dev == &ipip_fb_tunnel_dev) {
@@ -691,6 +692,8 @@
 			err = -EFAULT;
 		break;
 
+	case SIOCADDTUNNEL_PRIV:
+	case SIOCCHGTUNNEL_PRIV:
 	case SIOCADDTUNNEL:
 	case SIOCCHGTUNNEL:
 		err = -EPERM;
@@ -708,9 +711,11 @@
 		if (p.iph.ttl)
 			p.iph.frag_off |= __constant_htons(IP_DF);
 
-		t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
+		t = ipip_tunnel_locate(&p, (cmd == SIOCADDTUNNEL ||
+						cmd == SIOCADDTUNNEL_PRIV));
 
-		if (dev != &ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
+		if (dev != &ipip_fb_tunnel_dev &&
+			(cmd == SIOCCHGTUNNEL || cmd == SIOCCHGTUNNEL_PRIV) &&
 		    t != &ipip_fb_tunnel) {
 			if (t != NULL) {
 				if (t->dev != dev) {
@@ -736,7 +741,8 @@
 
 		if (t) {
 			err = 0;
-			if (cmd == SIOCCHGTUNNEL) {
+			if (cmd == SIOCCHGTUNNEL ||
+				cmd == SIOCCHGTUNNEL_PRIV) {
 				t->parms.iph.ttl = p.iph.ttl;
 				t->parms.iph.tos = p.iph.tos;
 				t->parms.iph.frag_off = p.iph.frag_off;
@@ -744,9 +750,11 @@
 			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
 				err = -EFAULT;
 		} else
-			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+			err = ((cmd == SIOCADDTUNNEL || cmd == SIOCADDTUNNEL_PRIV)
+					? -ENOBUFS : -ENOENT);
 		break;
 
+	case SIOCDELTUNNEL_PRIV:
 	case SIOCDELTUNNEL:
 		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
diff -Nur -X /home/flo/.dontdiff linux-2.4.19/net/ipv6/sit.c linux-2.4.19.flo/net/ipv6/sit.c
--- linux-2.4.19/net/ipv6/sit.c	Sat Aug  3 02:39:46 2002
+++ linux-2.4.19.flo/net/ipv6/sit.c	Tue Aug  6 11:06:38 2002
@@ -631,6 +631,7 @@
 	MOD_INC_USE_COUNT;
 
 	switch (cmd) {
+	case SIOCGETTUNNEL_PRIV:
 	case SIOCGETTUNNEL:
 		t = NULL;
 		if (dev == &ipip6_fb_tunnel_dev) {
@@ -647,6 +648,8 @@
 			err = -EFAULT;
 		break;
 
+	case SIOCADDTUNNEL_PRIV:
+	case SIOCCHGTUNNEL_PRIV:
 	case SIOCADDTUNNEL:
 	case SIOCCHGTUNNEL:
 		err = -EPERM;
@@ -664,9 +667,11 @@
 		if (p.iph.ttl)
 			p.iph.frag_off |= __constant_htons(IP_DF);
 
-		t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL);
+		t = ipip6_tunnel_locate(&p, (cmd == SIOCADDTUNNEL ||
+						cmd == SIOCADDTUNNEL_PRIV));
 
-		if (dev != &ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL &&
+		if (dev != &ipip6_fb_tunnel_dev &&
+			(cmd == SIOCCHGTUNNEL || cmd == SIOCCHGTUNNEL_PRIV) &&
 		    t != &ipip6_fb_tunnel) {
 			if (t != NULL) {
 				if (t->dev != dev) {
@@ -692,16 +697,19 @@
 
 		if (t) {
 			err = 0;
-			if (cmd == SIOCCHGTUNNEL) {
+			if (cmd == SIOCCHGTUNNEL ||
+				cmd == SIOCCHGTUNNEL_PRIV) {
 				t->parms.iph.ttl = p.iph.ttl;
 				t->parms.iph.tos = p.iph.tos;
 			}
 			if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
 				err = -EFAULT;
 		} else
-			err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT);
+			err = ((cmd == SIOCADDTUNNEL ||
+				cmd == SIOCADDTUNNEL_PRIV) ? -ENOBUFS : -ENOENT);
 		break;
 
+	case SIOCDELTUNNEL_PRIV:
 	case SIOCDELTUNNEL:
 		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))



-- 
Florian Lohoff                  flo@rfc822.org             +49-5201-669912
                        Heisenberg may have been here.

Attachment: pgpKtcQLgQfC4.pgp
Description: PGP signature


Reply to: