2012-12-02 25 views
1

我在scapy中实现GTPv2。目前的定义如下:show2()方法不会显示子类

class _GTPv2IE_HDR(Packet): 
    fields_desc = [ ByteEnumField("type", None, gtpv2_ie_types), 
        ShortField("length", None), 
        BitField("spare", 0, 4), 
        BitField("instance", 0, 4) ] 

class GTPv2IE(Packet): 
    name = "GTPv2 Information Element" 
    fields_desc = [ _GTPv2IE_HDR ] 

    def extract_padding(self, p): 
     return "", p 

    def post_build(self, p, pay): 
     if self.length is None: 
      l = len(p) - 4 
      p = p[:1] + struct.pack("!H", l) + p[3:] 
     return p + pay 

正如你可以GTPv2IE是信息元素的基类(类似于ipv6中的ext头)。

这里是我如何定义一个IE浏览器:

class GTPv2IE_Recovery(GTPv2IE): 
    name = "GTPv2 Recovery IE" 
    type = 3 
    fields_desc = [ _GTPv2IE_HDR, 
        ByteField("recovery", None) ] 
    def post_build(self, p, pay): 
     if self.recovery is None: 
      rec = random.getrandbits(8) 
      p = p[:4] + struct.pack("B", rec) 
     return GTPv2IE.post_build(self, p, pay) 

现在GTPv2的数据包本身具有以下领域的fields_desc列表的末尾:

PacketListField("info_elements", [], GTPv2IE, length_from=lambda p:p.length-4-(4 if p.flags & 0x8 != 0 else 0))) 

的问题是,当我创建一个GTPv2的包:

pkt = IP(dst='2.2.2.2')/UDP()/GTPv2(info_elements=[GTPv2IE_Recovery()]) 

和呼叫show2()我得到:

###[ IP ]### 
    version= 4L 
    ihl= 5L 
    tos= 0x0 
    len= 41 
    id= 1 
    flags= 
    frag= 0L 
    ttl= 64 
    proto= udp 
    chksum= 0x7465 
    src= 1.1.1.90 
    dst= 2.2.2.2 
    \options\ 
###[ UDP ]### 
    sport= 2123 
    dport= 2123 
    len= 21 
    chksum= 0xc380 
###[ GTPv2 ]### 
     version= 2L 
     flags= 
     type= echo_request 
     length= 9 
     sequence= 0x3a444d 
     spare2= 0 
     \info_elements\ 
     |###[ GTPv2 Information Element ]### 
     | type= recovery 
     | length= 1 
     | spare= 0L 
     | instance= 0L 
     |###[ GTPv2 Information Element ]### 
     | type= 90 
     | length= None 
     | spare= 0 
     | instance= 0 

的show()方法按预期工作:

###[ IP ]### 
    version= 4 
    ihl= None 
    tos= 0x0 
    len= None 
    id= 1 
    flags= 
    frag= 0 
    ttl= 64 
    proto= udp 
    chksum= None 
    src= 1.1.1.90 
    dst= 2.2.2.2 
    \options\ 
###[ UDP ]### 
    sport= 2123 
    dport= 2123 
    len= None 
    chksum= None 
###[ GTPv2 ]### 
     version= 2 
     flags= 
     type= echo_request 
     length= None 
     sequence= None 
     spare2= 0 
     \info_elements\ 
     |###[ GTPv2 Recovery IE ]### 
     | type= recovery 
     | length= None 
     | spare= 0 
     | instance= 0 
     | recovery= None 

感谢您的帮助球员。

Alex。

回答

1

我已经得到了这个工作(使用了IPOption为例):

我加2个classmethods到GTPv2IE基类如下:

registered_info_elements = {} 
@classmethod 
def register_variant(cls): 
    cls.registered_info_elements[cls.type.default] = cls 
@classmethod 
def dispatch_hook(cls, pkt=None, *args, **kargs): 
    if pkt: 
     t = ord(pkt[0]) 
     return cls.registered_info_elements.get(t, cls) 
    return cls 

现在show2()按预期工作:

>>> pkt.show2() 
###[ IP ]### 
    version= 4L 
    ihl= 5L 
    tos= 0x0 
    len= 46 
    id= 1 
    flags= 
    frag= 0L 
    ttl= 64 
    proto= udp 
    chksum= 0x7607 
    src= 1.1.1.90 
    dst= 1.1.1.92 
    \options\ 
###[ UDP ]### 
    sport= 2123 
    dport= 2123 
    len= 26 
    chksum= 0x52da 
###[ GTPv2 ]### 
     version= 2L 
     flags= 
     type= echo_request 
     length= 14 
     sequence= 0x8ce2a1 
     spare2= 0 
     \info_elements\ 
     |###[ GTPv2 Recovery IE ]### 
     | type= recovery 
     | length= 1 
     | spare= 0L 
     | instance= 0L 
     | recovery= 37 
     |###[ GTPv2 Sending Node Features IE ]### 
     | type= node_features 
     | length= 1 
     | spare= 0L 
     | instance= 0L 
     | node_features= PRN+MABR+NTSR