mirror of https://github.com/secdev/scapy.git
Fix VRRPv3 checksum
This commit is contained in:
parent
398e52e616
commit
caab83b26d
|
@ -475,6 +475,33 @@ class IP(Packet, IPTools):
|
|||
lst.append(q)
|
||||
return lst
|
||||
|
||||
def in4_chksum(proto, u, p):
|
||||
"""
|
||||
As Specified in RFC 2460 - 8.1 Upper-Layer Checksums
|
||||
|
||||
Performs IPv4 Upper Layer checksum computation. Provided parameters are:
|
||||
- 'proto' : value of upper layer protocol
|
||||
- 'u' : IP upper layer instance
|
||||
- 'p' : the payload of the upper layer provided as a string
|
||||
"""
|
||||
if not isinstance(u, IP):
|
||||
warning("No IP underlayer to compute checksum. Leaving null.")
|
||||
return 0
|
||||
if u.len is not None:
|
||||
if u.ihl is None:
|
||||
olen = sum(len(x) for x in u.options)
|
||||
ihl = 5 + olen / 4 + (1 if olen % 4 else 0)
|
||||
else:
|
||||
ihl = u.ihl
|
||||
ln = u.len - 4 * ihl
|
||||
else:
|
||||
ln = len(p)
|
||||
psdhdr = struct.pack("!4s4sHH",
|
||||
inet_aton(u.src),
|
||||
inet_aton(u.dst),
|
||||
proto,
|
||||
ln)
|
||||
return checksum(psdhdr+p)
|
||||
|
||||
class TCP(Packet):
|
||||
name = "TCP"
|
||||
|
@ -497,21 +524,7 @@ class TCP(Packet):
|
|||
p = p[:12]+chr((dataofs << 4) | ord(p[12])&0x0f)+p[13:]
|
||||
if self.chksum is None:
|
||||
if isinstance(self.underlayer, IP):
|
||||
if self.underlayer.len is not None:
|
||||
if self.underlayer.ihl is None:
|
||||
olen = sum(len(x) for x in self.underlayer.options)
|
||||
ihl = 5 + olen / 4 + (1 if olen % 4 else 0)
|
||||
else:
|
||||
ihl = self.underlayer.ihl
|
||||
ln = self.underlayer.len - 4 * ihl
|
||||
else:
|
||||
ln = len(p)
|
||||
psdhdr = struct.pack("!4s4sHH",
|
||||
inet_aton(self.underlayer.src),
|
||||
inet_aton(self.underlayer.dst),
|
||||
self.underlayer.proto,
|
||||
ln)
|
||||
ck=checksum(psdhdr+p)
|
||||
ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer, p)
|
||||
p = p[:16]+struct.pack("!H", ck)+p[18:]
|
||||
elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):
|
||||
ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)
|
||||
|
@ -576,21 +589,7 @@ class UDP(Packet):
|
|||
p = p[:4]+struct.pack("!H",l)+p[6:]
|
||||
if self.chksum is None:
|
||||
if isinstance(self.underlayer, IP):
|
||||
if self.underlayer.len is not None:
|
||||
if self.underlayer.ihl is None:
|
||||
olen = sum(len(x) for x in self.underlayer.options)
|
||||
ihl = 5 + olen / 4 + (1 if olen % 4 else 0)
|
||||
else:
|
||||
ihl = self.underlayer.ihl
|
||||
ln = self.underlayer.len - 4 * ihl
|
||||
else:
|
||||
ln = len(p)
|
||||
psdhdr = struct.pack("!4s4sHH",
|
||||
inet_aton(self.underlayer.src),
|
||||
inet_aton(self.underlayer.dst),
|
||||
self.underlayer.proto,
|
||||
ln)
|
||||
ck = checksum(psdhdr+p)
|
||||
ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer, p)
|
||||
# According to RFC768 if the result checksum is 0, it should be set to 0xFFFF
|
||||
if ck == 0:
|
||||
ck = 0xFFFF
|
||||
|
|
|
@ -292,6 +292,7 @@ ipv6nh = { 0:"Hop-by-Hop Option Header",
|
|||
58:"ICMPv6",
|
||||
59:"No Next Header",
|
||||
60:"Destination Option Header",
|
||||
112:"VRRP",
|
||||
132:"SCTP",
|
||||
135:"Mobility Header"}
|
||||
|
||||
|
@ -643,8 +644,9 @@ class PseudoIPv6(Packet): # IPv6 Pseudo-header for checksum computation
|
|||
|
||||
def in6_chksum(nh, u, p):
|
||||
"""
|
||||
Performs IPv6 Upper Layer checksum computation. Provided parameters are:
|
||||
As Specified in RFC 2460 - 8.1 Upper-Layer Checksums
|
||||
|
||||
Performs IPv6 Upper Layer checksum computation. Provided parameters are:
|
||||
- 'nh' : value of upper layer protocol
|
||||
- 'u' : upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be
|
||||
provided with all under layers (IPv6 and all extension headers,
|
||||
|
|
|
@ -10,15 +10,17 @@ VRRP (Virtual Router Redundancy Protocol).
|
|||
|
||||
from scapy.packet import *
|
||||
from scapy.fields import *
|
||||
from scapy.layers.inet import IP
|
||||
from scapy.layers.inet import *
|
||||
from scapy.layers.inet6 import *
|
||||
from scapy.error import warning
|
||||
|
||||
IPPROTO_VRRP=112
|
||||
|
||||
# RFC 3768 - Virtual Router Redundancy Protocol (VRRP)
|
||||
class VRRP(Packet):
|
||||
fields_desc = [
|
||||
BitField("version" , 2, 4),
|
||||
BitField("type" , 1, 4),
|
||||
BitField("version", 2, 4),
|
||||
BitField("type", 1, 4),
|
||||
ByteField("vrid", 1),
|
||||
ByteField("priority", 100),
|
||||
FieldLenField("ipcount", None, count_of="addrlist", fmt="B"),
|
||||
|
@ -36,4 +38,51 @@ class VRRP(Packet):
|
|||
p = p[:6]+chr(ck>>8)+chr(ck&0xff)+p[8:]
|
||||
return p
|
||||
|
||||
@classmethod
|
||||
def dispatch_hook(cls, _pkt=None, *args, **kargs):
|
||||
if _pkt and len(_pkt) >= 9:
|
||||
ver_n_type = ord(_pkt[0])
|
||||
if ver_n_type >= 48 and ver_n_type <= 57: # Version == 3
|
||||
return VRRPv3
|
||||
return VRRP
|
||||
|
||||
|
||||
# RFC 5798 - Virtual Router Redundancy Protocol (VRRP) Version 3
|
||||
class VRRPv3(Packet):
|
||||
fields_desc = [
|
||||
BitField("version", 3, 4),
|
||||
BitField("type", 1, 4),
|
||||
ByteField("vrid", 1),
|
||||
ByteField("priority", 100),
|
||||
FieldLenField("ipcount", None, count_of="addrlist", fmt="B"),
|
||||
BitField("res", 0, 4),
|
||||
BitField("adv", 100, 12),
|
||||
XShortField("chksum", None),
|
||||
# FIXME: addrlist should also allow IPv6 addresses :/
|
||||
FieldListField("addrlist", [], IPField("", "0.0.0.0"),
|
||||
count_from = lambda pkt: pkt.ipcount)]
|
||||
|
||||
def post_build(self, p, pay):
|
||||
if self.chksum is None:
|
||||
if isinstance(self.underlayer, IP):
|
||||
ck = in4_chksum(112, self.underlayer, p)
|
||||
elif isinstance(self.underlayer, IPv6):
|
||||
ck = in6_chksum(112, self.underlayer, p)
|
||||
else:
|
||||
warning("No IP(v6) layer to compute checksum on VRRP. Leaving null")
|
||||
ck = 0
|
||||
p = p[:6]+chr(ck>>8)+chr(ck&0xff)+p[8:]
|
||||
return p
|
||||
|
||||
@classmethod
|
||||
def dispatch_hook(cls, _pkt=None, *args, **kargs):
|
||||
if _pkt and len(_pkt) >= 16:
|
||||
ver_n_type = ord(_pkt[0])
|
||||
if ver_n_type < 48 or ver_n_type > 57: # Version != 3
|
||||
return VRRP
|
||||
return VRRPv3
|
||||
|
||||
# IPv6 is supported only on VRRPv3
|
||||
bind_layers( IP, VRRP, proto=IPPROTO_VRRP)
|
||||
bind_layers( IP, VRRPv3, proto=IPPROTO_VRRP)
|
||||
bind_layers( IPv6, VRRPv3, nh=IPPROTO_VRRP)
|
||||
|
|
Loading…
Reference in New Issue