Example #1
0
File: http.py Project: bjornua/dna
class HttpStream(object):
    """ An HTTP parser providing higher-level access to a readable,
    sequential io.RawIOBase object. You can use implementions of
    http_parser.reader (IterReader, StringReader, SocketReader) or 
    create your own.
    """
    def __init__(self, stream, kind=HTTP_BOTH, decompress=False):
        """ constructor of HttpStream. 

        :attr stream: an io.RawIOBase object
        :attr kind: Int,  could be 0 to parseonly requests, 
        1 to parse only responses or 2 if we want to let
        the parser detect the type.
        """
        self.parser = HttpParser(kind=kind, decompress=decompress)
        self.stream = stream

    def _check_headers_complete(self):
        if self.parser.is_headers_complete():
            return

        while True:
            try:
                data = self.next()
            except StopIteration:
                if self.parser.is_headers_complete():
                    return
                raise NoMoreData()

            if self.parser.is_headers_complete():
                return

    def url(self):
        """ get full url of the request """
        self._check_headers_complete()
        return self.parser.get_url()

    def path(self):
        """ get path of the request (url without query string and
        fragment """
        self._check_headers_complete()
        return self.parser.get_path()

    def query_string(self):
        """ get query string of the url """
        self._check_headers_complete()
        return self.parser.get_query_string()

    def fragment(self):
        """ get fragment of the url """
        self._check_headers_complete()
        return self.parser.get_fragment()

    def version(self):
        self._check_headers_complete()
        return self.parser.get_version()

    def status_code(self):
        """ get status code of a response as integer """
        self._check_headers_complete()
        return self.parser.get_status_code()

    def status(self):
        """ return complete status with reason """
        status_code = self.status_code()
        reason = status_reasons.get(int(status_code), 'unknown')
        return "%s %s" % (status_code, reason)

    def method(self):
        """ get HTTP method as string"""
        self._check_headers_complete()
        return self.parser.get_method()

    def headers(self):
        """ get request/response headers, headers are returned in a
        OrderedDict that allows you to get value using insensitive
        keys."""
        self._check_headers_complete()
        return self.parser.get_headers()

    def should_keep_alive(self):
        """ return True if the connection should be kept alive
        """
        self._check_headers_complete()
        return self.parser.should_keep_alive()

    def is_chunked(self):
        """ return True if Transfer-Encoding header value is chunked"""
        self._check_headers_complete()
        return self.parser.is_chunked()

    def wsgi_environ(self, initial=None):
        """ get WSGI environ based on the current request.
        
        :attr initial: dict, initial values to fill in environ.
        """
        self._check_headers_complete()
        return self.parser.get_wsgi_environ()

    def body_file(self,
                  buffering=None,
                  binary=True,
                  encoding=None,
                  errors=None,
                  newline=None):
        """ return the body as a buffered stream object. If binary is
        true an io.BufferedReader will be returned, else an
        io.TextIOWrapper.
        """
        self._check_headers_complete()

        if buffering is None:
            buffering = -1
        if buffering < 0:
            buffering = DEFAULT_BUFFER_SIZE

        raw = HttpBodyReader(self)
        buffer = BufferedReader(raw, buffering)
        if binary:
            return buffer
        text = TextIOWrapper(buffer, encoding, errors, newline)
        return text

    def body_string(self,
                    binary=True,
                    encoding=None,
                    errors=None,
                    newline=None):
        """ return body as string """
        return self.body_file(binary=binary,
                              encoding=encoding,
                              newline=newline).read()

    def __iter__(self):
        return self

    def next(self):
        if self.parser.is_message_complete():
            raise StopIteration

        # fetch data
        b = bytearray(DEFAULT_BUFFER_SIZE)
        recved = self.stream.readinto(b)
        if recved is None:
            raise NoMoreData("no more data")

        del b[recved:]

        # parse data
        nparsed = self.parser.execute(bytes(b), recved)
        if nparsed != recved and not self.parser.is_message_complete():
            raise ParserError("nparsed != recved")

        if recved == 0:
            raise StopIteration

        return bytes(b)
Example #2
0
class HttpStream(object):
    """ An HTTP parser providing higher-level access to a readable,
    sequential io.RawIOBase object. You can use implementions of
    http_parser.reader (IterReader, StringReader, SocketReader) or
    create your own.
    """

    def __init__(self, stream, kind=HTTP_BOTH, decompress=False):
        """ constructor of HttpStream.

        :attr stream: an io.RawIOBase object
        :attr kind: Int,  could be 0 to parseonly requests,
        1 to parse only responses or 2 if we want to let
        the parser detect the type.
        """
        self.parser = HttpParser(kind=kind, decompress=decompress)
        self.stream = stream

    def _check_headers_complete(self):
        if self.parser.is_headers_complete():
            return

        while True:
            try:
                next(self)
            except StopIteration:
                if self.parser.is_headers_complete():
                    return
                raise NoMoreData("Can't parse headers")

            if self.parser.is_headers_complete():
                return


    def _wait_status_line(self, cond):
        if self.parser.is_headers_complete():
            return True

        data = []
        if not cond():
            while True:
                try:
                    d = next(self)
                    data.append(d)
                except StopIteration:
                    if self.parser.is_headers_complete():
                        return True
                    raise BadStatusLine(b"".join(data))
                if cond():
                    return True
        return True

    def _wait_on_url(self):
        return self._wait_status_line(self.parser.get_url)

    def _wait_on_status(self):
        return self._wait_status_line(self.parser.get_status_code)

    def url(self):
        """ get full url of the request """
        self._wait_on_url()
        return self.parser.get_url()

    def path(self):
        """ get path of the request (url without query string and
        fragment """
        self._wait_on_url()
        return self.parser.get_path()

    def query_string(self):
        """ get query string of the url """
        self._wait_on_url()
        return self.parser.get_query_string()

    def fragment(self):
        """ get fragment of the url """
        self._wait_on_url()
        return self.parser.get_fragment()

    def version(self):
        self._wait_on_status()
        return self.parser.get_version()

    def status_code(self):
        """ get status code of a response as integer """
        self._wait_on_status()
        return self.parser.get_status_code()

    def status(self):
        """ return complete status with reason """
        status_code = self.status_code()
        reason = status_reasons.get(int(status_code), 'unknown')
        return "%s %s" % (status_code, reason)


    def method(self):
        """ get HTTP method as string"""
        self._wait_on_status()
        return self.parser.get_method()

    def headers(self):
        """ get request/response headers, headers are returned in a
        OrderedDict that allows you to get value using insensitive
        keys."""
        self._check_headers_complete()
        return self.parser.get_headers()

    def should_keep_alive(self):
        """ return True if the connection should be kept alive
        """
        self._check_headers_complete()
        return self.parser.should_keep_alive()

    def is_chunked(self):
        """ return True if Transfer-Encoding header value is chunked"""
        self._check_headers_complete()
        return self.parser.is_chunked()

    def wsgi_environ(self, initial=None):
        """ get WSGI environ based on the current request.

        :attr initial: dict, initial values to fill in environ.
        """
        self._check_headers_complete()
        return self.parser.get_wsgi_environ()

    def body_file(self, buffering=None, binary=True, encoding=None,
            errors=None, newline=None):
        """ return the body as a buffered stream object. If binary is
        true an io.BufferedReader will be returned, else an
        io.TextIOWrapper.
        """
        self._check_headers_complete()

        if buffering is None:
            buffering = -1
        if buffering < 0:
            buffering = DEFAULT_BUFFER_SIZE

        raw = HttpBodyReader(self)
        buf = BufferedReader(raw, buffering)
        if binary:
            return buf
        text = TextIOWrapper(buf, encoding, errors, newline)
        return text

    def body_string(self, binary=True, encoding=None, errors=None,
            newline=None):
        """ return body as string """
        return self.body_file(binary=binary, encoding=encoding,
                newline=newline).read()

    def __iter__(self):
        return self

    def __next__(self):
        if self.parser.is_message_complete():
            raise StopIteration

        # fetch data
        b = bytearray(DEFAULT_BUFFER_SIZE)
        recved = self.stream.readinto(b)
        if recved is None:
            raise NoMoreData("no more data")

        del b[recved:]
        to_parse = bytes(b)
        # parse data
        nparsed = self.parser.execute(to_parse, recved)
        if nparsed != recved and not self.parser.is_message_complete():
            raise ParserError("nparsed != recved (%s != %s) [%s]" % (nparsed,
                recved, bytes_to_str(to_parse)))

        if recved == 0:
            raise StopIteration

        return to_parse

    next = __next__
    def parse(self):
        data = [{
            'label':
            '以太网帧头部 / Ethernet Headers',
            'value':
            '',
            'bold':
            True,
            'children': [{
                'label': '目的端 MAC 地址',
                'value': self.ethHeader.destMac
            }, {
                'label': '发送端 MAC 地址',
                'value': self.ethHeader.sourceMac
            }, {
                'label':
                '帧类型',
                'value':
                '%s (0x%s)' % (self.ethHeader.type, self.ethHeader.type_code)
            }]
        }]

        if self.protocol == 'ARP':
            data.append({
                'label':
                'ARP 消息 / Address Resolution Protocol',
                'value':
                '',
                'bold':
                True,
                'children': [{
                    'label':
                    '硬件类型',
                    'value':
                    '%s (%s)' % (self.arpBody.hardware_type,
                                 self.arpBody.hardware_type_code)
                }, {
                    'label':
                    '协议类型',
                    'value':
                    '%s (0x%s)' % (self.arpBody.protocol_type,
                                   self.arpBody.protocol_type_code)
                }, {
                    'label': '硬件地址长度',
                    'value': str(self.arpBody.hardware_size)
                }, {
                    'label': '协议地址长度',
                    'value': str(self.arpBody.protocol_size)
                }, {
                    'label':
                    '操作码',
                    'value':
                    '%s (%s)' %
                    (self.arpBody.operation, self.arpBody.operation_code)
                }, {
                    'label': '发送端 MAC 地址',
                    'value': self.arpBody.sender_mac_address
                }, {
                    'label': '发送端 IP 地址',
                    'value': self.arpBody.sender_ip_address
                }, {
                    'label': '目的端 MAC 地址',
                    'value': self.arpBody.target_mac_address
                }, {
                    'label': '目的端 IP 地址',
                    'value': self.arpBody.target_ip_address
                }]
            })
        else:

            if self.ipHeader.version == 4:
                self.ipHeader.verifyChecksum = verifyChecksum(
                    self.ipHeader.header_raw, [], '').verifyChecksum
                data.append({
                    'label':
                    'IPv4 头部 / IPv4 Header',
                    'value':
                    '',
                    'bold':
                    True,
                    'children': [{
                        'label': '协议版本',
                        'value': self.ipHeader.version
                    }, {
                        'label':
                        '头部长度',
                        'value':
                        str(self.ipHeader.header_length) + ' Bytes'
                    }, {
                        'label':
                        '服务类型',
                        'value':
                        '0x%s' % (self.ipHeader.differentiated_services)
                    }, {
                        'label': '来源 IP',
                        'value': self.ipHeader.source_ip
                    }, {
                        'label': '目标 IP',
                        'value': self.ipHeader.dest_ip
                    }, {
                        'label': '总长度',
                        'value': self.ipHeader.total_length
                    }, {
                        'label':
                        '标识',
                        'value':
                        '0x%s (%s)' % (self.ipHeader.identification,
                                       self.ipHeader.identification_int)
                    }, {
                        'label':
                        '标志',
                        'value':
                        '%s' % (self.ipHeader.flags.raw),
                        'children': [{
                            'label':
                            '保留位',
                            'value':
                            '%s | %s... .... .... ....' %
                            (self.ipHeader.flags.reserved,
                             int(self.ipHeader.flags.reserved))
                        }, {
                            'label':
                            'Don\'t fragment',
                            'value':
                            '%s | .%s.. .... .... ....' %
                            (self.ipHeader.flags.fragment,
                             int(self.ipHeader.flags.fragment))
                        }, {
                            'label':
                            'More fragments',
                            'value':
                            '%s | ..%s. .... .... ....' %
                            (self.ipHeader.flags.more_fragment,
                             int(self.ipHeader.flags.more_fragment))
                        }, {
                            'label':
                            '分段偏移',
                            'value':
                            '%s | ...%s' %
                            (self.ipHeader.flags.fragment_offset,
                             self.ipHeader.flags.fragment_offset_bin)
                        }]
                    }, {
                        'label': '生存期',
                        'value': self.ipHeader.time_to_live
                    }, {
                        'label':
                        '协议',
                        'value':
                        '%s (%s)' %
                        (self.ipHeader.protocol, self.ipHeader.protocol_code)
                    }, {
                        'label':
                        '校验和',
                        'value':
                        '0x%s (%s)' % (self.ipHeader.origin_checksum, '校验' + {
                            True: '通过',
                            False: '失败'
                        }[self.ipHeader.verifyChecksum])
                    }]
                })

            else:
                ipv6_header = {
                    'label':
                    'IPv6 头部 / IPv6 Header',
                    'value':
                    '',
                    'bold':
                    True,
                    'children': [{
                        'label': '协议版本',
                        'value': self.ipHeader.version
                    }, {
                        'label': '通信分类',
                        'value': '0x%s' % (self.ipHeader._class)
                    }, {
                        'label': '流标签',
                        'value': '0x%s' % (self.ipHeader.float_label)
                    }, {
                        'label': '有效载荷长度',
                        'value': self.ipHeader.payload_length
                    }, {
                        'label':
                        '下一头部类型',
                        'value':
                        '%s (%s)' % (self.ipHeader.next_header,
                                     self.ipHeader.next_header_code)
                    }, {
                        'label': '跳数限制',
                        'value': self.ipHeader.hop_limit
                    }, {
                        'label': '源 IP',
                        'value': self.ipHeader.source_ip
                    }, {
                        'label': '目的 IP',
                        'value': self.ipHeader.dest_ip
                    }]
                }

                for option in self.ipHeader.options:
                    ipv6_header['children'].append({
                        'label':
                        consts.protocol_types[str(option['code'])],
                        'value':
                        '0x' + option['value'],
                        'children': [{
                            'label':
                            '下一头部类型',
                            'value':
                            '%s (%s)' % (consts.protocol_types[str(
                                option['next_header'])], option['next_header'])
                        }]
                    })

                data.append(ipv6_header)

            if self.ipHeader.version == 4 and self.ipHeader.flags.more_fragment == True:
                # print('Waiting for more fragments.')
                ids = self.ip_ids[self.ipHeader.identification_int]
                slicing = {
                    'label': 'IP 分片',
                    'value': '共 %s 个数据包' % len(ids),
                    'bold': True,
                    'children': []
                }
                for id in ids:
                    slicing['children'].append({
                        'label':
                        '#%s' % id,
                        'value':
                        '%s Bytes' % (self.ip_packets[id].length / 8)
                    })
                data.append(slicing)
            else:
                if self.ipHeader.protocol == 'TCP':
                    self.ipBody.tcpHeader.verifyChecksum = verifyChecksum(
                        self.ipBody.parameters[0], self.ipBody.parameters[1],
                        self.ipHeader.protocol).verifyChecksum
                    self.ipBody.tcpHeader.options = tcpOptions(
                        BitArray(self.ipBodyRaw)
                        [160:self.ipBody.tcpHeader.header_length * 8]).options
                    tcp_header = {
                        'label':
                        'TCP 头部 / Transmission Control Protocol Header',
                        'value':
                        '',
                        'bold':
                        True,
                        'children': [{
                            'label': '源端口',
                            'value': self.ipBody.tcpHeader.source_port
                        }, {
                            'label':
                            '目的端口',
                            'value':
                            self.ipBody.tcpHeader.destination_port
                        }, {
                            'label':
                            '数据序号 (seq)',
                            'value':
                            self.ipBody.tcpHeader.sequence_number
                        }, {
                            'label':
                            '确认序号 (ack)',
                            'value':
                            self.ipBody.tcpHeader.acknowledge_number
                        }, {
                            'label':
                            '首部长度',
                            'value':
                            self.ipBody.tcpHeader.header_length
                        }, {
                            'label':
                            '标志位',
                            'value':
                            '0x' + self.ipBody.tcpHeader.flags_raw,
                            'children': [{
                                'label':
                                'Reserved',
                                'value':
                                '%s | %s. .... ....' %
                                (self.ipBody.tcpHeader.flags.reserved.uint,
                                 self.ipBody.tcpHeader.flags.reserved.bin)
                            }, {
                                'label':
                                'Nonce',
                                'value':
                                '%s | ...%d .... ....' %
                                (self.ipBody.tcpHeader.flags.nonce,
                                 self.ipBody.tcpHeader.flags.nonce)
                            }, {
                                'label':
                                'Congestion Window Reduced',
                                'value':
                                '%s | .... %d... ....' %
                                (self.ipBody.tcpHeader.flags.cwr,
                                 self.ipBody.tcpHeader.flags.cwr)
                            }, {
                                'label':
                                'ECN-Echo',
                                'value':
                                '%s | .... .%d.. ....' %
                                (self.ipBody.tcpHeader.flags.ecn_echo,
                                 self.ipBody.tcpHeader.flags.ecn_echo)
                            }, {
                                'label':
                                'Urgent',
                                'value':
                                '%s | .... ..%d. ....' %
                                (self.ipBody.tcpHeader.flags.urgent,
                                 self.ipBody.tcpHeader.flags.urgent)
                            }, {
                                'label':
                                'Acknowledgment',
                                'value':
                                '%s | .... ...%d ....' %
                                (self.ipBody.tcpHeader.flags.acknowledgement,
                                 self.ipBody.tcpHeader.flags.acknowledgement)
                            }, {
                                'label':
                                'Push',
                                'value':
                                '%s | .... .... %d...' %
                                (self.ipBody.tcpHeader.flags.push,
                                 self.ipBody.tcpHeader.flags.push)
                            }, {
                                'label':
                                'Reset',
                                'value':
                                '%s | .... .... .%d..' %
                                (self.ipBody.tcpHeader.flags.reset,
                                 self.ipBody.tcpHeader.flags.reset)
                            }, {
                                'label':
                                'Syn',
                                'value':
                                '%s | .... .... ..%d.' %
                                (self.ipBody.tcpHeader.flags.syn,
                                 self.ipBody.tcpHeader.flags.syn)
                            }, {
                                'label':
                                'Fin',
                                'value':
                                '%s | .... .... ...%d' %
                                (self.ipBody.tcpHeader.flags.fin,
                                 self.ipBody.tcpHeader.flags.fin)
                            }]
                        }, {
                            'label': '窗口大小',
                            'value': self.ipBody.tcpHeader.window_size
                        }, {
                            'label':
                            '校验和',
                            'value':
                            '0x%s (%s)' %
                            (self.ipBody.tcpHeader.checksum, '校验' + {
                                True: '通过',
                                False: '失败'
                            }[self.ipBody.tcpHeader.verifyChecksum])
                        }]
                    }
                    options = []
                    if self.ipBody.tcpHeader.options:
                        for idx in range(len(self.ipBody.tcpHeader.options)):
                            option = {
                                'label':
                                self.ipBody.tcpHeader.options[idx][0]['label'],
                                'value':
                                '(%s)' %
                                self.ipBody.tcpHeader.options[idx][0]['value'],
                                'children':
                                self.ipBody.tcpHeader.options[idx][1:]
                            }
                            options.append(option)
                    if options:
                        tcp_header['children'].append({
                            'label': '选项',
                            'value': '',
                            'children': options
                        })

                    data.append(tcp_header)

                    print(self.id)
                    print(tcp_bodies)
                    if self.id in packet_id_struct:
                        tmp = []
                        http_payload = None
                        for p_id in packet_id_struct[self.id]:
                            tmp.append({'value': '', 'label': '#%s' % p_id})

                        if self.id in tcp_bodies:
                            # print(tcp_bodies[self.id]['data'].decode('utf-8', 'ignore'))
                            children = [{
                                'label':
                                '该包是 TCP 分段的最后一段, 可以通过右下角按钮「导出 TCP 分段数据」.',
                                'value': '',
                                'bold': True
                            }, {
                                'label': '共 %s 个分段' % len(tmp),
                                'value': '',
                                'bold': True,
                                'children': tmp
                            }]

                            try:
                                p = HttpParser()
                                recved = len(tcp_bodies[self.id]['data'])
                                nparsed = p.execute(
                                    tcp_bodies[self.id]['data'], recved)
                                assert nparsed == recved

                                headers = []
                                for header in p.get_headers():
                                    headers.append({
                                        'label':
                                        header,
                                        'value':
                                        p.get_headers()[header]
                                    })

                                print(p.get_path(), p.get_url(),
                                      p.get_fragment(), p.get_method(),
                                      p.get_query_string(),
                                      p.get_status_code(),
                                      p.get_wsgi_environ())

                                http_payload = [{
                                    'label':
                                    'HTTP 版本',
                                    'value':
                                    '%s.%s' %
                                    (p.get_version()[0], p.get_version()[1])
                                }, {
                                    'label': 'HTTP 头部',
                                    'value': '',
                                    'children': headers
                                }]

                                if len(p.get_url()) != 0:
                                    http_payload.append({
                                        'label': '请求方式',
                                        'value': p.get_method()
                                    })
                                    http_payload.append({
                                        'label': '路径',
                                        'value': p.get_url()
                                    })
                                    http_payload.append({
                                        'label':
                                        '请求参数',
                                        'value':
                                        p.get_query_string()
                                    })
                                    http_payload.append({
                                        'label':
                                        '主机名',
                                        'value':
                                        p.get_wsgi_environ()['HTTP_HOST']
                                    })
                                else:
                                    http_payload.append({
                                        'label':
                                        '状态码',
                                        'value':
                                        p.get_status_code()
                                    })

                            except AssertionError:
                                pass

                        else:
                            children = [{
                                'label': '共 %s 个分段' % len(tmp),
                                'value': '',
                                'bold': True,
                                'children': tmp
                            }]

                        data.append({
                            'label': 'TCP 数据 / TCP Payload',
                            'value': '',
                            'bold': True,
                            'children': children
                        })

                        if http_payload != None:
                            data.append({
                                'label': 'HTTP 数据 / HTTP Data',
                                'value': '',
                                'bold': True,
                                'children': http_payload
                            })
                    '''
                    if self.ipBody.tcpBody.has_body:
                        try:
                            p = HttpParser()
                            recved = len(self.ipBody.tcpBody.buf)
                            nparsed = p.execute(self.ipBody.tcpBody.buf, recved)
                            assert nparsed == recved

                            print(p.get_headers())
                        except AssertionError:
                            print('NOT HTTP')

                        data.append({
                            'label': 'TCP 数据 / Data',
                            'value': '',
                            'bold': True,
                            'children': [
                                {
                                    'label': '数据',
                                    'value': self.ipBody.tcpBody.raw
                                }
                            ]
                        })
                    '''

                elif self.ipHeader.protocol == 'UDP':
                    self.ipBody.udpHeader.verifyChecksum = verifyChecksum(
                        self.ipBody.parameters[0], self.ipBody.parameters[1],
                        self.ipHeader.protocol).verifyChecksum
                    data.append({
                        'label':
                        'UDP 头部 / User Datagram Protocol Header',
                        'value':
                        '',
                        'bold':
                        True,
                        'children': [{
                            'label': '源端口',
                            'value': self.ipBody.udpHeader.source_port
                        }, {
                            'label':
                            '目的端口',
                            'value':
                            self.ipBody.udpHeader.destination_port
                        }, {
                            'label': '长度',
                            'value': self.ipBody.udpHeader.length
                        }, {
                            'label':
                            '校验和',
                            'value':
                            '0x%s (%s)' %
                            (self.ipBody.udpHeader.checksum, '校验' + {
                                True: '通过',
                                False: '失败'
                            }[self.ipBody.udpHeader.verifyChecksum])
                        }]
                    })

                    if self.ipBody.udpHeader.source_port == 53 or self.ipBody.udpHeader.destination_port == 53:  # DNS
                        children = [{
                            'label': '会话标识',
                            'value': self.ipBody.dnsBody.transaction_id
                        }, {
                            'label':
                            '标志',
                            'value':
                            '0x' + self.ipBody.dnsBody.transaction_id
                        }, {
                            'label': '问题数',
                            'value': self.ipBody.dnsBody.questions
                        }, {
                            'label': '回答资源记录数',
                            'value': self.ipBody.dnsBody.answer_rrs
                        }, {
                            'label': '授权资源记录数',
                            'value': self.ipBody.dnsBody.authority_rrs
                        }, {
                            'label': '附加资源记录数',
                            'value': self.ipBody.dnsBody.additional_rrs
                        }]

                        if len(self.ipBody.dnsBody.queries) > 0:
                            queries = []
                            for query in self.ipBody.dnsBody.queries:
                                queries.append({
                                    'label':
                                    str(query.qname),
                                    'value':
                                    '',
                                    'bold':
                                    True,
                                    'children': [{
                                        'label': '域名',
                                        'value': str(query.qname)
                                    }, {
                                        'label':
                                        'Type',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_types[query.qtype],
                                         query.qtype)
                                    }, {
                                        'label':
                                        'Class',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_classes[query.qclass],
                                         query.qclass)
                                    }]
                                })
                            children.append({
                                'label': '查询问题',
                                'value': '',
                                'bold': True,
                                'children': queries
                            })

                        if len(self.ipBody.dnsBody.answers) > 0:
                            answers = []
                            for answer in self.ipBody.dnsBody.answers:
                                answers.append({
                                    'label':
                                    str(answer.rname),
                                    'value':
                                    '',
                                    'bold':
                                    True,
                                    'children': [{
                                        'label': '域名',
                                        'value': str(answer.rname)
                                    }, {
                                        'label':
                                        'Type',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_types[answer.rtype],
                                         answer.rtype)
                                    }, {
                                        'label':
                                        'Class',
                                        'value':
                                        '%s (%s)' %
                                        (consts.dns_classes[answer.rclass],
                                         answer.rclass)
                                    }, {
                                        'label': '生存时间 (ttl)',
                                        'value': str(answer.ttl)
                                    }, {
                                        'label': '数据',
                                        'value': str(answer.rdata)
                                    }]
                                })
                            children.append({
                                'label': '回答',
                                'value': '',
                                'bold': True,
                                'children': answers
                            })

                        data.append({
                            'label': 'DNS / Domain Name System',
                            'value': '',
                            'bold': True,
                            'children': children
                        })

                elif 'ICMP' in self.ipHeader.protocol:
                    if 'IPv6' in self.ipHeader.protocol:
                        self.ipBody.icmpHeader.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters[0],
                            self.ipBody.parameters[1],
                            self.ipHeader.protocol).verifyChecksum
                    else:
                        self.ipBody.icmpHeader.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters, [], '').verifyChecksum
                    data.append({
                        'label':
                        'ICMP 头部 / Internet Control Message Protocol Headers',
                        'value':
                        '',
                        'bold':
                        True,
                        'children': [{
                            'label':
                            '类型',
                            'value':
                            '%s (%s)' % (self.ipBody.icmpHeader.type,
                                         self.ipBody.icmpHeader.type_name)
                        }, {
                            'label': '代码',
                            'value': self.ipBody.icmpHeader.code
                        }, {
                            'label':
                            '校验和',
                            'value':
                            '0x%s (%s)' %
                            (self.ipBody.icmpHeader.checksum, '校验' + {
                                True: '通过',
                                False: '失败'
                            }[self.ipBody.icmpHeader.verifyChecksum])
                        }]
                    })

                elif 'IGMP' in self.ipHeader.protocol:
                    if self.ipHeader.payload_length == 8:
                        self.ipBody.igmpHeader.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters, [], '').verifyChecksum
                        data.append({
                            'label':
                            'IGMP 头部 / Internet Group Management Protocol Headers',
                            'value':
                            '',
                            'bold':
                            True,
                            'children': [{
                                'label':
                                '类型',
                                'value':
                                '0x%s(%s)' % (self.ipBody.igmpHeader.type,
                                              self.ipBody.igmpHeader.type_name)
                            }, {
                                'label':
                                '最大响应时延',
                                'value':
                                '%s 秒(0x%s)' %
                                (self.ipBody.igmpHeader.maxRespTime,
                                 self.ipBody.igmpHeader.maxRespTimeHex)
                            }, {
                                'label':
                                '校验和',
                                'value':
                                '0x%s(%s)' %
                                (self.ipBody.igmpHeader.checksum, '校验' + {
                                    True: '通过',
                                    False: '失败'
                                }[self.ipBody.igmpHeader.verifyChecksum])
                            }, {
                                'label':
                                '组地址',
                                'value':
                                self.ipBody.igmpHeader.groupAddress
                            }]
                        })
                    else:
                        self.ipBody.igmpv3Header.verifyChecksum = verifyChecksum(
                            self.ipBody.parameters, [], '').verifyChecksum
                        data.append({
                            'label':
                            'IGMPv3 头部 / Internet Group Management Protocol Version 3 Headers',
                            'value':
                            '',
                            'bold':
                            True,
                            'children': [{
                                'label':
                                '类型',
                                'value':
                                '0x%s' % self.ipBody.igmpv3Header.type
                            }, {
                                'label':
                                '校验和',
                                'value':
                                '0x%s(%s)' %
                                (self.ipBody.igmpv3Header.checksum, '校验' + {
                                    True: '通过',
                                    False: '失败'
                                }[self.ipBody.igmpv3Header.verifyChecksum])
                            }]
                        })

        return data