def test_decoding(self):
        '''Test IP6 Packet decoding.'''

        d = ImpactDecoder.IP6Decoder()
        parsed_packet = d.decode(self.binary_packet)

        protocol_version = parsed_packet.get_protocol_version()
        traffic_class = parsed_packet.get_traffic_class()
        flow_label = parsed_packet.get_flow_label()
        payload_length = parsed_packet.get_payload_length()
        next_header = parsed_packet.get_next_header()
        hop_limit = parsed_packet.get_hop_limit()
        source_address = parsed_packet.get_source_address()
        destination_address = parsed_packet.get_destination_address()

        self.assertEquals(protocol_version, 6,
                          "IP6 parsing - Incorrect protocol version")
        self.assertEquals(traffic_class, 72,
                          "IP6 parsing - Incorrect traffic class")
        self.assertEquals(flow_label, 148997,
                          "IP6 parsing - Incorrect flow label")
        self.assertEquals(payload_length, 1500,
                          "IP6 parsing - Incorrect payload length")
        self.assertEquals(next_header, 17,
                          "IP6 parsing - Incorrect next header")
        self.assertEquals(hop_limit, 1, "IP6 parsing - Incorrect hop limit")
        self.assertEquals(source_address.as_string(),
                          "FE80::78F8:89D1:30FF:256B",
                          "IP6 parsing - Incorrect source address")
        self.assertEquals(destination_address.as_string(), "FF02::1:3",
                          "IP6 parsing - Incorrect destination address")
    def test_decoding_chained_basic_options_inside_ipv6_packet(self):
        ipv6_binary_packet = [ 
           0x64, 0x82, 0x46, 0x05, 
           0x05, 0xdc, 0x00, 0x01, 
           0xfe, 0x80, 0x00, 0x00, 
           0x00, 0x00, 0x00, 0x00, 
           0x78, 0xf8, 0x89, 0xd1,
           0x30, 0xff, 0x25, 0x6b, 
           0xff, 0x02, 0x00, 0x00, 
           0x00, 0x00, 0x00, 0x00, 
           0x00, 0x00, 0x00, 0x00, 
           0x00, 0x01, 0x00, 0x03]
        
        hop_by_hop_binary_packet = [
            0x2b, 0x01, 0x01, 0x0C,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00]

        routing_options_binary_packet = [
           0x3c, 0x00, 0x00, 0x0a,
           0x00, 0x00, 0x00, 0x00]

        dest_opts_binary_packet = [
            0x3a, 0x00, 0x00, 0x01,
            0x03, 0x00, 0x00, 0x00]

        binary_packet = ipv6_binary_packet + hop_by_hop_binary_packet + routing_options_binary_packet + dest_opts_binary_packet
        
        d = ImpactDecoder.IP6Decoder()        
        parsed_ipv6_packet = d.decode(binary_packet)
        
        # IPv6 Parsing
        ipv6_protocol_version = parsed_ipv6_packet.get_ip_v()
        ipv6_traffic_class = parsed_ipv6_packet.get_traffic_class()
        ipv6_flow_label = parsed_ipv6_packet.get_flow_label()
        ipv6_payload_length = parsed_ipv6_packet.get_payload_length()
        ipv6_next_header = parsed_ipv6_packet.get_next_header()
        ipv6_hop_limit = parsed_ipv6_packet.get_hop_limit()
        ipv6_source_address = parsed_ipv6_packet.get_ip_src()
        ipv6_destination_address = parsed_ipv6_packet.get_ip_dst()
        
        # Hop By Hop Parsing
        hop_by_hop_parsed_packet = parsed_ipv6_packet.child()
        hop_by_hop_next_header = hop_by_hop_parsed_packet.get_next_header()
        hop_by_hop_header_extension_length = hop_by_hop_parsed_packet.get_header_extension_length()
        hop_by_hop_options = hop_by_hop_parsed_packet.get_options()
        self.assertEqual(1, len(hop_by_hop_options), "Hop By Hop Parsing - Wrong Quantity of Options")
        hop_by_hop_padn_option = hop_by_hop_options[0]
        hop_by_hop_padn_option_type = hop_by_hop_padn_option.get_option_type()
        hop_by_hop_padn_option_length = hop_by_hop_padn_option.get_option_length()
        
        # Routing Options Tests
        routing_options_parsed_packet = hop_by_hop_parsed_packet.child()
        routing_options_next_header = routing_options_parsed_packet.get_next_header()
        routing_options_header_extension_length = routing_options_parsed_packet.get_header_extension_length()
        routing_options_routing_type = routing_options_parsed_packet.get_routing_type()
        routing_options_segments_left = routing_options_parsed_packet.get_segments_left()
        routing_options_options = routing_options_parsed_packet.get_options()
        
        # Destination Options Parsing
        destination_options_parsed_packet = routing_options_parsed_packet.child()
        destination_options_next_header = destination_options_parsed_packet.get_next_header()
        destination_options_header_extension_length = destination_options_parsed_packet.get_header_extension_length()
        destination_options_options = destination_options_parsed_packet.get_options()
        self.assertEqual(2, len(destination_options_options), "Destination Options Parsing - Wrong Quantity of Options")
        destination_options_pad1_option = destination_options_options[0]
        destination_options_pad1_option_type = destination_options_pad1_option.get_option_type()
        destination_options_padn_option = destination_options_options[1]
        destination_options_padn_option_type = destination_options_padn_option.get_option_type()
        destination_options_padn_option_length = destination_options_padn_option.get_option_length()
        
        self.assertEqual(ipv6_protocol_version, 6, "IP6 parsing - Incorrect protocol version")
        self.assertEqual(ipv6_traffic_class, 72, "IP6 parsing - Incorrect traffic class")
        self.assertEqual(ipv6_flow_label, 148997, "IP6 parsing - Incorrect flow label")
        self.assertEqual(ipv6_payload_length, 1500, "IP6 parsing - Incorrect payload length")
        self.assertEqual(ipv6_next_header, 0, "IP6 parsing - Incorrect next header")
        self.assertEqual(ipv6_hop_limit, 1, "IP6 parsing - Incorrect hop limit")
        self.assertEqual(ipv6_source_address.as_string(), "FE80::78F8:89D1:30FF:256B", "IP6 parsing - Incorrect source address")
        self.assertEqual(ipv6_destination_address.as_string(), "FF02::1:3", "IP6 parsing - Incorrect destination address")
        self.assertEqual(hop_by_hop_parsed_packet.get_header_type(), 0, "Hop By Hop Parsing - Incorrect packet")
        self.assertEqual(hop_by_hop_next_header, 43, "Hop By Hop Parsing - Incorrect next header value")
        self.assertEqual(hop_by_hop_header_extension_length, 1, "Hop By Hop Parsing - Incorrect size")
        self.assertEqual(hop_by_hop_padn_option_type, 1, "Hop By Hop Parsing - Incorrect option type")
        self.assertEqual(hop_by_hop_padn_option_length, 12, "Hop By Hop Parsing - Incorrect option size")
        self.assertEqual(routing_options_parsed_packet.get_header_type(), 43, "Routing Options Parsing - Incorrect packet")
        self.assertEqual(routing_options_next_header, 60, "Routing Options Parsing - Incorrect next header value")
        self.assertEqual(routing_options_header_extension_length, 0, "Routing Options Parsing - Incorrect size")
        self.assertEqual(routing_options_routing_type, 0, "Routing Options Parsing - Incorrect routing type")
        self.assertEqual(routing_options_segments_left, 10, "Routing Options Parsing - Incorrect quantity of segments left size")
        self.assertEqual(0, len(routing_options_options), "Routing Options Parsing - Wrong Quantity of Options")
        self.assertEqual(destination_options_parsed_packet.get_header_type(), 60, "Destination Options Parsing - Incorrect packet")
        self.assertEqual(destination_options_next_header, 58, "Destination Options Parsing - Incorrect next header value")
        self.assertEqual(destination_options_header_extension_length, 0, "Destination Options Parsing - Incorrect size")
        self.assertEqual(destination_options_pad1_option_type, 0, "Destination Options Parsing - Incorrect option type")
        self.assertEqual(destination_options_padn_option_type, 1, "Destination Options Parsing - Incorrect option type")
        self.assertEqual(destination_options_padn_option_length, 3, "Destination Options Parsing - Incorrect option size")
    def collector(self, packet):

        packetdata = None

        try:
            eth = ImpactDecoder.EthDecoder().decode(packet)
            off = eth.get_header_size()

            if eth.get_ether_type() == ImpactPacket.IP.ethertype:
                ip_decoder = ImpactDecoder.IPDecoder()
                ip = ip_decoder.decode(packet[off:])
                dst = ip.get_ip_dst()
                src = ip.get_ip_src()
                if ip.get_ip_p() == ImpactPacket.UDP.protocol:
                    udp = ip.child()
                    payload = udp.child().get_bytes().tostring()
                    try:
                        import hexdump

                        try:
                            msg = message.from_wire(payload)
                        except Exception as e:
                            # Not an acceptable DNS packet
                            return None

                        if len(msg.answer) > 0:
                            # Packet should not have an answer section
                            return None

                        if len(msg.question) > 0:
                            for q in msg.question:
                                #if hasattr(q, 'name'):
                                if q.rdtype == rdatatype.A:

                                    if self.PROPERTIES['subdomain']['Value']:
                                        prefix = '.%s.%s.' % (
                                            self.PROPERTIES['subdomain']
                                            ['Value'],
                                            self.PROPERTIES['domain']['Value'])
                                    else:
                                        prefix = '.%s.' % (
                                            self.PROPERTIES['domain']['Value'])

                                    if prefix == q.name.to_text(
                                    )[-len(prefix):]:

                                        # Send a reply to the DNS packet
                                        try:
                                            r = message.make_response(msg)
                                            a = A(rdataclass.IN, rdatatype.A,
                                                  '79.70.84.71'
                                                  )  # OFTG in dotted-decimal
                                            rrs = rrset.from_rdata(
                                                q.name.to_text(), 30, a)
                                            r.answer.append(rrs)

                                            data = ImpactPacket.Data(
                                                r.to_wire())
                                            rudp = ImpactPacket.UDP()
                                            rudp.set_uh_sport(53)
                                            rudp.set_uh_dport(12345)
                                            rudp.contains(data)
                                            rip = ImpactPacket.IP()

                                            rip.set_ip_dst(src)
                                            rip.set_ip_src(self.getlocaladdr())
                                            rip.contains(rudp)
                                            s = socket.socket(
                                                socket.AF_INET,
                                                socket.SOCK_RAW,
                                                socket.IPPROTO_UDP)
                                            s.setsockopt(
                                                socket.IPPROTO_IP,
                                                socket.IP_HDRINCL, 1)
                                            s.sendto(rip.get_packet(),
                                                     (src, 12345))
                                        except Exception as e:
                                            self.logger.error(
                                                'Failed to send reply packet with %s: %s'
                                                % (self.__class__.__name__, e))

                                        dnsdata = q.name.to_text(
                                        )[:-len(prefix)]
                                        dnsdata = self.dnsb64unescape(dnsdata)
                                        payload = self.decoder(dnsdata)
                                        result = payload
                                        # TODO: Fix results
                                        result['Source Host'] = src
                                        result['Protocol Subtype'] = 'Port'
                                        result[
                                            'Subtype'] = 53  #str(ip.child().get_uh_sport())

                                        return result
                    except DNSException:
                        pass
                    except Exception as e:
                        if e:
                            print 'Error %s' % e.message
                        raise

            elif eth.get_ether_type() == IP6.IP6.ethertype:
                ip6_decoder = ImpactDecoder.IP6Decoder()
                ip6 = ip6_decoder.decode(packet[off:])
                src = ip6.get_source_address()
                packetdata = ip6.get_data_as_string()
                self.logger.debug(
                    'Skipping IPv6 packet (not supported for this plugin)')

            if not packetdata:
                return None

            return None

        except Exception as e:
            raise

        return None