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:
pgpfo5X0ZKggH.pgp
Description: PGP signature