move ipif slip process handling
[hippotat] / hippotat / __init__.py
CommitLineData
b0cfbfce
IJ
1# -*- python -*-
2
040ff511
IJ
3import twisted
4from twisted.internet import reactor
b0cfbfce
IJ
5
6import ipaddress
7from ipaddress import AddressValueError
8
040ff511
IJ
9import hippotat.slip as slip
10
b0cfbfce
IJ
11#---------- packet parsing ----------
12
13def packet_addrs(packet):
14 version = packet[0] >> 4
15 if version == 4:
16 addrlen = 4
17 saddroff = 3*4
18 factory = ipaddress.IPv4Address
19 elif version == 6:
20 addrlen = 16
21 saddroff = 2*4
22 factory = ipaddress.IPv6Address
23 else:
24 raise ValueError('unsupported IP version %d' % version)
25 saddr = factory(packet[ saddroff : saddroff + addrlen ])
26 daddr = factory(packet[ saddroff + addrlen : saddroff + addrlen*2 ])
27 return (saddr, daddr)
28
29#---------- address handling ----------
30
31def ipaddr(input):
32 try:
33 r = ipaddress.IPv4Address(input)
34 except AddressValueError:
35 r = ipaddress.IPv6Address(input)
36 return r
37
38def ipnetwork(input):
39 try:
40 r = ipaddress.IPv4Network(input)
41 except NetworkValueError:
42 r = ipaddress.IPv6Network(input)
43 return r
040ff511
IJ
44
45#---------- ipif (SLIP) subprocess ----------
46
47class _IpifProcessProtocol(twisted.internet.protocol.ProcessProtocol):
48 def __init__(self, router):
49 self._buffer = b''
50 self._router = router
51 def connectionMade(self): pass
52 def outReceived(self, data):
53 #print('RECV ', repr(data))
54 self._buffer += data
55 packets = slip.decode(self._buffer)
56 self._buffer = packets.pop()
57 for packet in packets:
58 if not len(packet): continue
59 (saddr, daddr) = packet_addrs(packet)
60 self._router(packet, saddr, daddr)
61 def processEnded(self, status):
62 status.raiseException()
63
64def start_ipif(command, router):
65 global ipif
66 ipif = _IpifProcessProtocol(router)
67 reactor.spawnProcess(ipif,
68 '/bin/sh',['sh','-xc', command],
69 childFDs={0:'w', 1:'r', 2:2})
70
71def queue_inbound(packet):
72 ipif.transport.write(slip.delimiter)
73 ipif.transport.write(slip.encode(packet))
74 ipif.transport.write(slip.delimiter)
75