def parser(self): """ Get a function for parsing a datagram read from a I{tun} device. @return: A function which accepts a datagram exactly as might be read from a I{tun} device. The datagram is expected to ultimately carry a UDP datagram. When called, it returns a L{list} of L{tuple}s. Each tuple has the UDP application data as the first element and the sender address as the second element. """ datagrams = [] receiver = DatagramProtocol() def capture(*args): datagrams.append(args) receiver.datagramReceived = capture udp = RawUDPProtocol() udp.addProto(12345, receiver) ip = IPProtocol() ip.addProto(17, udp) def parse(data): # TUN devices omit the ethernet framing so we can start parsing # right at the IP layer. ip.datagramReceived(data, False, None, None, None) return datagrams return parse
def main(reactor): startLogging(stdout, setStdout=False) udp = RawUDPProtocol() udp.addProto(42, MyProto()) ip = IPProtocol() ip.addProto(17, udp) eth = EthernetProtocol() eth.addProto(0x800, ip) port = TuntapPort(interface='tap0', proto=eth, reactor=reactor) port.startListening() # Run forever return Deferred()
def recv(self, nbytes): """ Receive a datagram sent to this port using the L{MemoryIOSystem} which created this object. This behaves like L{socket.socket.recv} but the data being I{sent} and I{received} only passes through various memory buffers managed by this object and L{MemoryIOSystem}. @see: L{socket.socket.recv} """ data = self._system._openFiles[self._fileno].writeBuffer.popleft() datagrams = [] receiver = DatagramProtocol() def capture(datagram, address): datagrams.append(datagram) receiver.datagramReceived = capture udp = RawUDPProtocol() udp.addProto(12345, receiver) ip = IPProtocol() ip.addProto(17, udp) mode = self._system._openFiles[self._fileno].tunnelMode if (mode & TunnelFlags.IFF_TAP.value): ether = EthernetProtocol() ether.addProto(0x800, ip) datagramReceived = ether.datagramReceived else: datagramReceived = lambda data: ip.datagramReceived( data, None, None, None, None) dataHasPI = not (mode & TunnelFlags.IFF_NO_PI.value) if dataHasPI: # datagramReceived can't handle the PI, get rid of it. data = data[_PI_SIZE:] datagramReceived(data) return datagrams[0][:nbytes]
def parser(self): """ Get a function for parsing a datagram read from a I{tap} device. @return: A function which accepts a datagram exactly as might be read from a I{tap} device. The datagram is expected to ultimately carry a UDP datagram. When called, it returns a L{list} of L{tuple}s. Each tuple has the UDP application data as the first element and the sender address as the second element. """ datagrams = [] receiver = DatagramProtocol() def capture(*args): datagrams.append(args) receiver.datagramReceived = capture udp = RawUDPProtocol() udp.addProto(12345, receiver) ip = IPProtocol() ip.addProto(17, udp) ether = EthernetProtocol() ether.addProto(0x800, ip) def parser(datagram): # TAP devices might include a PI header. Strip that off if we # expect it to be there. if self.pi: datagram = datagram[_PI_SIZE:] # TAP devices include ethernet framing so start parsing at the # ethernet layer. ether.datagramReceived(datagram) return datagrams return parser