1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
import fcntl
import os
import socket
import struct
TUNSETIFF = 0x400454CA
TUNSETOWNER = TUNSETIFF + 2
IFF_TUN = 0x0001
IFF_TAP = 0x0002
IFF_NAPI = 0x0010
IFF_NAPI_FRAGS = 0x0020
IFF_NO_PI = 0x1000
IFF_PERSIST = 0x0800
IFF_NOFILTER = 0x1000
# net/if.h
IFF_UP = 0x1
IFF_RUNNING = 0x40
IFNAMSIZ = 16
# From linux/sockios.h
SIOCGIFCONF = 0x8912
SIOCGIFINDEX = 0x8933
SIOCGIFFLAGS = 0x8913
SIOCSIFFLAGS = 0x8914
SIOCGIFHWADDR = 0x8927
SIOCSIFHWADDR = 0x8924
SIOCGIFADDR = 0x8915
SIOCSIFADDR = 0x8916
SIOCGIFNETMASK = 0x891B
SIOCSIFNETMASK = 0x891C
SIOCETHTOOL = 0x8946
SIOCGIFMTU = 0x8921 # get MTU size
SIOCSIFMTU = 0x8922 # set MTU size
class Tun:
mtu = 1500
def __init__(self, name, mode="tap", persist=True):
self.name = name.encode()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sockfd = sock
@property
def ifflags(self):
# Get existing device flags
ifreq = struct.pack("16sh", self.name, 0)
flags = struct.unpack("16sh", fcntl.ioctl(self.sockfd, SIOCGIFFLAGS, ifreq))[1]
return flags
@ifflags.setter
def ifflags(self, flags):
ifreq = struct.pack("16sh", self.name, flags)
fcntl.ioctl(self.sockfd, SIOCSIFFLAGS, ifreq)
def get_mtu(self):
ifreq = struct.pack("16sh", self.name, 0)
self.mtu = struct.unpack("16sh", fcntl.ioctl(self.sockfd, SIOCGIFMTU, ifreq))[1]
def up(self):
"""Bring up interface. Equivalent to ifconfig [iface] up."""
# Set new flags
flags = self.ifflags | IFF_UP
self.ifflags = flags
self.get_mtu()
def down(self):
"""Bring down interface. Equivalent to ifconfig [iface] down."""
# Set new flags
flags = self.ifflags & ~IFF_UP
self.ifflags = flags
def is_up(self):
"""Return True if the interface is up, False otherwise."""
if self.ifflags & IFF_UP:
return True
else:
return False
def open(self):
"""Open file corresponding to the TUN device."""
self.fd = open("/dev/net/tun", "rb+", buffering=0)
tun_flags = IFF_TAP | IFF_NO_PI | IFF_PERSIST
ifr = struct.pack("16sH", self.name, tun_flags)
fcntl.ioctl(self.fd, TUNSETIFF, ifr)
fcntl.ioctl(self.fd, TUNSETOWNER, os.getuid())
self.ifflags = self.ifflags | IFF_RUNNING
def close(self):
if self.fd:
self.ifflags = self.ifflags & ~IFF_RUNNING
self.fd.close()
|