zoukankan      html  css  js  c++  java
  • 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'x22x00xf0xc3x00x00x00x02' 
               b'x01x00x00x02xe1x00x00x33x0ax01x01x05x0ax01x01x05' 
               b'x01x00x00x02xe1x00x00x33x0ax01x01x05x0ax01x01x05'
        igmp = IGMP(test)
        for i in igmp.group_list : print(i)
    
    

    解析结果

    image-20201006134412446

    参考

  • 相关阅读:
    怎么判断一个bug到底是前端的bug还是后端的bug
    charles抓包原理
    java基础|Properties文件解析
    java基础|break、continue和return
    Java使用JSONPath解析JSON完整内容详解
    10/23/2019
    有什么好怕的
    [转]一个急刹车,过路老人吓得病发身亡 司机要担责吗?
    [转]7岁女孩练舞下腰致残,舞蹈培训机构被判赔115万
    Salesforce权限管理
  • 原文地址:https://www.cnblogs.com/lktop/p/13773267.html
Copyright © 2011-2022 走看看