Home | History | Annotate | Download | only in contrib
      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 = CARP
     16 # scapy.contrib.status = loads
     17 
     18 import struct, hmac, hashlib
     19 
     20 from scapy.packet import *
     21 from scapy.layers.inet import IP
     22 from scapy.fields import BitField, ByteField, XShortField, IntField, XIntField
     23 from scapy.utils import checksum, inet_aton
     24 
     25 class CARP(Packet):
     26     name = "CARP"
     27     fields_desc = [ BitField("version", 4, 4),
     28         BitField("type", 4, 4),
     29         ByteField("vhid", 1),
     30         ByteField("advskew", 0),
     31         ByteField("authlen", 0),
     32         ByteField("demotion", 0),
     33         ByteField("advbase", 0),
     34         XShortField("chksum", 0),
     35         XIntField("counter1", 0),
     36         XIntField("counter2", 0),
     37         XIntField("hmac1", 0),
     38         XIntField("hmac2", 0),
     39         XIntField("hmac3", 0),
     40         XIntField("hmac4", 0),
     41         XIntField("hmac5", 0)
     42     ]
     43 
     44     def post_build(self, pkt, pay):
     45         if self.chksum == None:
     46             pkt = pkt[:6] + struct.pack("!H", checksum(pkt)) + pkt[8:]
     47 
     48         return pkt
     49 
     50 def build_hmac_sha1(pkt, pw = b'\0' * 20, ip4l=None, ip6l=None):
     51     if ip4l is None:
     52         ip4l = []
     53     if ip6l is None:
     54         ip6l = []
     55     if not pkt.haslayer(CARP):
     56         return None 
     57 
     58     p = pkt[CARP]
     59     h = hmac.new(pw, digestmod = hashlib.sha1)
     60     # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field
     61     h.update(b'\x21')
     62     # XXX: mac addy if different from special link layer. comes before vhid
     63     h.update(struct.pack('!B', p.vhid))
     64 
     65     sl = []
     66     for i in ip4l:
     67         # sort ips from smallest to largest
     68         sl.append(inet_aton(i))
     69     sl.sort()
     70 
     71     for i in sl:
     72         h.update(i)
     73 
     74     # XXX: do ip6l sorting
     75 
     76     return h.digest()
     77 
     78 """
     79 XXX: Usually CARP is multicast to 224.0.0.18 but because of virtual setup, it'll 
     80 be unicast between nodes. Uncomment the following line for normal use
     81 bind_layers(IP, CARP, proto=112, dst='224.0.0.18')
     82 """
     83 bind_layers(IP, CARP, proto=112)
     84