File: tuntap.py

package info (click to toggle)
python-aiortc 1.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,052 kB
  • sloc: python: 20,294; javascript: 321; makefile: 21; sh: 1
file content (96 lines) | stat: -rw-r--r-- 2,504 bytes parent folder | download | duplicates (2)
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()