Re: cloneable tun
unit = 13; if ((fd = open(/dev/tun0, O_RDONLY)) == -1) err(1, failed to open /dev/tun0); if (ioctl(fd, TUNSIFUNIT, unit) == -1) err(1, ioctl failed); I like it. I've got a few questions from npppd and openvpn users hitting the 4 tun limit, and think it would make more sense to to write code that dynamically creates tun interfaces (in C/C++ progs such as the mentioned) if you didn't have to use system() or something like if (stat(node, _stat) == 0) continue; dev_t dev = makedev(40, i); // from MAKEDEV :( if (mknod(node, 0600 | S_IFCHR, dev) 0) // from MAKEDEV :( syslog(LOG_ERR, mknod %s: %m, node); chown(node, 0, 0); but rather the ioctl example above.
Re: cloneable tun
dev_t dev = makedev(40, i); // from MAKEDEV :( 40 is incorrect. It is MD. /usr/src/etc/etc.alpha/MAKEDEV: M tun$U c 7 $U 600 /usr/src/etc/etc.amd64/MAKEDEV: M tun$U c 40 $U 600 /usr/src/etc/etc.armish/MAKEDEV:M tun$U c 33 $U 600 /usr/src/etc/etc.aviion/MAKEDEV:M tun$U c 23 $U 600 /usr/src/etc/etc.beagle/MAKEDEV:M tun$U c 33 $U 600 /usr/src/etc/etc.hp300/MAKEDEV: M tun$U c 23 $U 600 /usr/src/etc/etc.hppa/MAKEDEV: M tun$U c 18 $U 600 /usr/src/etc/etc.hppa64/MAKEDEV:M tun$U c 18 $U 600 /usr/src/etc/etc.i386/MAKEDEV: M tun$U c 40 $U 600 /usr/src/etc/etc.landisk/MAKEDEV: M tun$U c 33 $U 600 /usr/src/etc/etc.loongson/MAKEDEV: M tun$U c 13 $U 600 /usr/src/etc/etc.luna88k/MAKEDEV: M tun$U c 23 $U 600 /usr/src/etc/etc.macppc/MAKEDEV:M tun$U c 23 $U 600 /usr/src/etc/etc.mvme68k/MAKEDEV: M tun$U c 23 $U 600 /usr/src/etc/etc.mvme88k/MAKEDEV: M tun$U c 23 $U 600 /usr/src/etc/etc.palm/MAKEDEV: M tun$U c 33 $U 600 /usr/src/etc/etc.sgi/MAKEDEV: M tun$U c 13 $U 600 /usr/src/etc/etc.socppc/MAKEDEV:M tun$U c 23 $U 600 /usr/src/etc/etc.sparc/MAKEDEV: M tun$U c 111 $U 600 /usr/src/etc/etc.sparc64/MAKEDEV: M tun$U c 111 $U 600 /usr/src/etc/etc.vax/MAKEDEV: M tun$U c 57 $U 600 /usr/src/etc/etc.zaurus/MAKEDEV:M tun$U c 33 $U 600
Re: cloneable tun
On Thu, Nov 29, 2012 at 11:05 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: #!/usr/bin/perl require sys/ioctl.ph; $TUNSIFUNIT = _IOC(IOC_INOUT, ord('t'), 90, 4); open(TUN0, +/dev/tun0) or die open; ioctl(TUN0, $TUNSIFUNIT, $unit = pack(i, -1)) or die ioctl $!; print Returned: tun.unpack(i, $unit).\n; close(TUN0); But you'll need to be a pretty hardcore Perl programmer to be able do this. Thanks, Mark, I take this as a compliment :-) But I don't see myself as a hardcore Perl programmer. My favourite quick-and-dirty language is Python, and I consider myself a fairly proficient Python programmer. I've never, ever, done ioctls from Python, and while it looks indeed as if it is possible to do so, I'm sure it'd take me some effort to get it right. I'm not a Python programmer at all, but doing ioctls there is not hard. Same thing: you have to master pack/unpack and call the ioctl function. But with your experience in Python, I'm sure that you know how to find API functions in the documentation. Google actually shows me lots of hints about using ioctl with python. The only problem with all these scripting languages is, that you have to get the ioctl number which is usually constructed with the _IO* macros in the C headers. If you don't have them, you have to figure out the hex number. And I have to admit that this is complicated and hard for non-C hackers. Some people just seem to include a pythonized version of the _IO* macros to construct the ioctl numbers, but this is most probably platform-specific code. #!/usr/local/bin/python import fcntl import struct file = open(/dev/tun0) unit = struct.pack(i, -1) ret = fcntl.ioctl(file, 0xc004745a, unit) print struct.unpack(i, ret) OK, let's find another way without an extra ioctl or keep tun as it is. Reyk
Re: cloneable tun
On Wed, Nov 28, 2012 at 10:42 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: From: Mike Belopuhov m...@belopuhov.com Date: Wed, 28 Nov 2012 22:21:07 +0100 On Wed, Nov 28, 2012 at 8:21 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: Date: Wed, 28 Nov 2012 17:39:24 +0100 From: Reyk Floeter r...@openbsd.org Hi, inspired by mikeb@'s clonable bpf patch, this slightly more complex diff implements clonable interface support to tun(4). The idea is to split the fixed relation between device minor number (/dev/tunX) and interface unit (ifconfig tunY). In difference to the current tun(4) implementation, opening /dev/tun0 will first do nothing and return an unuseable device. You first have to call the new TUNSIFUNIT to assign/request a specified interface unit. Why? Because people don't realize they need to run MAKEDEV to get more than four tun(4) devices? Drawback: This diff would require to patch all the existing users of /dev/tun* in ports and the tree to add the TUNSIFUNIT ioctl. The benefit is that you don't have to MAKEDEV all the tuns anymore and can open up to around 1024 active tun(4) interfaces (with the specinfo patch). That's a pretty big drawback. third party software has to be patched anyways, since tun is not standard. But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. sure, we can totally leave tun for legacy use in the shell scripts. so i guess reyk should go ahead and implement a dynamic tun interface (dun?) with whatever semantics we need and want.
Re: cloneable tun
On 2012/11/28 22:21, Mike Belopuhov wrote: Drawback: This diff would require to patch all the existing users of /dev/tun* in ports and the tree to add the TUNSIFUNIT ioctl. The benefit is that you don't have to MAKEDEV all the tuns anymore and can open up to around 1024 active tun(4) interfaces (with the specinfo patch). That's a pretty big drawback. third party software has to be patched anyways, since tun is not standard. The non-standard parts with the existing interface are mostly to do with configuration (in practice most third-party software e.g. openvpn, openconnect just calls out to ifconfig for that) and device node naming..
Re: cloneable tun
On Thu, Nov 29, 2012 at 10:59 AM, Mike Belopuhov m...@belopuhov.com wrote: But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. sure, we can totally leave tun for legacy use in the shell scripts. so i guess reyk should go ahead and implement a dynamic tun interface (dun?) with whatever semantics we need and want. Or even better duh? ;-) I wrote this diff because I wanted to experiment with clonable device nodes, I still don't like the fact that you have to MAKEDEV a device per dynamic interface, and because it adds some extra flexibility. But it doesn't have to go anywhere, I didn't even waste much time with writing it yesterday in the afternoon. btw., I like C and it is still my favorite language (sorry, CS people). But it shouldn't be a problem to do simple ioctls with most other languages except shell scripts. #!/usr/bin/perl require sys/ioctl.ph; $TUNSIFUNIT = _IOC(IOC_INOUT, ord('t'), 90, 4); open(TUN0, +/dev/tun0) or die open; ioctl(TUN0, $TUNSIFUNIT, $unit = pack(i, -1)) or die ioctl $!; print Returned: tun.unpack(i, $unit).\n; close(TUN0); reyk
Re: cloneable tun
On Thu, Nov 29, 2012 at 01:33:47PM +0100, Reyk Floeter wrote: On Thu, Nov 29, 2012 at 10:59 AM, Mike Belopuhov m...@belopuhov.com wrote: But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. sure, we can totally leave tun for legacy use in the shell scripts. so i guess reyk should go ahead and implement a dynamic tun interface (dun?) with whatever semantics we need and want. Or even better duh? ;-) I wrote this diff because I wanted to experiment with clonable device nodes, I still don't like the fact that you have to MAKEDEV a device per dynamic interface, and because it adds some extra flexibility. But it doesn't have to go anywhere, I didn't even waste much time with writing it yesterday in the afternoon. btw., I like C and it is still my favorite language (sorry, CS people). But it shouldn't be a problem to do simple ioctls with most other languages except shell scripts. #!/usr/bin/perl require sys/ioctl.ph; $TUNSIFUNIT = _IOC(IOC_INOUT, ord('t'), 90, 4); open(TUN0, +/dev/tun0) or die open; ioctl(TUN0, $TUNSIFUNIT, $unit = pack(i, -1)) or die ioctl $!; print Returned: tun.unpack(i, $unit).\n; close(TUN0); Any decent language will have ioctl support... Proof: perl does :)
Re: cloneable tun
On 11/29/2012 01:33 PM, Reyk Floeter wrote: On Thu, Nov 29, 2012 at 10:59 AM, Mike Belopuhov m...@belopuhov.com wrote: But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. sure, we can totally leave tun for legacy use in the shell scripts. so i guess reyk should go ahead and implement a dynamic tun interface (dun?) with whatever semantics we need and want. Or even better duh? ;-) I wrote this diff because I wanted to experiment with clonable device nodes, I still don't like the fact that you have to MAKEDEV a device per dynamic interface, and because it adds some extra flexibility. But it doesn't have to go anywhere, I didn't even waste much time with writing it yesterday in the afternoon. btw., I like C and it is still my favorite language (sorry, CS people). But it shouldn't be a problem to do simple ioctls with most other languages except shell scripts. #!/usr/bin/perl require sys/ioctl.ph; $TUNSIFUNIT = _IOC(IOC_INOUT, ord('t'), 90, 4); open(TUN0, +/dev/tun0) or die open; ioctl(TUN0, $TUNSIFUNIT, $unit = pack(i, -1)) or die ioctl $!; print Returned: tun.unpack(i, $unit).\n; close(TUN0); reyk I like cloning devices. But instead of needing an ioclt(2), wouldn't it be simpler to adapt the SVR4 API where the first parameter of cdevsw open() functions is an 'dev_t *dev'. Thus the open() routine can automatically do the cloning (or maybe not if minor is 0) by returning the device-Id of the cloned instance. and there is no need for using additional ioctl(2)s. Of course it requires a one-time API change with large impact. Gerhard
Re: cloneable tun
Date: Thu, 29 Nov 2012 13:33:47 +0100 From: Reyk Floeter r...@openbsd.org btw., I like C and it is still my favorite language (sorry, CS people). But it shouldn't be a problem to do simple ioctls with most other languages except shell scripts. #!/usr/bin/perl require sys/ioctl.ph; $TUNSIFUNIT = _IOC(IOC_INOUT, ord('t'), 90, 4); open(TUN0, +/dev/tun0) or die open; ioctl(TUN0, $TUNSIFUNIT, $unit = pack(i, -1)) or die ioctl $!; print Returned: tun.unpack(i, $unit).\n; close(TUN0); But you'll need to be a pretty hardcore Perl programmer to be able do this. My favourite quick-and-dirty language is Python, and I consider myself a fairly proficient Python programmer. I've never, ever, done ioctls from Python, and while it looks indeed as if it is possible to do so, I'm sure it'd take me some effort to get it right.
Re: cloneable tun
My favourite quick-and-dirty language is Python, and I consider myself a fairly proficient Python programmer. I've never, ever, done ioctls from Python, and while it looks indeed as if it is possible to do so, I'm sure it'd take me some effort to get it right. I definitely agree with your statement! I've found ioctls much easier to perform in brainf*ck than in python. Grumpy
Re: cloneable tun
Date: Thu, 29 Nov 2012 00:12:39 +0100 From: Reyk Floeter r...@openbsd.org On Wed, Nov 28, 2012 at 10:42 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. OK, I didn't think about VPN services written in node.js... I'm just kidding, but can you give me any examples of programs using tun that are written in an arbitrary language other than C/C++? There was some machine emulator software that I came across that had some Perl scripts that used /dev/tunN to hook itself up to the network stack. I guess the point I'm trying to make is that it is very simple to use /dev/tunN to insert ethernet packets into the network stack. The requirement to issue an ioctl to be able to use it makes it significantly more complex to do so.
Re: cloneable tun
Penned by Reyk Floeter on 20121129 6:33.47, we have: | On Thu, Nov 29, 2012 at 10:59 AM, Mike Belopuhov m...@belopuhov.com wrote: | But currently /dev/tunN is usable from any programming language that | that can do reads and writes. With Reyk's changes you need to do an | ioctl even for basic usage, which is at best quirky in languages other | than C/C++. That feels like a step backward to me. | | sure, we can totally leave tun for legacy use in the shell scripts. | so i guess reyk should go ahead and implement a dynamic tun interface | (dun?) with whatever semantics we need and want. | | Or even better duh? ;-) I wrote this diff because I wanted to | experiment with clonable device nodes, I still don't like the fact | that you have to MAKEDEV a device per dynamic interface, and because | it adds some extra flexibility. But it doesn't have to go anywhere, I | didn't even waste much time with writing it yesterday in the | afternoon. | | btw., I like C and it is still my favorite language (sorry, CS | people). But it shouldn't be a problem to do simple ioctls with most | other languages except shell scripts. | | #!/usr/bin/perl | require sys/ioctl.ph; | $TUNSIFUNIT = _IOC(IOC_INOUT, ord('t'), 90, 4); | open(TUN0, +/dev/tun0) or die open; | ioctl(TUN0, $TUNSIFUNIT, $unit = pack(i, -1)) or die ioctl $!; | print Returned: tun.unpack(i, $unit).\n; | close(TUN0); | | reyk Wouldn't it just be easier to auto assign on first read/write if the $TUNSIFUNIT ioctl has not yet been called? Thanks, -- Todd Fries .. t...@fries.net |\ 1.636.410.0632 (voice) | Free Daemon Consulting, LLC\ 1.405.227.9094 (voice) | http://FreeDaemonConsulting.com\ 1.866.792.3418 (FAX) | PO Box 16169, Oklahoma City, OK 73113 \ sip:freedae...@ekiga.net | ..in support of free software solutions. \ sip:4052279...@ekiga.net \ 37E7 D3EB 74D0 8D66 A68D B866 0326 204E 3F42 004A http://todd.fries.net/pgp.txt
cloneable tun
Hi, inspired by mikeb@'s clonable bpf patch, this slightly more complex diff implements clonable interface support to tun(4). The idea is to split the fixed relation between device minor number (/dev/tunX) and interface unit (ifconfig tunY). In difference to the current tun(4) implementation, opening /dev/tun0 will first do nothing and return an unuseable device. You first have to call the new TUNSIFUNIT to assign/request a specified interface unit. For example, if you want to open the network interface tun13: unit = 13; if ((fd = open(/dev/tun0, O_RDONLY)) == -1) err(1, failed to open /dev/tun0); if (ioctl(fd, TUNSIFUNIT, unit) == -1) err(1, ioctl failed); Or if you don't care and just want to open the next available interface: if ((fd = open(/dev/tun0, O_RDONLY)) == -1) err(1, failed to open /dev/tun0); unit = -1; if (ioctl(fd, TUNSIFUNIT, unit) == -1) err(1, ioctl failed); fprintf(stderr, got tun%d, unit); You can pre-created an interface with ifconfig and attach to it later: # ifconfig tun5 create ... unit = 5 ... ioctl(fd, TUNSIFUNIT, unit) ... - tun5 But the code will not return a pre-created interface if you're not explicitely asking for it: # ifconfig tun5 create ... unit = -1 ... ioctl(fd, TUNSIFUNIT, unit) ... - not tun5 Drawback: This diff would require to patch all the existing users of /dev/tun* in ports and the tree to add the TUNSIFUNIT ioctl. The benefit is that you don't have to MAKEDEV all the tuns anymore and can open up to around 1024 active tun(4) interfaces (with the specinfo patch). The concept is a bit similar to Linux's /dev/net/tun (*sorry*) that also uses an additional initial ioctl to set the interface unit (I added support for the Linux version to OpenSSH-portable in 2005: http://anoncvs.mindrot.org/index.cgi/openssh/openbsd-compat/port-tun.c?view=markup) Notes: - Does this provide any benefit? (This doesn't have to go anywhere, I hacked it as a PoC after chatting with mikeb.) - Would 1024 devices even be enough? Afaik, some daemons like npppd(8) can use a single device for multiple connections and don't seem to be affected by a fixed 1024 limit. - It is probably nice to have fewer files in /dev/ ;-) - Similar things could be done for pppx(4) (there is not manpage yet). Comments? Reyk Index: net/if_tun.c === RCS file: /cvs/src/sys/net/if_tun.c,v retrieving revision 1.112 diff -u -p -r1.112 if_tun.c --- net/if_tun.c9 Jul 2011 00:47:18 - 1.112 +++ net/if_tun.c28 Nov 2012 16:07:32 - @@ -87,6 +87,7 @@ struct tun_softc { struct selinfo tun_rsel; /* read select */ struct selinfo tun_wsel; /* write select (not used) */ LIST_ENTRY(tun_softc) tun_list; /* all tunnel interfaces */ + int tun_minor; int tun_unit; uid_t tun_siguid; /* uid for process that set tun_pgid */ uid_t tun_sigeuid;/* euid for process that set tun_pgid */ @@ -111,6 +112,7 @@ int tundebug = TUN_DEBUG; void tunattach(int); inttunopen(dev_t, int, int, struct proc *); inttunclose(dev_t, int, int, struct proc *); +inttuncreate(dev_t, int); inttun_ioctl(struct ifnet *, u_long, caddr_t); inttun_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -123,6 +125,7 @@ int tun_clone_create(struct if_clone *, inttun_create(struct if_clone *, int, int); inttun_clone_destroy(struct ifnet *); struct tun_softc *tun_lookup(int); +struct tun_softc *tun_lookup_cloner(int); void tun_wakeup(struct tun_softc *); inttun_switch(struct tun_softc *, int); @@ -173,6 +176,7 @@ tun_create(struct if_clone *ifc, int uni return (ENOMEM); tp-tun_unit = unit; + tp-tun_minor = -1; tp-tun_flags = TUN_INITED|TUN_STAYUP; ifp = tp-tun_if; @@ -253,7 +257,18 @@ tun_clone_destroy(struct ifnet *ifp) } struct tun_softc * -tun_lookup(int unit) +tun_lookup(int minor) +{ + struct tun_softc *tp; + + LIST_FOREACH(tp, tun_softc_list, tun_list) + if (tp-tun_minor == minor) + return (tp); + return (NULL); +} + +struct tun_softc * +tun_lookup_cloner(int unit) { struct tun_softc *tp; @@ -267,7 +282,7 @@ int tun_switch(struct tun_softc *tp, int flags) { struct ifnet*ifp = tp-tun_if; - int unit, open, r, s; + int unit, minor, open, r, s; struct ifg_list *ifgl; u_int ifgr_len; char*ifgrpnames, *p; @@ -276,6 +291,7 @@ tun_switch(struct tun_softc *tp, int fla return (0); /* tp will be removed so store unit number */ +
Re: cloneable tun
Date: Wed, 28 Nov 2012 17:39:24 +0100 From: Reyk Floeter r...@openbsd.org Hi, inspired by mikeb@'s clonable bpf patch, this slightly more complex diff implements clonable interface support to tun(4). The idea is to split the fixed relation between device minor number (/dev/tunX) and interface unit (ifconfig tunY). In difference to the current tun(4) implementation, opening /dev/tun0 will first do nothing and return an unuseable device. You first have to call the new TUNSIFUNIT to assign/request a specified interface unit. Why? Because people don't realize they need to run MAKEDEV to get more than four tun(4) devices? Drawback: This diff would require to patch all the existing users of /dev/tun* in ports and the tree to add the TUNSIFUNIT ioctl. The benefit is that you don't have to MAKEDEV all the tuns anymore and can open up to around 1024 active tun(4) interfaces (with the specinfo patch). That's a pretty big drawback.
Re: cloneable tun
From: Mike Belopuhov m...@belopuhov.com Date: Wed, 28 Nov 2012 22:21:07 +0100 On Wed, Nov 28, 2012 at 8:21 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: Date: Wed, 28 Nov 2012 17:39:24 +0100 From: Reyk Floeter r...@openbsd.org Hi, inspired by mikeb@'s clonable bpf patch, this slightly more complex diff implements clonable interface support to tun(4). The idea is to split the fixed relation between device minor number (/dev/tunX) and interface unit (ifconfig tunY). In difference to the current tun(4) implementation, opening /dev/tun0 will first do nothing and return an unuseable device. You first have to call the new TUNSIFUNIT to assign/request a specified interface unit. Why? Because people don't realize they need to run MAKEDEV to get more than four tun(4) devices? Drawback: This diff would require to patch all the existing users of /dev/tun* in ports and the tree to add the TUNSIFUNIT ioctl. The benefit is that you don't have to MAKEDEV all the tuns anymore and can open up to around 1024 active tun(4) interfaces (with the specinfo patch). That's a pretty big drawback. third party software has to be patched anyways, since tun is not standard. But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me.
Re: cloneable tun
On Wed, Nov 28, 2012 at 1:42 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. I agree. Philip
Re: cloneable tun
On Wed, Nov 28, 2012 at 10:42 PM, Mark Kettenis mark.kette...@xs4all.nl wrote: But currently /dev/tunN is usable from any programming language that that can do reads and writes. With Reyk's changes you need to do an ioctl even for basic usage, which is at best quirky in languages other than C/C++. That feels like a step backward to me. OK, I didn't think about VPN services written in node.js... I'm just kidding, but can you give me any examples of programs using tun that are written in an arbitrary language other than C/C++? Reyk