我想用Vlan部分构建一个IP数据包。 Scapy很容易做到:
from scapy import inet
newpkt = inet.Ether()/inet.Dot1Q()/inet.IP()
有时候我希望在数据包中有inet.Dot1Q()
,有时候没有。
inet.Dot1Q()
的默认值应该是什么,因此只需在操作符中绕过' /&#39 ;?
我尝试了''
和None
- 他们不能工作。
from scapy import inet
myDot1Q = SOME DEFAULT VALUE
newpkt = inet.Ether()/myDot1Q/inet.IP()
#new packet is a valid IP packet here
编辑:对我的问题的不同解释
1)我可以使用VLAN标记
创建数据包inet.Ether()/inet.Dot1Q/inet.IP()
2)我可以创建一个带有双VLAN标记的数据包
inet.Ether()/inet.Dot1Q/inet.Dot1Q/inet.IP()
3)如何构建可能是未标记数据包,VLAN标记数据包或双VLAN标记数据包的数据包?有这样的东西会很棒:
#No VLAN
myVlan = ???
myDoubleVlan = ???
#VLAN
myVlan = inet.Dot1Q()
myDoubleVlan = ???
#Double VLAN
myVlan = inet.Dot1Q()
myDoubleVlan = inet.Dot1Q()
#In any case the packet structure should remain the same
inet.Ether()/myVlan/myDoubleVlan/inet.IP()
我无法弄清楚默认值???
应该能够正确构建数据包。
答案 0 :(得分:4)
首先,我无法想出为什么你不会使用这样一个简单的解决方案:
# example for single Vlan
# myVlan = Dot1Q()
# myDoubleVlan = None
# generate the package
package = Ether()
if myVlan: package /= myVlan
if myDoubleVlan: package /= myDoubleVlan
package /= IP()
但无论如何,如果这种方法出于任何不可接受的原因,还有另一种可能性......
您可以覆盖Packet
类并创建属于除法运算符中立的类。您唯一需要的是覆盖__div__
方法并添加一些括号以保留正确的优先级。
这是你实现它的方式:
from scapy.all import *
class NeutralPacket(Packet):
def __init__(self, _pkt="", _internal=0, **fields):
super(NeutralPacket, self).__init__(_pkt, _internal, **fields)
def __div__(self, other):
return other
#No VLAN
myVlan = NeutralPacket()
myDoubleVlan = NeutralPacket()
#VLAN
myVlan = Dot1Q()
myDoubleVlan = NeutralPacket()
#Double VLAN
myVlan = Dot1Q()
myDoubleVlan = Dot1Q()
# this part doesn't need to change, but you need to have two
# additional parenthesis for proper precedence
Ether()/(myVlan/(myDoubleVlan/IP()))
__div__()
方法是分区operator
实施。解释器将a/b
作为a.__div__(b)
执行,Packet
类具有自己的此运算符实现。如果您查看其code,可以看到它基本上将payload
包裹b
附加到a
包。
我们在这里所做的只是返回other
包,在这种情况下为b
,有效地完全忽略a
。
请注意,当NeutralPacket
是左侧操作员时,这仅适用于一个方向,因为否则它会影响其他一些类别的操作。正在执行的__div__()
方法。为了解决这个问题,我们必须添加括号,以便优先级使我们的NeutralPacket
类始终是左侧运算符。由于Packet
的实现不会对整体结果产生影响,因此适用于您的情况。唯一不起作用的是NeutralPacket
是最右手边(即最后一个)算子,从那时起你就不能强制执行正确的优先权。但是对于VLAN来说这不是问题,因为它上面总是有层......
答案 1 :(得分:1)
我完全忘记了Raw()
。
Raw
图层就是您想要的。
Raw()
,如果没有放置数据,则不会对构建的数据包添加任何内容。您可以将其用作myDot1Q
变量的默认值。
>>> b = Raw() / ICMP()
>>> a = Raw() / ICMP()
>>> b = ICMP()
>>> a.show()
###[ Raw ]###
load= ''
###[ ICMP ]###
type= echo-request
code= 0
chksum= None
id= 0x0
seq= 0x0
>>> b.show()
###[ ICMP ]###
type= echo-request
code= 0
chksum= None
id= 0x0
seq= 0x0
>>> a.build()
'\x08\x00\xf7\xff\x00\x00\x00\x00'
>>> b.build()
'\x08\x00\xf7\xff\x00\x00\x00\x00'
>>> a.build() == b.build()
True