IGMPv3报文解析

通过使用Python struct库来解析IGMPv3报文

struct模块中的函数

函数 return explain
pack(fmt,v1,v2…) string 按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回.
pack_into(fmt,buffer,offset,v1,v2…) None 按照给定的格式(fmt),将数据转换成字符串(字节流),并将字节流写入以offset开始的buffer中.(buffer为可写的缓冲区,可用array模块)
unpack(fmt,v1,v2…..) tuple 按照给定的格式(fmt)解析字节流,并返回解析结果
pack_from(fmt,buffer,offset) tuple 按照给定的格式(fmt)解析以offset开始的缓冲区,并返回解析结果
calcsize(fmt) size of fmt 计算给定的格式(fmt)占用多少字节的内存,注意对齐方式

格式化字符串

当打包或者解包的时,需要按照特定的方式来打包或者解包.该方式就是格式化字符串,它指定了数据类型,除此之外,还有用于控制字节顺序、大小和对齐方式的特殊字符.

对齐方式

为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下

Character Byte order Size Alignment
@(默认) 本机 本机 本机,凑够4字节
= 本机 标准 none,按原字节数
< 小端 标准 none,按原字节数
> 大端 标准 none,按原字节数
! network(大端) 标准 none,按原字节数

如果不懂大小端,见大小端参考网址.

格式符

格式符 C语言类型 Python类型 Standard size
x pad byte(填充字节) no value
c char string of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I(大写的i) unsigned int integer 4
l(小写的L) long integer 4
L unsigned long long 4
q long long long 8
Q unsigned long long long 8
f float float 4
d double float 8
s char[] string
p char[] string
P void * long

注- -!

  1. _Bool在C99中定义,如果没有这个类型,则将这个类型视为char,一个字节;
  2. q和Q只适用于64位机器;
  3. 每个格式前可以有一个数字,表示这个类型的个数,如s格式表示一定长度的字符串,4s表示长度为4的字符串;4i表示四个int;
  4. P用来转换一个指针,其长度和计算机相关;
  5. f和d的长度和计算机相关;

报文结构

image-20201006123726614

Group Record格式:

image-20201006123749720

来源:https://tools.ietf.org/html/rfc3376

Code

import struct

class IGMP:
    def __init__(self, raw):
        raw_head = raw[:8]
        self.type, self.reserved, self.checknum, self.reserved2, self.number_group_records = struct.unpack(">BBHHH", raw_head)
        raw_group = raw[8:]
        self.group_list = []
        self.deal_group_record(self.number_group_records, raw_group)

    def deal_group_record(self, number_group, raw_group):
        group_pointer = 0
        for _ in range(number_group):
            record_type, aux_data_len, number_source, multicast_address = struct.unpack(">BBHI",raw_group[group_pointer : group_pointer + 8])
            source_address_list = []
            for k in range(number_source):
                tmp_pointer = group_pointer + 8 + k * 4
                source_address = struct.unpack(">I",raw_group[tmp_pointer : tmp_pointer + 4])
                source_address_list.append(source_address)
            tmp_pointer = group_pointer + 8 + number_source * 4
            if aux_data_len>0:
                auxiliary_data = struct.unpack(">%sI"%aux_data_len,raw_group[tmp_pointer : tmp_pointer + 4 * aux_data_len])
            else:
                auxiliary_data = ""
            self.group_list.append({"record_type": record_type,"aux_data_len": aux_data_len,"number_source": number_source,"multicast_address": multicast_address,"source_address_list": source_address_list,"auxiliary_data": auxiliary_data})
            group_pointer = group_pointer + 8 + number_source * 4 + aux_data_len * 4


if __name__ == '__main__':
    test = b'\x22\x00\xf0\xc3\x00\x00\x00\x02' \
           b'\x01\x00\x00\x02\xe1\x00\x00\x33\x0a\x01\x01\x05\x0a\x01\x01\x05' \
           b'\x01\x00\x00\x02\xe1\x00\x00\x33\x0a\x01\x01\x05\x0a\x01\x01\x05'
    igmp = IGMP(test)
    for i in igmp.group_list : print(i)

解析结果

image-20201006134412446

参考

posted @ 2020-10-06 13:46  lktop  阅读(1311)  评论(0编辑  收藏  举报