def test_udpv4_raw(self): # Create a packet for raw injection and verify it meets criteria. from pcs import inet_atol from pcs.packets.payload import payload c = ethernet(src="\x01\x02\x03\x04\x05\x06", \ dst="\xff\xff\xff\xff\xff\xff") / \ ipv4(src=inet_atol("192.168.123.17"), \ dst=inet_atol("192.0.2.2"), id=5235) / \ udp(sport=67, dport=68) / \ payload("foobar\n") c.calc_lengths() c.calc_checksums() c.encode() expected = \ "\xFF\xFF\xFF\xFF\xFF\xFF\x01\x02" \ "\x03\x04\x05\x06\x08\x00\x45\x00" \ "\x00\x23\x14\x73\x00\x00\x40\x11" \ "\x68\x9B\xC0\xA8\x7B\x11\xC0\x00" \ "\x02\x02\x00\x43\x00\x44\x00\x0F" \ "\xC0\x48\x66\x6F\x6F\x62\x61\x72" \ "\x0A" gotttted = c.bytes self.assertEqual(expected, gotttted, "test raw encoding")
def test_icmpv4_compare(self): """Test the underlying __compare__ functionality of the packet. Two packets constructed from the same bytes should be equal and two that are not should not be equal.""" file = PcapConnector("loopping.out") packet = file.read() ip1 = ipv4(packet[file.dloff : len(packet)]) ip2 = ipv4(packet[file.dloff : len(packet)]) assert ip1 != None assert ip2 != None icmp1 = ip1.data icmp2 = ip2.data self.assertEqual(icmp1, icmp2, "packets should be equal but are not") icmp1.code = 32 self.assertNotEqual(icmp1, icmp2, "packets compare equal but should not")
def test_tcpv4_read(self): """This test reads from a pre-stored pcap file generated with tcpdump.""" file = PcapConnector("wwwtcp.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) tcppacket = tcp(ip.data.bytes) self.assertEqual(tcppacket.sport, 53678, "source port not equal %d" % tcppacket.sport) self.assertEqual(tcppacket.dport, 80, "destination port not equal %d" % tcppacket.dport) self.assertEqual(tcppacket.sequence, 1351059655, "sequence number not equal %d" % tcppacket.sequence) self.assertEqual(tcppacket.ack_number, 0, "ack number not equal %d" % tcppacket.ack_number) self.assertEqual(tcppacket.offset, 11, "offset not equal %d" % tcppacket.offset) self.assertEqual(tcppacket.reserved, 0, "reserved not equal %d" % tcppacket.reserved) self.assertEqual(tcppacket.urgent, 0, "urgent not equal %d" % tcppacket.urgent) self.assertEqual(tcppacket.ack, 0, "ack not equal %d" % tcppacket.ack) self.assertEqual(tcppacket.push, 0, "push not equal %d" % tcppacket.push) self.assertEqual(tcppacket.reset, 0, "reset not equal %d" % tcppacket.reset) self.assertEqual(tcppacket.syn, 1, "syn not equal %d" % tcppacket.syn) self.assertEqual(tcppacket.fin, 0, "fin not equal %d" % tcppacket.fin) self.assertEqual(tcppacket.window, 65535, "window not equal %d" % tcppacket.window) self.assertEqual(tcppacket.checksum, 15295, "checksum not equal %d" % tcppacket.checksum)
def test_tcpv4_compare(self): """Test the underlying __compare__ functionality of the packet. Two packets constructed from the same bytes should be equal and two that are not should not be equal.""" file = PcapConnector("wwwtcp.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) tcp1 = tcp(ip.data.bytes) tcp2 = tcp(ip.data.bytes) assert (tcp1 != None) assert (tcp2 != None) #hd = hexdumper() #print hd.dump(tcp1.bytes) #print hd.dump(tcp2.bytes) # tcp1 should not equal tcp2, they are different instances, # and will therefore have different timestamps -- unless # we end up racing the system clock. self.assertNotEqual(tcp1, tcp2, "instances SHOULD be equal") self.assertEqual(tcp1.bytes, tcp2.bytes, "packet data SHOULD be equal") tcp1.dport = 0 self.assertNotEqual(tcp1.bytes, tcp2.bytes, "packet data SHOULD NOT be equal")
def test_ipv4_ra(self): # create one packet with the IP Router Alert option, # and check that it is as you'd expect. ip = ipv4() assert (ip != None) ip.version = 4 ip.hlen = 6 # XXX We add an IP option below. ip.tos = 0 ip.length = 24 # a bare IP header w/o data ip.id = 1 ip.flags = IP_DF ip.offset = 0 ip.ttl = 1 ip.protocol = 2 # a fake IGMP packet ip.src = inet_atol("192.0.2.1") ip.dst = inet_atol("224.0.0.22") # Add Router Alert option. # hlen should, in fact, be 6 words after adding a single RA option. ip.options.append(ipv4opt(IPOPT_RA)) ip.calc_checksum() #hd = hexdumper() #print hd.dump(ip.bytes) expected = "\x46\x00\x00\x18\x00\x01\x40\x00" \ "\x01\x02\x42\xC7\xC0\x00\x02\x01" \ "\xE0\x00\x00\x16\x94\x04\x00\x00" gotttted = ip.bytes self.assertEqual(expected, gotttted, "packet bytes not expected")
def test_icmpv4_compare(self): """Test the underlying __compare__ functionality of the packet. Two packets constructed from the same bytes should be equal and two that are not should not be equal.""" file = PcapConnector("loopping.out") packet = file.read() ip1 = ipv4(packet[file.dloff:len(packet)]) ip2 = ipv4(packet[file.dloff:len(packet)]) assert (ip1 != None) assert (ip2 != None) icmp1 = ip1.data icmp2 = ip2.data self.assertEqual(icmp1, icmp2, "packets should be equal but are not") icmp1.code = 32 self.assertNotEqual(icmp1, icmp2, "packets compare equal but should not")
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group to spoof a leave message for.") parser.add_option("-A", "--no-router-alert", action="store_true", dest="no_ra", help="Disable the use of the IP Router Alert option.") (options, args) = parser.parse_args() if options.igmp_group is None or \ options.ether_source is None or \ options.ether_iface is None or \ options.ip_source is None: print "A required argument is missing." return output = PcapConnector(options.ether_iface) c = ethernet(src=ether_atob(options.ether_source), \ dst=ETHER_MAP_IP_MULTICAST(INADDR_ALLRTRS_GROUP)) / \ ipv4(flags=IP_DF, id=123, ttl=1, \ src=inet_atol(options.ip_source), \ dst=INADDR_ALLRTRS_GROUP) / \ igmp(type=IGMP_HOST_LEAVE_MESSAGE) / \ igmpv2(group=inet_atol(options.igmp_group)) c.fixup() out = output.write(c.bytes, len(c.bytes))
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group to spoof an IGMPv3 leave for.") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ip_source is None or \ options.igmp_group is None: print "Non-optional argument missing." return # Create an IGMPv3 change-to-include report for the given group # with no sources, which means we're leaving the group. # IGMPv3 Host Reports are always sent to IGMP.MCAST.NET (224.0.0.22), # and must always contain the Router Alert option. c = ethernet(src=ether_atob(options.ether_source), \ dst=ETHER_MAP_IP_MULTICAST(INADDR_ALLRPTS_GROUP)) / \ ipv4(src=inet_atol(options.ip_source), dst=INADDR_ALLRPTS_GROUP, \ ttl=1, flags=IP_DF, options=[ipvt4opt(IPOPT_RA)]) / \ igmp(type=IGMP_v3_HOST_MEMBERSHIP_REPORT) / \ igmpv3.report(records=[GroupRecordField("", \ group=inet_atol(options.igmp_group), \ type=IGMP_CHANGE_TO_INCLUDE)]) c.fixup() # Send it. output = PcapConnector(options.ether_iface) out = output.write(c.bytes, len(c.bytes))
def test_icmpv4_read(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff : len(packet)]) assert ip != None icmp = ip.data self.assertEqual(icmp.type, 8, "type not equal to 8") self.assertEqual(icmp.code, 0, "code not equal to 0")
def executeTrigger(self, pkt): """ Execute the trigger action the pkt which satisfies the trigger's action conditions. @param pkt: The packet against which a trigger is actioned @return: A trigger Chain for transmission, None if action is internal """ retChain = None # Action based on trigger type if self.action == Trigger.Trigger.STOP: # Test if pkt is really a HTTP packet (p, i) = pkt.chain().find_first_of(pcs.packets.http.httpResponse) if not p: self.logger.debug("HTTP trigger.STOP:\n%s" % pkt.chain()) raise PcapReplayError(Trigger.ERR_PCAPR_TRIGGER_INVALID, 'executeTrigger : Invalid trigger/pkt ' + 'pair execution') # Create a terminating response chain for xmit by the caller ether = pkt e = ethernet() e.dst = ether.src e.src = ether.dst e.type = ether.type ip = pkt.data if type(ip) == pcs.packets.ipv4.ipv4: i = ipv4() i.tos = ip.tos i.protocol = ip.protocol i.id = 0 i.flags = 0 elif type(ip) == pcs.packets.ipv6.ipv6: i = ipv6() i.traffic_class = ip.traffic_class i.next_header = ip.next_header i.src = ip.dst i.dst = ip.src tcp = pkt.data.data t = pcs.packets.tcp.tcp() t.sport = tcp.dport t.dport = tcp.sport t.reset = 1 t.ack = 1 t.ack_number = tcp.ack_number t.sequence = tcp.sequence t.data = None retChain = pcs.Chain([e, i, t]) retChain.fixup() return retChain
def test_icmpv4_read(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) icmp = ip.data self.assertEqual(icmp.type, 8, "type not equal to 8") self.assertEqual(icmp.code, 0, "code not equal to 0")
def test_ipv4(self): # create one packet, copy its bytes, then compare their fields ip = ipv4() assert (ip != None) ip.version = 4 ip.hlen = 5 ip.tos = 0 ip.length = 64 ip.id = 1 ip.flags = 1 ip.offset = 2 ip.ttl = 33 ip.protocol = 6 ip.src = 2130706433 ip.dst = 2130706433 # Create a packet to compare against ipnew = ipv4() ipnew.decode(ip.bytes) self.assertEqual(ip.bytes, ipnew.bytes, "bytes not equal") for field in ip._fieldnames: self.assertEqual(getattr(ip, field), getattr(ipnew, field), ("%s not equal" % field))
def test_ipv4_compare(self): """Test the underlying __compare__ functionality of the packet. Two packets constructed from the same bytes should be equal and two that are not should not be equal.""" file = PcapConnector("loopping.out") packet = file.readpkt() ip1 = packet.data ip2 = ipv4(packet.data.bytes) assert (ip1 != None) assert (ip2 != None) self.assertEqual(ip1, ip2, "packets should be equal but are not") ip1.dst = 0xffffffffL self.assertNotEqual(ip1, ip2, "packets compare equal but should not")
def test_tcpv4_println(self): """Test the println method.""" file = PcapConnector("wwwtcp.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) tcppacket = tcp(ip.data.bytes) assert (tcppacket) # pre tcp options: #expected = "<TCP: sport: 53678, dport: 80, sequence: 1351059655, ack_number: 0, offset: 11, reserved: 0, urgent: 0, ack: 0, push: 0, reset: 0, syn: 1, fin: 0, window: 65535, checksum: 15295, urg_pointer: 0>" # post tcp options: # XXX println() uses __repr__(), not __str__(). the rules for the # game "python" say we have to preserve the structure of # objects returned by __repr__(). expected = "<TCP: sport: 53678, dport: 80, sequence: 1351059655, " \ "ack_number: 0, offset: 11, reserved: 0, " \ "ns: 0, cwr: 0, ece: 0, urgent: 0, " \ "ack: 0, push: 0, reset: 0, syn: 1, fin: 0, " \ "window: 65535, checksum: 15295, urg_pointer: 0, " \ "options: [" \ "[Field: mss, Value: " \ "<pcs.Field name v, 16 bits, " \ "default 1460, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: wscale, Value: " \ "<pcs.Field name v, 8 bits, " \ "default 0, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: nop, Value: 1], " \ "[Field: tstamp, Value: " \ "<pcs.Field name v, 64 bits, " \ "default 0, discriminator 0>], " \ "[Field: sackok, Value: " \ "<pcs.Field name v, 0 bits, " \ "default 0, discriminator 0>], " \ "[Field: end, Value: 0], " \ "[Field: end, Value: 0]" \ "]>" # unusual naming to make it easier to spot deltas in an # 80 column display. gotttted = tcppacket.println() self.assertEqual( expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_tcpv4_println(self): """Test the println method.""" file = PcapConnector("wwwtcp.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) tcppacket = tcp(ip.data.bytes) assert (tcppacket) # pre tcp options: #expected = "<TCP: sport: 53678, dport: 80, sequence: 1351059655, ack_number: 0, offset: 11, reserved: 0, urgent: 0, ack: 0, push: 0, reset: 0, syn: 1, fin: 0, window: 65535, checksum: 15295, urg_pointer: 0>" # post tcp options: # XXX println() uses __repr__(), not __str__(). the rules for the # game "python" say we have to preserve the structure of # objects returned by __repr__(). expected = "<TCP: sport: 53678, dport: 80, sequence: 1351059655, " \ "ack_number: 0, offset: 11, reserved: 0, " \ "ns: 0, cwr: 0, ece: 0, urgent: 0, " \ "ack: 0, push: 0, reset: 0, syn: 1, fin: 0, " \ "window: 65535, checksum: 15295, urg_pointer: 0, " \ "options: [" \ "[Field: mss, Value: " \ "<pcs.Field name v, 16 bits, " \ "default 1460, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: wscale, Value: " \ "<pcs.Field name v, 8 bits, " \ "default 0, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: nop, Value: 1], " \ "[Field: tstamp, Value: " \ "<pcs.Field name v, 64 bits, " \ "default 0, discriminator 0>], " \ "[Field: sackok, Value: " \ "<pcs.Field name v, 0 bits, " \ "default 0, discriminator 0>], " \ "[Field: end, Value: 0], " \ "[Field: end, Value: 0]" \ "]>" # unusual naming to make it easier to spot deltas in an # 80 column display. gotttted = tcppacket.println() self.assertEqual(expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_icmpv4_print(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface and tests the __str__ method to make sure the correct values are printed.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff : len(packet)]) assert ip != None icmp = ip.data # test_string = "ICMPv4\ntype 8\ncode 0\nchecksum 60550\n" test_string = "ICMPv4 Echo Request\ntype 8\ncode 0\nchecksum 60550\n" string = icmp.__str__() self.assertEqual(string, test_string, "strings are not equal \nexpected %s \ngot %s " % (test_string, string))
def test_ipv4_println(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface and tests the __str__ method to make sure the correct values are printed.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) expected = "<IPv4: version: 4, hlen: 5, tos: 0, length: 84, " \ "id: 59067, flags: 0, offset: 0, ttl: 64, protocol: 1, " \ "checksum: 0, src: 2130706433, dst: 2130706433, options: []>" gotttted = ip.println() self.assertEqual(expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_ipv4_println(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface and tests the __str__ method to make sure the correct values are printed.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) expected = "<IPv4: version: 4, hlen: 5, tos: 0, length: 84, " \ "id: 59067, flags: 0, offset: 0, ttl: 64, protocol: 1, " \ "checksum: 0, src: 2130706433, dst: 2130706433, options: []>" gotttted = ip.println() self.assertEqual( expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_ipv4_print(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface and tests the __str__ method to make sure the correct values are printed.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) expected = "IPv4\nversion 4\nhlen 5\ntos 0\nlength 84\n" \ "id 59067\nflags 0\noffset 0\nttl 64\nprotocol 1\n" \ "checksum 0\nsrc 127.0.0.1\ndst 127.0.0.1\n" \ "options []\n" gotttted = ip.__str__() self.assertEqual(expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_icmpv4_print(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface and tests the __str__ method to make sure the correct values are printed.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) icmp = ip.data #test_string = "ICMPv4\ntype 8\ncode 0\nchecksum 60550\n" test_string = "ICMPv4 Echo Request\ntype 8\ncode 0\nchecksum 60550\n" string = icmp.__str__() self.assertEqual(string, test_string, "strings are not equal \nexpected %s \ngot %s " % (test_string, string))
def createIpv4Pkt(self, ipproto=6, layer1=None, layer2=None): e = ethernet() e.dst = self.dmac e.src = self.smac e.type = 0x0800 i = ipv4() i.protocol = ipproto i.id = 0 i.flags = 0 i.src = self.src i.dst = self.dst e.data = i i.data = layer1 layer1.data = layer2 if layer2 == None: retChain = pcs.Chain([e, i, layer1]).packets[0] else: retChain = pcs.Chain([e, i, layer1, layer2]).packets[0] return retChain
def test_ipv4_read(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) self.assertEqual(ip.version, 4, "version not equal %d" % ip.version) self.assertEqual(ip.hlen, 5, "hlen not equal %d" % ip.hlen) self.assertEqual(ip.tos, 0, "tos not equal %d" % ip.tos) self.assertEqual(ip.length, 84, "length not equal %d" % ip.length) self.assertEqual(ip.id, 59067, "id not equal %d" % ip.id) self.assertEqual(ip.flags, 0, "flags not equal %d" % ip.flags) self.assertEqual(ip.offset, 0, "offset not equal %d" % ip.offset) self.assertEqual(ip.ttl, 64, "ttl not equal %d" % ip.ttl) self.assertEqual(ip.protocol, 1, "protocol not equal %d" % ip.protocol) self.assertEqual(ip.src, inet_atol("127.0.0.1"), "src not equal %d" % ip.src) self.assertEqual(ip.dst, inet_atol("127.0.0.1"), "dst not equal %d" % ip.dst)
def test_ipv4_print(self): """This test reads from a pre-stored pcap file generated with tcpdump and ping on the loopback interface and tests the __str__ method to make sure the correct values are printed.""" file = PcapConnector("loopping.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) expected = "IPv4\nversion 4\nhlen 5\ntos 0\nlength 84\n" \ "id 59067\nflags 0\noffset 0\nttl 64\nprotocol 1\n" \ "checksum 0\nsrc 127.0.0.1\ndst 127.0.0.1\n" \ "options []\n" gotttted = ip.__str__() self.assertEqual( expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_tcpv4_str(self): """Test the ___str__ method to make sure the correct values are printed.""" file = PcapConnector("wwwtcp.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) tcppacket = tcp(ip.data.bytes) assert (tcppacket) # pre tcp options: #expected = "TCP\nsport 53678\ndport 80\nsequence 1351059655\nack_number 0\noffset 11\nreserved 0\nns 0\ncwr 0\nece 0\nurgent 0\nack 0\npush 0\nreset 0\nsyn 1\nfin 0\nwindow 65535\nchecksum 15295\nurg_pointer 0\n" # post tcp options: expected = "TCP\nsport 53678\ndport 80\nsequence 1351059655\nack_number 0\noffset 11\nreserved 0\nns 0\ncwr 0\nece 0\nurgent 0\nack 0\npush 0\nreset 0\nsyn 1\nfin 0\nwindow 65535\nchecksum 15295\nurg_pointer 0\n" \ "options [" \ "[Field: mss, Value: " \ "<pcs.Field name v, 16 bits, " \ "default 1460, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: wscale, Value: " \ "<pcs.Field name v, 8 bits, " \ "default 0, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: nop, Value: 1], " \ "[Field: tstamp, Value: " \ "<pcs.Field name v, 64 bits, " \ "default 0, discriminator 0>], " \ "[Field: sackok, Value: " \ "<pcs.Field name v, 0 bits, " \ "default 0, discriminator 0>], " \ "[Field: end, Value: 0], " \ "[Field: end, Value: 0]" \ "]\n" gotttted = tcppacket.__str__() self.assertEqual( expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def test_tcpv4_str(self): """Test the ___str__ method to make sure the correct values are printed.""" file = PcapConnector("wwwtcp.out") packet = file.read() ip = ipv4(packet[file.dloff:len(packet)]) assert (ip != None) tcppacket = tcp(ip.data.bytes) assert (tcppacket) # pre tcp options: #expected = "TCP\nsport 53678\ndport 80\nsequence 1351059655\nack_number 0\noffset 11\nreserved 0\nns 0\ncwr 0\nece 0\nurgent 0\nack 0\npush 0\nreset 0\nsyn 1\nfin 0\nwindow 65535\nchecksum 15295\nurg_pointer 0\n" # post tcp options: expected = "TCP\nsport 53678\ndport 80\nsequence 1351059655\nack_number 0\noffset 11\nreserved 0\nns 0\ncwr 0\nece 0\nurgent 0\nack 0\npush 0\nreset 0\nsyn 1\nfin 0\nwindow 65535\nchecksum 15295\nurg_pointer 0\n" \ "options [" \ "[Field: mss, Value: " \ "<pcs.Field name v, 16 bits, " \ "default 1460, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: wscale, Value: " \ "<pcs.Field name v, 8 bits, " \ "default 0, discriminator 0>], " \ "[Field: nop, Value: 1], " \ "[Field: nop, Value: 1], " \ "[Field: tstamp, Value: " \ "<pcs.Field name v, 64 bits, " \ "default 0, discriminator 0>], " \ "[Field: sackok, Value: " \ "<pcs.Field name v, 0 bits, " \ "default 0, discriminator 0>], " \ "[Field: end, Value: 0], " \ "[Field: end, Value: 0]" \ "]\n" gotttted = tcppacket.__str__() self.assertEqual(expected, gotttted, "strings are not equal \nexpected %s \ngotttted %s " % (expected, gotttted))
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group for a group-specific query. " "If omitted, send a general query.") parser.add_option("-M", "--maxresp", dest="igmp_maxresp", default=None, help="The maximum time for end-stations to respond " "(in seconds).") parser.add_option("-c", "--count", dest="count", default=None, help="Stop after receiving at least count responses.") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ip_source is None or \ options.count is None: print "Non-optional argument missing." return maxresp = 3 * 10 if options.igmp_maxresp is not None: maxresp = int(options.igmp_maxresp) * 10 # in units of deciseconds if options.igmp_group is None: # General query. dst = INADDR_ALLHOSTS_GROUP group = INADDR_ANY else: # Group-specific query. dst = inet_atol(options.igmp_group) group = dst # Queries don't contain the Router Alert option as they are # destined for end stations, not routers. c = ethernet(src=ether_atob(options.ether_source), \ dst=ETHER_MAP_IP_MULTICAST(dst)) / \ ipv4(flags=IP_DF, ttl=1, \ src=inet_atol(options.ip_source), \ dst=dst) / \ igmp(type=IGMP_HOST_MEMBERSHIP_QUERY, code=maxresp) / \ igmpv2(group=group) c.fixup() input = PcapConnector(options.ether_iface) input.setfilter("igmp") output = PcapConnector(options.ether_iface) out = output.write(c.bytes, len(c.bytes)) # # Wait for up to 'count' responses to the query to arrive and print them. # count = int(options.count) while count > 0: packet = input.readpkt() chain = packet.chain() if chain.packets[2].type == IGMP_v2_HOST_MEMBERSHIP_REPORT: #print chain.packets[2].println() print "%s is in %s" % \ (inet_ntop(AF_INET, struct.pack('!L', chain.packets[1].src)), \ inet_ntop(AF_INET, struct.pack('!L', chain.packets[3].group))) count -= 1
def test_field(self): ip = ipv4() assert (ip != None) self.assertRaises(pcs.FieldBoundsError, setattr, ip, 'version', 9999)
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-g", "--ether_dest", dest="ether_dest", default=None, help="The host Ethernet destination address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-D", "--ip_dest", dest="ip_dest", default=None, help="The IP destination address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group to query.") parser.add_option("-S", "--igmp_sources", dest="igmp_sources", default=None, help="Comma-delimited list of IPv4 sources for " "a group-and-source specific query.") parser.add_option("-M", "--igmp_maxresp", dest="igmp_maxresp", default=None, help="The maximum time for end-stations to " "respond (in seconds).") parser.add_option("-c", "--count", dest="count", default=None, help="Stop after receiving at least count responses.") parser.add_option("-2", "--igmp_v2_listen", action="store_true", dest="igmp_v2_listen", help="Listen for responses from IGMPv2 end-stations.") parser.add_option("-R", "--igmp_robustness", dest="igmp_robustness", default=None, help="Querier Robustness (default 2)") parser.add_option("-Q", "--igmp_qqic", dest="igmp_qqic", default=None, help="Querier's Query Interval (default 10s)") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ip_source is None or \ options.count is None: print "Non-optional argument missing." return #if options.ip_dest is not None and options.ether_dest is None: # print "Non-optional argument missing." # return maxresp = 10 * 10 if options.igmp_maxresp is not None: maxresp = int(options.igmp_maxresp) * 10 # in units of deciseconds # # Parse source list for a GSR query. # sources = [] if options.igmp_sources is not None: if options.igmp_group is None: raise "A group must be specified for a GSR query." else: for source in options.igmp_sources.split(','): sources.append(inet_atol(source)) if len(sources) == 0: raise "Error parsing source list." # Set up the vanilla packet if options.ether_dest is not None: edst = ether_atob(options.ether_dest) else: edst = ETHER_MAP_IP_MULTICAST(INADDR_ALLHOSTS_GROUP) c = ethernet(src=ether_atob(options.ether_source), dst=edst) / \ ipv4(flags=IP_DF, ttl=1, src=inet_atol(options.ip_source)) / \ igmp(type=IGMP_HOST_MEMBERSHIP_QUERY, code=maxresp) / \ igmpv3.query() ip = c.packets[1] q = c.packets[3] # IGMPv3 General Queries are always sent to ALL-SYSTEMS.MCAST.NET. # However we allow this to be overidden for protocol testing -- Windows, # in particular, doesn't seem to respond. # # We expect reports on 224.0.0.22. # Queries don't contain the Router Alert option as they are # destined for end stations, not routers. if options.igmp_robustness is not None: q.qrv = int(options.igmp_robustness) else: q.qrv = 2 # SHOULD NOT be 1, MUST NOT be 0 if options.igmp_qqic is not None: q.qqic = int(options.igmp_qqic) else: q.qqic = 10 # I query every 10 seconds if options.igmp_group is None: # General query. if options.ip_dest is not None: ip.dst = inet_atol(options.ip_dest) else: ip.dst = INADDR_ALLHOSTS_GROUP q.group = INADDR_ANY else: # Group-specific query, possibly with sources. if options.ip_dest is not None: ip.dst = inet_atol(options.ip_dest) else: ip.dst = inet_atol(options.igmp_group) q.group = ip.dst if IN_MULTICAST(ip.dst) is True and \ options.ether_dest is None: c.packets[0].dst = ETHER_MAP_IP_MULTICAST(ip.dst) for src in sources: q.sources.append(pcs.Field("", 32, default=src)) c.fixup() input = PcapConnector(options.ether_iface) input.setfilter("igmp") output = PcapConnector(options.ether_iface) out = output.write(c.bytes, len(c.bytes)) # # Wait for up to 'count' responses to the query to arrive and print them. # If options.igmp_v2_listen is True, also count responses from # end-stations which respond with IGMPv2. # # TODO: Pretty-print IGMPv3 reports. # count = int(options.count) while count > 0: packet = input.readpkt() chain = packet.chain() if ((chain.packets[2].type == IGMP_v3_HOST_MEMBERSHIP_REPORT) or ((chain.packets[2].type == IGMP_v2_HOST_MEMBERSHIP_REPORT) and \ (options.igmp_v2_listen is True))): version = 3 if chain.packets[2].type == IGMP_v2_HOST_MEMBERSHIP_REPORT: version = 2 #print chain.packets[2].println() print "%s responded to query with IGMPv%d." % \ ((inet_ntop(AF_INET, struct.pack('!L', chain.packets[1].src))), version) count -= 1
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group for a group-specific query. " "If omitted, send a general query.") parser.add_option("-S", "--seconds", dest="seconds", default=1.0, help="Number of seconds between packets.") parser.add_option("-c", "--count", dest="count", default=None, help="Stop after sending count packets.") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ip_source is None or \ options.count is None: print "Non-optional argument missing." return maxresp = 3 * 10 if options.igmp_group is None: # General query. dst = INADDR_ALLHOSTS_GROUP group = INADDR_ANY else: # Group-specific query. dst = inet_atol(options.igmp_group) group = dst # Queries don't contain the Router Alert option as they are # destined for end stations, not routers. c = ethernet(src=ether_atob(options.ether_source), \ dst=ETHER_MAP_IP_MULTICAST(dst)) / \ ipv4(flags=IP_DF, ttl=1, \ src=inet_atol(options.ip_source), \ dst=dst) / \ igmp(type=IGMP_v2_HOST_MEMBERSHIP_REPORT, code=maxresp) / \ igmpv2(group=group) c.fixup() output = PcapConnector(options.ether_iface) # # Send count packets, delayed by seconds # count = int(options.count) if count < 0: count = sys.maxint while count > 0: out = output.write(c.bytes, len(c.bytes)) count -= 1 sleep(float(options.seconds))
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-g", "--ether_dest", dest="ether_dest", default=None, help="The host Ethernet destination address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-D", "--ip_dest", dest="ip_dest", default=None, help="The IP destination address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group to query.") parser.add_option("-S", "--igmp_sources", dest="igmp_sources", default=None, help="Comma-delimited list of IPv4 sources for " "a group-and-source specific query.") parser.add_option("-M", "--igmp_maxresp", dest="igmp_maxresp", default=None, help="The maximum time for end-stations to " "respond (in seconds).") parser.add_option("-c", "--count", dest="count", default=None, help="Stop after receiving at least count responses.") parser.add_option("-2", "--igmp_v2_listen", action="store_true", dest="igmp_v2_listen", help="Listen for responses from IGMPv2 end-stations.") parser.add_option("-R", "--igmp_robustness", dest="igmp_robustness", default=None, help="Querier Robustness (default 2)") parser.add_option("-Q", "--igmp_qqic", dest="igmp_qqic", default=None, help="Querier's Query Interval (default 10s)") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ip_source is None or \ options.count is None: print "Non-optional argument missing." return #if options.ip_dest is not None and options.ether_dest is None: # print "Non-optional argument missing." # return maxresp = 10 * 10 if options.igmp_maxresp is not None: maxresp = int(options.igmp_maxresp) * 10 # in units of deciseconds # # Parse source list for a GSR query. # sources = [] if options.igmp_sources is not None: if options.igmp_group is None: raise "A group must be specified for a GSR query." else: for source in options.igmp_sources.split(','): sources.append(inet_atol(source)) if len(sources) == 0: raise "Error parsing source list." # Set up the vanilla packet if options.ether_dest is not None: edst = ether_atob(options.ether_dest) else: edst = ETHER_MAP_IP_MULTICAST(INADDR_ALLHOSTS_GROUP) c = ethernet(src=ether_atob(options.ether_source), dst=edst) / \ ipv4(flags=IP_DF, ttl=1, src=inet_atol(options.ip_source)) / \ igmp(type=IGMP_HOST_MEMBERSHIP_QUERY, code=maxresp) / \ igmpv3.query() ip = c.packets[1] q = c.packets[3] # IGMPv3 General Queries are always sent to ALL-SYSTEMS.MCAST.NET. # However we allow this to be overidden for protocol testing -- Windows, # in particular, doesn't seem to respond. # # We expect reports on 224.0.0.22. # Queries don't contain the Router Alert option as they are # destined for end stations, not routers. if options.igmp_robustness is not None: q.qrv = int(options.igmp_robustness) else: q.qrv = 2 # SHOULD NOT be 1, MUST NOT be 0 if options.igmp_qqic is not None: q.qqic = int(options.igmp_qqic) else: q.qqic = 10 # I query every 10 seconds if options.igmp_group is None: # General query. if options.ip_dest is not None: ip.dst = inet_atol(options.ip_dest) else: ip.dst = INADDR_ALLHOSTS_GROUP q.group = INADDR_ANY else: # Group-specific query, possibly with sources. if options.ip_dest is not None: ip.dst = inet_atol(options.ip_dest) else: ip.dst = inet_atol(options.igmp_group) q.group = ip.dst if IN_MULTICAST(ip.dst) is True and \ options.ether_dest is None: c.packets[0].dst = ETHER_MAP_IP_MULTICAST(ip.dst) for src in sources: q.sources.append(pcs.Field("", 32, default = src)) c.fixup() input = PcapConnector(options.ether_iface) input.setfilter("igmp") output = PcapConnector(options.ether_iface) out = output.write(c.bytes, len(c.bytes)) # # Wait for up to 'count' responses to the query to arrive and print them. # If options.igmp_v2_listen is True, also count responses from # end-stations which respond with IGMPv2. # # TODO: Pretty-print IGMPv3 reports. # count = int(options.count) while count > 0: packet = input.readpkt() chain = packet.chain() if ((chain.packets[2].type == IGMP_v3_HOST_MEMBERSHIP_REPORT) or ((chain.packets[2].type == IGMP_v2_HOST_MEMBERSHIP_REPORT) and \ (options.igmp_v2_listen is True))): version = 3 if chain.packets[2].type == IGMP_v2_HOST_MEMBERSHIP_REPORT: version = 2 #print chain.packets[2].println() print "%s responded to query with IGMPv%d." % \ ((inet_ntop(AF_INET, struct.pack('!L', chain.packets[1].src))), version) count -= 1
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-G", "--ether_dest", dest="ether_dest", default=None, help="The gateway Ethernet destination address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-d", "--ip_dest", dest="ip_dest", default=None, help="The IP destination address.") parser.add_option("-c", "--count", dest="count", default=None, help="Stop after receiving at least count responses.") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ether_dest is None or \ options.ip_source is None or \ options.count is None: print "Non-optional argument missing." return if options.ip_dest is None: idst = INADDR_DVMRP_GROUP else: idst = inet_atol(options.ip_dest) c = ethernet(src=ether_atob(options.ether_source), \ dst=ether_atob(options.ether_dest)) / \ ipv4(ttl=1, src=inet_atol(options.ip_source), dst=idst) / \ igmp(type=IGMP_DVMRP, code=DVMRP_ASK_NEIGHBORS2) / \ dvmrp(capabilities=DVMRP_CAP_DEFAULT, minor=0xFF, major=3) # # DVMRP "ask neighbors" does not contain the Router Alert option, # because DVMRP traffic is usually tunneled, and we don't need to # wake up every router on the path. # # The Ask_neighbors2 payload is: reserved, caps, minor, major: # 0x00, 0E, 0xFF, 0x03 is how mrinfo fills this out (DVMRPv3 compliant). # # PIM itself knows nothing about these messages, however, a DVMRP router # which handles these messages MAY tell you if it's peering with other # PIM routers (I believe only Ciscos do this). # c.calc_lengths() c.calc_checksums() c.encode() input = PcapConnector(options.ether_iface) input.setfilter("igmp") output = PcapConnector(options.ether_iface) out = output.write(c.bytes, len(c.bytes)) # # Wait for up to 'count' responses to the query to arrive and print them. # count = int(options.count) while count > 0: packet = input.readpkt() chain = packet.chain() if chain.packets[2].type == IGMP_DVMRP: print chain.packets[2].println() #print "%s is in %s" % \ # (inet_ntop(AF_INET, struct.pack('!L', chain.packets[1].src)), \ # inet_ntop(AF_INET, struct.pack('!L', chain.packets[2].group))) count -= 1
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-c", "--count", dest="count", default=1, help="Stop after sending (and recieving) count ECHO_RESPONSE packets..") parser.add_option("-D", "--dont_fragment", dest="df", default=False, help="Set the Don't Fragment bit.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-d", "--ip_dest", dest="ip_dest", default=None, help="The IP destination address.") parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-g", "--ether_dest", dest="ether_dest", default=None, help="The gateway Ethernet destination address.") (options, args) = parser.parse_args() c = ethernet(src=ether_atob(options.ether_source), \ dst=ether_atob(options.ether_dest)) / \ ipv4(ttl=64, src=inet_atol(options.ip_source), \ dst=inet_atol(options.ip_dest)) / \ icmpv4(type=8) / icmpv4echo(id=12345) / payload(payload="foobar") c.calc_lengths() # # Increment ICMP echo sequence number with each iteration. # output = PcapConnector(options.ether_iface) ip = c.packets[1] echo = c.packets[3] count = int(options.count) while (count > 0): c.calc_checksums() c.encode() out = output.write(c.bytes, len(c.bytes)) # packet = input.read() # print packet sleep(1) count -= 1 ip.id += 1 echo.sequence += 1
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-d", "--devname", dest="devname", default=None, help="The name of the tap device to open.") parser.add_option("-i", "--ifname", dest="ifname", default=None, help="The name of the interface to listen on.") parser.add_option("-g", "--group", dest="group", default=None, help="The IPv4 group to use for UML-style multicasts.") parser.add_option("-p", "--port", dest="port", default=None, help="The IPv4 port to use for UML-style multicasts.") parser.add_option("-a", "--ifaddr", dest="ifaddr", default=None, help="The IP address to listen on.") parser.add_option("-S", "--ether_source", dest="ether_source", default=None, help="The Ethernet address to listen on.") (options, args) = parser.parse_args() if options.devname is not None: input = TapConnector(options.devname) output = input elif options.group is not None: if options.port is None: print "Non-optional argument missing." return # XXX Currently, UmlMcast4Connector has to use the same broken # semantics as QEMU does, to see its traffic -- apps SHOULD be # joining groups on specific interfaces. # Note that we'll also end up seeing our own traffic. #input = UmlMcast4Connector(options.group, options.port, options.ifaddr) input = UmlMcast4Connector(options.group, options.port, "0.0.0.0") output = input elif options.ifname is not None: input = PcapConnector(options.ifname) output = PcapConnector(options.ifname) input.setfilter("udp port 67 or udp port 68") if options.ifaddr is None or \ options.ether_source is None: print "Non-optional argument missing." return ifaddr = inet_atol(options.ifaddr) ether_source = ether_atob(options.ether_source) ip_id = int(random.random() * 32768) # XXX Should really have an API for extracting our # local ethernet address. running = True while running is True: packet = input.readpkt() chain = packet.chain() # Must have: ether + ip + udp + dhcp. # UDP checksum ignored. Assume pcap filter above did its job. if len(chain.packets) < 4 or \ not isinstance(chain.packets[3], dhcpv4): continue i_ether = chain.packets[0] i_ip = chain.packets[1] i_udp = chain.packets[2] i_dhcp = chain.packets[3] # check dhcp htype is ethernet. # check if dhcp.cid in map. if i_dhcp.op != pcs.packets.dhcpv4.BOOTREQUEST or \ i_dhcp.htype != pcs.packets.dhcpv4.HTYPE_ETHER or \ i_dhcp.hlen != 6: continue #print i_dhcp chaddr_s = ether_btoa(i_dhcp.chaddr[:i_dhcp.hlen]) if not chaddr_s in map: print "%s not in map" % chaddr_s continue ciaddr = inet_atol(map[chaddr_s]) # from map dhcp = dhcpv4() dhcp.op = pcs.packets.dhcpv4.BOOTREPLY dhcp.htype = pcs.packets.dhcpv4.HTYPE_ETHER dhcp.hlen = 6 dhcp.hops = 0 dhcp.xid = i_dhcp.xid dhcp.flags = 0 #dhcp.ciaddr = ciaddr dhcp.siaddr = ifaddr # XXX should only fill out if i_dhcp.ciaddr was 0.0.0.0 dhcp.yiaddr = ciaddr dhcp.chaddr = i_dhcp.chaddr #dhcp.sname = "myhost" #dhcp.file = "/vmunix" #dhcp.options.append(dhcpv4_options.cookie().field()) # server ID. # XXX Weeiiird! #sid = dhcpv4_options.dhcp_server_identifier() #sid.value = ifaddr #sid.value = inet_atol("0.0.0.0") #dhcp.options.append(sid.field()) # Subnet mask. #sm = dhcpv4_options.subnet_mask() #sm.value = inet_atol("255.255.255.0") #dhcp.options.append(sm.field()) # Default gateway. #dg = dhcpv4_options.routers() #dg.value = ifaddr #dhcp.options.append(dg.field()) # Add end marker. #end = dhcpv4_options.end() #dhcp.options.append(end.field()) # Pad BOOTP payload to 32-bit width. # XXX BOOTP is problematic because the field which contains # the options needs to be clamped to 64 bytes in total. This # means we need to know the encoded length of each option. # For now, guess it... total length of an RFC-951 payload # is always 300 bytes. # this shuts up wireshark. #padlen = 300 - (len(dhcp.bytes) % 4) #padlen = 50 - (len(dhcp.bytes) % 4) #padlen = 4 #pad = dhcpv4_options.pad(padlen) #dhcp.options.append(pad.field()) # Encapsulate ethernet. ether = ethernet() ether.type = 0x0800 ether.src = ether_source ether.dst = i_dhcp.chaddr[:i_dhcp.hlen] # Encapsulate IPv4. ip = ipv4() ip.version = 4 ip.hlen = 5 ip.tos = 0 ip.id = ip_id ip.flags = 0x00 ip.offset = 0 ip.ttl = 1 ip.protocol = IPPROTO_UDP ip.src = ifaddr ip.dst = ciaddr ip_id += 1 # Encapsulate UDPv4. udp = udpv4() udp.sport = 67 udp.dport = 68 udp.length = len(dhcp.bytes) udp.checksum = udp.cksum(ip, dhcp.bytes) # Compute header checksums. ip.length = len(ip.bytes) + len(udp.bytes) + len(dhcp.bytes) ip.checksum = ip.cksum() # Send the lot. packet = Chain([ether, ip, udp, dhcp]) packet.encode() out = output.write(packet.bytes, len(packet.bytes)) print out
def test_icmpv4_ping(self): import os uname = os.uname()[0] if uname == "FreeBSD": devname = "edsc0" elif uname == "Linux": devname = "lo" elif uname == "Darwin": devname = "en0" else: print "unknown host os %s" % uname return e = ethernet() e.type = 0x0800 e.src = "\x00\x00\x00\x00\x00\x00" e.dst = "\xff\xff\xff\xff\xff\xff" e.type = 0x0800 ip = ipv4() ip.version = 4 ip.hlen = 5 ip.tos = 0 ip.length = 28 ip.id = 1234 ip.flags = 0 ip.offset = 0 ip.ttl = 64 ip.protocol = IPPROTO_ICMP ip.src = inet_atol("127.0.0.1") ip.dst = inet_atol("127.0.0.1") icmp = icmpv4() icmp.type = 8 icmp.code = 0 icmp.cksum = 0 echo = icmpv4echo() echo.id = 37123 echo.sequence = 0 ip.len = len(ip.bytes) + len(icmp.bytes) + len(echo.bytes) packet = Chain([e, ip, icmp, echo]) packet.calc_checksums() packet.encode() input = PcapConnector(devname) input.setfilter("icmp") output = PcapConnector(devname) assert ip != None # XXX The use of IP triggers a bpf header format bug if used # with loopback device on FreeBSD, so we use edsc(4) there. n_out = output.write(packet.bytes, 42) assert n_out == 42 packet_in = input.read() assert n_out == len(packet_in)
def test_icmpv4_ping(self): import os uname = os.uname()[0] if uname == "FreeBSD": devname = "edsc0" elif uname == "Linux": devname = "lo" elif uname == "Darwin": devname = "en0" else: print "unknown host os %s" % uname return e = ethernet() e.type = 0x0800 e.src = "\x00\x00\x00\x00\x00\x00" e.dst = "\xff\xff\xff\xff\xff\xff" e.type = 0x0800 ip = ipv4() ip.version = 4 ip.hlen = 5 ip.tos = 0 ip.length = 28 ip.id = 1234 ip.flags = 0 ip.offset = 0 ip.ttl = 64 ip.protocol = IPPROTO_ICMP ip.src = inet_atol("127.0.0.1") ip.dst = inet_atol("127.0.0.1") icmp = icmpv4() icmp.type = 8 icmp.code = 0 icmp.cksum = 0 echo = icmpv4echo() echo.id = 37123 echo.sequence = 0 ip.len = len(ip.bytes) + len(icmp.bytes) + len(echo.bytes) packet = Chain([e, ip, icmp, echo]) packet.calc_checksums() packet.encode() input = PcapConnector(devname) input.setfilter("icmp") output = PcapConnector(devname) assert (ip != None) # XXX The use of IP triggers a bpf header format bug if used # with loopback device on FreeBSD, so we use edsc(4) there. n_out = output.write(packet.bytes, 42) assert (n_out == 42) packet_in = input.read() assert (n_out == len(packet_in))
def main(): from optparse import OptionParser parser = OptionParser() parser.add_option("-I", "--ether_iface", dest="ether_iface", default=None, help="The name of the source interface.") parser.add_option("-e", "--ether_source", dest="ether_source", default=None, help="The host Ethernet source address.") parser.add_option("-s", "--ip_source", dest="ip_source", default=None, help="The IP source address.") parser.add_option("-G", "--igmp_group", dest="igmp_group", default=None, help="The IPv4 group for a group-specific query. " "If omitted, send a general query.") parser.add_option("-M", "--maxresp", dest="igmp_maxresp", default=None, help="The maximum time for end-stations to respond " "(in seconds).") parser.add_option("-l", "--host_list", dest="hostlist", action="append", help="List of hosts we expect responses from.") parser.add_option("-n", "--number", dest="number", default = 1, type=int, help="Query a number of groups starting at " "the one given by -G") parser.add_option("-c", "--count", dest="count", default=None, help="Stop after receiving at least count responses.") (options, args) = parser.parse_args() if options.ether_iface is None or \ options.ether_source is None or \ options.ip_source is None or \ options.count is None: print "Non-optional argument missing." return maxresp = 3 * 10 if options.igmp_maxresp is not None: maxresp = int(options.igmp_maxresp) * 10 # in units of deciseconds if options.igmp_group is None: # General query. dst = INADDR_ALLHOSTS_GROUP group = INADDR_ANY else: # Group-specific query. dst = inet_atol(options.igmp_group) group = dst # Set up our match table global match match = {} for host in options.hostlist: for addr in range(group, group + options.number): match[(inet_atol(host), (addr))] = False signal.signal(signal.SIGINFO, results) while (options.number >= 0): # Queries don't contain the Router Alert option as they are # destined for end stations, not routers. c = ethernet(src=ether_atob(options.ether_source), \ dst=ETHER_MAP_IP_MULTICAST(dst)) / \ ipv4(flags=IP_DF, ttl=1, \ src=inet_atol(options.ip_source), \ dst=dst + options.number) / \ igmp(type=IGMP_HOST_MEMBERSHIP_QUERY, code=maxresp) / \ igmpv2(group=(group + options.number)) c.fixup() input = PcapConnector(options.ether_iface) input.setfilter("igmp") output = PcapConnector(options.ether_iface) out = output.write(c.bytes, len(c.bytes)) options.number -= 1 # # Wait for up to 'count' responses to the query to arrive and print them. # count = int(options.count) while count > 0: packet = input.readpkt() chain = packet.chain() if chain.packets[2].type == IGMP_v2_HOST_MEMBERSHIP_REPORT: #print chain.packets[2].println() # print "%s is in %s" % \ # (inet_ntop(AF_INET, struct.pack('!L', chain.packets[1].src)), \ # inet_ntop(AF_INET, struct.pack('!L', chain.packets[3].group))) match[(chain.packets[1].src, chain.packets[3].group)] = True count -= 1 results(0, 0)