d25ff06d9a1a6580e8ce9a1888938bbd2b789f5a
4 signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
)
7 from twisted
.internet
import reactor
10 from ipaddress
import AddressValueError
12 import hippotat
.slip
as slip
14 #---------- packet parsing ----------
16 def packet_addrs(packet
):
17 version
= packet
[0] >> 4
21 factory
= ipaddress
.IPv4Address
25 factory
= ipaddress
.IPv6Address
27 raise ValueError('unsupported IP version %d' % version
)
28 saddr
= factory(packet
[ saddroff
: saddroff
+ addrlen
])
29 daddr
= factory(packet
[ saddroff
+ addrlen
: saddroff
+ addrlen
*2 ])
32 #---------- address handling ----------
36 r
= ipaddress
.IPv4Address(input)
37 except AddressValueError
:
38 r
= ipaddress
.IPv6Address(input)
43 r
= ipaddress
.IPv4Network(input)
44 except NetworkValueError
:
45 r
= ipaddress
.IPv6Network(input)
48 #---------- ipif (SLIP) subprocess ----------
50 class _IpifProcessProtocol(twisted
.internet
.protocol
.ProcessProtocol
):
51 def __init__(self
, router
):
54 def connectionMade(self
): pass
55 def outReceived(self
, data
):
56 #print('RECV ', repr(data))
58 packets
= slip
.decode(self
._buffer
)
59 self
._buffer
= packets
.pop()
60 for packet
in packets
:
61 if not len(packet
): continue
62 (saddr
, daddr
) = packet_addrs(packet
)
63 self
._router(packet
, saddr
, daddr
)
64 def processEnded(self
, status
):
65 status
.raiseException()
67 def start_ipif(command
, router
):
69 ipif
= _IpifProcessProtocol(router
)
70 reactor
.spawnProcess(ipif
,
71 '/bin/sh',['sh','-xc', command
],
72 childFDs
={0:'w', 1:'r', 2:2})
74 def queue_inbound(packet
):
75 ipif
.transport
.write(slip
.delimiter
)
76 ipif
.transport
.write(slip
.encode(packet
))
77 ipif
.transport
.write(slip
.delimiter
)
79 #---------- packet queue ----------
82 def __init__(self
, max_queue_time
):
83 self
._max_queue_time
= max_queue_time
84 self
._pq
= collections
.deque() # packets
86 def append(self
, packet
):
87 self
._pq
.append((time
.monotonic(), packet
))
91 try: (queuetime
, packet
) = self
._pq
[0]
92 except IndexError: return False
94 age
= time
.monotonic() - queuetime
95 if age
> self
.max_queue_time
:
96 # strip old packets off the front
103 # caller must have checked nonempty
104 try: (dummy
, packet
) = self
._pq
[0]
105 except IndexError: return None