用Scapy解析PPPoE标签

tho*_*hor 11 python scapy pppoe

我试图用Scapy正确剖析PPPoE Discovery数据包.以下是Scapy如何显示示例PADI数据包:

>>> p = Ether("\xff\xff\xff\xff\xff\xff\x08\x00'\xf3<5\x88c\x11\t\x00\x00\x00\x0c\x01\x01\x00\x00\x01\x03\x00\x04\xe0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
>>> p.show()
 ###[ Ethernet ]###
  dst= ff:ff:ff:ff:ff:ff
  src= 08:00:27:f3:3c:35
  type= 0x8863
###[ PPP over Ethernet Discovery ]###
     version= 1L
     type= 1L
     code= PADI
     sessionid= 0x0
     len= 12
###[ Raw ]###
        load= '\x01\x01\x00\x00\x01\x03\x00\x04\xe0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Run Code Online (Sandbox Code Playgroud)

我想解析Raw有效负载.此有效负载只是一个PPPoE标记列表.每个标签由两个字节的代码字段,两个字节长度的字段和一个值组成(当然,它是由前一个字段给出的长度).

这是我尝试代表所有这些:

from scapy.all import *

class PPPoETag(Packet):
    name = "PPPoE Tag"
    fields_desc = [ ShortEnumField('tag_type', None,
                                   {0x0000: 'End-Of-List',
                                    0x0101: 'Service-Name',
                                    0x0102: 'AC-Name',
                                    0x0103: 'Host-Uniq',
                                    0x0104: 'AC-Cookie',
                                    0x0105: 'Vendor-Specific',
                                    0x0110: 'Relay-Session-Id',
                                    0x0201: 'Service-Name-Error',
                                    0x0202: 'AC-System-Error',
                                    0x0203: 'Generic-Error'}),
                    FieldLenField('tag_len', None, length_of='tag_value', fmt='H'),
                    StrLenField('tag_value', '', length_from=lambda pkt:pkt.tag_len)]
    def extract_padding(self, s):
        return '', s

class PPPoED_Tags(Packet):
    name = "PPPoE Tag List"
    fields_desc = [ PacketListField('tag_list', None, PPPoETag) ]

bind_layers(PPPoED, PPPoED_Tags, type=1)
Run Code Online (Sandbox Code Playgroud)

不确定这是否是正确和最好的方式.有关改善的建议吗?

Tec*_*gon 0

在我自己的代码中,针对类似的低级问题(使用基于 ASCII 控制代码的信息分隔符(例如 SOT、EOT、NULL、BELL 等)解析串行端口协议的原始流),我使用了一组正则表达式和标准比较器。它很容易在代码中构建以便其他人理解,并且使用预编译的正则表达式也非常快。

如果我想在不添加任何非系统依赖项的情况下取出字段,我会使用大致类似于此伪代码的东西。

    Start Loop over packet content.
        Match any Tag
            Match specific tag type
                set array index based on tag type
            extract length of value
            extract tag value
            store value in array at the index set above
            slice off all the entire now matched & extracted tag.
        Loop until end no more tags match.
    End of loop
Run Code Online (Sandbox Code Playgroud)