def setUp(self): """ """ import random #constants self.thisside = 0 self.thatside = 1 self.tcb = tcptest.tcb() self.tcb.ip = { self.thisside : pcs.inet_atol("10.211.55.210") , \ self.thatside : pcs.inet_atol("10.211.55.255")} self.tcb.ipid = { self.thisside : random.randrange(1,(1<<16)-1) , \ self.thatside : 0} self.tcb.tcpport = { self.thisside : random.randrange(50000,60000) , \ self.thatside : 9} self.tcb.tcpsequence = { self.thisside : random.randrange(1,(1<<32)-1),\ self.thatside : 0} self.tcb.ether = \ { self.thisside : ethernet.ether_atob("00:1c:42:9d:57:c9") , \ self.thatside : ethernet.ether_atob("00:1c:42:db:c5:22") } self.tcb.output = { self.thisside : pcs.PcapConnector("ed0") ,\ self.thatside : pcs.PcapConnector("ed0") }
def setUp(self): """ As it's the first test, I will use this method as a simple TCB. I'm planning use some object to handle that. In this version, TCB is being initialized with test setup values. Tcpdump file format would a form to store setup values. """ import random self.tcb = self #constants self.thisside = 0 self.thatside = 1 #...Can add other sides #opt 1 - this opt reduce the scalability, and bring more code. #self.ipsrc = pcs.inet_atol("192.168.1.10") #self.ipdst = pcs.inet_atol("192.168.1.20") #opt 2 self.ip = { self.thisside : pcs.inet_atol("10.211.55.210") , \ self.thatside : pcs.inet_atol("10.211.55.220")} self.ipid = { self.thisside : random.randrange(1,(1<<16)-1) , \ self.thatside : 0} self.tcpport = { self.thisside : random.randrange(50000,60000) , \ self.thatside : 9} self.tcpsequence = { self.thisside: random.randrange(1, (1 << 32) - 1), self.thatside: 0 } # see TODO self.ether = \ { self.thisside : ethernet.ether_atob("00:1c:42:9d:57:c9") , \ self.thatside : ethernet.ether_atob("00:1c:42:db:c5:22") } # see TODO self.output = { self.thisside : pcs.PcapConnector("ed0") ,\ self.thatside : pcs.PcapConnector("ed0") }
def test_deepcopy_typelengthvaluefield(self): """Test deep copy of TypeLengthValueField. It contains three other Fields, so a deep copy should copy everything.""" addr1 = inet_atol("192.0.2.1") tf1 = pcs.Field("", 8) lf1 = pcs.Field("", 8) vf1 = pcs.Field("", 32) tlvf1 = TypeLengthValueField("tlvf1", tf1, lf1, vf1) self.assert_(isinstance(tlvf1, pcs.TypeLengthValueField)) self.assert_(isinstance(tlvf1.type, pcs.Field)) self.assert_(isinstance(tlvf1.length, pcs.Field)) self.assert_(isinstance(tlvf1.value, pcs.Field)) self.assert_(id(tf1) == id(tlvf1.type)) self.assert_(id(lf1) == id(tlvf1.length)) self.assert_(id(vf1) == id(tlvf1.value)) tlvf1.value.value = addr1 self.assertEqual(tlvf1.value.value, addr1, \ "tlvf1's value-field value not set by assignment!") addr2 = ether_atob("01:02:03:04:05:06") tlvf2 = deepcopy(tlvf1) self.assert_(id(tlvf1) != id(tlvf2)) self.assertEqual(tlvf2.packet, None, "tlvf2.packet is not None!") self.assert_(isinstance(tlvf2, pcs.TypeLengthValueField)) self.assert_(isinstance(tlvf2.type, pcs.Field)) self.assert_(isinstance(tlvf2.length, pcs.Field)) self.assert_(isinstance(tlvf2.value, pcs.Field)) # Must be a deep copy self.assert_(id(tf1) != id(tlvf2.type)) self.assert_(id(lf1) != id(tlvf2.length)) self.assert_(id(vf1) != id(tlvf2.value)) self.assertEqual(tlvf2.name, "tlvf1", \ "tlvf2's name not set by deepcopy()!") # Paranoia self.assertEqual(tlvf2.value.value, inet_atol("192.0.2.1"), \ "tlvf2's value-field value differs after deepcopy!") tlvf1.value.value = inet_atol("192.0.2.2") self.assertEqual(tlvf2.value.value, inet_atol("192.0.2.1"), \ "tlvf2's value-field value was changed by assignment to tvf1!") tlvf2.type.value = 123 self.assertNotEqual( tlvf1.type.value, tlvf2.type.value, "tlvf2's type-field value does not differ after assignment!") tlvf2.length.value = len(addr2) self.assertNotEqual( tlvf1.length.value, tlvf2.length.value, "tlvf2's length-field value does not differ after assignment!") tlvf2.value.value = addr2 self.assertNotEqual( tlvf1.type.value, tlvf2.type.value, "tvf2's type-field value does not differ after assignment!")
def test_deepcopy_typelengthvaluefield(self): """Test deep copy of TypeLengthValueField. It contains three other Fields, so a deep copy should copy everything.""" addr1 = inet_atol("192.0.2.1") tf1 = pcs.Field("", 8) lf1 = pcs.Field("", 8) vf1 = pcs.Field("", 32) tlvf1 = TypeLengthValueField("tlvf1", tf1, lf1, vf1) self.assert_(isinstance(tlvf1, pcs.TypeLengthValueField)) self.assert_(isinstance(tlvf1.type, pcs.Field)) self.assert_(isinstance(tlvf1.length, pcs.Field)) self.assert_(isinstance(tlvf1.value, pcs.Field)) self.assert_(id(tf1) == id(tlvf1.type)) self.assert_(id(lf1) == id(tlvf1.length)) self.assert_(id(vf1) == id(tlvf1.value)) tlvf1.value.value = addr1 self.assertEqual(tlvf1.value.value, addr1, \ "tlvf1's value-field value not set by assignment!") addr2 = ether_atob("01:02:03:04:05:06") tlvf2 = deepcopy(tlvf1) self.assert_(id(tlvf1) != id(tlvf2)) self.assertEqual(tlvf2.packet, None, "tlvf2.packet is not None!") self.assert_(isinstance(tlvf2, pcs.TypeLengthValueField)) self.assert_(isinstance(tlvf2.type, pcs.Field)) self.assert_(isinstance(tlvf2.length, pcs.Field)) self.assert_(isinstance(tlvf2.value, pcs.Field)) # Must be a deep copy self.assert_(id(tf1) != id(tlvf2.type)) self.assert_(id(lf1) != id(tlvf2.length)) self.assert_(id(vf1) != id(tlvf2.value)) self.assertEqual(tlvf2.name, "tlvf1", \ "tlvf2's name not set by deepcopy()!") # Paranoia self.assertEqual(tlvf2.value.value, inet_atol("192.0.2.1"), \ "tlvf2's value-field value differs after deepcopy!") tlvf1.value.value = inet_atol("192.0.2.2") self.assertEqual(tlvf2.value.value, inet_atol("192.0.2.1"), \ "tlvf2's value-field value was changed by assignment to tvf1!") tlvf2.type.value = 123 self.assertNotEqual(tlvf1.type.value, tlvf2.type.value, "tlvf2's type-field value does not differ after assignment!") tlvf2.length.value = len(addr2) self.assertNotEqual(tlvf1.length.value, tlvf2.length.value, "tlvf2's length-field value does not differ after assignment!") tlvf2.value.value = addr2 self.assertNotEqual(tlvf1.type.value, tlvf2.type.value, "tvf2's type-field value does not differ after assignment!")
def resetTcb(self, tcb): tcb.ip = { self.thisside : pcs.inet_atol("10.211.55.210") , \ self.thatside : pcs.inet_atol("10.211.55.220")} tcb.ipid = { self.thisside : random.randrange(1, (1<<16)-1) , \ self.thatside : 0} tcb.tcpport = { self.thisside : random.randrange(50000, 60000) , \ self.thatside : 9} tcb.tcpsequence = { self.thisside : random.randrange(1,(1<<32)-1),\ self.thatside : 0} tcb.ether = \ { self.thisside : ethernet.ether_atob("00:1c:42:9d:57:c9") , \ self.thatside : ethernet.ether_atob("00:1c:42:db:c5:22") } tcb.output = { self.thisside : pcs.PcapConnector("ed0") , \ self.thatside : pcs.PcapConnector("ed0") }
def test_dhcpv4_decode(self): """This test reads from a pre-stored pcap file.""" file = PcapConnector("dhcp_minimal.pcap") packet = file.readpkt() chain = packet.chain() #print chain ether = chain.packets[0] assert (ether != None) ip = chain.packets[1] assert (ip != None) udp = chain.packets[2] assert (udp != None) dhcp = chain.packets[3] assert (dhcp != None) self.assertEqual(dhcp.op, 1, "op not equal") self.assertEqual(dhcp.xid, 0xffff0001, "xid not equal") self.assertEqual(dhcp.secs, 42848, "secs not equal") self.assertEqual(dhcp.flags, 0x8000, "flags not equal") mac = ether_atob("52:54:00:12:34:56") #print ether_btoa(dhcp.chaddr) self.assertEqual(dhcp.chaddr[:dhcp.hlen], mac, "mac not equal") self.assertEqual( len(dhcp.options), 6, "wrong option field count %d should be %d" % (len(dhcp.options), 6)) # Not a tlv field self.assertEqual(dhcp.options[0], pcs.packets.dhcpv4_options.DHCP_OPTIONS_COOKIE, "invalid cookie value") # TLV fields self.assertEqual(dhcp.options[1].value, 1460, "invalid maximum message size value") self.assertEqual(dhcp.options[2].value, "FreeBSD:i386:6.3-RELEASE", \ "invalid vendor class") self.assertEqual(dhcp.options[3].value, pcs.packets.dhcpv4_options.DHCPDISCOVER, "invalud dhcp message type") # Not a tlv field self.assertEqual(dhcp.options[4], pcs.packets.dhcpv4_options.DHO_END, "invalid end value")
def test_dhcpv4_decode(self): """This test reads from a pre-stored pcap file.""" file = PcapConnector("dhcp_minimal.pcap") packet = file.readpkt() chain = packet.chain() #print chain ether = chain.packets[0] assert (ether != None) ip = chain.packets[1] assert (ip != None) udp = chain.packets[2] assert (udp != None) dhcp = chain.packets[3] assert (dhcp != None) self.assertEqual(dhcp.op, 1, "op not equal") self.assertEqual(dhcp.xid, 0xffff0001, "xid not equal") self.assertEqual(dhcp.secs, 42848, "secs not equal") self.assertEqual(dhcp.flags, 0x8000, "flags not equal") mac = ether_atob("52:54:00:12:34:56") #print ether_btoa(dhcp.chaddr) self.assertEqual(dhcp.chaddr[:dhcp.hlen], mac, "mac not equal") self.assertEqual(len(dhcp.options), 6, "wrong option field count %d should be %d" % (len(dhcp.options), 6)) # Not a tlv field self.assertEqual(dhcp.options[0], pcs.packets.dhcpv4_options.DHCP_OPTIONS_COOKIE, "invalid cookie value") # TLV fields self.assertEqual(dhcp.options[1].value, 1460, "invalid maximum message size value") self.assertEqual(dhcp.options[2].value, "FreeBSD:i386:6.3-RELEASE", \ "invalid vendor class") self.assertEqual(dhcp.options[3].value, pcs.packets.dhcpv4_options.DHCPDISCOVER, "invalud dhcp message type") # Not a tlv field self.assertEqual(dhcp.options[4], pcs.packets.dhcpv4_options.DHO_END, "invalid end value")
def test_dhcpv4_encode(self): p = dhcpv4() assert (p != None) p.op = pcs.packets.dhcpv4.BOOTREQUEST p.htype = pcs.packets.dhcpv4.HTYPE_ETHER p.hlen = 6 # sizeof(struct ether_addr) p.hops = 99 p.xid = 0xABADCAFE p.secs = 123 p.flags = pcs.packets.dhcpv4.BOOTP_BROADCAST p.ciaddr = inet_atol("1.2.3.4") p.yiaddr = inet_atol("5.6.7.8") p.siaddr = inet_atol("9.10.11.12") p.giaddr = inet_atol("13.14.15.16") p.chaddr = ether_atob("00:01:02:03:04:05") p.sname = "fubar" p.file = "barfu" # Append DHCP options, which MUST include the cookie. p.options.append(dhcpv4_options.cookie().field()) # Maximum DHCP message size. msz = dhcpv4_options.dhcp_max_message_size() msz.value = 1460 p.options.append(msz.field()) # DHCP message type. dhcp = dhcpv4_options.dhcp_message_type() dhcp.value = DHCPDISCOVER p.options.append(dhcp.field()) # DHCP vendor class. vc = dhcpv4_options.dhcp_class_identifier() vc.value = "FreeBSD:amd64:7-CURRENT" p.options.append(vc.field()) # BOOTP options end marker. end = dhcpv4_options.end() p.options.append(end.field()) # Pad BOOTP payload to 32-bit width. padlen = 4 - (len(p.bytes) % 4) pad = dhcpv4_options.pad(padlen) p.options.append(pad.field()) p.encode() #hd = hexdumper() #print p #print hd.dump2(p.bytes) gotttted = p.bytes expected = \ "\x01\x01\x06\x63\xAB\xAD\xCA\xFE" \ "\x00\x7B\x80\x00\x01\x02\x03\x04" \ "\x05\x06\x07\x08\x09\x0A\x0B\x0C" \ "\x0D\x0E\x0F\x10\x00\x01\x02\x03" \ "\x04\x05\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x66\x75\x62\x61" \ "\x72\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x62\x61\x72\x66" \ "\x75\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x63\x82\x53\x63" \ "\x39\x02\x05\xB4\x35\x01\x01\x3C" \ "\x17\x46\x72\x65\x65\x42\x53\x44" \ "\x3A\x61\x6D\x64\x36\x34\x3A\x37" \ "\x2D\x43\x55\x52\x52\x45\x4E\x54" \ "\xFF\x00\x00\x00" self.assertEqual(expected, gotttted, "test encoding")
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-i", "--interface", dest="interface", default=None, help="Network interface to send on.") parser.add_option("-t", "--target", dest="ip_target", default=None, help="IPv4 target address to lookup.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="IPv4 source address to use.") parser.add_option("-d", "--ether_destination", dest="ether_destination", default=None, help="Ethernet destination address to use.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="Ethernet source address to use.") parser.add_option("-o", "--source-port", dest="source_port", default=None, help="Tcp source port.") parser.add_option("-x", "--destination-port", dest="destination_port", default=None, help="Tcp destination port.") (options, args) = parser.parse_args() import random ipid = random.randrange(1, (1 << 16) - 1) tcpsport = random.randrange(50000, 60000) #int(options.source_port ) tcpsequence = random.randrange(1, (1 << 32) - 1) output = pcs.PcapConnector(options.interface) replyip = None replytcp = None reply = None packet = None # SYN what = "SYN" ip1 = ipv4.ipv4() ip1.version = 4 ip1.hlen = 5 ip1.tos = 0 ip1.id = ++ipid ip1.flags = 0 ip1.offset = 0 ip1.ttl = 64 ip1.protocol = pcs.IPPROTO_TCP ip1.src = pcs.inet_atol(options.ip_source) ip1.dst = pcs.inet_atol(options.ip_target) tcp1 = tcp.tcp() tcp1.sport = tcpsport tcp1.dport = int(options.destination_port) tcp1.sequence = tcpsequence tcpsequence = tcpsequence + 1 # SYN consumes the sequence tcp1.ack_number = 0 tcp1.offset = 5 tcp1.urgent = 0 tcp1.ack = 0 tcp1.push = 0 tcp1.reset = 0 tcp1.syn = 1 tcp1.fin = 0 tcp1.window = (1 << 16) - 1 tcp1.urg_point = 0 #tcp1.options tcp1.checksum = tcp_cksum(tcp1, ip1) ip1.length = len(ip1.bytes) + len(tcp1.bytes) # important, only calcs the ip checksum after fill length field ip1.checksum = ip_cksum(ip1) ether1 = ethernet.ethernet() ether1.src = ethernet.ether_atob(options.ether_source) ether1.dst = ethernet.ether_atob(options.ether_destination) ether1.type = 0x800 packet = pcs.Chain([ether1, ip1, tcp1]) print "\n%s---------------------------------" % what print tcp1 print "---------------------------------" out = output.write(packet.bytes, len(packet.bytes)) ## SYN # SYN+ACK what = "SYN+ACK" while 1: reply = output.read() packet = ethernet.ethernet(reply) try: replyip = packet.data replytcp = replyip.data if (ip1.src==replyip.dst and \ ip1.dst==replyip.src and \ tcp1.sport==replytcp.dport and \ tcp1.dport==replytcp.sport): break except: #it cannot be a tcp packet (without sport:) pass print "\n%s---------------------------------" % what print packet.data.data print "---------------------------------" ## SYN+ACK # ACK 134,187 what = "ACK (SYN)" ip3 = ipv4.ipv4() ip3.version = 4 ip3.hlen = 5 ip3.tos = 0 ip3.id = ++ipid ip3.flags = 0 ip3.offset = 0 ip3.ttl = 64 ip3.protocol = pcs.IPPROTO_TCP ip3.src = pcs.inet_atol(options.ip_source) ip3.dst = pcs.inet_atol(options.ip_target) tcp3 = tcp.tcp() tcp3.sport = tcpsport tcp3.dport = int(options.destination_port) tcp3.sequence = tcpsequence ##tcpsequence = tcpsequence + 1 # ACK DOES NOT consumes the sequence tcp3.ack_number = replytcp.sequence + 1 tcp3.offset = 5 tcp3.urgent = 0 tcp3.ack = 1 tcp3.push = 0 tcp3.reset = 0 tcp3.syn = 0 tcp3.fin = 0 tcp3.window = (1 << 16) - 1 tcp3.urg_point = 0 #tcp3.options tcp3.checksum = tcp_cksum(tcp3, ip3) ip3.length = len(ip3.bytes) + len(tcp3.bytes) # important, only calcs the ip checksum after fill length field ip3.checksum = ip_cksum(ip3) ether3 = ethernet.ethernet() ether3.src = ethernet.ether_atob(options.ether_source) ether3.dst = ethernet.ether_atob(options.ether_destination) ether3.type = 0x800 packet = pcs.Chain([ether3, ip3, tcp3]) print "\n%s---------------------------------" % what print tcp3 print "---------------------------------" out = output.write(packet.bytes, len(packet.bytes)) ## ACK # FIN 188,241 what = "FIN" ip4 = ipv4.ipv4() ip4.version = 4 ip4.hlen = 5 ip4.tos = 0 ip4.id = ++ipid ip4.flags = 0 ip4.offset = 0 ip4.ttl = 64 ip4.protocol = pcs.IPPROTO_TCP ip4.src = pcs.inet_atol(options.ip_source) ip4.dst = pcs.inet_atol(options.ip_target) tcp4 = tcp.tcp() tcp4.sport = tcpsport tcp4.dport = int(options.destination_port) tcp4.sequence = tcpsequence tcpsequence = tcpsequence + 1 # FIN consumes the sequence tcp4.ack_number = replytcp.sequence + 1 tcp4.offset = 5 tcp4.urgent = 0 tcp4.ack = 1 tcp4.push = 0 tcp4.reset = 0 tcp4.syn = 0 tcp4.fin = 1 tcp4.window = (1 << 16) - 1 tcp4.urg_point = 0 #tcp4.options tcp4.checksum = tcp_cksum(tcp4, ip4) ip4.length = len(ip4.bytes) + len(tcp4.bytes) # important, only calcs the ip checksum after fill length field ip4.checksum = ip_cksum(ip4) ether4 = ethernet.ethernet() ether4.src = ethernet.ether_atob(options.ether_source) ether4.dst = ethernet.ether_atob(options.ether_destination) ether4.type = 0x800 packet = pcs.Chain([ether4, ip4, tcp4]) print "\n%s---------------------------------" % what print tcp4 print "---------------------------------" out = output.write(packet.bytes, len(packet.bytes)) ## FIN # ACK (FIN) what = "ACK (FIN)" while 1: reply = output.read() packet = ethernet.ethernet(reply) try: replyip = packet.data replytcp = replyip.data if (ip1.src==replyip.dst and \ ip1.dst==replyip.src and \ tcp1.sport==replytcp.dport and \ tcp1.dport==replytcp.sport): break except: #it cannot be a tcp packet (without sport:) pass print "\n%s---------------------------------" % what print packet.data.data print "---------------------------------" ## ACK (FIN) # FIN what = "FIN" while 1: reply = output.read() packet = ethernet.ethernet(reply) try: replyip = packet.data replytcp = replyip.data if (ip1.src==replyip.dst and \ ip1.dst==replyip.src and \ tcp1.sport==replytcp.dport and \ tcp1.dport==replytcp.sport): break except: #it cannot be a tcp packet (without sport:) pass print "\n%s---------------------------------" % what print packet.data.data print "---------------------------------" ## FIN # ACK (FIN) 288,341 what = "ACK (FIN)" ip7 = ipv4.ipv4() ip7.version = 4 ip7.hlen = 5 ip7.tos = 0 ip7.id = ++ipid ip7.flags = 0 ip7.offset = 0 ip7.ttl = 64 ip7.protocol = pcs.IPPROTO_TCP ip7.src = pcs.inet_atol(options.ip_source) ip7.dst = pcs.inet_atol(options.ip_target) tcp7 = tcp.tcp() tcp7.sport = tcpsport tcp7.dport = int(options.destination_port) tcp7.sequence = tcpsequence ##tcpsequence = tcpsequence + 1 # ACK DOES NOT consumes the sequence tcp7.ack_number = replytcp.sequence + 1 tcp7.offset = 5 tcp7.urgent = 0 tcp7.ack = 1 tcp7.push = 0 tcp7.reset = 0 tcp7.syn = 0 tcp7.fin = 0 tcp7.window = (1 << 16) - 1 tcp7.urg_point = 0 #tcp7.options tcp7.checksum = tcp_cksum(tcp7, ip7) ip7.length = len(ip7.bytes) + len(tcp7.bytes) # important, only calcs the ip checksum after fill length field ip7.checksum = ip_cksum(ip7) ether7 = ethernet.ethernet() ether7.src = ethernet.ether_atob(options.ether_source) ether7.dst = ethernet.ether_atob(options.ether_destination) ether7.type = 0x800 packet = pcs.Chain([ether7, ip7, tcp7]) print "\n%s---------------------------------" % what print tcp7 print "---------------------------------" out = output.write(packet.bytes, len(packet.bytes))