1# This file is part of Scapy 2# Scapy is free software: you can redistribute it and/or modify 3# it under the terms of the GNU General Public License as published by 4# the Free Software Foundation, either version 2 of the License, or 5# any later version. 6# 7# Scapy is distributed in the hope that it will be useful, 8# but WITHOUT ANY WARRANTY; without even the implied warranty of 9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10# GNU General Public License for more details. 11# 12# You should have received a copy of the GNU General Public License 13# along with Scapy. If not, see <http://www.gnu.org/licenses/>. 14 15# scapy.contrib.description = Common Address Redundancy Protocol (CARP) 16# scapy.contrib.status = loads 17 18import struct 19import hmac 20import hashlib 21 22from scapy.packet import Packet, split_layers, bind_layers 23from scapy.layers.inet import IP 24from scapy.fields import BitField, ByteField, XShortField, XIntField 25from scapy.layers.vrrp import IPPROTO_VRRP, VRRP, VRRPv3 26from scapy.utils import checksum, inet_aton 27from scapy.error import warning 28 29 30class CARP(Packet): 31 name = "CARP" 32 fields_desc = [BitField("version", 4, 4), 33 BitField("type", 4, 4), 34 ByteField("vhid", 1), 35 ByteField("advskew", 0), 36 ByteField("authlen", 0), 37 ByteField("demotion", 0), 38 ByteField("advbase", 0), 39 XShortField("chksum", None), 40 XIntField("counter1", 0), 41 XIntField("counter2", 0), 42 XIntField("hmac1", 0), 43 XIntField("hmac2", 0), 44 XIntField("hmac3", 0), 45 XIntField("hmac4", 0), 46 XIntField("hmac5", 0) 47 ] 48 49 def post_build(self, pkt, pay): 50 if self.chksum is None: 51 pkt = pkt[:6] + struct.pack("!H", checksum(pkt)) + pkt[8:] 52 53 return pkt 54 55 def build_hmac_sha1(self, pw=b'\x00' * 20, ip4l=[], ip6l=[]): 56 h = hmac.new(pw, digestmod=hashlib.sha1) 57 # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field # noqa: E501 58 h.update(b'\x21') 59 # XXX: mac addy if different from special link layer. comes before vhid 60 h.update(struct.pack('!B', self.vhid)) 61 62 sl = [] 63 for i in ip4l: 64 # sort ips from smallest to largest 65 sl.append(inet_aton(i)) 66 sl.sort() 67 68 for i in sl: 69 h.update(i) 70 71 # XXX: do ip6l sorting 72 73 return h.digest() 74 75 76warning("CARP overwrites VRRP !") 77# This cancel the bindings done in vrrp.py 78split_layers(IP, VRRP, proto=IPPROTO_VRRP) 79split_layers(IP, VRRPv3, proto=IPPROTO_VRRP) 80# CARP bindings 81bind_layers(IP, CARP, proto=112, dst='224.0.0.18') 82