Interfacing with TUN\TAP for MAC OSX (Lion) using Python
Question: I found the following tun\tap example program and can not get it to work:

<http://www.secdev.org/projects/tuntap_udp/files/tunproxy.py>

I have modified the following lines:

    
    
    f = os.open("/dev/tun0", os.O_RDWR)
    ifs = ioctl(f, TUNSETIFF, struct.pack("16sH", "toto%d", TUNMODE))
    ifname = ifs[:16].strip("\x00")
    

The first line was modified to reflect the real location of the driver. It was
originally

    
    
    f = os.open("/dev/net/tun", os.O_RDWR)
    

Upon running I get the following error:

    
    
     sudo ./tuntap.py -s 9000
     Password:
     Traceback (most recent call last):
       File "./tuntap.py", line 65, in <module>
         ifs = ioctl(f, TUNSETIFF, struct.pack("16sH", "toto%d", TUNMODE))
     IOError: [Errno 25] Inappropriate ioctl for device
    

I am using the latest tun\tap drivers installed from
<http://tuntaposx.sourceforge.net/download.xhtml>


Answer: The OSX tun/tap driver seems to work a bit different. The Linux example
dynamically allocates a tun interface, which does not work in OSX, at least
not in the same way.

I stripped the code to create a basic example of how tun can be used on OSX
using a self-selected tun device, printing each packet to the console. I added
[Scapy](http://www.secdev.org/projects/scapy/doc/) as a dependency for pretty
printing, but you can replace it by a raw packet dump if you want:

    
    
    import os, sys
    from select import select
    from scapy.all import IP
    
    f = os.open("/dev/tun12", os.O_RDWR)
    try:
        while 1:
            r = select([f],[],[])[0][0]
            if r == f:
                packet = os.read(f, 4000)
                # print len(packet), packet
                ip = IP(packet)
                ip.show()
    except KeyboardInterrupt:
        print "Stopped by user."
    

You will either have to run this as root, or do a `sudo chown your_username
/dev/tun12` to be allowed to open the device.

To configure it as a point-to-point interface, type:

    
    
    $ sudo ifconfig tun12 10.12.0.2 10.12.0.1
    

Note that the `tun12` interface will only be available while `/dev/tun12` is
open, i.e. while the program is running. If you interrupt the program, your
tun interface will disappear, and you will need to configure it again next
time you run the program.

If you now ping your endpoint, your packets will be printed to the console:

    
    
    $ ping 10.12.0.1
    

Ping itself will print request timeouts, because there is no tunnel endpoint
responding to your ping requests.

