From b89efa188810bf95a9d245e69e2961b5721c3b0f Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 21 Mar 2016 16:03:47 +0200 Subject: scapy python 2/3 --- .../scapy-2.3.1/python2/scapy/contrib/eigrp.py | 488 +++++++++++++++++++++ 1 file changed, 488 insertions(+) create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/contrib/eigrp.py (limited to 'scripts/external_libs/scapy-2.3.1/python2/scapy/contrib/eigrp.py') diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/contrib/eigrp.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/contrib/eigrp.py new file mode 100644 index 00000000..73b4ce02 --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/contrib/eigrp.py @@ -0,0 +1,488 @@ +#!/usr/bin/env python + +# scapy.contrib.description = EIGRP +# scapy.contrib.status = loads + +""" + EIGRP Scapy Extension + ~~~~~~~~~~~~~~~~~~~~~ + + :version: 2009-08-13 + :copyright: 2009 by Jochen Bartl + :e-mail: lobo@c3a.de / jochen.bartl@gmail.com + :license: GPL v2 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + :TODO + + - Replace TLV code with a more generic solution + * http://trac.secdev.org/scapy/ticket/90 + - Write function for calculating authentication data + + :Known bugs: + + - + + :Thanks: + + - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard) + http://trac.secdev.org/scapy/ticket/18 + - IOS / EIGRP Version Representation FIX by Dirk Loss +""" + +from scapy.packet import * +from scapy.fields import * +from scapy.layers.inet import IP +from scapy.layers.inet6 import * + +class EigrpIPField(StrField, IPField): + """ + This is a special field type for handling ip addresses of destination networks in internal and + external route updates. + + EIGRP removes zeros from the host portion of the ip address if the netmask is 8, 16 or 24 bits. + """ + + def __init__(self, name, default, length=None, length_from=None): + StrField.__init__(self, name, default) + self.length_from = length_from + if length is not None: + self.length_from = lambda pkt,length=length: length + + def h2i(self, pkt, x): + return IPField.h2i(self, pkt, x) + + def i2m(self, pkt, x): + x = inet_aton(x) + l = self.length_from(pkt) + + if l <= 8: + return x[:1] + elif l <= 16: + return x[:2] + elif l <= 24: + return x[:3] + else: + return x + + def m2i(self, pkt, x): + l = self.length_from(pkt) + + if l <= 8: + x += "\x00\x00\x00" + elif l <= 16: + x += "\x00\x00" + elif l <= 24: + x += "\x00" + + return inet_ntoa(x) + + def prefixlen_to_bytelen(self, l): + if l <= 8: + l = 1 + elif l <= 16: + l = 2 + elif l <= 24: + l = 3 + else: + l = 4 + + return l + + def i2len(self, pkt, x): + l = self.length_from(pkt) + l = self.prefixlen_to_bytelen(l) + + return l + + def getfield(self, pkt, s): + l = self.length_from(pkt) + l = self.prefixlen_to_bytelen(l) + + return s[l:], self.m2i(pkt, s[:l]) + + def randval(self): + return IPField.randval(self) + +class EigrpIP6Field(StrField, IP6Field, EigrpIPField): + """ + This is a special field type for handling ip addresses of destination networks in internal and + external route updates. + + """ + + def __init__(self, name, default, length=None, length_from=None): + StrField.__init__(self, name, default) + self.length_from = length_from + if length is not None: + self.length_from = lambda pkt,length=length: length + + def any2i(self, pkt, x): + return IP6Field.any2i(self, pkt, x) + + def i2repr(self, pkt, x): + return IP6Field.i2repr(self, pkt, x) + + def h2i(self, pkt, x): + return IP6Field.h2i(self, pkt, x) + + def i2m(self, pkt, x): + x = inet_pton(socket.AF_INET6, x) + l = self.length_from(pkt) + l = self.prefixlen_to_bytelen(l) + + return x[:l] + + def m2i(self, pkt, x): + l = self.length_from(pkt) + + prefixlen = self.prefixlen_to_bytelen(l) + if l > 128: + warning("EigrpIP6Field: Prefix length is > 128. Dissection of this packet will fail") + else: + pad = "\x00" * (16 - prefixlen) + x += pad + + return inet_ntop(socket.AF_INET6, x) + + def prefixlen_to_bytelen(self, l): + l = l / 8 + + if l < 16: + l += 1 + + return l + + def i2len(self, pkt, x): + return EigrpIPField.i2len(self, pkt, x) + + def getfield(self, pkt, s): + return EigrpIPField.getfield(self, pkt, s) + +class ThreeBytesField(X3BytesField, ByteField): + def i2repr(self, pkt, x): + return ByteField.i2repr(self, pkt, x) + + +class EIGRPGeneric(Packet): + name = "EIGRP Generic TLV" + fields_desc = [ XShortField("type", 0x0000), + FieldLenField("len", None, "value", "!H", adjust=lambda pkt,x: x + 4), + StrLenField("value", "\x00", length_from=lambda pkt: pkt.len - 4)] + + def guess_payload_class(self, p): + return conf.padding_layer + +class EIGRPParam(EIGRPGeneric): + name = "EIGRP Parameters" + fields_desc = [ XShortField("type", 0x0001), + ShortField("len", 12), + # Bandwidth + ByteField("k1", 1), + # Load + ByteField("k2", 0), + # Delay + ByteField("k3", 1), + # Reliability + ByteField("k4", 0), + # MTU + ByteField("k5", 0), + ByteField("reserved", 0), + ShortField("holdtime", 15) + ] + +class EIGRPAuthData(EIGRPGeneric): + name = "EIGRP Authentication Data" + fields_desc = [ XShortField("type", 0x0002), + FieldLenField("len", None, "authdata", "!H", adjust=lambda pkt,x: x + 24), + ShortEnumField("authtype", 2, {2 : "MD5"}), + ShortField("keysize", None), + IntField("keyid", 1), + StrFixedLenField("nullpad", "\x00" * 12, 12), + StrLenField("authdata", RandString(16), length_from=lambda pkt: pkt.keysize) + ] + + def post_build(self, p, pay): + p += pay + + if self.keysize is None: + keysize = len(self.authdata) + p = p[:6] + chr((keysize >> 8) & 0xff) + chr(keysize & 0xff) + p[8:] + + return p + +class EIGRPSeq(EIGRPGeneric): + name = "EIGRP Sequence" + fields_desc = [ XShortField("type", 0x0003), + ShortField("len", None), + ByteField("addrlen", 4), + ConditionalField(IPField("ipaddr", "192.168.0.1"), + lambda pkt:pkt.addrlen == 4), + ConditionalField(IP6Field("ip6addr", "2001::"), + lambda pkt:pkt.addrlen == 16) + ] + + def post_build(self, p, pay): + p += pay + + if self.len is None: + l = len(p) + p = p[:2] + chr((l >> 8) & 0xff) + chr(l & 0xff) + p[4:] + + return p + +class ShortVersionField(ShortField): + def i2repr(self, pkt, x): + try: + minor = x & 0xff + major = (x >> 8) & 0xff + except TypeError: + return "unknown" + else: + # We print a leading 'v' so that these values don't look like floats + return "v%s.%s" % (major, minor) + + def h2i(self, pkt, x): + """The field accepts string values like v12.1, v1.1 or integer values. + String values have to start with a "v" folled by a floating point number. + Valid numbers are between 0 and 255. + """ + + if type(x) is str and x.startswith("v") and len(x) <= 8: + major = int(x.split(".")[0][1:]) + minor = int(x.split(".")[1]) + + return (major << 8) | minor + + elif type(x) is int and x >= 0 and x <= 65535: + return x + else: + if self.default != None: + warning("set value to default. Format of %r is invalid" % x) + return self.default + else: + raise Scapy_Exception("Format of value is invalid") + + def randval(self): + return RandShort() + +class EIGRPSwVer(EIGRPGeneric): + name = "EIGRP Software Version" + fields_desc = [ XShortField("type", 0x0004), + ShortField("len", 8), + ShortVersionField("ios", "v12.0"), + ShortVersionField("eigrp", "v1.2") + ] + +class EIGRPNms(EIGRPGeneric): + name = "EIGRP Next Multicast Sequence" + fields_desc = [ XShortField("type", 0x0005), + ShortField("len", 8), + IntField("nms", 2) + ] + +# Don't get confused by the term "receive-only". This flag is always set, when you configure +# one of the stub options. It's also the only flag set, when you configure "eigrp stub receive-only". +_EIGRP_STUB_FLAGS = ["connected", "static", "summary", "receive-only", "redistributed", "leak-map"] + +class EIGRPStub(EIGRPGeneric): + name = "EIGRP Stub Router" + fields_desc = [ XShortField("type", 0x0006), + ShortField("len", 6), + FlagsField("flags", 0x000d, 16, _EIGRP_STUB_FLAGS)] + +# Delay 0xffffffff == Destination Unreachable +class EIGRPIntRoute(EIGRPGeneric): + name = "EIGRP Internal Route" + fields_desc = [ XShortField("type", 0x0102), + FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 25), + IPField("nexthop", "192.168.0.0"), + IntField("delay", 128000), + IntField("bandwidth", 256), + ThreeBytesField("mtu", 1500), + ByteField("hopcount", 0), + ByteField("reliability", 255), + ByteField("load", 0), + XShortField("reserved", 0), + ByteField("prefixlen", 24), + EigrpIPField("dst", "192.168.1.0", length_from=lambda pkt: pkt.prefixlen), + ] + +_EIGRP_EXTERNAL_PROTOCOL_ID = { + 0x01 : "IGRP", + 0x02 : "EIGRP", + 0x03 : "Static Route", + 0x04 : "RIP", + 0x05 : "Hello", + 0x06 : "OSPF", + 0x07 : "IS-IS", + 0x08 : "EGP", + 0x09 : "BGP", + 0x0A : "IDRP", + 0x0B : "Connected Link" + } + +_EIGRP_EXTROUTE_FLAGS = ["external", "candidate-default"] + +class EIGRPExtRoute(EIGRPGeneric): + name = "EIGRP External Route" + fields_desc = [ XShortField("type", 0x0103), + FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 45), + IPField("nexthop", "192.168.0.0"), + IPField("originrouter", "192.168.0.1"), + IntField("originasn", 0), + IntField("tag", 0), + IntField("externalmetric", 0), + ShortField("reserved", 0), + ByteEnumField("extprotocolid", 3, _EIGRP_EXTERNAL_PROTOCOL_ID), + FlagsField("flags", 0, 8, _EIGRP_EXTROUTE_FLAGS), + IntField("delay", 0), + IntField("bandwidth", 256), + ThreeBytesField("mtu", 1500), + ByteField("hopcount", 0), + ByteField("reliability", 255), + ByteField("load", 0), + XShortField("reserved2", 0), + ByteField("prefixlen", 24), + EigrpIPField("dst", "192.168.1.0", length_from=lambda pkt: pkt.prefixlen) + ] + +class EIGRPv6IntRoute(EIGRPGeneric): + name = "EIGRP for IPv6 Internal Route" + fields_desc = [ XShortField("type", 0x0402), + FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 37), + IP6Field("nexthop", "::"), + IntField("delay", 128000), + IntField("bandwidth", 256000), + ThreeBytesField("mtu", 1500), + ByteField("hopcount", 1), + ByteField("reliability", 255), + ByteField("load", 0), + XShortField("reserved", 0), + ByteField("prefixlen", 16), + EigrpIP6Field("dst", "2001::", length_from=lambda pkt: pkt.prefixlen) + ] + +class EIGRPv6ExtRoute(EIGRPGeneric): + name = "EIGRP for IPv6 External Route" + fields_desc = [ XShortField("type", 0x0403), + FieldLenField("len", None, "dst", "!H", adjust=lambda pkt,x: x + 57), + IP6Field("nexthop", "::"), + IPField("originrouter", "192.168.0.1"), + IntField("originasn", 0), + IntField("tag", 0), + IntField("externalmetric", 0), + ShortField("reserved", 0), + ByteEnumField("extprotocolid", 3, _EIGRP_EXTERNAL_PROTOCOL_ID), + FlagsField("flags", 0, 8, _EIGRP_EXTROUTE_FLAGS), + IntField("delay", 0), + IntField("bandwidth", 256000), + ThreeBytesField("mtu", 1500), + ByteField("hopcount", 1), + ByteField("reliability", 0), + ByteField("load", 1), + XShortField("reserved2", 0), + ByteField("prefixlen", 8), + EigrpIP6Field("dst", "::", length_from=lambda pkt: pkt.prefixlen) + ] + +_eigrp_tlv_cls = { + 0x0001: "EIGRPParam", + 0x0002: "EIGRPAuthData", + 0x0003: "EIGRPSeq", + 0x0004: "EIGRPSwVer", + 0x0005: "EIGRPNms", + 0x0006: "EIGRPStub", + 0x0102: "EIGRPIntRoute", + 0x0103: "EIGRPExtRoute", + 0x0402: "EIGRPv6IntRoute", + 0x0403: "EIGRPv6ExtRoute" + } + +class RepeatedTlvListField(PacketListField): + def __init__(self, name, default, cls): + PacketField.__init__(self, name, default, cls) + + def getfield(self, pkt, s): + lst = [] + remain = s + while len(remain) > 0: + p = self.m2i(pkt, remain) + if conf.padding_layer in p: + pad = p[conf.padding_layer] + remain = pad.load + del(pad.underlayer.payload) + else: + remain = "" + lst.append(p) + return remain,lst + + def addfield(self, pkt, s, val): + return s + reduce(str.__add__, map(str, val), "") + +def _EIGRPGuessPayloadClass(p, **kargs): + cls = conf.raw_layer + if len(p) >= 2: + t = struct.unpack("!H", p[:2])[0] + clsname = _eigrp_tlv_cls.get(t, "EIGRPGeneric") + cls = globals()[clsname] + return cls(p, **kargs) + +_EIGRP_OPCODES = { 1 : "Update", + 2 : "Request", + 3 : "Query", + 4 : "Replay", + 5 : "Hello", + 6 : "IPX SAP", + 10 : "SIA Query", + 11 : "SIA Reply" } + +# The Conditional Receive bit is used for reliable multicast communication. +# Update-Flag: Not sure if Cisco calls it that way, but it's set when neighbors +# are exchanging routing information +_EIGRP_FLAGS = ["init", "cond-recv", "unknown", "update"] + +class EIGRP(Packet): + name = "EIGRP" + fields_desc = [ ByteField("ver", 2), + ByteEnumField("opcode", 5, _EIGRP_OPCODES), + XShortField("chksum", None), + FlagsField("flags", 0, 32, _EIGRP_FLAGS), + IntField("seq", 0), + IntField("ack", 0), + IntField("asn", 100), + RepeatedTlvListField("tlvlist", [], _EIGRPGuessPayloadClass) + ] + + def post_build(self, p, pay): + p += pay + if self.chksum is None: + c = checksum(p) + p = p[:2] + chr((c >> 8) & 0xff) + chr(c & 0xff) + p[4:] + return p + + def mysummary(self): + summarystr = "EIGRP (AS=%EIGRP.asn% Opcode=%EIGRP.opcode%" + if self.opcode == 5 and self.ack != 0: + summarystr += " (ACK)" + if self.flags != 0: + summarystr += " Flags=%EIGRP.flags%" + + return self.sprintf(summarystr + ")") + +bind_layers(IP, EIGRP, proto=88) +bind_layers(IPv6, EIGRP, nh=88) + +if __name__ == "__main__": + from scapy.main import interact + interact(mydict=globals(), mybanner="EIGRP") + -- cgit