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

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM