8 ipbytes = map(ord,ip.decode("hex"))
9 return '.'.join(map(str,ipbytes))
15 '8863' : 'PPPoE discover',
19 def etherProto(packet):
20 packet = packet.encode("hex")
22 if packet[12:14] == "\x81\x00":
30 def formatPacket(packet, ether_mode):
32 stripped_packet = etherStrip(packet)
33 if not stripped_packet:
34 packet = packet.encode("hex")
36 return "malformed eth " + packet.encode("hex")
38 if packet[24:28] == "8100":
40 ethertype = tagtype.get(packet[32:36], 'eth')
41 return ethertype + " " + ( '-'.join( (
42 packet[0:12], # MAC dest
43 packet[12:24], # MAC src
44 packet[24:32], # VLAN tag
45 packet[32:36], # Ethertype/len
46 packet[36:], # Payload
50 ethertype = tagtype.get(packet[24:28], 'eth')
51 return ethertype + " " + ( '-'.join( (
52 packet[0:12], # MAC dest
53 packet[12:24], # MAC src
54 packet[24:28], # Ethertype/len
55 packet[28:], # Payload
58 packet = stripped_packet
59 packet = packet.encode("hex")
61 return "malformed ip " + packet
63 return "ip " + ( '-'.join( (
65 packet[1:2], #header length
66 packet[2:4], #diffserv/ECN
67 packet[4:8], #total length
69 packet[12:16], #flags/fragment offs
71 packet[18:20], #ip-proto
72 packet[20:24], #checksum
73 ipfmt(packet[24:32]), # src-ip
74 ipfmt(packet[32:40]), # dst-ip
75 packet[40:48] if (int(packet[1],16) > 5) else "", # options
76 packet[48:] if (int(packet[1],16) > 5) else packet[40:], # payload
79 def packetReady(buf, ether_mode):
85 _,totallen = struct.unpack('HH',buf[:4])
86 totallen = socket.htons(totallen)
87 return len(buf) >= totallen
89 def pullPacket(buf, ether_mode):
93 _,totallen = struct.unpack('HH',buf[:4])
94 totallen = socket.htons(totallen)
95 return buf[:totallen], buf[totallen:]
100 if buf[12:14] == '\x08\x10' and buf[16:18] in '\x08\x00':
101 # tagged ethernet frame
103 elif buf[12:14] == '\x08\x00':
104 # untagged ethernet frame
109 def etherWrap(packet):
111 "\x00"*6*2 # bogus src and dst mac
114 +"\x00"*4 # bogus crc
123 def piWrap(buf, ether_mode):
125 proto = etherProto(buf)
129 "\x00\x00" # PI: 16 bits flags
130 +proto # 16 bits proto
134 def encrypt(packet, crypter):
136 padding = crypter.block_size - len(packet) % crypter.block_size
137 packet += chr(padding) * padding
140 return crypter.encrypt(packet)
142 def decrypt(packet, crypter):
144 packet = crypter.decrypt(packet)
147 padding = ord(packet[-1])
148 if not (0 < padding <= crypter.block_size):
150 raise RuntimeError, "Truncated packet"
151 packet = packet[:-padding]
156 def tun_fwd(tun, remote, with_pi, ether_mode, cipher_key, udp, TERMINATE, stderr=sys.stderr):
160 import Crypto.Cipher.AES
163 hashed_key = hashlib.sha256(cipher_key).digest()
164 crypter = Crypto.Cipher.AES.new(
166 Crypto.Cipher.AES.MODE_ECB)
170 traceback.print_exc()
175 print >>stderr, "Packets are transmitted in CIPHER"
177 print >>stderr, "Packets are transmitted in PLAINTEXT"
179 # Limited frame parsing, to preserve packet boundaries.
180 # Which is needed, since /dev/net/tun is unbuffered
185 if packetReady(bkbuf, ether_mode):
187 if packetReady(fwbuf, ether_mode):
189 rdrdy, wrdy, errs = select.select((tun,remote),wset,(tun,remote),1)
195 # check to see if we can write
196 if remote in wrdy and packetReady(fwbuf, ether_mode):
197 packet, fwbuf = pullPacket(fwbuf, ether_mode)
200 enpacket = encrypt(packet, crypter)
203 os.write(remote.fileno(), enpacket)
206 # in UDP mode, we ignore errors - packet loss man...
208 print >>stderr, '>', formatPacket(packet, ether_mode)
209 if tun in wrdy and packetReady(bkbuf, ether_mode):
210 packet, bkbuf = pullPacket(bkbuf, ether_mode)
211 formatted = formatPacket(packet, ether_mode)
213 packet = piWrap(packet, ether_mode)
214 os.write(tun.fileno(), packet)
215 print >>stderr, '<', formatted
217 # check incoming data packets
219 packet = os.read(tun.fileno(),2000) # tun.read blocks until it gets 2k!
221 packet = piStrip(packet)
225 packet = os.read(remote.fileno(),2000) # remote.read blocks until it gets 2k!
227 packet = decrypt(packet, crypter)
230 # in UDP mode, we ignore errors - packet loss man...