1*fa9278d9Sbluhm#!/usr/local/bin/python3 2*fa9278d9Sbluhm# $OpenBSD: sendrecv.py,v 1.3 2020/12/25 13:47:43 bluhm Exp $ 3d6191a09Sbluhm 4d6191a09Sbluhmimport os 5d6191a09Sbluhmfrom scapy.all import * 6d6191a09Sbluhmfrom struct import pack 7d6191a09Sbluhmimport getopt, sys 8d6191a09Sbluhm 9d6191a09Sbluhmdef usage(): 10*fa9278d9Sbluhm print("sendrecv [-hi] [-c ckoff] [-r recvsz] [-s sendsz]") 11*fa9278d9Sbluhm print(" -c ckoff set checksum offset within payload") 12*fa9278d9Sbluhm print(" -h help, show usage") 13*fa9278d9Sbluhm print(" -i expect icmp6 error message as response") 14*fa9278d9Sbluhm print(" -r recvsz expected payload size") 15*fa9278d9Sbluhm print(" -s sendsz set payload size") 16d6191a09Sbluhm exit(1) 17d6191a09Sbluhm 18d6191a09Sbluhmopts, args = getopt.getopt(sys.argv[1:], "c:hir:s:") 19d6191a09Sbluhm 20d6191a09Sbluhmip = IPv6(src="::1", dst="::1", nh=255) 21d6191a09Sbluhm 22d6191a09Sbluhmckoff = None 23d6191a09Sbluhmicmp = False 24d6191a09Sbluhmrecvsz = None 25d6191a09Sbluhmsendsz = None 26d6191a09Sbluhmfor o, a in opts: 27d6191a09Sbluhm if o == "-c": 28d6191a09Sbluhm ckoff = int(a) 29d6191a09Sbluhm elif o == "-i": 30d6191a09Sbluhm icmp = True 31d6191a09Sbluhm elif o == "-r": 32d6191a09Sbluhm recvsz = int(a) 33d6191a09Sbluhm elif o == "-s": 34d6191a09Sbluhm sendsz = int(a) 35d6191a09Sbluhm else: 36d6191a09Sbluhm usage() 37d6191a09Sbluhm 38*fa9278d9Sbluhmpayload = b""; 39d6191a09Sbluhmif sendsz is not None: 40d6191a09Sbluhm for i in range(sendsz): 41*fa9278d9Sbluhm payload += pack('B', i) 42*fa9278d9Sbluhm print("payload length is", len(payload)) 43d6191a09Sbluhm 44d6191a09Sbluhmif ckoff is not None: 45d6191a09Sbluhm payload = payload[:ckoff] + pack("xx") + payload[ckoff+2:] 46d6191a09Sbluhm cksum = in6_chksum(255, ip, payload) 47*fa9278d9Sbluhm print("calculated checksum is", cksum) 48d6191a09Sbluhm payload = payload[:ckoff] + pack("!H", cksum) + payload[ckoff+2:] 49d6191a09Sbluhm 50d6191a09Sbluhmreq=ip/payload 51d6191a09Sbluhm# As we are sending from ::1 to ::1 we sniff our own packet as answer. 52d6191a09Sbluhm# Add a filter that matches on the expected answer using the payload size. 53d6191a09Sbluhmif icmp: 54d6191a09Sbluhm filter="icmp6" 55d6191a09Sbluhm if recvsz is not None: 56d6191a09Sbluhm filter += (" and len = %d" % (4 + 40 + 8 + 40 + recvsz)) 57d6191a09Sbluhmelse: 58d6191a09Sbluhm filter="proto 255" 59d6191a09Sbluhm if recvsz is not None: 60d6191a09Sbluhm filter += (" and len = %d" % (4 + 40 + recvsz)) 61*fa9278d9Sbluhmprint("filter", filter) 62d6191a09Sbluhmans=sr(req, iface="lo0", filter=filter, timeout=10) 63*fa9278d9Sbluhmprint(ans) 64d6191a09Sbluhmres=ans[0][0][1] 65d6191a09Sbluhmres.show() 66d6191a09Sbluhm 67*fa9278d9Sbluhmprint("response protocol next header is", res.nh) 68d6191a09Sbluhmif icmp: 69d6191a09Sbluhm if res.nh != 58: 70*fa9278d9Sbluhm print("response wrong protocol, expected icmp6") 71d6191a09Sbluhm exit(1) 72*fa9278d9Sbluhm print("response icmp6 type is", res.payload.type) 73d6191a09Sbluhm if res.payload.type != 4: 74*fa9278d9Sbluhm print("response wrong icmp6 type, expected parameter problem") 75d6191a09Sbluhm exit(1) 76d6191a09Sbluhm exit(0) 77d6191a09Sbluhm 78d6191a09Sbluhmif res.nh != 255: 79*fa9278d9Sbluhm print("response with wrong protocol, expected 255, got") 80d6191a09Sbluhm exit(1) 81d6191a09Sbluhm 82d6191a09Sbluhmcksum = in6_chksum(255, res, res.payload.load) 83*fa9278d9Sbluhmprint("received checksum is", cksum) 84d6191a09Sbluhmif ckoff is not None and cksum != 0: 85*fa9278d9Sbluhm print("received invalid checksum", cksum) 86d6191a09Sbluhm exit(1) 87d6191a09Sbluhm 88*fa9278d9Sbluhmprint("received payload length is", len(res.payload.load)) 89d6191a09Sbluhmif recvsz is not None: 90d6191a09Sbluhm if len(res.payload.load) != recvsz: 91*fa9278d9Sbluhm print("wrong payload length, expected", recvsz) 92d6191a09Sbluhm exit(1) 93d6191a09Sbluhm 94d6191a09Sbluhmexit(0) 95