def frame_handler(self, hdr, buff): e = Ethernet(buff) src = e.get_ether_shost().tostring() ether_type = e.get_ether_type() if ether_type != frames.WiwoFrame.ethertype: return wf = frames.WiwoFrame(buff[e.get_header_size():]) wiwo_sub_frame = wf.get_packet()[wf.get_header_size():] if wf.get_type() == frames.WiwoDataFrame.frametype: self.data_handler(self.manager, src, wiwo_sub_frame) elif wf.get_type() == frames.WiwoDataFragmentFrame.frametype: wdf = frames.WiwoDataFragmentFrame( wf.get_packet()[wf.get_header_size():]) if not (src in self.data_fragments): self.data_fragments[src] = list() self.data_fragments[src].append(wdf.get_data_as_string()) if wdf.is_last_fragment(): frame = str() for fragment in self.data_fragments[src]: frame += fragment self.data_handler(self.manager, src, frame) del (self.data_fragments[src])
def test_wiwo_info_response_multiple_interfaces_frame_success(self): """ Getting the iface info of the Wiwo Info Response frame should return the same info that was defined on the info dictionary. """ info_1 = { "iface": "wlan1", "protocol": "IEEE 802.11an", "channels": "\x24\x28\x2c\x30\x34\x38\x3c\x40\x95\x99\x9d\xa1\xa5", "channel": "\x24" } info_2 = { "iface": "wlan0", "protocol": "IEEE 802.11g", "channels": "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e", "channel": "\x01" } frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoInfoResponseFrame.frametype) \ + "%s%s" % (struct.pack("B", len(info_1["iface"])), info_1["iface"]) \ + "%s%s" % (struct.pack("B", len(info_1["protocol"])), info_1["protocol"]) \ + "%s%s" % (struct.pack("B", len(info_1["channels"])), info_1["channels"]) \ + "%s" % info_1["channel"] \ + "%s%s" % (struct.pack("B", len(info_2["iface"])), info_2["iface"]) \ + "%s%s" % (struct.pack("B", len(info_2["protocol"])), info_2["protocol"]) \ + "%s%s" % (struct.pack("B", len(info_2["channels"])), info_2["channels"]) \ + "%s" % info_2["channel"] eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoInfoResponseFrame.frametype: wirf = WiwoInfoResponseFrame(wf.get_body_as_string()) ifaces = wirf.get_interfaces() self.assertEqual(len(info_1["iface"]), ifaces[0].get_iface_len()) self.assertEqual(info_1["iface"], ifaces[0].get_iface_as_string()) self.assertEqual(len(info_1["protocol"]), ifaces[0].get_protocol_len()) self.assertEqual(info_1["protocol"], ifaces[0].get_protocol_as_string()) self.assertEqual(len(info_1["channels"]), ifaces[0].get_channels_count()) self.assertEqual(array.array("B", info_1["channels"]), ifaces[0].get_channels()) self.assertEqual(len(info_2["iface"]), ifaces[1].get_iface_len()) self.assertEqual(info_2["iface"], ifaces[1].get_iface_as_string()) self.assertEqual(len(info_2["protocol"]), ifaces[1].get_protocol_len()) self.assertEqual(info_2["protocol"], ifaces[1].get_protocol_as_string()) self.assertEqual(len(info_2["channels"]), ifaces[1].get_channels_count()) self.assertEqual(array.array("B", info_2["channels"]), ifaces[1].get_channels())
def __create_wiwo_ethernet_frame(dst, src): """ Returns a WiWo Ethernet frame. """ ethernet_frame = Ethernet() dst_array = array.array('B', dst) ethernet_frame.set_ether_dhost(dst_array) src_array = array.array('B', src) ethernet_frame.set_ether_shost(src_array) ethernet_frame.set_ether_type(frames.WiwoFrame.ethertype) return ethernet_frame
def test_wiwo_frame_get_type_fail(self): """ Getting the type of a Wiwo ACK frame shouldn't return a Wiwo Error frame type. """ frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoAckFrame.frametype) eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) self.assertNotEqual(WiwoErrorFrame.frametype, wf.get_type())
def test_wiwo_info_request_frame_type_success(self): """ Getting the type of a Wiwo Info Request frame should return a Wiwo Info Request frame type. """ frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoInfoRequestFrame.frametype) eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) self.assertEqual(WiwoInfoRequestFrame.frametype, wf.get_type())
def test_05(self): """Test manipulation with VLAN tags""" def check_tags(*tags): self.assertEqual(self.eth.tag_cnt, len(tags)) self.assertEqual(self.eth.get_header_size(), 14 + 4 * len(tags)) self.assertEqual(self.eth.get_ether_type(), 0x0800) for i, tag in enumerate(tags): self.assertEqual( self.eth.get_tag(i).get_buffer_as_string(), tag) # Add S-tag (outer tag, closest to the Ethernet header) self.eth.push_tag(EthernetTag(0x88a85001)) check_tags(b'\x88\xa8\x50\x01', b'\x81\x00\xac\xf3') # Set C-tag (inner tag, closest to the payload) to default self.eth.set_tag(1, EthernetTag()) check_tags(b'\x88\xa8\x50\x01', b'\x81\x00\x00\x00') # Insert a deprecated 802.1QinQ header between S-tag and C-tag self.eth.push_tag(EthernetTag(0x910054d2), index=1) check_tags(b'\x88\xa8\x50\x01', b'\x91\x00\x54\xd2', b'\x81\x00\x00\x00') # Test negative indices tags = {} for i in range(-3, 3): tags[i] = self.eth.get_tag(i).get_buffer_as_string() self.assertEqual(tags[-1], tags[2]) self.assertEqual(tags[-2], tags[1]) self.assertEqual(tags[-3], tags[0]) # Accessing non-existent tags raises IndexError self.assertRaises(IndexError, self.eth.get_tag, 3) self.assertRaises(IndexError, self.eth.get_tag, -4) self.assertRaises(IndexError, self.eth.set_tag, 3, EthernetTag()) self.assertRaises(IndexError, self.eth.set_tag, -4, EthernetTag()) # Test Ethernet constructor data = self.eth.get_buffer_as_string() eth_copy = Ethernet(data) self.assertEqual(eth_copy.tag_cnt, 3) self.assertEqual(eth_copy.get_header_size(), 26) self.assertEqual(eth_copy.get_ether_type(), 0x0800) # Remove the deprecated 802.1QinQ header and check resulting frame eth_copy.pop_tag(1) self.assertEqual(eth_copy.tag_cnt, 2) self.assertEqual(eth_copy.get_packet(), self.frame[:12] + tags[0] + tags[2] + self.frame[-2:])
def test_wiwo_error_frame_fail(self): """ Getting the message of the Wiwo Error frame shouldn't return the same message that was defined on error_msg. """ error_msg = "Error message." frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoErrorFrame.frametype) \ + error_msg eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoErrorFrame.frametype: wef = WiwoErrorFrame(wf.get_body_as_string()) self.assertNotEqual("fafa", wef.get_msg_as_string())
def test_wiwo_data_frame_fail(self): """ Getting the data of the Wiwo Data frame shouldn't return the same data that was defined on frame_data. """ frame_data = "\x00\x01\x02\x03\x04\x05" frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoDataFrame.frametype) \ + frame_data eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoDataFrame.frametype: wdf = WiwoDataFrame(wf.get_body_as_string()) self.assertNotEqual("\x00\x02\x05\x06", wdf.get_data_as_string())
def test_wiwo_data_fragment_frame_fail(self): """ Getting the data of the Wiwo Data frame shouldn't return the same data that was defined on frame_data. """ frame_data = "\x00\x01\x02" + ("\xff" * 1400) frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoDataFragmentFrame.frametype) \ + "\x82" \ + frame_data eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoDataFragmentFrame.frametype: wdff = WiwoDataFragmentFrame(wf.get_body_as_string()) self.assertNotEqual(1, wdff.get_sequence_number()) self.assertNotEqual(False, wdff.is_last_fragment()) self.assertNotEqual("\x00" * 1400, wdff.get_data_as_string())
def __management_frame_handler(self, wiwo_frame_buffer): """ Method that process management frame from a WiWo Worker. """ ethernet_frame = Ethernet(wiwo_frame_buffer) ether_dst_addr = ethernet_frame.get_ether_dhost().tostring() ether_src_addr = ethernet_frame.get_ether_shost().tostring() ether_type = ethernet_frame.get_ether_type() if ether_type != frames.WiwoFrame.ethertype: return wiwo_frame_buffer = wiwo_frame_buffer[ethernet_frame.get_header_size():] wiwo_frame = frames.WiwoFrame(wiwo_frame_buffer) ethernet_frame.contains(wiwo_frame) if not (ether_src_addr in self.__worker_dict.keys()): if wiwo_frame.get_type() == frames.WiwoAckFrame.frametype: # We assume it's a ACK from an Announce worker = Worker(ether_src_addr) self.__worker_dict[ether_src_addr] = worker wiwo_req_info_frame_buffer = self.__create_wiwo_request_info_frame(ether_src_addr, ether_dst_addr) worker.send(wiwo_req_info_frame_buffer, self.__iface_name) self.__event_handler(WiwoEvent(ether_src_addr, WiwoEvent.WorkerAdded)) else: if wiwo_frame.get_type() == frames.WiwoErrorFrame.frametype: worker = self.__worker_dict[ether_src_addr] worker.update_after_error() wiwo_error_frame_buffer = wiwo_frame_buffer[wiwo_frame.get_header_size():] we = frames.WiwoErrorFrame(wiwo_error_frame_buffer) self.__event_handler(WiwoEvent(ether_src_addr, WiwoEvent.Error, we.get_msg_as_string())) else: worker = self.__worker_dict[ether_src_addr] type_from_last_frame_sent = worker.get_type_from_last_frame_sent() worker.process_ctrl_and_mgnt_frame_received(ethernet_frame, self.__iface_name) if type_from_last_frame_sent == -1: return elif type_from_last_frame_sent == frames.WiwoDataInjectFrame.frametype: self.__event_handler(WiwoEvent(ether_src_addr, WiwoEvent.DataInjected)) else: self.__event_handler(WiwoEvent(ether_src_addr, WiwoEvent.WorkerUpdated))
def test_wiwo_data_fragment_frame_fail(self): """ Getting the data of the Wiwo Data Inject frame shouldn't return the same data that was defined on frame_data. """ iface = "wlan0" frame_data = "\xff" * 1400 frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoDataInjectFrame.frametype) \ + "%s%s" % (struct.pack("B", len(iface)), iface) \ + frame_data eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoDataInjectFrame.frametype: wdif = WiwoDataInjectFrame(wf.get_body_as_string()) self.assertNotEqual(0, wdif.get_iface_len()) self.assertNotEqual("wlan1", wdif.get_iface_as_string()) self.assertNotEqual("\x00" * 1400, wdif.get_data_as_string())
def test_wiwo_set_channel_frame_fail(self): """ Getting the iface and channel of the Wiwo Set Channel frame shouldn't return the same info that was defined on the frame buffer. """ info = {"iface": "wlan0", "channel": 1} frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoSetChannelFrame.frametype) \ + "%s%s" % (struct.pack("B", len(info["iface"])), info["iface"]) \ + "%s" % struct.pack("B", info["channel"]) eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoSetChannelFrame.frametype: wscf = WiwoSetChannelFrame(wf.get_body_as_string()) self.assertNotEqual(0, wscf.get_iface_len()) self.assertNotEqual("wlan1", wscf.get_iface_as_string()) self.assertNotEqual(14, wscf.get_channel())
def test_wiwo_info_response_frame_fail(self): """ Getting the iface info of the Wiwo Info Response frame shouldn't return the same info that was defined on the info dictionary. """ info = { "iface": "wlan0", "protocol": "IEEE 802.11g", "channels": "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e", "channel": "\x01" } frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoInfoResponseFrame.frametype) \ + "%s%s" % (struct.pack("B", len(info["iface"])), info["iface"]) \ + "%s%s" % (struct.pack("B", len(info["protocol"])), info["protocol"]) \ + "%s%s" % (struct.pack("B", len(info["channels"])), info["channels"]) \ + "%s" % info["channel"] eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoInfoResponseFrame.frametype: wirf = WiwoInfoResponseFrame(wf.get_body_as_string()) ifaces = wirf.get_interfaces() for iface in ifaces: self.assertNotEqual(0, iface.get_iface_len()) self.assertNotEqual("wlan1", iface.get_iface_as_string()) self.assertNotEqual(0, iface.get_protocol_len()) self.assertNotEqual("IEEE 802.3", iface.get_protocol_as_string()) self.assertNotEqual(0, iface.get_channels_count()) self.assertNotEqual(array.array("b", "\x00\x01"), iface.get_channels()) self.assertNotEqual(14, iface.get_channel())
def test_wiwo_start_frame_fail(self): """ Getting the iface and bpf filter of the Wiwo Set Channel frame shouldn't return the same info that was defined on the frame buffer. """ info = { "iface": "wlan0", "filter": "ip and (tcp port 80 or tcp port 443)" } frame_buffer = "\x00\x11\x22\x33\x44\x55" \ "\x00\xde\xad\xbe\xef\x00" \ "\xfa\xfa" \ + chr(WiwoStartFrame.frametype) \ + "%s%s" % (struct.pack("B", len(info["iface"])), info["iface"]) \ + "%s%s" % (struct.pack("!H", len(info["filter"])), info["filter"]) eth = Ethernet(frame_buffer) data = frame_buffer[eth.get_header_size():] wf = WiwoFrame(data) if wf.get_type() == WiwoStartFrame.frametype: wsf = WiwoStartFrame(wf.get_body_as_string()) self.assertNotEqual(0, wsf.get_iface_len()) self.assertNotEqual("wlan1", wsf.get_iface_as_string()) self.assertNotEqual(0, wsf.get_filter_len()) self.assertNotEqual("udp port 69", wsf.get_filter_as_string())
def setUp(self): # Ethernet frame with a 802.1Q tag (TPID=0x8100, PCP=5, DEI=0, VID=3315) # and ethertype 0x0800 (IPv4) self.frame = b'\x54\xab\xa3\xb9\x38\x3d\xe2\xef\x8d\xc7\xa8\x5e\x81\x00\xac\xf3\x08\x00' self.eth = Ethernet(self.frame)