// Copyright 2018 The GoPacket Authors. All rights reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file in the root of the source // tree. package layers import ( "bytes" "encoding/binary" "errors" "fmt" "github.com/google/gopacket" ) // DHCPv6Opt represents a DHCP option or parameter from RFC-3315 type DHCPv6Opt uint16 // Constants for the DHCPv6Opt options. const ( DHCPv6OptClientID DHCPv6Opt = 1 DHCPv6OptServerID DHCPv6Opt = 2 DHCPv6OptIANA DHCPv6Opt = 3 DHCPv6OptIATA DHCPv6Opt = 4 DHCPv6OptIAAddr DHCPv6Opt = 5 DHCPv6OptOro DHCPv6Opt = 6 DHCPv6OptPreference DHCPv6Opt = 7 DHCPv6OptElapsedTime DHCPv6Opt = 8 DHCPv6OptRelayMessage DHCPv6Opt = 9 DHCPv6OptAuth DHCPv6Opt = 11 DHCPv6OptUnicast DHCPv6Opt = 12 DHCPv6OptStatusCode DHCPv6Opt = 13 DHCPv6OptRapidCommit DHCPv6Opt = 14 DHCPv6OptUserClass DHCPv6Opt = 15 DHCPv6OptVendorClass DHCPv6Opt = 16 DHCPv6OptVendorOpts DHCPv6Opt = 17 DHCPv6OptInterfaceID DHCPv6Opt = 18 DHCPv6OptReconfigureMessage DHCPv6Opt = 19 DHCPv6OptReconfigureAccept DHCPv6Opt = 20 // RFC 3319 Session Initiation Protocol (SIP) DHCPv6OptSIPServersDomainList DHCPv6Opt = 21 DHCPv6OptSIPServersAddressList DHCPv6Opt = 22 // RFC 3646 DNS Configuration DHCPv6OptDNSServers DHCPv6Opt = 23 DHCPv6OptDomainList DHCPv6Opt = 24 // RFC 3633 Prefix Delegation DHCPv6OptIAPD DHCPv6Opt = 25 DHCPv6OptIAPrefix DHCPv6Opt = 26 // RFC 3898 Network Information Service (NIS) DHCPv6OptNISServers DHCPv6Opt = 27 DHCPv6OptNISPServers DHCPv6Opt = 28 DHCPv6OptNISDomainName DHCPv6Opt = 29 DHCPv6OptNISPDomainName DHCPv6Opt = 30 // RFC 4075 Simple Network Time Protocol (SNTP) DHCPv6OptSNTPServers DHCPv6Opt = 31 // RFC 4242 Information Refresh Time Option DHCPv6OptInformationRefreshTime DHCPv6Opt = 32 // RFC 4280 Broadcast and Multicast Control Servers DHCPv6OptBCMCSServerDomainNameList DHCPv6Opt = 33 DHCPv6OptBCMCSServerAddressList DHCPv6Opt = 34 // RFC 4776 Civic Address ConfigurationOption DHCPv6OptGeoconfCivic DHCPv6Opt = 36 // RFC 4649 Relay Agent Remote-ID DHCPv6OptRemoteID DHCPv6Opt = 37 // RFC 4580 Relay Agent Subscriber-ID DHCPv6OptSubscriberID DHCPv6Opt = 38 // RFC 4704 Client Full Qualified Domain Name (FQDN) DHCPv6OptClientFQDN DHCPv6Opt = 39 // RFC 5192 Protocol for Carrying Authentication for Network Access (PANA) DHCPv6OptPanaAgent DHCPv6Opt = 40 // RFC 4833 Timezone Options DHCPv6OptNewPOSIXTimezone DHCPv6Opt = 41 DHCPv6OptNewTZDBTimezone DHCPv6Opt = 42 // RFC 4994 Relay Agent Echo Request DHCPv6OptEchoRequestOption DHCPv6Opt = 43 // RFC 5007 Leasequery DHCPv6OptLQQuery DHCPv6Opt = 44 DHCPv6OptCLTTime DHCPv6Opt = 45 DHCPv6OptClientData DHCPv6Opt = 46 DHCPv6OptLQRelayData DHCPv6Opt = 47 DHCPv6OptLQClientLink DHCPv6Opt = 48 // RFC 6610 Home Information Discovery in Mobile IPv6 (MIPv6) DHCPv6OptMIP6HNIDF DHCPv6Opt = 49 DHCPv6OptMIP6VDINF DHCPv6Opt = 50 DHCPv6OptMIP6IDINF DHCPv6Opt = 69 DHCPv6OptMIP6UDINF DHCPv6Opt = 70 DHCPv6OptMIP6HNP DHCPv6Opt = 71 DHCPv6OptMIP6HAA DHCPv6Opt = 72 DHCPv6OptMIP6HAF DHCPv6Opt = 73 // RFC 5223 Discovering Location-to-Service Translation (LoST) Servers DHCPv6OptV6LOST DHCPv6Opt = 51 // RFC 5417 Control And Provisioning of Wireless Access Points (CAPWAP) DHCPv6OptCAPWAPACV6 DHCPv6Opt = 52 // RFC 5460 Bulk Leasequery DHCPv6OptRelayID DHCPv6Opt = 53 // RFC 5678 IEEE 802.21 Mobility Services (MoS) Discovery DHCPv6OptIPv6AddressMoS DHCPv6Opt = 54 DHCPv6OptIPv6FQDNMoS DHCPv6Opt = 55 // RFC 5908 NTP Server Option DHCPv6OptNTPServer DHCPv6Opt = 56 // RFC 5986 Discovering the Local Location Information Server (LIS) DHCPv6OptV6AccessDomain DHCPv6Opt = 57 // RFC 5986 SIP User Agent DHCPv6OptSIPUACSList DHCPv6Opt = 58 // RFC 5970 Options for Network Boot DHCPv6OptBootFileURL DHCPv6Opt = 59 DHCPv6OptBootFileParam DHCPv6Opt = 60 DHCPv6OptClientArchType DHCPv6Opt = 61 DHCPv6OptNII DHCPv6Opt = 62 // RFC 6225 Coordinate-Based Location Configuration Information DHCPv6OptGeolocation DHCPv6Opt = 63 // RFC 6334 Dual-Stack Lite DHCPv6OptAFTRName DHCPv6Opt = 64 // RFC 6440 EAP Re-authentication Protocol (ERP) DHCPv6OptERPLocalDomainName DHCPv6Opt = 65 // RFC 6422 Relay-Supplied DHCP Options DHCPv6OptRSOO DHCPv6Opt = 66 // RFC 6603 Prefix Exclude Option for DHCPv6-based Prefix Delegation DHCPv6OptPDExclude DHCPv6Opt = 67 // RFC 6607 Virtual Subnet Selection DHCPv6OptVSS DHCPv6Opt = 68 // RFC 6731 Improved Recursive DNS Server Selection for Multi-Interfaced Nodes DHCPv6OptRDNSSSelection DHCPv6Opt = 74 // RFC 6784 Kerberos Options for DHCPv6 DHCPv6OptKRBPrincipalName DHCPv6Opt = 75 DHCPv6OptKRBRealmName DHCPv6Opt = 76 DHCPv6OptKRBKDC DHCPv6Opt = 77 // RFC 6939 Client Link-Layer Address Option DHCPv6OptClientLinkLayerAddress DHCPv6Opt = 79 // RFC 6977 Triggering DHCPv6 Reconfiguration from Relay Agents DHCPv6OptLinkAddress DHCPv6Opt = 80 // RFC 7037 RADIUS Option for the DHCPv6 Relay Agent DHCPv6OptRADIUS DHCPv6Opt = 81 // RFC 7083 Modification to Default Values of SOL_MAX_RT and INF_MAX_RT DHCPv6OptSolMaxRt DHCPv6Opt = 82 DHCPv6OptInfMaxRt DHCPv6Opt = 83 // RFC 7078 Distributing Address Selection Policy DHCPv6OptAddrSel DHCPv6Opt = 84 DHCPv6OptAddrSelTable DHCPv6Opt = 85 // RFC 7291 DHCP Options for the Port Control Protocol (PCP) DHCPv6OptV6PCPServer DHCPv6Opt = 86 // RFC 7341 DHCPv4-over-DHCPv6 (DHCP 4o6) Transport DHCPv6OptDHCPv4Message DHCPv6Opt = 87 DHCPv6OptDHCPv4OverDHCPv6Server DHCPv6Opt = 88 // RFC 7598 Configuration of Softwire Address and Port-Mapped Clients DHCPv6OptS46Rule DHCPv6Opt = 89 DHCPv6OptS46BR DHCPv6Opt = 90 DHCPv6OptS46DMR DHCPv6Opt = 91 DHCPv6OptS46V4V4Bind DHCPv6Opt = 92 DHCPv6OptS46PortParameters DHCPv6Opt = 93 DHCPv6OptS46ContMAPE DHCPv6Opt = 94 DHCPv6OptS46ContMAPT DHCPv6Opt = 95 DHCPv6OptS46ContLW DHCPv6Opt = 96 // RFC 7600 IPv4 Residual Deployment via IPv6 DHCPv6Opt4RD DHCPv6Opt = 97 DHCPv6Opt4RDMapRule DHCPv6Opt = 98 DHCPv6Opt4RDNonMapRule DHCPv6Opt = 99 // RFC 7653 Active Leasequery DHCPv6OptLQBaseTime DHCPv6Opt = 100 DHCPv6OptLQStartTime DHCPv6Opt = 101 DHCPv6OptLQEndTime DHCPv6Opt = 102 // RFC 7710 Captive-Portal Identification DHCPv6OptCaptivePortal DHCPv6Opt = 103 // RFC 7774 Multicast Protocol for Low-Power and Lossy Networks (MPL) Parameter Configuration DHCPv6OptMPLParameters DHCPv6Opt = 104 // RFC 7839 Access-Network-Identifier (ANI) DHCPv6OptANIATT DHCPv6Opt = 105 DHCPv6OptANINetworkName DHCPv6Opt = 106 DHCPv6OptANIAPName DHCPv6Opt = 107 DHCPv6OptANIAPBSSID DHCPv6Opt = 108 DHCPv6OptANIOperatorID DHCPv6Opt = 109 DHCPv6OptANIOperatorRealm DHCPv6Opt = 110 // RFC 8026 Unified IPv4-in-IPv6 Softwire Customer Premises Equipment (CPE) DHCPv6OptS46Priority DHCPv6Opt = 111 // draft-ietf-opsawg-mud-25 Manufacturer Usage Description (MUD) DHCPv6OptMUDURLV6 DHCPv6Opt = 112 // RFC 8115 IPv4-Embedded Multicast and Unicast IPv6 Prefixes DHCPv6OptV6Prefix64 DHCPv6Opt = 113 // RFC 8156 DHCPv6 Failover Protocol DHCPv6OptFBindingStatus DHCPv6Opt = 114 DHCPv6OptFConnectFlags DHCPv6Opt = 115 DHCPv6OptFDNSRemovalInfo DHCPv6Opt = 116 DHCPv6OptFDNSHostName DHCPv6Opt = 117 DHCPv6OptFDNSZoneName DHCPv6Opt = 118 DHCPv6OptFDNSFlags DHCPv6Opt = 119 DHCPv6OptFExpirationTime DHCPv6Opt = 120 DHCPv6OptFMaxUnacknowledgedBNDUPD DHCPv6Opt = 121 DHCPv6OptFMCLT DHCPv6Opt = 122 DHCPv6OptFPartnerLifetime DHCPv6Opt = 123 DHCPv6OptFPartnerLifetimeSent DHCPv6Opt = 124 DHCPv6OptFPartnerDownTime DHCPv6Opt = 125 DHCPv6OptFPartnerRawCltTime DHCPv6Opt = 126 DHCPv6OptFProtocolVersion DHCPv6Opt = 127 DHCPv6OptFKeepaliveTime DHCPv6Opt = 128 DHCPv6OptFReconfigureData DHCPv6Opt = 129 DHCPv6OptFRelationshipName DHCPv6Opt = 130 DHCPv6OptFServerFlags DHCPv6Opt = 131 DHCPv6OptFServerState DHCPv6Opt = 132 DHCPv6OptFStartTimeOfState DHCPv6Opt = 133 DHCPv6OptFStateExpirationTime DHCPv6Opt = 134 // RFC 8357 Generalized UDP Source Port for DHCP Relay DHCPv6OptRelayPort DHCPv6Opt = 135 // draft-ietf-netconf-zerotouch-25 Zero Touch Provisioning for Networking Devices DHCPv6OptV6ZeroTouchRedirect DHCPv6Opt = 136 // RFC 6153 Access Network Discovery and Selection Function (ANDSF) Discovery DHCPv6OptIPV6AddressANDSF DHCPv6Opt = 143 ) // String returns a string version of a DHCPv6Opt. func (o DHCPv6Opt) String() string { switch o { case DHCPv6OptClientID: return "ClientID" case DHCPv6OptServerID: return "ServerID" case DHCPv6OptIANA: return "IA_NA" case DHCPv6OptIATA: return "IA_TA" case DHCPv6OptIAAddr: return "IAAddr" case DHCPv6OptOro: return "Oro" case DHCPv6OptPreference: return "Preference" case DHCPv6OptElapsedTime: return "ElapsedTime" case DHCPv6OptRelayMessage: return "RelayMessage" case DHCPv6OptAuth: return "Auth" case DHCPv6OptUnicast: return "Unicast" case DHCPv6OptStatusCode: return "StatusCode" case DHCPv6OptRapidCommit: return "RapidCommit" case DHCPv6OptUserClass: return "UserClass" case DHCPv6OptVendorClass: return "VendorClass" case DHCPv6OptVendorOpts: return "VendorOpts" case DHCPv6OptInterfaceID: return "InterfaceID" case DHCPv6OptReconfigureMessage: return "ReconfigureMessage" case DHCPv6OptReconfigureAccept: return "ReconfigureAccept" case DHCPv6OptSIPServersDomainList: return "SIPServersDomainList" case DHCPv6OptSIPServersAddressList: return "SIPServersAddressList" case DHCPv6OptDNSServers: return "DNSRecursiveNameServer" case DHCPv6OptDomainList: return "DomainSearchList" case DHCPv6OptIAPD: return "IdentityAssociationPrefixDelegation" case DHCPv6OptIAPrefix: return "IAPDPrefix" case DHCPv6OptNISServers: return "NISServers" case DHCPv6OptNISPServers: return "NISv2Servers" case DHCPv6OptNISDomainName: return "NISDomainName" case DHCPv6OptNISPDomainName: return "NISv2DomainName" case DHCPv6OptSNTPServers: return "SNTPServers" case DHCPv6OptInformationRefreshTime: return "InformationRefreshTime" case DHCPv6OptBCMCSServerDomainNameList: return "BCMCSControlServersDomainNameList" case DHCPv6OptBCMCSServerAddressList: return "BCMCSControlServersAddressList" case DHCPv6OptGeoconfCivic: return "CivicAddress" case DHCPv6OptRemoteID: return "RelayAgentRemoteID" case DHCPv6OptSubscriberID: return "RelayAgentSubscriberID" case DHCPv6OptClientFQDN: return "ClientFQDN" case DHCPv6OptPanaAgent: return "PANAAuthenticationAgent" case DHCPv6OptNewPOSIXTimezone: return "NewPOSIXTimezone" case DHCPv6OptNewTZDBTimezone: return "NewTZDBTimezone" case DHCPv6OptEchoRequestOption: return "EchoRequest" case DHCPv6OptLQQuery: return "LeasequeryQuery" case DHCPv6OptClientData: return "LeasequeryClientData" case DHCPv6OptCLTTime: return "LeasequeryClientLastTransactionTime" case DHCPv6OptLQRelayData: return "LeasequeryRelayData" case DHCPv6OptLQClientLink: return "LeasequeryClientLink" case DHCPv6OptMIP6HNIDF: return "MIPv6HomeNetworkIDFQDN" case DHCPv6OptMIP6VDINF: return "MIPv6VisitedHomeNetworkInformation" case DHCPv6OptMIP6IDINF: return "MIPv6IdentifiedHomeNetworkInformation" case DHCPv6OptMIP6UDINF: return "MIPv6UnrestrictedHomeNetworkInformation" case DHCPv6OptMIP6HNP: return "MIPv6HomeNetworkPrefix" case DHCPv6OptMIP6HAA: return "MIPv6HomeAgentAddress" case DHCPv6OptMIP6HAF: return "MIPv6HomeAgentFQDN" case DHCPv6OptV6LOST: return "LoST Server" case DHCPv6OptCAPWAPACV6: return "CAPWAPAccessControllerV6" case DHCPv6OptRelayID: return "LeasequeryRelayID" case DHCPv6OptIPv6AddressMoS: return "MoSIPv6Address" case DHCPv6OptIPv6FQDNMoS: return "MoSDomainNameList" case DHCPv6OptNTPServer: return "NTPServer" case DHCPv6OptV6AccessDomain: return "AccessNetworkDomainName" case DHCPv6OptSIPUACSList: return "SIPUserAgentConfigurationServiceDomains" case DHCPv6OptBootFileURL: return "BootFileURL" case DHCPv6OptBootFileParam: return "BootFileParameters" case DHCPv6OptClientArchType: return "ClientSystemArchitectureType" case DHCPv6OptNII: return "ClientNetworkInterfaceIdentifier" case DHCPv6OptGeolocation: return "Geolocation" case DHCPv6OptAFTRName: return "AFTRName" case DHCPv6OptERPLocalDomainName: return "AFTRName" case DHCPv6OptRSOO: return "RSOOption" case DHCPv6OptPDExclude: return "PrefixExclude" case DHCPv6OptVSS: return "VirtualSubnetSelection" case DHCPv6OptRDNSSSelection: return "RDNSSSelection" case DHCPv6OptKRBPrincipalName: return "KerberosPrincipalName" case DHCPv6OptKRBRealmName: return "KerberosRealmName" case DHCPv6OptKRBKDC: return "KerberosKDC" case DHCPv6OptClientLinkLayerAddress: return "ClientLinkLayerAddress" case DHCPv6OptLinkAddress: return "LinkAddress" case DHCPv6OptRADIUS: return "RADIUS" case DHCPv6OptSolMaxRt: return "SolMaxRt" case DHCPv6OptInfMaxRt: return "InfMaxRt" case DHCPv6OptAddrSel: return "AddressSelection" case DHCPv6OptAddrSelTable: return "AddressSelectionTable" case DHCPv6OptV6PCPServer: return "PCPServer" case DHCPv6OptDHCPv4Message: return "DHCPv4Message" case DHCPv6OptDHCPv4OverDHCPv6Server: return "DHCP4o6ServerAddress" case DHCPv6OptS46Rule: return "S46Rule" case DHCPv6OptS46BR: return "S46BR" case DHCPv6OptS46DMR: return "S46DMR" case DHCPv6OptS46V4V4Bind: return "S46IPv4IPv6AddressBinding" case DHCPv6OptS46PortParameters: return "S46PortParameters" case DHCPv6OptS46ContMAPE: return "S46MAPEContainer" case DHCPv6OptS46ContMAPT: return "S46MAPTContainer" case DHCPv6OptS46ContLW: return "S46Lightweight4Over6Container" case DHCPv6Opt4RD: return "4RD" case DHCPv6Opt4RDMapRule: return "4RDMapRule" case DHCPv6Opt4RDNonMapRule: return "4RDNonMapRule" case DHCPv6OptLQBaseTime: return "LQBaseTime" case DHCPv6OptLQStartTime: return "LQStartTime" case DHCPv6OptLQEndTime: return "LQEndTime" case DHCPv6OptCaptivePortal: return "CaptivePortal" case DHCPv6OptMPLParameters: return "MPLParameterConfiguration" case DHCPv6OptANIATT: return "ANIAccessTechnologyType" case DHCPv6OptANINetworkName: return "ANINetworkName" case DHCPv6OptANIAPName: return "ANIAccessPointName" case DHCPv6OptANIAPBSSID: return "ANIAccessPointBSSID" case DHCPv6OptANIOperatorID: return "ANIOperatorIdentifier" case DHCPv6OptANIOperatorRealm: return "ANIOperatorRealm" case DHCPv6OptS46Priority: return "S64Priority" case DHCPv6OptMUDURLV6: return "ManufacturerUsageDescriptionURL" case DHCPv6OptV6Prefix64: return "V6Prefix64" case DHCPv6OptFBindingStatus: return "FailoverBindingStatus" case DHCPv6OptFConnectFlags: return "FailoverConnectFlags" case DHCPv6OptFDNSRemovalInfo: return "FailoverDNSRemovalInfo" case DHCPv6OptFDNSHostName: return "FailoverDNSHostName" case DHCPv6OptFDNSZoneName: return "FailoverDNSZoneName" case DHCPv6OptFDNSFlags: return "FailoverDNSFlags" case DHCPv6OptFExpirationTime: return "FailoverExpirationTime" case DHCPv6OptFMaxUnacknowledgedBNDUPD: return "FailoverMaxUnacknowledgedBNDUPDMessages" case DHCPv6OptFMCLT: return "FailoverMaximumClientLeadTime" case DHCPv6OptFPartnerLifetime: return "FailoverPartnerLifetime" case DHCPv6OptFPartnerLifetimeSent: return "FailoverPartnerLifetimeSent" case DHCPv6OptFPartnerDownTime: return "FailoverPartnerDownTime" case DHCPv6OptFPartnerRawCltTime: return "FailoverPartnerRawClientLeadTime" case DHCPv6OptFProtocolVersion: return "FailoverProtocolVersion" case DHCPv6OptFKeepaliveTime: return "FailoverKeepaliveTime" case DHCPv6OptFReconfigureData: return "FailoverReconfigureData" case DHCPv6OptFRelationshipName: return "FailoverRelationshipName" case DHCPv6OptFServerFlags: return "FailoverServerFlags" case DHCPv6OptFServerState: return "FailoverServerState" case DHCPv6OptFStartTimeOfState: return "FailoverStartTimeOfState" case DHCPv6OptFStateExpirationTime: return "FailoverStateExpirationTime" case DHCPv6OptRelayPort: return "RelayPort" case DHCPv6OptV6ZeroTouchRedirect: return "ZeroTouch" case DHCPv6OptIPV6AddressANDSF: return "ANDSFIPv6Address" default: return fmt.Sprintf("Unknown(%d)", uint16(o)) } } // DHCPv6Options is used to get nicely printed option lists which would normally // be cut off after 5 options. type DHCPv6Options []DHCPv6Option // String returns a string version of the options list. func (o DHCPv6Options) String() string { buf := &bytes.Buffer{} buf.WriteByte('[') for i, opt := range o { buf.WriteString(opt.String()) if i+1 != len(o) { buf.WriteString(", ") } } buf.WriteByte(']') return buf.String() } // DHCPv6Option rerpresents a DHCP option. type DHCPv6Option struct { Code DHCPv6Opt Length uint16 Data []byte } // String returns a string version of a DHCP Option. func (o DHCPv6Option) String() string { switch o.Code { case DHCPv6OptClientID, DHCPv6OptServerID: duid, err := decodeDHCPv6DUID(o.Data) if err != nil { return fmt.Sprintf("Option(%s:INVALID)", o.Code) } return fmt.Sprintf("Option(%s:[%s])", o.Code, duid.String()) case DHCPv6OptOro: options := "" for i := 0; i < int(o.Length); i += 2 { if options != "" { options += "," } option := DHCPv6Opt(binary.BigEndian.Uint16(o.Data[i : i+2])) options += option.String() } return fmt.Sprintf("Option(%s:[%s])", o.Code, options) default: return fmt.Sprintf("Option(%s:%v)", o.Code, o.Data) } } // NewDHCPv6Option constructs a new DHCPv6Option with a given type and data. func NewDHCPv6Option(code DHCPv6Opt, data []byte) DHCPv6Option { o := DHCPv6Option{Code: code} if data != nil { o.Data = data o.Length = uint16(len(data)) } return o } func (o *DHCPv6Option) encode(b []byte, opts gopacket.SerializeOptions) error { binary.BigEndian.PutUint16(b[0:2], uint16(o.Code)) if opts.FixLengths { binary.BigEndian.PutUint16(b[2:4], uint16(len(o.Data))) } else { binary.BigEndian.PutUint16(b[2:4], o.Length) } copy(b[4:], o.Data) return nil } func (o *DHCPv6Option) decode(data []byte) error { if len(data) < 4 { return errors.New("not enough data to decode") } o.Code = DHCPv6Opt(binary.BigEndian.Uint16(data[0:2])) o.Length = binary.BigEndian.Uint16(data[2:4]) if len(data) < 4+int(o.Length) { return fmt.Errorf("dhcpv6 option size < length %d", 4+o.Length) } o.Data = data[4 : 4+o.Length] return nil }