% Regression tests for the Dot15D4, SixLoWPAN and Zigbee layers

###################
##### Dot15D4 #####
###################

+ Dot15D4 tests

= Dot15D4 layers

# a crazy packet with all classes in it!
pkt = Dot15d4()/Dot15d4Ack()/Dot15d4AuxSecurityHeader()/Dot15d4Beacon()/Dot15d4Cmd()/Dot15d4CmdAssocReq()/Dot15d4CmdAssocResp()/Dot15d4CmdCoordRealign()/Dot15d4CmdDisassociation()/Dot15d4CmdGTSReq()/Dot15d4Data()/Dot15d4FCS()
assert Dot15d4 in pkt.layers()
assert Dot15d4Ack in pkt.layers()
assert Dot15d4AuxSecurityHeader in pkt.layers()
assert Dot15d4Beacon in pkt.layers()
assert Dot15d4Cmd in pkt.layers()
assert Dot15d4CmdAssocReq in pkt.layers()
assert Dot15d4CmdAssocResp in pkt.layers()
assert Dot15d4CmdCoordRealign in pkt.layers()
assert Dot15d4CmdDisassociation in pkt.layers()
assert Dot15d4CmdGTSReq in pkt.layers()
assert Dot15d4Data in pkt.layers()
assert Dot15d4FCS in pkt.layers()

###################
#### SixLoWPAN ####
###################

+ SixLoWPAN tests

= Set SixLoWPAN

conf.dot15d4_protocol = "sixlowpan"

= SixLoWPAN layers

# a crazy packet with all classes in it!
pkt = SixLoWPAN()/LoWPANFragmentationFirst()/LoWPANFragmentationSubsequent()/LoWPANMesh()/LoWPANUncompressedIPv6()
assert SixLoWPAN in pkt.layers()
assert LoWPANFragmentationFirst in pkt.layers()
assert LoWPANFragmentationSubsequent in pkt.layers()
assert LoWPANMesh in pkt.layers()
assert LoWPANUncompressedIPv6 in pkt.layers()

= Default dissection

# some sample packet extracted

lowpan_frag_first = b'\xc29\x00\x17`\x00\x00\x00\x00\x00\x00\x00 \x02\r\xb8\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x01 \x02\r\xb8\x00\x00\x00\x00\x00\x11"\xff\xfe3DU\xc4\xf9\x00Pw\x9b\x18\x9d\x00\x00\x01\xa2P\x18\x13X\x08\x10\x00\x00GET / HTTP/1.1\r\nHost: [aaaa::11:22ff'
lowpan_frag_first_packet = SixLoWPAN(lowpan_frag_first)

assert lowpan_frag_first_packet.load == b'`\x00\x00\x00\x00\x00\x00\x00 \x02\r\xb8\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x01 \x02\r\xb8\x00\x00\x00\x00\x00\x11"\xff\xfe3DU\xc4\xf9\x00Pw\x9b\x18\x9d\x00\x00\x01\xa2P\x18\x13X\x08\x10\x00\x00GET / HTTP/1.1\r\nHost: [aaaa::11:22ff'

= Frag second dissection

lowpan_frag_second = b'\xe29\x00\x17\x0c`\x00\x00\x00\x00\x00\x00\x00 \x02\r\xb8\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x01 \x02\r\xb8\x00\x00\x00\x00\x00\x11"\xff\xfe3DUerer: http://[aaaa::11:22ff:fe33:4455]/sensor.shtml\r\nUse'
lowpan_frag_sec_packet = SixLoWPAN(lowpan_frag_second)

assert LoWPANFragmentationSubsequent in lowpan_frag_sec_packet
assert lowpan_frag_sec_packet.datagramSize == 569
assert lowpan_frag_sec_packet.datagramTag == 0x17

= LoWPAN_IPHC dissections

lowpan_iphc = b"\x78\xf6\x00\x06\x80\x00\x01\x00\x50\xc4\xf9\x00\x00\x02\x12\x77\x9b\x1a\x9a\x50\x18\x04\xc4\x12\xd5\x00\x00\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x48\x54\x4d\x4c\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x48\x54\x4d\x4c\x20\x34\x2e\x30\x31\x20\x54\x72\x61\x6e\x73\x69\x74\x69\x6f\x6e\x61\x6c\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70"
lowpan_frag_iphc = LoWPAN_IPHC(lowpan_iphc)

assert IPv6 in lowpan_frag_iphc
assert lowpan_frag_iphc.load == b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http'

p = LoWPAN_IPHC(tf=0x0, flowlabel=0x8, _nhField=0x3a, _hopLimit=64)/IPv6(dst="aaaa::11:22ff:fe33:4455", src="aaaa::1")/ICMPv6EchoRequest()
p = LoWPAN_IPHC(raw(p))
assert ICMPv6EchoRequest in p
assert p.destinyAddr == "aaaa::11:22ff:fe33:4455"

q = LoWPAN_IPHC(tf=0x0)
assert raw(q) == b'`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

= Advanced packets - dissection

# SAMPLE PACKETSS!!! IEEE 802.15.4 containing

ieee802_firstfrag = b"\x41\xcc\xa3\xcd\xab\x16\x15\x14\xfe\xff\x13\x12\x02\x55\x44\x33\xfe\xff\x22\x11\x02\xc3\x42\x00\x23\x78\xf6\x00\x06\x80\x00\x01\x00\x50\xc4\xf9\x00\x00\x02\x12\x77\x9b\x1a\x9a\x50\x18\x04\xc4\x12\xd5\x00\x00\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x48\x54\x4d\x4c\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x48\x54\x4d\x4c\x20\x34\x2e\x30\x31\x20\x54\x72\x61\x6e\x73\x69\x74\x69\x6f\x6e\x61\x6c\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x39\xb5"
ieee = Dot15d4FCS(ieee802_firstfrag)
ieee.show2()

ieee802_secfrag = b"\x41\xcc\x4d\xcd\xab\x55\x44\x33\xfe\xff\x22\x11\x02\x16\x15\x14\xfe\xff\x13\x12\x02\xe2\x39\x00\x17\x10\x69\x76\x65\x0d\x0a\x52\x65\x66\x65\x72\x65\x72\x3a\x20\x68\x74\x74\x70\x3a\x2f\x2f\x5b\x61\x61\x61\x61\x3a\x3a\x31\x31\x3a\x32\x32\x66\x66\x3a\x66\x65\x33\x33\x3a\x34\x34\x35\x35\x5d\x2f\x73\x65\x6e\x73\x6f\x72\x2e\x73\x68\x74\x6d\x6c\x0d\x0a\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x58\x31\x31\x3b\x20\x55\x3b\x20\x4c\x69\x66\xac"
ieee = Dot15d4FCS(ieee802_secfrag)
ieee.show2()

ieee802_iphc = b"\x41\xcc\xb5\xcd\xab\x16\x15\x14\xfe\xff\x13\x12\x02\x55\x44\x33\xfe\xff\x22\x11\x02\x78\xf6\x00\x06\x80\x00\x01\x00\x50\xc4\xfa\x00\x00\x01\xf7\x89\xf3\x02\x5f\x50\x18\x04\xc4\x48\x28\x00\x00\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x74\x79\x70\x65\x3a\x20\x74\x65\x78\x74\x2f\x63\x73\x73\x0d\x0a\x0d\x0a\xc1\x16"
ieee = Dot15d4FCS(ieee802_iphc)
ieee.show2()

= Dot15d4AuxSecurityHeader - build & dissect

p = Dot15d4AuxSecurityHeader(b"\x04\x05\x00\x00\x00")
assert p.sec_sc_keyidmode == 0
assert p.sec_sc_seclevel == 4

p = Dot15d4AuxSecurityHeader(b"\x18\x05\x00\x00\x00\xff\xee\xdd\xcc\xbb\xaa\x00\x99\x88\x77")
assert p.sec_sc_keyidmode == 3
assert p.sec_keyid_keysource == 11024999611375677183

# RPL: unimplemented
#p = SixLoWPAN(b"\x7b\x3b\x3a\x1a\x9b\x02\xae\x30\x21\x00\x00\xef\x05\x12\x00\x80\x20\x02\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x33\x44\x09\x04\x00\x00\x00\x00\x06\x04\x00\x01\xef\xff")
#p.show2()

= Fragmentate packet & defragmentate

ipv6p = b"\x60\x00\x00\x00\x02\x11\x06\x80\x20\x02\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x01\x20\x02\x0d\xb8\x00\x00\x00\x00\x00\x11\x22\xff\xfe\x33\x44\x55"
tcpp = b"\xc4\xf9\x00\x50\x77\x9b\x18\x9d\x00\x00\x01\xa2\x50\x18\x13\x58\x08\x10\x00\x00"
httpp = b"\x47\x45\x54\x20\x2f\x20\x48\x54\x54\x50\x2f\x31\x2e\x31\x0d\x0a\x48\x6f\x73\x74\x3a\x20\x5b\x61\x61\x61\x61\x3a\x3a\x31\x31\x3a\x32\x32\x66\x66\x3a\x66\x65\x33\x33\x3a\x34\x34\x35\x35\x5d\x0d\x0a\x43\x6f\x6e\x6e\x65\x63\x74\x69\x6f\x6e\x3a\x20\x6b\x65\x65\x70\x2d\x61\x6c\x69\x76\x65\x0d\x0a\x52\x65\x66\x65\x72\x65\x72\x3a\x20\x68\x74\x74\x70\x3a\x2f\x2f\x5b\x61\x61\x61\x61\x3a\x3a\x31\x31\x3a\x32\x32\x66\x66\x3a\x66\x65\x33\x33\x3a\x34\x34\x35\x35\x5d\x2f\x73\x65\x6e\x73\x6f\x72\x2e\x73\x68\x74\x6d\x6c\x0d\x0a\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x58\x31\x31\x3b\x20\x55\x3b\x20\x4c\x69\x6e\x75\x78\x20\x69\x36\x38\x36\x3b\x20\x65\x6e\x2d\x55\x53\x29\x20\x41\x70\x70\x6c\x65\x57\x65\x62\x4b\x69\x74\x2f\x35\x33\x34\x2e\x31\x36\x20\x28\x4b\x48\x54\x4d\x4c\x2c\x20\x6c\x69\x6b\x65\x20\x47\x65\x63\x6b\x6f\x29\x20\x55\x62\x75\x6e\x74\x75\x2f\x31\x30\x2e\x31\x30\x20\x43\x68\x72\x6f\x6d\x69\x75\x6d\x2f\x31\x30\x2e\x30\x2e\x36\x34\x38\x2e\x31\x33\x33\x20\x43\x68\x72\x6f\x6d\x65\x2f\x31\x30\x2e\x30\x2e\x36\x34\x38\x2e\x31\x33\x33\x20\x53\x61\x66\x61\x72\x69\x2f\x35\x33\x34\x2e\x31\x36\x0d\x0a\x41\x63\x63\x65\x70\x74\x3a\x20\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x6d\x6c\x2c\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x78\x68\x74\x6d\x6c\x2b\x78\x6d\x6c\x2c\x74\x65\x78\x74\x2f\x68\x74\x6d\x6c\x3b\x71\x3d\x30\x2e\x39\x2c\x74\x65\x78\x74\x2f\x70\x6c\x61\x69\x6e\x3b\x71\x3d\x30\x2e\x38\x2c\x69\x6d\x61\x67\x65\x2f\x70\x6e\x67\x2c\x2a\x2f\x2a\x3b\x71\x3d\x30\x2e\x35\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x45\x6e\x63\x6f\x64\x69\x6e\x67\x3a\x20\x67\x7a\x69\x70\x2c\x64\x65\x66\x6c\x61\x74\x65\x2c\x73\x64\x63\x68\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x4c\x61\x6e\x67\x75\x61\x67\x65\x3a\x20\x65\x6e\x2d\x55\x53\x2c\x65\x6e\x3b\x71\x3d\x30\x2e\x38\x0d\x0a\x41\x63\x63\x65\x70\x74\x2d\x43\x68\x61\x72\x73\x65\x74\x3a\x20\x49\x53\x4f\x2d\x38\x38\x35\x39\x2d\x31\x2c\x75\x74\x66\x2d\x38\x3b\x71\x3d\x30\x2e\x37\x2c\x2a\x3b\x71\x3d\x30\x2e\x33\x0d\x0a\x0d\x0a"
ipv6_tcp_http = IPv6(ipv6p + tcpp + httpp)
pkt = sixlowpan_fragment(ipv6_tcp_http, 0x17)

assert len(pkt) == 6
assert isinstance(pkt[0], LoWPANFragmentationFirst)
assert all(isinstance(x, LoWPANFragmentationSubsequent) for x in pkt[1:])

ipv6 = sixlowpan_defragment(pkt)[0x17]
assert TCP in ipv6
assert raw(ipv6_tcp_http) == raw(ipv6)

= Mesh Header.
# DOESN'T WORK! (In wireshark it reports, malformed packet)

######## TODO ########

#packet = SixLoWPAN(b"\x83\x00\x0a\x00\xff\x0a\x11\x78\x04\x00\x28\x00\x00\x00\x80\x00")
#packet.show2()

= SixLoWPAN - Advanced 1

packet = LoWPAN_IPHC(b"\x7b\x49\x3a\x02\x01\xff\x02\x02\x02\x87\x00\x02\x0b\x00\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x12\x74\x02\x00\x02\x02\x02")
assert packet._nhField == 0x3a
assert packet.src == "::"
assert packet.dst == "ff02::1:ff02:202"

= SixLoWPAN - Advanced 2

packet = SixLoWPAN(b"\x7b\x49\x3a\x02\x01\xff\x01\x01\x01\x87\x00\x57\xe6\x00\x00\x00\x00\xaa\xaa\x00\x00\x00\x00\x00\x00\x02\x12\x74\x01\x00\x01\x01\x01")
assert packet._nhField == 0x3a
assert packet.sourceAddr == "::"
assert packet.destinyAddr == "ff02::1:ff01:101"

= SixLoWPAN - Advanced 3

packet = Ether()/IP()/UDP()/ZEP2()/Dot15d4(fcf_srcaddrmode=2)/Dot15d4Data(src_addr=0x0)/b"\x7b\x33\x3a\x88\x00\x3c\xb9\x60\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x12\x74\x02\x00\x02\x02\x02\x02\x02\x00\x12\x74\x02\x00\x02\x02\x02\x00\x00\x00\x00\x00\x00"
packet = Ether(raw(packet))
packet.show2()
assert packet.sourceAddr == 'fe80::ff:fe00:0'
assert packet.destinyAddr == 'fe80::ff:fe00:ffff'

= SixLoWPAN - Using ICMP

#ICMP: Neighbour Solicitation
icmp = b"\x7b\xf6\x00\x3a\x00\x01\x87\x00\xaa\x66\x00\x00\x00\x00\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x02\x02\x11\x22\xff\xfe\x33\x44\x55\x00\x00\x00\x00\x00\x00"
packet = SixLoWPAN(icmp)
#packet.show2()
assert packet.tf == 0x3
assert packet.nh == 0
assert packet.hlim == 0x3
assert packet.cid == True
assert packet.sac == True
assert packet.sam == 0x3
assert packet.m == False
assert packet.dac == True
assert packet.dam == 0x2
assert packet._nhField == 0x3a

= LoWPAN_IPHC - Extracted packet
icmp = Ether()/IP()/UDP()/ZEP2()/Dot15d4(fcf_srcaddrmode=2)/Dot15d4Data(src_addr=0xFFFF)/b"\x7b\x3b\x3a\x01\x86\x00\xd3\xfd\x80\x00\x00\xc8\x00\x05\x7e\x40\x00\x00\x00\x00\x03\x04\x40\xc0\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x00\x00\x00\x00\x05\x00\x01\x02\x02\x12\x13\xff\xfe\x14\x15\x16\x7b\x66\x6f\x6e\x74\x2d"
packet = Ether(raw(icmp))
assert packet[LoWPAN_IPHC][IPv6].dst == 'ff02::1'

#the same message with ethernet header
eth = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b"\x41\xc8\x49\xcd\xab\xff\xff\x16\x15\x14\xfe\xff\x13\x12\x02\x7b\x3b\x3a\x01\x86\x00\xd3\xfd\x80\x00\x00\xc8\x00\x05\x7e\x40\x00\x00\x00\x00\x03\x04\x40\xc0\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x00\x00\x00\x00\x05\x00\x01\x02\x02\x12\x13\xff\xfe\x14\x15\x16\x7b\x66\x6f\x6e\x74\x2d\xa0\x90"
packet = Ether(raw(eth))
assert LoWPANUncompressedIPv6 in packet

= LoWPAN_IPHC - Extracted packet 2

#NOTE: this is not a real package, it's the first fragment from a udp packet
# extracted from 6lowpan-test.pcap
udp = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b"\x7e\xf7\x00\xf0\x22\x3d\x16\x2e\x8e\x60\x10\x03\x00\x00\xaa\xaa\x00\x00\x00\x00\x00\x00\x48\x65\x6c\x6c\x6f\x20\x31\x20\x66\x72\x6f\x6d\x20\x74\x68\x65\x20\x63\x6c\x69\x65\x6e\x74\x2e\x2d\x2e\x2d\x2e\x2d\x20\x30\x20\x33\x34\x35\x36\x37\x38\x39\x20\x31\x20\x33\x34\x35\x36\x37\x38\x39\x20\x32\x20\x33\x34\x35\x36\x37\x38\x39\x20\x33\x20\x33\x34\x35\x36\x37\x38\x39\x20\x34\x20\x33\x34\x35\x36"
packet = Ether(raw(udp))
assert packet.udpSourcePort == 8765
assert packet.udpDestinyPort == 5678
assert packet.udpChecksum == 0x8e60
assert packet[IPv6].nh == 0x11 # the ipv6 header
assert packet[IPv6][UDP].sport == 8765 #udp decompressed header
assert packet[IPv6][UDP].dport == 5678 #udp decompressed header
assert packet[IPv6][UDP].chksum == 0x8e60 #udp decompressed header
packet.show2()

= SixLoWPAN - Check Traffic Class and Flow Label when TF=0
packet = SixLoWPAN()/LoWPAN_IPHC(tf=0)/IPv6(tc = 12, fl=467)
packet = SixLoWPAN(raw(packet))
assert (packet.tc_ecn << 6) + packet.tc_dscp == 12
assert packet.flowlabel == 467

= SixLoWPAN - Check Traffic Class and Flow Label when TF=1

packet = SixLoWPAN()/LoWPAN_IPHC(tf=1)/IPv6(tc = 12, fl=467)
packet = SixLoWPAN(raw(packet))
assert packet.tc_ecn == 0 and packet.flowlabel == 467

= SixLoWPAN - Check Traffic Class and Flow Label when TF=2

packet = SixLoWPAN()/LoWPAN_IPHC(tf=2)/IPv6(tc = 12, fl=467)
packet = SixLoWPAN(raw(packet))
assert (packet.tc_ecn << 6) + packet.tc_dscp == 12 and packet.flowlabel == 0
packet = SixLoWPAN()/LoWPAN_IPHC(tf=3)/IPv6(tc = 12, fl=467)
packet = SixLoWPAN(raw(packet))
assert (packet.tc_ecn << 6) + packet.tc_dscp == 0 and packet.flowlabel == 0

#TODO: Next Header Test

= SixLoWPAN - Checking the Hop Limit value in the IPv6 packet decompressed
packet = SixLoWPAN()/LoWPAN_IPHC()/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()
packet = SixLoWPAN(raw(packet))
assert packet[IPv6].hlim == 65
packet = SixLoWPAN()/LoWPAN_IPHC(hlim=1)/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()
packet = SixLoWPAN(raw(packet))
assert packet[IPv6].hlim == 1
packet = SixLoWPAN()/LoWPAN_IPHC(hlim=2)/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()
packet = SixLoWPAN(raw(packet))
assert packet[IPv6].hlim == 64
packet = SixLoWPAN()/LoWPAN_IPHC(hlim=3)/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()
packet = SixLoWPAN(raw(packet))
assert packet[IPv6].hlim == 255

#TODO: Context Test

= SixLoWPAN - Check Source Address
packet = SixLoWPAN()/LoWPAN_IPHC(sam = 0, sac = 0, destinyAddr='ff02::1a')/IPv6(hlim=65, src="aaaa::1", dst="ff02::1a")/ICMPv6EchoRequest()
packet = SixLoWPAN(raw(packet))
assert packet.sourceAddr == "aaaa::1"
assert packet.destinyAddr == "ff02::1a"

+ Dot15d4 with SixLoWPAN - Advanced dissection

= Compressed SixLoWPAN - real packets with ZEP2

basic_ipv6 = b'\x00"\x19\x100\xe5\x00\x1c\xda\x00\x10\x04\x08\x00E\x00\x00g>\x0c\x00\x00@\x11\xe1\x95\xac\x10\x01\x90\xac\x10\x014EZEZ\x00S\xda\x93EX\x02\x01\x03\x00Y\x01\xff\x00\x02\xab\xa2\x81\xba\xc2\xdf\x00\x00<\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+A\x88U\xaa\x1b\xff\xfffU{;:\x1a\x9b\x01uE\x00\xf1\x03Z\x8b\xf0\x00\x00\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x11"lF'
ack_frame = b'\x00"\x19\x100\xe5\x00\x1c\xda\x00\x10\x04\x08\x00E\x00\x00A>\x0e\x00\x00@\x11\xe1\xb9\xac\x10\x01\x90\xac\x10\x014EZEZ\x00-d7EX\x02\x01\x03\x00Y\x01\xff\x00\x02\xab\xa8\x84\xcb\x07\xd0\x00\x00<\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\x00[\xeeY'
router_adv = b'\x00"\x19\x100\xe5\x00\x1c\xda\x00\x10\x04\x08\x00E\x00\x00\xab>F\x00\x00@\x11\xe1\x17\xac\x10\x01\x90\xac\x10\x014EZEZ\x00\x97\x81\xb0EX\x02\x01\x03\x00Y\x01\xff\x00\x02\xab\xe8E\xce\xbf\xec\x00\x00<N\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00oA\x88_\xaa\x1b\xff\xfffU{;:\x01\x86\x00\xbe\x87@\x00\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01Uf\x00\x00\x00\x00!\x03\x00\x00\x00\x00\x00\x01\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x11"\x03\x04@@\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02@\x10\x00\x00\x00\x03\xfd\x00\x00\x00\x00\x00\x00\x00\xc27'

pkt_1 = Ether(basic_ipv6)
pkt_2 = Ether(ack_frame)
pkt_3 = Ether(router_adv)

assert ZEP2 in pkt_1
assert pkt_1[LoWPAN_IPHC].sourceAddr == "fe80::ff:fe00:5566"

assert ZEP2 in pkt_2
assert Dot15d4Ack in pkt_2

assert ZEP2 in pkt_3
assert ICMPv6NDOptSrcLLAddr in pkt_3
assert pkt_3[Dot15d4Data].dest_panid == 0x1baa

= SixLoWPAN - Using ETH

# It requires the ETH message
lowpan_iphc_header = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b"\x78\xe7\x00\x06\x80\x00\x01"
packet = Ether(raw(lowpan_iphc_header))
assert packet.tf == 0x3
assert packet.nh == 0
assert packet.hlim == 0x0
assert packet.cid == True
assert packet.sac == True
assert packet.sam == 0x2
assert packet.m == 0x0
assert packet.dac == 0x1
assert packet.dam == 0x03
assert packet._nhField == 0x06
assert packet._hopLimit == 128

= SixLoWPAN - Using ETH 2

# It requires the ETH message
lowpan_iphc_header = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b"\x78\xf6\x00\x06\x80\x00\x01"
packet = Ether(raw(lowpan_iphc_header))
assert packet.tf == 0x3
assert packet.nh == 0
assert packet.hlim == 0x0
assert packet.cid == True
assert packet.sac == True
assert packet.sam == 0x3
assert packet.m == 0x0
assert packet.dac == 0x1
assert packet.dam == 0x02
assert packet._nhField == 0x06
assert packet._hopLimit == 128

= SixLoWPAN - Using ETH 3

lowpan_iphc_header = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b"\x78\xe7\x00\x06\x80\x00\x01"
packet = Ether(raw(lowpan_iphc_header))
assert packet.tf == 0x3
assert packet.nh == 0
assert packet.hlim == 0x0
assert packet.cid == True
assert packet.sac == True
assert packet.sam == 0x2
assert packet.m == 0x0
assert packet.dac == 0x1
assert packet.dam == 0x03
assert packet._nhField == 0x06
assert packet._hopLimit == 128
packet.show2()


###################
#### Zigbee ####
###################

+ Zigbee tests

= Set zigbee

conf.dot15d4_protocol = "zigbee"

= Zigbee - layers

# a crazy packet with all classes in it!
pkt = ZigBeeBeacon()/ZigbeeAppCommandPayload()/ZigbeeAppDataPayload()/ZigbeeAppDataPayloadStub()/ZigbeeClusterLibrary()/ZigbeeNWK()/ZigbeeNWKCommandPayload()/ZigbeeNWKStub()/ZigbeeSecurityHeader()
assert ZigBeeBeacon in pkt.layers()
assert ZigbeeAppCommandPayload in pkt.layers()
assert ZigbeeAppDataPayload in pkt.layers()
assert ZigbeeAppDataPayloadStub in pkt.layers()
assert ZigbeeClusterLibrary in pkt.layers()
assert ZigbeeNWK in pkt.layers()
assert ZigbeeNWKCommandPayload in pkt.layers()
assert ZigbeeNWKStub in pkt.layers()
assert ZigbeeSecurityHeader in pkt.layers()

= Zigbee - advanced dissection

import os
tmp = "/test/pcaps/zigbee-join-authenticate.pcap"
filename = os.path.abspath(os.path.join(os.path.dirname(__file__),"../")) + tmp
filename = os.getenv("SCAPY_ROOT_DIR")+tmp if not os.path.exists(filename) else filename
a = rdpcap(filename)

pkt1 = a[0]  # Data
pkt2 = a[1]  # Command
pkt3 = a[2]  # Beacon
pkt4 = a[38]  # ack

assert Dot15d4 in pkt1
assert ZigbeeNWK in pkt1
assert ZigbeeSecurityHeader in pkt1
assert pkt1[ZigbeeNWK].flags == 18
assert pkt1[ZigbeeNWK].ext_src == 3781220488824152
f,v = pkt1[ZigbeeNWK].getfield_and_val("ext_src")
assert f.i2repr(None, v) == "00:0d:6f:00:00:0d:c5:58"
assert pkt1[ZigbeeSecurityHeader].source == 3781220488824152
assert pkt1[ZigbeeSecurityHeader].key_type == 1
assert pkt1[ZigbeeSecurityHeader].extended_nonce == 1

assert Dot15d4 in pkt2
assert Dot15d4Cmd in pkt2
assert pkt2[Dot15d4Cmd].dest_addr == 0xffff
assert pkt2[Dot15d4Cmd].dest_panid == 0xffff
assert pkt2[Dot15d4Cmd].cmd_id == 7

assert Dot15d4 in pkt3
assert Dot15d4Beacon in pkt3
assert ZigBeeBeacon in pkt3
assert pkt3[Dot15d4Beacon].src_panid == 0x1ff
assert pkt3[ZigBeeBeacon].nwkc_protocol_version== 2
assert pkt3[ZigBeeBeacon].extended_pan_id == 125823003551091
f,v = pkt3[ZigBeeBeacon].getfield_and_val("extended_pan_id")
assert f.i2repr(None, v) == "00:00:72:6f:73:6e:65:73"
assert pkt3[ZigBeeBeacon].tx_offset == 16777215

= Zigbee - skke_1 transport key

tmp = "/test/pcaps/zigbee-transport-key-skke_1.pcap"
filename = os.path.abspath(os.path.join(os.path.dirname(__file__),"../")) + tmp
filename = os.getenv("SCAPY_ROOT_DIR")+tmp if not os.path.exists(filename) else filename
a = rdpcap(filename)

pkt1 = a[0]  # AppCommandPayload with transport key

assert Dot15d4FCS in pkt1
assert ZigbeeNWK in pkt1
assert ZigbeeAppDataPayload in pkt1
assert ZigbeeAppCommandPayload in pkt1
assert pkt1[ZigbeeAppCommandPayload].cmd_identifier == 1
f,v = pkt1[ZigbeeAppCommandPayload].getfield_and_val("cmd_identifier")
assert f.i2repr(None, v) == "APS_CMD_SKKE_1"
assert pkt1[ZigbeeAppCommandPayload].key == b"&Tkr;9jr{]RqQ}9/"
assert pkt1[ZigbeeAppCommandPayload].key_seqnum == 0
assert pkt1[ZigbeeAppCommandPayload].dest_addr == 4502500120025882
f,v = pkt1[ZigbeeAppCommandPayload].getfield_and_val("dest_addr")
assert f.i2repr(None, v) == "00:0f:ff:00:00:41:5b:1a"
assert pkt1[ZigbeeAppCommandPayload].src_addr == 18446744073709551615
f,v = pkt1[ZigbeeAppCommandPayload].getfield_and_val("src_addr")
assert f.i2repr(None, v) == "ff:ff:ff:ff:ff:ff:ff:ff"
