diff options
Diffstat (limited to '')
| -rw-r--r-- | tools/tunbridge.py | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/tools/tunbridge.py b/tools/tunbridge.py index f5e391c..d5669e4 100644 --- a/tools/tunbridge.py +++ b/tools/tunbridge.py @@ -27,6 +27,49 @@ def slip_encode(pkt): out.append(END) return bytes(out) +# ---- built-in DHCP server: the bridge leases the GB 10.0.0.2 ---------------- +GB_IP = b"\x0a\x00\x00\x02"; GW = b"\x0a\x00\x00\x01" +def _cksum(d): + s = 0 + for i in range(0, len(d) - 1, 2): s += (d[i] << 8) | d[i + 1] + if len(d) % 2: s += d[-1] << 8 + while s >> 16: s = (s & 0xFFFF) + (s >> 16) + return (~s) & 0xFFFF +def _dhcp_mtype(dhcp): + p = 240 + while p < len(dhcp) and dhcp[p] != 255: + if dhcp[p] == 0: p += 1; continue + if dhcp[p] == 53: return dhcp[p + 2] + p += 2 + dhcp[p + 1] + return 0 +def _dhcp_reply(req, mt): + d = bytearray(240) + d[0] = 2; d[1] = 1; d[2] = 6 + d[4:8] = req[4:8] # xid + d[16:20] = GB_IP # yiaddr + d[20:24] = GW # siaddr + d[28:44] = req[28:44] # chaddr + d[236:240] = b"\x63\x82\x53\x63" + d += bytes([53, 1, mt, 54, 4]) + GW + bytes([255]) + udp = bytearray(8); udp[1] = 67; udp[3] = 68 + ul = 8 + len(d); udp[4] = ul >> 8; udp[5] = ul & 0xFF + udp += d + tot = 20 + len(udp) + ip = bytearray(20); ip[0] = 0x45; ip[2] = tot >> 8; ip[3] = tot & 0xFF + ip[8] = 64; ip[9] = 17; ip[12:16] = GW; ip[16:20] = b"\xff\xff\xff\xff" + ck = _cksum(ip); ip[10] = ck >> 8; ip[11] = ck & 0xFF + return bytes(ip) + bytes(udp) +def dhcp_intercept(frame, send_raw): + """If frame is a DHCP request (UDP -> :67), answer it and return True.""" + if len(frame) < 28 or frame[9] != 17: return False + ihl = (frame[0] & 0x0f) * 4 + if len(frame) < ihl + 4 or ((frame[ihl + 2] << 8) | frame[ihl + 3]) != 67: return False + dhcp = frame[ihl + 8:] + mt = _dhcp_mtype(dhcp) + if mt == 1: send_raw(_dhcp_reply(dhcp, 2)) # DISCOVER -> OFFER + elif mt == 3: send_raw(_dhcp_reply(dhcp, 5)) # REQUEST -> ACK + return True + def sh(cmd, quiet=True): subprocess.run(cmd, shell=True, check=False, stdout=subprocess.DEVNULL if quiet else None, @@ -81,8 +124,10 @@ def main(): c = b[0] if c == END: if in_frame and buf: - try: os.write(tun, bytes(buf)) - except Exception: pass + fr = bytes(buf) + if not dhcp_intercept(fr, lambda pk: (p.stdin.write(slip_encode(pk)), p.stdin.flush())): + try: os.write(tun, fr) + except Exception: pass buf, in_frame, esc = bytearray(), False, False else: buf, in_frame, esc = bytearray(), True, False |
