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