diff --git a/scapy/contrib/mpls.py b/scapy/contrib/mpls.py index 640a0c57239e903a0b488589de58d0ae12a8e4a9..6af1d4ac146087da84771c012495a741cd234f85 100644 --- a/scapy/contrib/mpls.py +++ b/scapy/contrib/mpls.py @@ -18,6 +18,8 @@ class MPLS(Packet): def guess_payload_class(self, payload): if len(payload) >= 1: + if not self.s: + return MPLS ip_version = (ord(payload[0]) >> 4) & 0xF if ip_version == 4: return IP diff --git a/scapy/contrib/mpls.uts b/scapy/contrib/mpls.uts new file mode 100644 index 0000000000000000000000000000000000000000..6057b67a3d4d75d18234891318570407646edbd0 --- /dev/null +++ b/scapy/contrib/mpls.uts @@ -0,0 +1,21 @@ +# MPLS unit tests +# +# Type the following command to launch start the tests: +# $ test/run_tests -P "load_contrib('mpls')" -t scapy/contrib/mpls.uts + ++ MPLS + += Build & dissect - IPv4 +s = str(Ether(src="00:01:02:04:05")/MPLS()/IP()) +assert(s == b'\xff\xff\xff\xff\xff\xff\x00\x01\x02\x04\x05\x00\x88G\x00\x001\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01') + +p = Ether(s) +assert(MPLS in p and IP in p) + + += Build & dissect - IPv6 +s = str(Ether(src="00:01:02:04:05")/MPLS(s=0)/MPLS()/IPv6()) +assert(s == b'\xff\xff\xff\xff\xff\xff\x00\x01\x02\x04\x05\x00\x88G\x00\x000\x00\x00\x001\x00`\x00\x00\x00\x00\x00;@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01') + +p = Ether(s) +assert(IPv6 in p and isinstance(p[MPLS].payload, MPLS)) diff --git a/scapy/layers/dhcp6.py b/scapy/layers/dhcp6.py index 65c30203b0ebdf47ccba7550a633af8f67eb042a..59dc36a975c0b19f0fd70f87a2b3e4a367e8a597 100644 --- a/scapy/layers/dhcp6.py +++ b/scapy/layers/dhcp6.py @@ -75,7 +75,9 @@ dhcp6opts = { 1: "CLIENTID", 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 + 39: "OPTION_CLIENT_FQDN", #RFC4704 + 68: "OPTION_VSS", #RFC6607 + 79: "OPTION_CLIENT_LINKLAYER_ADDR" } #RFC6939 dhcp6opts_by_code = { 1: "DHCP6OptClientId", 2: "DHCP6OptServerId", @@ -117,12 +119,14 @@ dhcp6opts_by_code = { 1: "DHCP6OptClientId", #40: "DHCP6OptPANAAgent", #RFC-ietf-dhc-paa-option-05.txt #41: "DHCP6OptNewPOSIXTimeZone, #RFC4833 #42: "DHCP6OptNewTZDBTimeZone, #RFC4833 - 43: "DHCP6OptRelayAgentERO" #RFC4994 + 43: "DHCP6OptRelayAgentERO", #RFC4994 #44: "DHCP6OptLQQuery", #RFC5007 #45: "DHCP6OptLQClientData", #RFC5007 #46: "DHCP6OptLQClientTime", #RFC5007 #47: "DHCP6OptLQRelayData", #RFC5007 #48: "DHCP6OptLQClientLink", #RFC5007 + 68: "DHCP6OptVSS", #RFC6607 + 79: "DHCP6OptClientLinkLayerAddr", #RFC6939 } @@ -839,6 +843,27 @@ class DHCP6OptRelayAgentERO(_DHCP6OptGuessPayload): # RFC4994 _OptReqListField("reqopts", [23, 24], length_from = lambda pkt: pkt.optlen) ] +# "Client link-layer address type. The link-layer type MUST be a valid hardware +# type assigned by the IANA, as described in [RFC0826] +class DHCP6OptClientLinkLayerAddr(_DHCP6OptGuessPayload): # RFC6939 + name = "DHCP6 Option - Client Link Layer address" + fields_desc = [ ShortEnumField("optcode", 79, dhcp6opts), + FieldLenField("optlen", None, length_of="clladdr", + adjust = lambda pkt,x: x+1), + ShortField("lltype", 1), # ethernet + _LLAddrField("clladdr", ETHER_ANY) ] + +# Virtual Subnet selection +class DHCP6OptVSS(_DHCP6OptGuessPayload): # RFC6607 + name = "DHCP6 Option - Virtual Subnet Selection" + fields_desc = [ ShortEnumField("optcode", 68, dhcp6opts), + FieldLenField("optlen", None, length_of="data", + adjust = lambda pkt,x: x+1), + ByteField("type", 255), # Default Global/default table + StrLenField("data", "", + length_from = lambda pkt: pkt.optlen) ] + + ##################################################################### ### DHCPv6 messages ### ##################################################################### diff --git a/test/regression.uts b/test/regression.uts index a4205431f1dbc20a00595af7c973caa5a553503c..80de536c151e365adf074df20e2da15ba05c9e8f 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -1175,6 +1175,13 @@ str(Ether(src="00:00:00:00:00:00", dst="ff:ff:ff:ff:ff:ff")/IPv6()/TCP()) == b'\ a=Ether(str(Ether()/IPv6()/TCP())) a.type == 0x86dd += IPv6 Class binding with GRE - build +str(IP()/GRE()/Ether()/IP()/GRE()/IPv6()) == b'E\x00\x00f\x00\x01\x00\x00@/|f\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x00eX\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x08\x00E\x00\x00@\x00\x01\x00\x00@/|\x8c\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x00\x86\xdd`\x00\x00\x00\x00\x00;@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' + += IPv6 Class binding with GRE - dissection +p = IP(str(IP()/GRE()/Ether()/IP()/GRE()/IPv6())) +GRE in p and p[GRE:1].proto == 0x6558 and p[GRE:2].proto == 0x86DD and IPv6 in p + ########### IPv6ExtHdrRouting Class ########################### @@ -3861,6 +3868,30 @@ a=DHCP6OptRelayAgentERO(b'\x00+\x00\x08\x00\x01\x00\x02\x00\x03\x00\x04') a.optcode == 43 and a.optlen == 8 and a.reqopts == [1,2,3,4] +############ +############ ++ Test DHCP6 Option Client Link Layer address + += Basic build & dissect +s = str(DHCP6OptClientLinkLayerAddr()) +assert(s == b"\x00O\x00\x07\x00\x01\x00\x00\x00\x00\x00\x00") + +p = DHCP6OptClientLinkLayerAddr(s) +assert(p.clladdr == "00:00:00:00:00:00") + + +############ +############ ++ Test DHCP6 Option Virtual Subnet Selection + += Basic build & dissect +s = str(DHCP6OptVSS()) +assert(s == b"\x00D\x00\x01\xff") + +p = DHCP6OptVSS(s) +assert(p.type == 255) + + ############ ############ + Test DHCP6 Messages - DHCP6_Solicit