summaryrefslogtreecommitdiffstats
path: root/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-03-21 16:03:47 +0200
committerimarom <imarom@cisco.com>2016-03-21 16:03:47 +0200
commitb89efa188810bf95a9d245e69e2961b5721c3b0f (patch)
tree454273ac6c4ae972ebb8a2c86b893296970b4fa9 /scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py
parentf72c6df9d2e9998ae1f3529d729ab7930b35785a (diff)
scapy python 2/3
Diffstat (limited to 'scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py')
-rw-r--r--scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py1718
1 files changed, 0 insertions, 1718 deletions
diff --git a/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py b/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py
deleted file mode 100644
index a11a4149..00000000
--- a/scripts/external_libs/scapy-python3-0.18/scapy/layers/dhcp6.py
+++ /dev/null
@@ -1,1718 +0,0 @@
-## This file is part of Scapy
-## See http://www.secdev.org/projects/scapy for more informations
-## Copyright (C) Philippe Biondi <phil@secdev.org>
-## This program is published under a GPLv2 license
-
-## Copyright (C) 2005 Guillaume Valadon <guedou@hongo.wide.ad.jp>
-## Arnaud Ebalard <arnaud.ebalard@eads.net>
-
-"""
-DHCPv6: Dynamic Host Configuration Protocol for IPv6. [RFC 3315]
-"""
-
-import socket
-from scapy.packet import *
-from scapy.fields import *
-from scapy.utils6 import *
-from scapy.layers.inet6 import *
-from scapy.ansmachine import AnsweringMachine
-
-#############################################################################
-# Helpers ##
-#############################################################################
-
-def get_cls(name, fallback_cls):
- return globals().get(name, fallback_cls)
-
-
-#############################################################################
-#############################################################################
-### DHCPv6 ###
-#############################################################################
-#############################################################################
-
-All_DHCP_Relay_Agents_and_Servers = "ff02::1:2"
-All_DHCP_Servers = "ff05::1:3" # Site-Local scope : deprecated by 3879
-
-dhcp6opts = { 1: "CLIENTID",
- 2: "SERVERID",
- 3: "IA_NA",
- 4: "IA_TA",
- 5: "IAADDR",
- 6: "ORO",
- 7: "PREFERENCE",
- 8: "ELAPSED_TIME",
- 9: "RELAY_MSG",
- 11: "AUTH",
- 12: "UNICAST",
- 13: "STATUS_CODE",
- 14: "RAPID_COMMIT",
- 15: "USER_CLASS",
- 16: "VENDOR_CLASS",
- 17: "VENDOR_OPTS",
- 18: "INTERFACE_ID",
- 19: "RECONF_MSG",
- 20: "RECONF_ACCEPT",
- 21: "SIP Servers Domain Name List", #RFC3319
- 22: "SIP Servers IPv6 Address List", #RFC3319
- 23: "DNS Recursive Name Server Option", #RFC3646
- 24: "Domain Search List option", #RFC3646
- 25: "OPTION_IA_PD", #RFC3633
- 26: "OPTION_IAPREFIX", #RFC3633
- 27: "OPTION_NIS_SERVERS", #RFC3898
- 28: "OPTION_NISP_SERVERS", #RFC3898
- 29: "OPTION_NIS_DOMAIN_NAME", #RFC3898
- 30: "OPTION_NISP_DOMAIN_NAME", #RFC3898
- 31: "OPTION_SNTP_SERVERS", #RFC4075
- 32: "OPTION_INFORMATION_REFRESH_TIME", #RFC4242
- 33: "OPTION_BCMCS_SERVER_D", #RFC4280
- 34: "OPTION_BCMCS_SERVER_A", #RFC4280
- 36: "OPTION_GEOCONF_CIVIC", #RFC-ietf-geopriv-dhcp-civil-09.txt
- 37: "OPTION_REMOTE_ID", #RFC4649
- 38: "OPTION_SUBSCRIBER_ID", #RFC4580
- 39: "OPTION_CLIENT_FQDN" } #RFC4704
-
-dhcp6opts_by_code = { 1: "DHCP6OptClientId",
- 2: "DHCP6OptServerId",
- 3: "DHCP6OptIA_NA",
- 4: "DHCP6OptIA_TA",
- 5: "DHCP6OptIAAddress",
- 6: "DHCP6OptOptReq",
- 7: "DHCP6OptPref",
- 8: "DHCP6OptElapsedTime",
- 9: "DHCP6OptRelayMsg",
- 11: "DHCP6OptAuth",
- 12: "DHCP6OptServerUnicast",
- 13: "DHCP6OptStatusCode",
- 14: "DHCP6OptRapidCommit",
- 15: "DHCP6OptUserClass",
- 16: "DHCP6OptVendorClass",
- 17: "DHCP6OptVendorSpecificInfo",
- 18: "DHCP6OptIfaceId",
- 19: "DHCP6OptReconfMsg",
- 20: "DHCP6OptReconfAccept",
- 21: "DHCP6OptSIPDomains", #RFC3319
- 22: "DHCP6OptSIPServers", #RFC3319
- 23: "DHCP6OptDNSServers", #RFC3646
- 24: "DHCP6OptDNSDomains", #RFC3646
- 25: "DHCP6OptIA_PD", #RFC3633
- 26: "DHCP6OptIAPrefix", #RFC3633
- 27: "DHCP6OptNISServers", #RFC3898
- 28: "DHCP6OptNISPServers", #RFC3898
- 29: "DHCP6OptNISDomain", #RFC3898
- 30: "DHCP6OptNISPDomain", #RFC3898
- 31: "DHCP6OptSNTPServers", #RFC4075
- 32: "DHCP6OptInfoRefreshTime", #RFC4242
- 33: "DHCP6OptBCMCSDomains", #RFC4280
- 34: "DHCP6OptBCMCSServers", #RFC4280
- #36: "DHCP6OptGeoConf", #RFC-ietf-geopriv-dhcp-civil-09.txt
- 37: "DHCP6OptRemoteID", #RFC4649
- 38: "DHCP6OptSubscriberID", #RFC4580
- 39: "DHCP6OptClientFQDN", #RFC4704
- #40: "DHCP6OptPANAAgent", #RFC-ietf-dhc-paa-option-05.txt
- #41: "DHCP6OptNewPOSIXTimeZone, #RFC4833
- #42: "DHCP6OptNewTZDBTimeZone, #RFC4833
- 43: "DHCP6OptRelayAgentERO" #RFC4994
- #44: "DHCP6OptLQQuery", #RFC5007
- #45: "DHCP6OptLQClientData", #RFC5007
- #46: "DHCP6OptLQClientTime", #RFC5007
- #47: "DHCP6OptLQRelayData", #RFC5007
- #48: "DHCP6OptLQClientLink", #RFC5007
-}
-
-
-# sect 5.3 RFC 3315 : DHCP6 Messages types
-dhcp6types = { 1:"SOLICIT",
- 2:"ADVERTISE",
- 3:"REQUEST",
- 4:"CONFIRM",
- 5:"RENEW",
- 6:"REBIND",
- 7:"REPLY",
- 8:"RELEASE",
- 9:"DECLINE",
- 10:"RECONFIGURE",
- 11:"INFORMATION-REQUEST",
- 12:"RELAY-FORW",
- 13:"RELAY-REPL" }
-
-
-#####################################################################
-### DHCPv6 DUID related stuff ###
-#####################################################################
-
-duidtypes = { 1: "Link-layer address plus time",
- 2: "Vendor-assigned unique ID based on Enterprise Number",
- 3: "Link-layer Address" }
-
-# DUID hardware types - RFC 826 - Extracted from
-# http://www.iana.org/assignments/arp-parameters on 31/10/06
-# We should add the length of every kind of address.
-duidhwtypes = { 0: "NET/ROM pseudo", # Not referenced by IANA
- 1: "Ethernet (10Mb)",
- 2: "Experimental Ethernet (3Mb)",
- 3: "Amateur Radio AX.25",
- 4: "Proteon ProNET Token Ring",
- 5: "Chaos",
- 6: "IEEE 802 Networks",
- 7: "ARCNET",
- 8: "Hyperchannel",
- 9: "Lanstar",
- 10: "Autonet Short Address",
- 11: "LocalTalk",
- 12: "LocalNet (IBM PCNet or SYTEK LocalNET)",
- 13: "Ultra link",
- 14: "SMDS",
- 15: "Frame Relay",
- 16: "Asynchronous Transmission Mode (ATM)",
- 17: "HDLC",
- 18: "Fibre Channel",
- 19: "Asynchronous Transmission Mode (ATM)",
- 20: "Serial Line",
- 21: "Asynchronous Transmission Mode (ATM)",
- 22: "MIL-STD-188-220",
- 23: "Metricom",
- 24: "IEEE 1394.1995",
- 25: "MAPOS",
- 26: "Twinaxial",
- 27: "EUI-64",
- 28: "HIPARP",
- 29: "IP and ARP over ISO 7816-3",
- 30: "ARPSec",
- 31: "IPsec tunnel",
- 32: "InfiniBand (TM)",
- 33: "TIA-102 Project 25 Common Air Interface (CAI)" }
-
-class UTCTimeField(IntField):
- epoch = (2000, 1, 1, 0, 0, 0, 5, 1, 0) # required Epoch
- def i2repr(self, pkt, x):
- x = self.i2h(pkt, x)
- from time import gmtime, strftime, mktime
- delta = mktime(self.epoch) - mktime(gmtime(0))
- x = x + delta
- t = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(x))
- return "%s (%d)" % (t, x)
-
-class _LLAddrField(MACField):
- pass
-
-# XXX We only support Ethernet addresses at the moment. _LLAddrField
-# will be modified when needed. Ask us. --arno
-class DUID_LLT(Packet): # sect 9.2 RFC 3315
- name = "DUID - Link-layer address plus time"
- fields_desc = [ ShortEnumField("type", 1, duidtypes),
- XShortEnumField("hwtype", 1, duidhwtypes),
- UTCTimeField("timeval", 0), # i.e. 01 Jan 2000
- _LLAddrField("lladdr", ETHER_ANY) ]
-
-# In fact, IANA enterprise-numbers file available at
-# http//www.iana.org/asignments/enterprise-numbers)
-# is simply huge (more than 2Mo and 600Ko in bz2). I'll
-# add only most common vendors, and encountered values.
-# -- arno
-iana_enterprise_num = { 9: "ciscoSystems",
- 35: "Nortel Networks",
- 43: "3Com",
- 311: "Microsoft",
- 2636: "Juniper Networks, Inc.",
- 4526: "Netgear",
- 5771: "Cisco Systems, Inc.",
- 5842: "Cisco Systems",
- 16885: "Nortel Networks" }
-
-class DUID_EN(Packet): # sect 9.3 RFC 3315
- name = "DUID - Assigned by Vendor Based on Enterprise Number"
- fields_desc = [ ShortEnumField("type", 2, duidtypes),
- IntEnumField("enterprisenum", 311, iana_enterprise_num),
- StrField("id",b"") ]
-
-class DUID_LL(Packet): # sect 9.4 RFC 3315
- name = "DUID - Based on Link-layer Address"
- fields_desc = [ ShortEnumField("type", 3, duidtypes),
- XShortEnumField("hwtype", 1, duidhwtypes),
- _LLAddrField("lladdr", ETHER_ANY) ]
-
-duid_cls = { 1: "DUID_LLT",
- 2: "DUID_EN",
- 3: "DUID_LL"}
-
-#####################################################################
-### DHCPv6 Options classes ###
-#####################################################################
-
-class _DHCP6OptGuessPayload(Packet):
- def guess_payload_class(self, payload):
- cls = conf.raw_layer
- if len(payload) > 2 :
- opt = struct.unpack("!H", payload[:2])[0]
- cls = get_cls(dhcp6opts_by_code.get(opt, "DHCP6OptUnknown"), DHCP6OptUnknown)
- return cls
-
-class DHCP6OptUnknown(_DHCP6OptGuessPayload): # A generic DHCPv6 Option
- name = "Unknown DHCPv6 OPtion"
- fields_desc = [ ShortEnumField("optcode", 0, dhcp6opts),
- FieldLenField("optlen", None, length_of="data", fmt="!H"),
- StrLenField("data", b"",
- length_from = lambda pkt: pkt.optlen)]
-
-class _DUIDField(PacketField):
- holds_packets=1
- def __init__(self, name, default, length_from=None):
- StrField.__init__(self, name, default)
- self.length_from = length_from
-
- def i2m(self, pkt, i):
- return bytes(i)
-
- def m2i(self, pkt, x):
- cls = conf.raw_layer
- if len(x) > 4:
- o = struct.unpack("!H", x[:2])[0]
- cls = get_cls(duid_cls.get(o, conf.raw_layer), conf.raw_layer)
- return cls(x)
-
- def getfield(self, pkt, s):
- l = self.length_from(pkt)
- return s[l:], self.m2i(pkt,s[:l])
-
-
-class DHCP6OptClientId(_DHCP6OptGuessPayload): # RFC sect 22.2
- name = "DHCP6 Client Identifier Option"
- fields_desc = [ ShortEnumField("optcode", 1, dhcp6opts),
- FieldLenField("optlen", None, length_of="duid", fmt="!H"),
- _DUIDField("duid", "",
- length_from = lambda pkt: pkt.optlen) ]
-
-
-class DHCP6OptServerId(DHCP6OptClientId): # RFC sect 22.3
- name = "DHCP6 Server Identifier Option"
- optcode = 2
-
-# Should be encapsulated in the option field of IA_NA or IA_TA options
-# Can only appear at that location.
-# TODO : last field IAaddr-options is not defined in the reference document
-class DHCP6OptIAAddress(_DHCP6OptGuessPayload): # RFC sect 22.6
- name = "DHCP6 IA Address Option (IA_TA or IA_NA suboption)"
- fields_desc = [ ShortEnumField("optcode", 5, dhcp6opts),
- FieldLenField("optlen", None, length_of="iaaddropts",
- fmt="!H", adjust = lambda pkt,x: x+24),
- IP6Field("addr", "::"),
- IntField("preflft", 0),
- IntField("validlft", 0),
- XIntField("iaid", None),
- StrLenField("iaaddropts", b"",
- length_from = lambda pkt: pkt.optlen - 24) ]
- def guess_payload_class(self, payload):
- return conf.padding_layer
-
-class _IANAOptField(PacketListField):
- def i2len(self, pkt, z):
- if z is None or z == []:
- return 0
- return sum(map(lambda x: len(bytes(x)) ,z))
-
- def getfield(self, pkt, s):
- l = self.length_from(pkt)
- lst = []
- remain, payl = s[:l], s[l:]
- 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 payl,lst
-
-class DHCP6OptIA_NA(_DHCP6OptGuessPayload): # RFC sect 22.4
- name = "DHCP6 Identity Association for Non-temporary Addresses Option"
- fields_desc = [ ShortEnumField("optcode", 3, dhcp6opts),
- FieldLenField("optlen", None, length_of="ianaopts",
- fmt="!H", adjust = lambda pkt,x: x+12),
- XIntField("iaid", None),
- IntField("T1", None),
- IntField("T2", None),
- _IANAOptField("ianaopts", [], DHCP6OptIAAddress,
- length_from = lambda pkt: pkt.optlen-12) ]
-
-class _IATAOptField(_IANAOptField):
- pass
-
-class DHCP6OptIA_TA(_DHCP6OptGuessPayload): # RFC sect 22.5
- name = "DHCP6 Identity Association for Temporary Addresses Option"
- fields_desc = [ ShortEnumField("optcode", 4, dhcp6opts),
- FieldLenField("optlen", None, length_of="iataopts",
- fmt="!H", adjust = lambda pkt,x: x+4),
- XIntField("iaid", None),
- _IATAOptField("iataopts", [], DHCP6OptIAAddress,
- length_from = lambda pkt: pkt.optlen-4) ]
-
-
-#### DHCPv6 Option Request Option ###################################
-
-class _OptReqListField(StrLenField):
- islist = 1
- def i2h(self, pkt, x):
- if x is None:
- return []
- return x
-
- def i2len(self, pkt, x):
- return 2*len(x)
-
- def any2i(self, pkt, x):
- return x
-
- def i2repr(self, pkt, x):
- s = []
- for y in self.i2h(pkt, x):
- if y in dhcp6opts:
- s.append(dhcp6opts[y])
- else:
- s.append("%d" % y)
- return "[%s]" % ", ".join(s)
-
- def m2i(self, pkt, x):
- r = []
- while len(x) != 0:
- if len(x)<2:
- warning("Odd length for requested option field. Rejecting last byte")
- return r
- r.append(struct.unpack("!H", x[:2])[0])
- x = x[2:]
- return r
-
- def i2m(self, pkt, x):
- return b"".join(map(lambda y: struct.pack("!H", y), x))
-
-# A client may include an ORO in a solicit, Request, Renew, Rebind,
-# Confirm or Information-request
-class DHCP6OptOptReq(_DHCP6OptGuessPayload): # RFC sect 22.7
- name = "DHCP6 Option Request Option"
- fields_desc = [ ShortEnumField("optcode", 6, dhcp6opts),
- FieldLenField("optlen", None, length_of="reqopts", fmt="!H"),
- _OptReqListField("reqopts", [23, 24],
- length_from = lambda pkt: pkt.optlen) ]
-
-
-#### DHCPv6 Preference Option #######################################
-
-# emise par un serveur pour affecter le choix fait par le client. Dans
-# les messages Advertise, a priori
-class DHCP6OptPref(_DHCP6OptGuessPayload): # RFC sect 22.8
- name = "DHCP6 Preference Option"
- fields_desc = [ ShortEnumField("optcode", 7, dhcp6opts),
- ShortField("optlen", 1 ),
- ByteField("prefval",255) ]
-
-
-#### DHCPv6 Elapsed Time Option #####################################
-
-class _ElapsedTimeField(ShortField):
- def i2repr(self, pkt, x):
- if x == 0xffff:
- return "infinity (0xffff)"
- return "%.2f sec" % (self.i2h(pkt, x)/100.)
-
-class DHCP6OptElapsedTime(_DHCP6OptGuessPayload):# RFC sect 22.9
- name = "DHCP6 Elapsed Time Option"
- fields_desc = [ ShortEnumField("optcode", 8, dhcp6opts),
- ShortField("optlen", 2),
- _ElapsedTimeField("elapsedtime", 0) ]
-
-
-#### DHCPv6 Relay Message Option ####################################
-
-# Relayed message is seen as a payload.
-class DHCP6OptRelayMsg(_DHCP6OptGuessPayload):# RFC sect 22.10
- name = "DHCP6 Relay Message Option"
- fields_desc = [ ShortEnumField("optcode", 9, dhcp6opts),
- ShortField("optlen", None ) ]
- def post_build(self, p, pay):
- if self.optlen is None:
- l = len(pay)
- p = p[:2]+struct.pack("!H", l)
- return p + pay
-
-
-#### DHCPv6 Authentication Option ###################################
-
-# The following fields are set in an Authentication option for the
-# Reconfigure Key Authentication Protocol:
-#
-# protocol 3
-#
-# algorithm 1
-#
-# RDM 0
-#
-# The format of the Authentication information for the Reconfigure Key
-# Authentication Protocol is:
-#
-# 0 1 2 3
-# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-# | Type | Value (128 bits) |
-# +-+-+-+-+-+-+-+-+ |
-# . .
-# . .
-# . +-+-+-+-+-+-+-+-+
-# | |
-# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-#
-# Type Type of data in Value field carried in this option:
-#
-# 1 Reconfigure Key value (used in Reply message).
-#
-# 2 HMAC-MD5 digest of the message (used in Reconfigure
-# message).
-#
-# Value Data as defined by field.
-
-
-# TODO : Decoding only at the moment
-class DHCP6OptAuth(_DHCP6OptGuessPayload): # RFC sect 22.11
- name = "DHCP6 Option - Authentication"
- fields_desc = [ ShortEnumField("optcode", 11, dhcp6opts),
- FieldLenField("optlen", None, length_of="authinfo",
- adjust = lambda pkt,x: x+11),
- ByteField("proto", 3), # TODO : XXX
- ByteField("alg", 1), # TODO : XXX
- ByteField("rdm", 0), # TODO : XXX
- StrFixedLenField("replay", b"A"*8, 8), # TODO: XXX
- StrLenField("authinfo", b"",
- length_from = lambda pkt: pkt.optlen - 11) ]
-
-#### DHCPv6 Server Unicast Option ###################################
-
-class _SrvAddrField(IP6Field):
- def i2h(self, pkt, x):
- if x is None:
- return "::"
- return x
-
- def i2m(self, pkt, x):
- return inet_pton(socket.AF_INET6, self.i2h(pkt,x))
-
-class DHCP6OptServerUnicast(_DHCP6OptGuessPayload):# RFC sect 22.12
- name = "DHCP6 Server Unicast Option"
- fields_desc = [ ShortEnumField("optcode", 12, dhcp6opts),
- ShortField("optlen", 16 ),
- _SrvAddrField("srvaddr",None) ]
-
-
-#### DHCPv6 Status Code Option ######################################
-
-dhcp6statuscodes = { 0:"Success", # sect 24.4
- 1:"UnspecFail",
- 2:"NoAddrsAvail",
- 3:"NoBinding",
- 4:"NotOnLink",
- 5:"UseMulticast",
- 6:"NoPrefixAvail"} # From RFC3633
-
-class DHCP6OptStatusCode(_DHCP6OptGuessPayload):# RFC sect 22.13
- name = "DHCP6 Status Code Option"
- fields_desc = [ ShortEnumField("optcode", 13, dhcp6opts),
- FieldLenField("optlen", None, length_of="statusmsg",
- fmt="!H", adjust = lambda pkt,x:x+2),
- ShortEnumField("statuscode",None,dhcp6statuscodes),
- StrLenField("statusmsg", b"",
- length_from = lambda pkt: pkt.optlen-2) ]
-
-
-#### DHCPv6 Rapid Commit Option #####################################
-
-class DHCP6OptRapidCommit(_DHCP6OptGuessPayload): # RFC sect 22.14
- name = "DHCP6 Rapid Commit Option"
- fields_desc = [ ShortEnumField("optcode", 14, dhcp6opts),
- ShortField("optlen", 0)]
-
-
-#### DHCPv6 User Class Option #######################################
-
-class _UserClassDataField(PacketListField):
- def i2len(self, pkt, z):
- if z is None or z == []:
- return 0
- return sum(map(lambda x: len(bytes(x)) ,z))
-
- def getfield(self, pkt, s):
- l = self.length_from(pkt)
- lst = []
- remain, payl = s[:l], s[l:]
- 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 = b""
- lst.append(p)
- return payl,lst
-
-
-class USER_CLASS_DATA(Packet):
- name = "user class data"
- fields_desc = [ FieldLenField("len", None, length_of="data"),
- StrLenField("data", b"",
- length_from = lambda pkt: pkt.len) ]
- def guess_payload_class(self, payload):
- return conf.padding_layer
-
-class DHCP6OptUserClass(_DHCP6OptGuessPayload):# RFC sect 22.15
- name = "DHCP6 User Class Option"
- fields_desc = [ ShortEnumField("optcode", 15, dhcp6opts),
- FieldLenField("optlen", None, fmt="!H",
- length_of="userclassdata"),
- _UserClassDataField("userclassdata", [], USER_CLASS_DATA,
- length_from = lambda pkt: pkt.optlen) ]
-
-
-#### DHCPv6 Vendor Class Option #####################################
-
-class _VendorClassDataField(_UserClassDataField):
- pass
-
-class VENDOR_CLASS_DATA(USER_CLASS_DATA):
- name = "vendor class data"
-
-class DHCP6OptVendorClass(_DHCP6OptGuessPayload):# RFC sect 22.16
- name = "DHCP6 Vendor Class Option"
- fields_desc = [ ShortEnumField("optcode", 16, dhcp6opts),
- FieldLenField("optlen", None, length_of="vcdata", fmt="!H",
- adjust = lambda pkt,x: x+4),
- IntEnumField("enterprisenum",None , iana_enterprise_num ),
- _VendorClassDataField("vcdata", [], VENDOR_CLASS_DATA,
- length_from = lambda pkt: pkt.optlen-4) ]
-
-#### DHCPv6 Vendor-Specific Information Option ######################
-
-class VENDOR_SPECIFIC_OPTION(_DHCP6OptGuessPayload):
- name = "vendor specific option data"
- fields_desc = [ ShortField("optcode", None),
- FieldLenField("optlen", None, length_of="optdata"),
- StrLenField("optdata", b"",
- length_from = lambda pkt: pkt.optlen) ]
- def guess_payload_class(self, payload):
- return conf.padding_layer
-
-# The third one that will be used for nothing interesting
-class DHCP6OptVendorSpecificInfo(_DHCP6OptGuessPayload):# RFC sect 22.17
- name = "DHCP6 Vendor-specific Information Option"
- fields_desc = [ ShortEnumField("optcode", 17, dhcp6opts),
- FieldLenField("optlen", None, length_of="vso", fmt="!H",
- adjust = lambda pkt,x: x+4),
- IntEnumField("enterprisenum",None , iana_enterprise_num),
- _VendorClassDataField("vso", [], VENDOR_SPECIFIC_OPTION,
- length_from = lambda pkt: pkt.optlen-4) ]
-
-#### DHCPv6 Interface-ID Option #####################################
-
-# Repasser sur cette option a la fin. Elle a pas l'air d'etre des
-# masses critique.
-class DHCP6OptIfaceId(_DHCP6OptGuessPayload):# RFC sect 22.18
- name = "DHCP6 Interface-Id Option"
- fields_desc = [ ShortEnumField("optcode", 18, dhcp6opts),
- FieldLenField("optlen", None, fmt="!H",
- length_of="ifaceid"),
- StrLenField("ifaceid", b"",
- length_from = lambda pkt: pkt.optlen) ]
-
-
-#### DHCPv6 Reconfigure Message Option ##############################
-
-# A server includes a Reconfigure Message option in a Reconfigure
-# message to indicate to the client whether the client responds with a
-# renew message or an Informatiion-request message.
-class DHCP6OptReconfMsg(_DHCP6OptGuessPayload): # RFC sect 22.19
- name = "DHCP6 Reconfigure Message Option"
- fields_desc = [ ShortEnumField("optcode", 19, dhcp6opts),
- ShortField("optlen", 1 ),
- ByteEnumField("msgtype", 11, { 5:"Renew Message",
- 11:"Information Request"}) ]
-
-
-#### DHCPv6 Reconfigure Accept Option ###############################
-
-# A client uses the Reconfigure Accept option to announce to the
-# server whether the client is willing to accept Recoonfigure
-# messages, and a server uses this option to tell the client whether
-# or not to accept Reconfigure messages. The default behavior in the
-# absence of this option, means unwillingness to accept reconfigure
-# messages, or instruction not to accept Reconfigure messages, for the
-# client and server messages, respectively.
-class DHCP6OptReconfAccept(_DHCP6OptGuessPayload): # RFC sect 22.20
- name = "DHCP6 Reconfigure Accept Option"
- fields_desc = [ ShortEnumField("optcode", 20, dhcp6opts),
- ShortField("optlen", 0)]
-
-# As required in Sect 8. of RFC 3315, Domain Names must be encoded as
-# described in section 3.1 of RFC 1035
-# XXX Label should be at most 63 octets in length : we do not enforce it
-# Total length of domain should be 255 : we do not enforce it either
-class DomainNameListField(StrLenField):
- islist = 1
-
- def i2len(self, pkt, x):
- return len(self.i2m(pkt, x))
-
- def m2i(self, pkt, x):
- res = []
- while x:
- cur = []
- #while x and x[0] != b'\x00':
- while x and x[0] != 0:
- l = (x[0])
- cur.append(x[1:l+1])
- x = x[l+1:]
- res.append(b".".join(cur))
- if x and x[0] == 0:
- x = x[1:]
- return res
-
- def i2m(self, pkt, x):
- def conditionalTrailingDot(z):
- if z and z[-1] == 0:
- return z
- return z+b'\x00'
- res = b""
- x = [ i.encode('ascii') for i in x if type(i) is str ]
- tmp = map(lambda y: map((lambda z: chr(len(z)).encode('ascii')+z), y.split(b'.')), x)
- return b"".join(map(lambda x: conditionalTrailingDot(b"".join(x)), tmp))
-
-class DHCP6OptSIPDomains(_DHCP6OptGuessPayload): #RFC3319
- name = "DHCP6 Option - SIP Servers Domain Name List"
- fields_desc = [ ShortEnumField("optcode", 21, dhcp6opts),
- FieldLenField("optlen", None, length_of="sipdomains"),
- DomainNameListField("sipdomains", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-class DHCP6OptSIPServers(_DHCP6OptGuessPayload): #RFC3319
- name = "DHCP6 Option - SIP Servers IPv6 Address List"
- fields_desc = [ ShortEnumField("optcode", 22, dhcp6opts),
- FieldLenField("optlen", None, length_of="sipservers"),
- IP6ListField("sipservers", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-class DHCP6OptDNSServers(_DHCP6OptGuessPayload): #RFC3646
- name = "DHCP6 Option - DNS Recursive Name Server"
- fields_desc = [ ShortEnumField("optcode", 23, dhcp6opts),
- FieldLenField("optlen", None, length_of="dnsservers"),
- IP6ListField("dnsservers", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-class DHCP6OptDNSDomains(_DHCP6OptGuessPayload): #RFC3646
- name = "DHCP6 Option - Domain Search List option"
- fields_desc = [ ShortEnumField("optcode", 24, dhcp6opts),
- FieldLenField("optlen", None, length_of="dnsdomains"),
- DomainNameListField("dnsdomains", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-# TODO: Implement iaprefopts correctly when provided with more
-# information about it.
-class DHCP6OptIAPrefix(_DHCP6OptGuessPayload): #RFC3633
- name = "DHCP6 Option - IA_PD Prefix option"
- fields_desc = [ ShortEnumField("optcode", 26, dhcp6opts),
- FieldLenField("optlen", None, length_of="iaprefopts",
- adjust = lambda pkt,x: x+26),
- IntField("preflft", 0),
- IntField("validlft", 0),
- ByteField("plen", 48), # TODO: Challenge that default value
- IP6Field("prefix", "2001:db8::"), # At least, global and won't hurt
- StrLenField("iaprefopts", b"",
- length_from = lambda pkt: pkt.optlen-26) ]
-
-class DHCP6OptIA_PD(_DHCP6OptGuessPayload): #RFC3633
- name = "DHCP6 Option - Identity Association for Prefix Delegation"
- fields_desc = [ ShortEnumField("optcode", 25, dhcp6opts),
- FieldLenField("optlen", None, length_of="iapdopt",
- adjust = lambda pkt,x: x+12),
- IntField("iaid", 0),
- IntField("T1", 0),
- IntField("T2", 0),
- PacketListField("iapdopt", [], DHCP6OptIAPrefix,
- length_from = lambda pkt: pkt.optlen-12) ]
-
-class DHCP6OptNISServers(_DHCP6OptGuessPayload): #RFC3898
- name = "DHCP6 Option - NIS Servers"
- fields_desc = [ ShortEnumField("optcode", 27, dhcp6opts),
- FieldLenField("optlen", None, length_of="nisservers"),
- IP6ListField("nisservers", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-class DHCP6OptNISPServers(_DHCP6OptGuessPayload): #RFC3898
- name = "DHCP6 Option - NIS+ Servers"
- fields_desc = [ ShortEnumField("optcode", 28, dhcp6opts),
- FieldLenField("optlen", None, length_of="nispservers"),
- IP6ListField("nispservers", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-class DomainNameField(StrLenField):
- def getfield(self, pkt, s):
- l = self.length_from(pkt)
- return s[l:], self.m2i(pkt,s[:l])
-
- def i2len(self, pkt, x):
- return len(self.i2m(pkt, x))
-
- def m2i(self, pkt, x):
- cur = []
- while x:
- l = (x[0])
- cur.append(x[1:1+l])
- x = x[l+1:]
- ret_str = b".".join(cur)
- return ret_str
-
- def i2m(self, pkt, x):
- if not x:
- return b""
- tmp = b"".join(map(lambda z: chr(len(z)).encode('ascii')+z, x.split(b'.')))
- return tmp
-
-class DHCP6OptNISDomain(_DHCP6OptGuessPayload): #RFC3898
- name = "DHCP6 Option - NIS Domain Name"
- fields_desc = [ ShortEnumField("optcode", 29, dhcp6opts),
- FieldLenField("optlen", None, length_of="nisdomain"),
- DomainNameField("nisdomain", "",
- length_from = lambda pkt: pkt.optlen) ]
-
-class DHCP6OptNISPDomain(_DHCP6OptGuessPayload): #RFC3898
- name = "DHCP6 Option - NIS+ Domain Name"
- fields_desc = [ ShortEnumField("optcode", 30, dhcp6opts),
- FieldLenField("optlen", None, length_of="nispdomain"),
- DomainNameField("nispdomain", "",
- length_from= lambda pkt: pkt.optlen) ]
-
-class DHCP6OptSNTPServers(_DHCP6OptGuessPayload): #RFC4075
- name = "DHCP6 option - SNTP Servers"
- fields_desc = [ ShortEnumField("optcode", 31, dhcp6opts),
- FieldLenField("optlen", None, length_of="sntpservers"),
- IP6ListField("sntpservers", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-IRT_DEFAULT=86400
-IRT_MINIMUM=600
-class DHCP6OptInfoRefreshTime(_DHCP6OptGuessPayload): #RFC4242
- name = "DHCP6 Option - Information Refresh Time"
- fields_desc = [ ShortEnumField("optcode", 32, dhcp6opts),
- ShortField("optlen", 4),
- IntField("reftime", IRT_DEFAULT)] # One day
-
-class DHCP6OptBCMCSDomains(_DHCP6OptGuessPayload): #RFC4280
- name = "DHCP6 Option - BCMCS Domain Name List"
- fields_desc = [ ShortEnumField("optcode", 33, dhcp6opts),
- FieldLenField("optlen", None, length_of="bcmcsdomains"),
- DomainNameListField("bcmcsdomains", [],
- length_from = lambda pkt: pkt.optlen) ]
-
-class DHCP6OptBCMCSServers(_DHCP6OptGuessPayload): #RFC4280
- name = "DHCP6 Option - BCMCS Addresses List"
- fields_desc = [ ShortEnumField("optcode", 34, dhcp6opts),
- FieldLenField("optlen", None, length_of="bcmcsservers"),
- IP6ListField("bcmcsservers", [],
- length_from= lambda pkt: pkt.optlen) ]
-
-# TODO : Does Nothing at the moment
-class DHCP6OptGeoConf(_DHCP6OptGuessPayload): #RFC-ietf-geopriv-dhcp-civil-09.txt
- name = ""
- fields_desc = [ ShortEnumField("optcode", 36, dhcp6opts),
- FieldLenField("optlen", None, length_of="optdata"),
- StrLenField("optdata", "",
- length_from = lambda pkt: pkt.optlen) ]
-
-# TODO: see if we encounter opaque values from vendor devices
-class DHCP6OptRemoteID(_DHCP6OptGuessPayload): #RFC4649
- name = "DHCP6 Option - Relay Agent Remote-ID"
- fields_desc = [ ShortEnumField("optcode", 37, dhcp6opts),
- FieldLenField("optlen", None, length_of="remoteid",
- adjust = lambda pkt,x: x+4),
- IntEnumField("enterprisenum", None, iana_enterprise_num),
- StrLenField("remoteid", b"",
- length_from = lambda pkt: pkt.optlen-4) ]
-
-# TODO : 'subscriberid' default value should be at least 1 byte long
-class DHCP6OptSubscriberID(_DHCP6OptGuessPayload): #RFC4580
- name = "DHCP6 Option - Subscriber ID"
- fields_desc = [ ShortEnumField("optcode", 38, dhcp6opts),
- FieldLenField("optlen", None, length_of="subscriberid"),
- StrLenField("subscriberid", b"",
- length_from = lambda pkt: pkt.optlen) ]
-
-# TODO : "The data in the Domain Name field MUST be encoded
-# as described in Section 8 of [5]"
-class DHCP6OptClientFQDN(_DHCP6OptGuessPayload): #RFC4704
- name = "DHCP6 Option - Client FQDN"
- fields_desc = [ ShortEnumField("optcode", 39, dhcp6opts),
- FieldLenField("optlen", None, length_of="fqdn",
- adjust = lambda pkt,x: x+1),
- BitField("res", 0, 5),
- FlagsField("flags", 0, 3, "SON" ),
- DomainNameField("fqdn", "",
- length_from = lambda pkt: pkt.optlen-1) ]
-
-class DHCP6OptRelayAgentERO(_DHCP6OptGuessPayload): # RFC4994
- name = "DHCP6 Option - RelayRequest Option"
- fields_desc = [ ShortEnumField("optcode", 43, dhcp6opts),
- FieldLenField("optlen", None, length_of="reqopts", fmt="!H"),
- _OptReqListField("reqopts", [23, 24],
- length_from = lambda pkt: pkt.optlen) ]
-
-#####################################################################
-### DHCPv6 messages ###
-#####################################################################
-
-# Some state parameters of the protocols that should probably be
-# useful to have in the configuration (and keep up-to-date)
-DHCP6RelayAgentUnicastAddr=""
-DHCP6RelayHopCount=""
-DHCP6ServerUnicastAddr=""
-DHCP6ClientUnicastAddr=""
-DHCP6ClientIA_TA=""
-DHCP6ClientIA_NA=""
-DHCP6ClientIAID=""
-T1="" # Voir 2462
-T2="" # Voir 2462
-DHCP6ServerDUID=""
-DHCP6CurrentTransactionID="" # devrait etre utilise pour matcher une
-# reponse et mis a jour en mode client par une valeur aleatoire pour
-# laquelle on attend un retour de la part d'un serveur.
-DHCP6PrefVal="" # la valeur de preference a utiliser dans
-# les options preference
-
-# Emitted by :
-# - server : ADVERTISE, REPLY, RECONFIGURE, RELAY-REPL (vers relay)
-# - client : SOLICIT, REQUEST, CONFIRM, RENEW, REBIND, RELEASE, DECLINE,
-# INFORMATION REQUEST
-# - relay : RELAY-FORW (toward server)
-
-class _DHCP6GuessPayload(Packet):
- def guess_payload_class(self, payload):
- if len(payload) > 1 :
- print((payload[0]))
- return get_cls(dhcp6opts.get(ord(payload[0]),"DHCP6OptUnknown"), conf.raw_layer)
- return conf.raw_layer
-
-#####################################################################
-## DHCPv6 messages sent between Clients and Servers (types 1 to 11)
-# Comme specifie en section 15.1 de la RFC 3315, les valeurs de
-# transaction id sont selectionnees de maniere aleatoire par le client
-# a chaque emission et doivent matcher dans les reponses faites par
-# les clients
-class DHCP6(_DHCP6OptGuessPayload):
- name = "DHCPv6 Generic Message)"
- fields_desc = [ ByteEnumField("msgtype",None,dhcp6types),
- X3BytesField("trid",0x000000) ]
- overload_fields = { UDP: {"sport": 546, "dport": 547} }
-
- def hashret(self):
- return struct.pack("!I", self.trid)[1:4]
-
-#####################################################################
-# Solicit Message : sect 17.1.1 RFC3315
-# - sent by client
-# - must include a client identifier option
-# - the client may include IA options for any IAs to which it wants the
-# server to assign address
-# - The client use IA_NA options to request the assignment of
-# non-temporary addresses and uses IA_TA options to request the
-# assignment of temporary addresses
-# - The client should include an Option Request option to indicate the
-# options the client is interested in receiving (eventually
-# including hints)
-# - The client includes a Reconfigure Accept option if is willing to
-# accept Reconfigure messages from the server.
-# Le cas du send and reply est assez particulier car suivant la
-# presence d'une option rapid commit dans le solicit, l'attente
-# s'arrete au premier message de reponse recu ou alors apres un
-# timeout. De la meme maniere, si un message Advertise arrive avec une
-# valeur de preference de 255, il arrete l'attente et envoie une
-# Request.
-# - The client announces its intention to use DHCP authentication by
-# including an Authentication option in its solicit message. The
-# server selects a key for the client based on the client's DUID. The
-# client and server use that key to authenticate all DHCP messages
-# exchanged during the session
-
-class DHCP6_Solicit(DHCP6):
- name = "DHCPv6 Solicit Message"
- msgtype = 1
- overload_fields = { UDP: {"sport": 546, "dport": 547} }
-
-#####################################################################
-# Advertise Message
-# - sent by server
-# - Includes a server identifier option
-# - Includes a client identifier option
-# - the client identifier option must match the client's DUID
-# - transaction ID must match
-
-class DHCP6_Advertise(DHCP6):
- name = "DHCPv6 Advertise Message"
- msgtype = 2
- overload_fields = { UDP: {"sport": 547, "dport": 546} }
-
- def answers(self, other):
- return (isinstance(other,DHCP6_Solicit) and
- other.msgtype == 1 and
- self.trid == other.trid)
-
-#####################################################################
-# Request Message
-# - sent by clients
-# - includes a server identifier option
-# - the content of Server Identifier option must match server's DUID
-# - includes a client identifier option
-# - must include an ORO Option (even with hints) p40
-# - can includes a reconfigure Accept option indicating whether or
-# not the client is willing to accept Reconfigure messages from
-# the server (p40)
-# - When the server receives a Request message via unicast from a
-# client to which the server has not sent a unicast option, the server
-# discards the Request message and responds with a Reply message
-# containinig Status Code option with the value UseMulticast, a Server
-# Identifier Option containing the server's DUID, the client
-# Identifier option from the client message and no other option.
-
-class DHCP6_Request(DHCP6):
- name = "DHCPv6 Request Message"
- msgtype = 3
-
-#####################################################################
-# Confirm Message
-# - sent by clients
-# - must include a clien identifier option
-# - When the server receives a Confirm Message, the server determines
-# whether the addresses in the Confirm message are appropriate for the
-# link to which the client is attached. cf p50
-
-class DHCP6_Confirm(DHCP6):
- name = "DHCPv6 Confirm Message"
- msgtype = 4
-
-#####################################################################
-# Renew Message
-# - sent by clients
-# - must include a server identifier option
-# - content of server identifier option must match the server's identifier
-# - must include a client identifier option
-# - the clients includes any IA assigned to the interface that may
-# have moved to a new link, along with the addresses associated with
-# those IAs in its confirm messages
-# - When the server receives a Renew message that contains an IA
-# option from a client, it locates the client's binding and verifies
-# that the information in the IA from the client matches the
-# information for that client. If the server cannot find a client
-# entry for the IA the server returns the IA containing no addresses
-# with a status code option est to NoBinding in the Reply message. cf
-# p51 pour le reste.
-
-class DHCP6_Renew(DHCP6):
- name = "DHCPv6 Renew Message"
- msgtype = 5
-
-#####################################################################
-# Rebind Message
-# - sent by clients
-# - must include a client identifier option
-# cf p52
-
-class DHCP6_Rebind(DHCP6):
- name = "DHCPv6 Rebind Message"
- msgtype = 6
-
-#####################################################################
-# Reply Message
-# - sent by servers
-# - the message must include a server identifier option
-# - transaction-id field must match the value of original message
-# The server includes a Rapid Commit option in the Reply message to
-# indicate that the reply is in response to a solicit message
-# - if the client receives a reply message with a Status code option
-# with the value UseMulticast, the client records the receipt of the
-# message and sends subsequent messages to the server through the
-# interface on which the message was received using multicast. The
-# client resends the original message using multicast
-# - When the client receives a NotOnLink status from the server in
-# response to a Confirm message, the client performs DHCP server
-# solicitation as described in section 17 and client-initiated
-# configuration as descrribed in section 18 (RFC 3315)
-# - when the client receives a NotOnLink status from the server in
-# response to a Request, the client can either re-issue the Request
-# without specifying any addresses or restart the DHCP server
-# discovery process.
-# - the server must include a server identifier option containing the
-# server's DUID in the Reply message
-
-class DHCP6_Reply(DHCP6):
- name = "DHCPv6 Reply Message"
- msgtype = 7
-
- overload_fields = { UDP: {"sport": 547, "dport": 546} }
-
- def answers(self, other):
-
- types = (DHCP6_InfoRequest, DHCP6_Confirm, DHCP6_Rebind, DHCP6_Decline, DHCP6_Request, DHCP6_Release, DHCP6_Renew)
-
- return (isinstance(other, types) and
- self.trid == other.trid)
-
-#####################################################################
-# Release Message
-# - sent by clients
-# - must include a server identifier option
-# cf p53
-
-class DHCP6_Release(DHCP6):
- name = "DHCPv6 Release Message"
- msgtype = 8
-
-#####################################################################
-# Decline Message
-# - sent by clients
-# - must include a client identifier option
-# - Server identifier option must match server identifier
-# - The addresses to be declined must be included in the IAs. Any
-# addresses for the IAs the client wishes to continue to use should
-# not be in added to the IAs.
-# - cf p54
-
-class DHCP6_Decline(DHCP6):
- name = "DHCPv6 Decline Message"
- msgtype = 9
-
-#####################################################################
-# Reconfigure Message
-# - sent by servers
-# - must be unicast to the client
-# - must include a server identifier option
-# - must include a client identifier option that contains the client DUID
-# - must contain a Reconfigure Message Option and the message type
-# must be a valid value
-# - the server sets the transaction-id to 0
-# - The server must use DHCP Authentication in the Reconfigure
-# message. Autant dire que ca va pas etre le type de message qu'on va
-# voir le plus souvent.
-
-class DHCP6_Reconf(DHCP6):
- name = "DHCPv6 Reconfigure Message"
- msgtype = 10
- overload_fields = { UDP: { "sport": 547, "dport": 546 } }
-
-
-#####################################################################
-# Information-Request Message
-# - sent by clients when needs configuration information but no
-# addresses.
-# - client should include a client identifier option to identify
-# itself. If it doesn't the server is not able to return client
-# specific options or the server can choose to not respond to the
-# message at all. The client must include a client identifier option
-# if the message will be authenticated.
-# - client must include an ORO of option she's interested in receiving
-# (can include hints)
-
-class DHCP6_InfoRequest(DHCP6):
- name = "DHCPv6 Information Request Message"
- msgtype = 11
-
-#####################################################################
-# sent between Relay Agents and Servers
-#
-# Normalement, doit inclure une option "Relay Message Option"
-# peut en inclure d'autres.
-# voir section 7.1 de la 3315
-
-# Relay-Forward Message
-# - sent by relay agents to servers
-# If the relay agent relays messages to the All_DHCP_Servers multicast
-# address or other multicast addresses, it sets the Hop Limit field to
-# 32.
-
-class DHCP6_RelayForward(_DHCP6GuessPayload,Packet):
- name = "DHCPv6 Relay Forward Message (Relay Agent/Server Message)"
- fields_desc = [ ByteEnumField("msgtype", 12, dhcp6types),
- ByteField("hopcount", None),
- IP6Field("linkaddr", "::"),
- IP6Field("peeraddr", "::") ]
- def hashret(self): # we filter on peer address field
- return inet_pton(socket.AF_INET6, self.peeraddr)
-
-#####################################################################
-# sent between Relay Agents and Servers
-# Normalement, doit inclure une option "Relay Message Option"
-# peut en inclure d'autres.
-# Les valeurs des champs hop-count, link-addr et peer-addr
-# sont copiees du messsage Forward associe. POur le suivi de session.
-# Pour le moment, comme decrit dans le commentaire, le hashret
-# se limite au contenu du champ peer address.
-# Voir section 7.2 de la 3315.
-
-# Relay-Reply Message
-# - sent by servers to relay agents
-# - if the solicit message was received in a Relay-Forward message,
-# the server constructs a relay-reply message with the Advertise
-# message in the payload of a relay-message. cf page 37/101. Envoie de
-# ce message en unicast au relay-agent. utilisation de l'adresse ip
-# presente en ip source du paquet recu
-
-class DHCP6_RelayReply(DHCP6_RelayForward):
- name = "DHCPv6 Relay Reply Message (Relay Agent/Server Message)"
- msgtype = 13
- def hashret(self): # We filter on peer address field.
- return inet_pton(socket.AF_INET6, self.peeraddr)
- def answers(self, other):
- return (isinstance(other, DHCP6_RelayForward) and
- self.hopcount == other.hopcount and
- self.linkaddr == other.linkaddr and
- self.peeraddr == other.peeraddr )
-
-
-dhcp6_cls_by_type = { 1: "DHCP6_Solicit",
- 2: "DHCP6_Advertise",
- 3: "DHCP6_Request",
- 4: "DHCP6_Confirm",
- 5: "DHCP6_Renew",
- 6: "DHCP6_Rebind",
- 7: "DHCP6_Reply",
- 8: "DHCP6_Release",
- 9: "DHCP6_Decline",
- 10: "DHCP6_Reconf",
- 11: "DHCP6_InfoRequest",
- 12: "DHCP6_RelayForward",
- 13: "DHCP6_RelayReply" }
-
-def _dhcp6_dispatcher(x, *args, **kargs):
- cls = conf.raw_layer
- if len(x) >= 2:
- cls = get_cls(dhcp6_cls_by_type.get((x[0]), "Raw"), conf.raw_layer)
- return cls(x, *args, **kargs)
-
-bind_bottom_up(UDP, _dhcp6_dispatcher, { "dport": 547 } )
-bind_bottom_up(UDP, _dhcp6_dispatcher, { "dport": 546 } )
-
-
-
-class DHCPv6_am(AnsweringMachine):
- function_name = "dhcp6d"
- filter = "udp and port 546 and port 547"
- send_function = staticmethod(send)
- def usage(self):
- msg = """
-dhcp6d( dns="2001:500::1035", domain="localdomain, local", duid=None)
- iface=conf.iface6, advpref=255, sntpservers=None,
- sipdomains=None, sipservers=None,
- nisdomain=None, nisservers=None,
- nispdomain=None, nispservers=None,
- bcmcsdomain=None, bcmcsservers=None)
-
- debug : When set, additional debugging information is printed.
-
- duid : some DUID class (DUID_LLT, DUID_LL or DUID_EN). If none
- is provided a DUID_LLT is constructed based on the MAC
- address of the sending interface and launch time of dhcp6d
- answering machine.
-
- iface : the interface to listen/reply on if you do not want to use
- conf.iface6.
-
- advpref : Value in [0,255] given to Advertise preference field.
- By default, 255 is used. Be aware that this specific
- value makes clients stops waiting for further Advertise
- messages from other servers.
-
- dns : list of recursive DNS servers addresses (as a string or list).
- By default, it is set empty and the associated DHCP6OptDNSServers
- option is inactive. See RFC 3646 for details.
- domain : a list of DNS search domain (as a string or list). By default,
- it is empty and the associated DHCP6OptDomains option is inactive.
- See RFC 3646 for details.
-
- sntpservers : a list of SNTP servers IPv6 addresses. By default,
- it is empty and the associated DHCP6OptSNTPServers option
- is inactive.
-
- sipdomains : a list of SIP domains. By default, it is empty and the
- associated DHCP6OptSIPDomains option is inactive. See RFC 3319
- for details.
- sipservers : a list of SIP servers IPv6 addresses. By default, it is
- empty and the associated DHCP6OptSIPDomains option is inactive.
- See RFC 3319 for details.
-
- nisdomain : a list of NIS domains. By default, it is empty and the
- associated DHCP6OptNISDomains option is inactive. See RFC 3898
- for details. See RFC 3646 for details.
- nisservers : a list of NIS servers IPv6 addresses. By default, it is
- empty and the associated DHCP6OptNISServers option is inactive.
- See RFC 3646 for details.
-
- nispdomain : a list of NIS+ domains. By default, it is empty and the
- associated DHCP6OptNISPDomains option is inactive. See RFC 3898
- for details.
- nispservers : a list of NIS+ servers IPv6 addresses. By default, it is
- empty and the associated DHCP6OptNISServers option is inactive.
- See RFC 3898 for details.
-
- bcmcsdomain : a list of BCMCS domains. By default, it is empty and the
- associated DHCP6OptBCMCSDomains option is inactive. See RFC 4280
- for details.
- bcmcsservers : a list of BCMCS servers IPv6 addresses. By default, it is
- empty and the associated DHCP6OptBCMCSServers option is inactive.
- See RFC 4280 for details.
-
- If you have a need for others, just ask ... or provide a patch."""
- print(msg)
-
- def parse_options(self, dns="2001:500::1035", domain="localdomain, local",
- startip="2001:db8::1", endip="2001:db8::20", duid=None,
- sntpservers=None, sipdomains=None, sipservers=None,
- nisdomain=None, nisservers=None, nispdomain=None,
- nispservers=None, bcmcsservers=None, bcmcsdomains=None,
- iface=None, debug=0, advpref=255):
- def norm_list(val, param_name):
- if val is None:
- return None
- if type(val) is list:
- return val
- elif type(val) is str:
- l = val.split(',')
- return map(lambda x: x.strip(), l)
- else:
- print("Bad '%s' parameter provided." % param_name)
- self.usage()
- return -1
-
- if iface is None:
- iface = conf.iface6
-
- self.debug = debug
-
- # Dictionary of provided DHCPv6 options, keyed by option type
- self.dhcpv6_options={}
-
- for o in [(dns, "dns", 23, lambda x: DHCP6OptDNSServers(dnsservers=x)),
- (domain, "domain", 24, lambda x: DHCP6OptDNSDomains(dnsdomains=x)),
- (sntpservers, "sntpservers", 31, lambda x: DHCP6OptSNTPServers(sntpservers=x)),
- (sipservers, "sipservers", 22, lambda x: DHCP6OptSIPServers(sipservers=x)),
- (sipdomains, "sipdomains", 21, lambda x: DHCP6OptSIPDomains(sipdomains=x)),
- (nisservers, "nisservers", 27, lambda x: DHCP6OptNISServers(nisservers=x)),
- (nisdomain, "nisdomain", 29, lambda x: DHCP6OptNISDomain(nisdomain=(x+[""])[0])),
- (nispservers, "nispservers", 28, lambda x: DHCP6OptNISPServers(nispservers=x)),
- (nispdomain, "nispdomain", 30, lambda x: DHCP6OptNISPDomain(nispdomain=(x+[""])[0])),
- (bcmcsservers, "bcmcsservers", 33, lambda x: DHCP6OptBCMCSServers(bcmcsservers=x)),
- (bcmcsdomains, "bcmcsdomains", 34, lambda x: DHCP6OptBCMCSDomains(bcmcsdomains=x))]:
-
- opt = norm_list(o[0], o[1])
- if opt == -1: # Usage() was triggered
- return False
- elif opt is None: # We won't return that option
- pass
- else:
- self.dhcpv6_options[o[2]] = o[3](opt)
-
- if self.debug:
- print("\n[+] List of active DHCPv6 options:")
- opts = self.dhcpv6_options.keys()
- opts.sort()
- for i in opts:
- print(" %d: %s" % (i, repr(self.dhcpv6_options[i])))
-
- # Preference value used in Advertise.
- self.advpref = advpref
-
- # IP Pool
- self.startip = startip
- self.endip = endip
- # XXX TODO Check IPs are in same subnet
-
- ####
- # The interface we are listening/replying on
- self.iface = iface
-
- ####
- # Generate a server DUID
- if duid is not None:
- self.duid = duid
- else:
- # Timeval
- from time import gmtime, strftime, mktime
- epoch = (2000, 1, 1, 0, 0, 0, 5, 1, 0)
- delta = mktime(epoch) - mktime(gmtime(0))
- timeval = time.time() - delta
-
- # Mac Address
- rawmac = get_if_raw_hwaddr(iface)
- mac = ":".join(map(lambda x: "%.02x" % x, rawmac))
-
- self.duid = DUID_LLT(timeval = timeval, lladdr = mac)
-
- if self.debug:
- print("\n[+] Our server DUID:" )
- self.duid.show(label_lvl=" "*4)
-
- ####
- # Find the source address we will use
- #l = filter(lambda x: x[2] == iface and in6_islladdr(x[0]), in6_getifaddr())
- l = [ x for x in in6_getifaddr() if x[2] == iface and in6_islladdr(x[0]) ]
- if not l:
- warning("Unable to get a Link-Local address")
- return
-
- self.src_addr = l[0][0]
-
- ####
- # Our leases
- self.leases = {}
-
-
- if self.debug:
- print("\n[+] Starting DHCPv6 service on %s:" % self.iface )
-
- def is_request(self, p):
- if not IPv6 in p:
- return False
-
- src = p[IPv6].src
- dst = p[IPv6].dst
-
- p = p[IPv6].payload
- if not isinstance(p, UDP) or p.sport != 546 or p.dport != 547 :
- return False
-
- p = p.payload
- if not isinstance(p, DHCP6):
- return False
-
- # Message we considered client messages :
- # Solicit (1), Request (3), Confirm (4), Renew (5), Rebind (6)
- # Decline (9), Release (8), Information-request (11),
- if not (p.msgtype in [1, 3, 4, 5, 6, 8, 9, 11]):
- return False
-
- # Message validation following section 15 of RFC 3315
-
- if ((p.msgtype == 1) or # Solicit
- (p.msgtype == 6) or # Rebind
- (p.msgtype == 4)): # Confirm
- if ((not DHCP6OptClientId in p) or
- DHCP6OptServerId in p):
- return False
-
- if (p.msgtype == 6 or # Rebind
- p.msgtype == 4): # Confirm
- # XXX We do not reply to Confirm or Rebind as we
- # XXX do not support address assignment
- return False
-
- elif (p.msgtype == 3 or # Request
- p.msgtype == 5 or # Renew
- p.msgtype == 8): # Release
-
- # Both options must be present
- if ((not DHCP6OptServerId in p) or
- (not DHCP6OptClientId in p)):
- return False
- # provided server DUID must match ours
- duid = p[DHCP6OptServerId].duid
- if (type(duid) != type(self.duid)):
- return False
- if bytes(duid) != bytes(self.duid):
- return False
-
- if (p.msgtype == 5 or # Renew
- p.msgtype == 8): # Release
- # XXX We do not reply to Renew or Release as we
- # XXX do not support address assignment
- return False
-
- elif p.msgtype == 9: # Decline
- # XXX We should check if we are tracking that client
- if not self.debug:
- return False
-
- bo = Color.bold
- g = Color.green + bo
- b = Color.blue + bo
- n = Color.normal
- r = Color.red
-
- vendor = in6_addrtovendor(src)
- if (vendor and vendor != "UNKNOWN"):
- vendor = " [" + b + vendor + n + "]"
- else:
- vendor = ""
- src = bo + src + n
-
- it = p
- addrs = []
- while it:
- l = []
- if isinstance(it, DHCP6OptIA_NA):
- l = it.ianaopts
- elif isinstance(it, DHCP6OptIA_TA):
- l = it.iataopts
-
- #opsaddr = filter(lambda x: isinstance(x, DHCP6OptIAAddress),l)
- opsaddr = [ x for x in l if isinstance(x, DHCP6OptIAAddress) ]
- a=map(lambda x: x.addr, opsaddr)
- addrs += a
- it = it.payload
-
- addrs = map(lambda x: bo + x + n, addrs)
- if debug:
- msg = r + "[DEBUG]" + n + " Received " + g + "Decline" + n
- msg += " from " + bo + src + vendor + " for "
- msg += ", ".join(addrs)+ n
- print(msg)
-
- # See sect 18.1.7
-
- # Sent by a client to warn us she has determined
- # one or more addresses assigned to her is already
- # used on the link.
- # We should simply log that fact. No messaged should
- # be sent in return.
-
- # - Message must include a Server identifier option
- # - the content of the Server identifier option must
- # match the server's identifier
- # - the message must include a Client Identifier option
- return False
-
- elif p.msgtype == 11: # Information-Request
- if DHCP6OptServerId in p:
- duid = p[DHCP6OptServerId].duid
- if (type(duid) != type(self.duid)):
- return False
- if bytes(duid) != bytes(self.duid):
- return False
- if ((DHCP6OptIA_NA in p) or
- (DHCP6OptIA_TA in p) or
- (DHCP6OptIA_PD in p)):
- return False
- else:
- return False
-
- return True
-
- def print_reply(self, req, reply):
- def norm(s):
- if s.startswith("DHCPv6 "):
- s = s[7:]
- if s.endswith(" Message"):
- s = s[:-8]
- return s
-
- if reply is None:
- return
-
- bo = Color.bold
- g = Color.green + bo
- b = Color.blue + bo
- n = Color.normal
- reqtype = g + norm(req.getlayer(UDP).payload.name) + n
- reqsrc = req.getlayer(IPv6).src
- vendor = in6_addrtovendor(reqsrc)
- if (vendor and vendor != "UNKNOWN"):
- vendor = " [" + b + vendor + n + "]"
- else:
- vendor = ""
- reqsrc = bo + reqsrc + n
- reptype = g + norm(reply.getlayer(UDP).payload.name) + n
-
- print("Sent %s answering to %s from %s%s" % (reptype, reqtype, reqsrc, vendor))
-
- def make_reply(self, req):
- req_mac_src = req.src
- req_mac_dst = req.dst
-
- p = req[IPv6]
- req_src = p.src
- req_dst = p.dst
-
- p = p.payload.payload
-
- msgtype = p.msgtype
- trid = p.trid
-
- if msgtype == 1: # SOLICIT (See Sect 17.1 and 17.2 of RFC 3315)
-
- # XXX We don't support address or prefix assignment
- # XXX We also do not support relay function --arno
-
- client_duid = p[DHCP6OptClientId].duid
- resp = IPv6(src=self.src_addr, dst=req_src)
- resp /= UDP(sport=547, dport=546)
-
- if p.haslayer(DHCP6OptRapidCommit):
- # construct a Reply packet
- resp /= DHCP6_Reply(trid=trid)
- resp /= DHCP6OptRapidCommit() # See 17.1.2
- resp /= DHCP6OptServerId(duid = self.duid)
- resp /= DHCP6OptClientId(duid = client_duid)
-
- else: # No Rapid Commit in the packet. Reply with an Advertise
-
- if (p.haslayer(DHCP6OptIA_NA) or
- p.haslayer(DHCP6OptIA_TA)):
- # XXX We don't assign addresses at the moment
- msg = "Scapy6 dhcp6d does not support address assignment"
- resp /= DHCP6_Advertise(trid = trid)
- resp /= DHCP6OptStatusCode(statuscode=2, statusmsg=msg)
- resp /= DHCP6OptServerId(duid = self.duid)
- resp /= DHCP6OptClientId(duid = client_duid)
-
- elif p.haslayer(DHCP6OptIA_PD):
- # XXX We don't assign prefixes at the moment
- msg = "Scapy6 dhcp6d does not support prefix assignment"
- resp /= DHCP6_Advertise(trid = trid)
- resp /= DHCP6OptStatusCode(statuscode=6, statusmsg=msg)
- resp /= DHCP6OptServerId(duid = self.duid)
- resp /= DHCP6OptClientId(duid = client_duid)
-
- else: # Usual case, no request for prefixes or addresse
- resp /= DHCP6_Advertise(trid = trid)
- resp /= DHCP6OptPref(prefval = self.advpref)
- resp /= DHCP6OptServerId(duid = self.duid)
- resp /= DHCP6OptClientId(duid = client_duid)
- resp /= DHCP6OptReconfAccept()
-
- # See which options should be included
- reqopts = []
- if p.haslayer(DHCP6OptOptReq): # add only asked ones
- reqopts = p[DHCP6OptOptReq].reqopts
- for o in self.dhcpv6_options.keys():
- if o in reqopts:
- resp /= self.dhcpv6_options[o]
- else: # advertise everything we have available
- for o in self.dhcpv6_options.keys():
- resp /= self.dhcpv6_options[o]
-
- return resp
-
- elif msgtype == 3: #REQUEST (INFO-REQUEST is further below)
- client_duid = p[DHCP6OptClientId].duid
- resp = IPv6(src=self.src_addr, dst=req_src)
- resp /= UDP(sport=547, dport=546)
- resp /= DHCP6_Solicit(trid=trid)
- resp /= DHCP6OptServerId(duid = self.duid)
- resp /= DHCP6OptClientId(duid = client_duid)
-
- # See which options should be included
- reqopts = []
- if p.haslayer(DHCP6OptOptReq): # add only asked ones
- reqopts = p[DHCP6OptOptReq].reqopts
- for o in self.dhcpv6_options.keys():
- if o in reqopts:
- resp /= self.dhcpv6_options[o]
- else:
- # advertise everything we have available.
- # Should not happen has clients MUST include
- # and ORO in requests (sec 18.1.1) -- arno
- for o in self.dhcpv6_options.keys():
- resp /= self.dhcpv6_options[o]
-
- return resp
-
- elif msgtype == 4: # CONFIRM
- # see Sect 18.1.2
-
- # Client want to check if addresses it was assigned
- # are still appropriate
-
- # Server must discard any Confirm messages that
- # do not include a Client Identifier option OR
- # THAT DO INCLUDE a Server Identifier Option
-
- # XXX we must discard the SOLICIT if it is received with
- # a unicast destination address
-
- pass
-
- elif msgtype == 5: # RENEW
- # see Sect 18.1.3
-
- # Clients want to extend lifetime of assigned addresses
- # and update configuration parameters. This message is sent
- # specifically to the server that provided her the info
-
- # - Received message must include a Server Identifier
- # option.
- # - the content of server identifier option must match
- # the server's identifier.
- # - the message must include a Client identifier option
-
- pass
-
- elif msgtype == 6: # REBIND
- # see Sect 18.1.4
-
- # Same purpose as the Renew message but sent to any
- # available server after he received no response
- # to its previous Renew message.
-
-
- # - Message must include a Client Identifier Option
- # - Message can't include a Server identifier option
-
- # XXX we must discard the SOLICIT if it is received with
- # a unicast destination address
-
- pass
-
- elif msgtype == 8: # RELEASE
- # See section 18.1.6
-
- # Message is sent to the server to indicate that
- # she will no longer use the addresses that was assigned
- # We should parse the message and verify our dictionary
- # to log that fact.
-
-
- # - The message must include a server identifier option
- # - The content of the Server Identifier option must
- # match the server's identifier
- # - the message must include a Client Identifier option
-
- pass
-
- elif msgtype == 9: # DECLINE
- # See section 18.1.7
- pass
-
- elif msgtype == 11: # INFO-REQUEST
- client_duid = None
- if not p.haslayer(DHCP6OptClientId):
- if self.debug:
- warning("Received Info Request message without Client Id option")
- else:
- client_duid = p[DHCP6OptClientId].duid
-
- resp = IPv6(src=self.src_addr, dst=req_src)
- resp /= UDP(sport=547, dport=546)
- resp /= DHCP6_Reply(trid=trid)
- resp /= DHCP6OptServerId(duid = self.duid)
-
- if client_duid:
- resp /= DHCP6OptClientId(duid = client_duid)
-
- # Stack requested options if available
- reqopts = []
- if p.haslayer(DHCP6OptOptReq):
- reqopts = p[DHCP6OptOptReq].reqopts
- for o in self.dhcpv6_options.keys():
- resp /= self.dhcpv6_options[o]
-
- return resp
-
- else:
- # what else ?
- pass
-
- # - We won't support reemission
- # - We won't support relay role, nor relay forwarded messages
- # at the beginning