1#!/usr/bin/env python3 2# 3# Copyright (c) 2020, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30import unittest 31 32import config 33import thread_cert 34from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, NETWORK_DATA_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV 35from pktverify.packet_verifier import PacketVerifier 36 37ROUTER = 1 38LEADER = 2 39 40# Test Purpose and Description: 41# ----------------------------- 42# The purpose of this test case is to verify the DUT’s behavior when receiving 43# MGMT_ACTIVE_SET.req from an active Thread node. 44# 45# Test Topology: 46# ------------- 47# Router 48# | 49# Leader 50# 51# DUT Types: 52# ---------- 53# Leader 54 55 56class Cert_9_2_05_ActiveDataset(thread_cert.TestCase): 57 USE_MESSAGE_FACTORY = False 58 SUPPORT_NCP = False 59 60 TOPOLOGY = { 61 ROUTER: { 62 'name': 'ROUTER', 63 'channel': 11, 64 'network_key': '00112233445566778899aabbccddeeff', 65 'mode': 'rdn', 66 'allowlist': [LEADER] 67 }, 68 LEADER: { 69 'name': 'LEADER', 70 'channel': 11, 71 'network_key': '00112233445566778899aabbccddeeff', 72 'mode': 'rdn', 73 'allowlist': [ROUTER] 74 }, 75 } 76 77 def test(self): 78 self.nodes[LEADER].start() 79 self.simulator.go(config.LEADER_STARTUP_DELAY) 80 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 81 82 self.nodes[ROUTER].start() 83 self.simulator.go(config.ROUTER_STARTUP_DELAY) 84 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 85 86 self.nodes[ROUTER].commissioner_start() 87 self.simulator.go(5) 88 89 self.collect_rlocs() 90 # Step 2: new, valid Timestamp TLV 91 # all valid Active Operational Dataset parameters, 92 # with new values in the TLVs that don’t affect connectivity 93 # binary = new pskc and security policy [3600, 0b11101111] 94 self.nodes[ROUTER].send_mgmt_active_set( 95 active_timestamp=100, 96 channel_mask=0x3fff800, 97 extended_panid='000db80000000001', 98 mesh_local='fd00:0db8::', 99 network_name='TEST_1', 100 network_key='00112233445566778899aabbccddeeff', 101 panid=0xface, 102 channel=11, 103 binary='0410d2aa9cd8dff7919122d77d37ec3c1b5f0c030e10ef', 104 ) 105 self.simulator.go(5) 106 107 # Step 7: old, invalid Active Timestamp TLV 108 # all valid Active Operational Dataset parameters, with 109 # new values in the TLVs that don’t affect connectivity 110 # binary = new pskc and security policy [3600, 0b11111111] 111 self.nodes[ROUTER].send_mgmt_active_set( 112 active_timestamp=100, 113 channel_mask=0x1fff800, 114 extended_panid='000db80000000002', 115 mesh_local='fd00:0db8::', 116 network_name='TEST_2', 117 network_key='00112233445566778899aabbccddeeff', 118 panid=0xface, 119 channel=11, 120 binary='041017d672be32b0c24a2f8385f2fbaf1d970c030e10ff', 121 ) 122 self.simulator.go(5) 123 124 # Step 9: new, valid Active Timestamp TLV 125 # all of valid Commissioner Dataset parameters plus one bogus TLV, and 126 # new values in the TLVs that don’t affect connectivity 127 # binary = new pskc and security policy [3600, 0b11111111] and BogusTLV=0x400 128 self.nodes[ROUTER].send_mgmt_active_set( 129 active_timestamp=101, 130 channel_mask=0xfff800, 131 extended_panid='000db80000000003', 132 mesh_local='fd00:0db8::', 133 network_name='TEST_3', 134 network_key='00112233445566778899aabbccddeeff', 135 panid=0xface, 136 channel=11, 137 binary='041008f4e9531e8efa8e852d5f4fb951b13e0c030e10ff8202aa55', 138 ) 139 self.simulator.go(5) 140 141 # Step 14: new, valid Active Timestamp TLV 142 # attempt to set Channel TLV to an unsupported channel + all of other TLVs 143 # binary = pskc and security policy step 9 144 self.nodes[ROUTER].send_mgmt_active_set( 145 active_timestamp=102, 146 channel_mask=0x1fff800, 147 extended_panid='000db80000000003', 148 mesh_local='fd00:0db8::', 149 network_name='TEST_3', 150 network_key='00112233445566778899aabbccddeeff', 151 panid=0xface, 152 channel=63, 153 binary='041008f4e9531e8efa8e852d5f4fb951b13e0c030e10f8', 154 ) 155 self.simulator.go(5) 156 157 ipaddr = self.nodes[LEADER].get_rloc() 158 self.assertTrue(self.nodes[ROUTER].ping(ipaddr)) 159 160 def verify(self, pv): 161 pkts = pv.pkts 162 pv.summary.show() 163 164 LEADER = pv.vars['LEADER'] 165 LEADER_RLOC = pv.vars['LEADER_RLOC'] 166 ROUTER = pv.vars['ROUTER'] 167 ROUTER_RLOC = pv.vars['ROUTER_RLOC'] 168 169 # Step 1: Ensure the topology is formed correctly 170 pv.verify_attached('ROUTER', 'LEADER') 171 _pkt = pkts.last() 172 173 # Step 3: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 174 # with the following format: 175 # CoAP Response Code 176 # 2.04 Changed 177 # CoAP Payload 178 # State TLV (value = Accept (01)) 179 pkts.filter_wpan_src64(LEADER).\ 180 filter_ipv6_dst(ROUTER_RLOC).\ 181 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 182 filter(lambda p: p.thread_meshcop.tlv.state == 1).\ 183 must_next() 184 185 # Step 4: Leader MUST send a multicast MLE Data Response, including 186 # the following TLVs: 187 # - Source Address TLV 188 # - Leader Data TLV 189 # Data version field [incremented] 190 # Stable Version field [incremented] 191 # - Network Data TLV 192 # - Active Timestamp TLV [new value set in Step 9] 193 _dr_pkt = pkts.filter_wpan_src64(LEADER).\ 194 filter_LLANMA().\ 195 filter_mle_cmd(MLE_DATA_RESPONSE).\ 196 filter(lambda p: { 197 NETWORK_DATA_TLV, 198 SOURCE_ADDRESS_TLV, 199 LEADER_DATA_TLV, 200 ACTIVE_TIMESTAMP_TLV 201 } <= set(p.mle.tlv.type) and\ 202 p.mle.tlv.active_tstamp == 100 and\ 203 (p.mle.tlv.leader_data.data_version - 204 _pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\ 205 (p.mle.tlv.leader_data.stable_data_version - 206 _pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 207 ).\ 208 must_next() 209 210 # Step 6: Leader MUST send a unicast MLE Data Response to Router, including 211 # the following TLVs: 212 # - Source Address TLV 213 # - Leader Data TLV 214 # - Active Operational Dataset TLV 215 # - Channel TLV 216 # - Channel Mask TLV [new value set in Step 2] 217 # - Extended PAN ID TLV [new value set in Step 2] 218 # - Network Mesh-Local Prefix TLV 219 # - Network Key TLV 220 # - Network Name TLV [new value set in Step 2] 221 # - PAN ID TLV 222 # - PSKc TLV [new value set in Step 2] 223 # - Security Policy TLV [new value set in Step 2] 224 # - Active Timestamp TLV [new value set in Step 2] 225 pkts.filter_wpan_src64(LEADER).\ 226 filter_wpan_dst64(ROUTER).\ 227 filter_mle_cmd(MLE_DATA_RESPONSE).\ 228 filter(lambda p: { 229 NETWORK_DATA_TLV, 230 SOURCE_ADDRESS_TLV, 231 LEADER_DATA_TLV, 232 ACTIVE_OPERATION_DATASET_TLV, 233 ACTIVE_TIMESTAMP_TLV 234 } <= set(p.mle.tlv.type) and\ 235 { 236 NM_CHANNEL_TLV, 237 NM_CHANNEL_MASK_TLV, 238 NM_EXTENDED_PAN_ID_TLV, 239 NM_NETWORK_MESH_LOCAL_PREFIX_TLV, 240 NM_NETWORK_KEY_TLV, 241 NM_NETWORK_NAME_TLV, 242 NM_PAN_ID_TLV, 243 NM_PSKC_TLV, 244 NM_SECURITY_POLICY_TLV 245 } <= set(p.thread_meshcop.tlv.type) and\ 246 p.mle.tlv.active_tstamp == 100 and\ 247 p.thread_meshcop.tlv.chan_mask_mask == '001fffc0' and\ 248 p.thread_meshcop.tlv.xpan_id == '000db80000000001' and\ 249 p.thread_meshcop.tlv.net_name == ['TEST_1'] and\ 250 p.thread_meshcop.tlv.pskc == 'd2aa9cd8dff7919122d77d37ec3c1b5f' 251 ).\ 252 must_next() 253 254 # Step 8: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 255 # with the following format: 256 # CoAP Response Code 257 # 2.04 Changed 258 # CoAP Payload 259 # State TLV (value = Reject (ff)) 260 pkts.filter_wpan_src64(LEADER).\ 261 filter_ipv6_dst(ROUTER_RLOC).\ 262 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 263 filter(lambda p: p.thread_meshcop.tlv.state == -1).\ 264 must_next() 265 266 # Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 267 # with the following format: 268 # CoAP Response Code 269 # 2.04 Changed 270 # CoAP Payload 271 # State TLV (value = Accept (01)) 272 pkts.filter_wpan_src64(LEADER).\ 273 filter_ipv6_dst(ROUTER_RLOC).\ 274 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 275 filter(lambda p: p.thread_meshcop.tlv.state == 1).\ 276 must_next() 277 278 # Step 11: Leader MUST send a multicast MLE Data Response, including 279 # the following TLVs: 280 # - Source Address TLV 281 # - Leader Data TLV 282 # Data version field [incremented] 283 # Stable Version field [incremented] 284 # - Network Data TLV 285 # - Active Timestamp TLV [new value set in Step 9] 286 pkts.filter_wpan_src64(LEADER).\ 287 filter_LLANMA().\ 288 filter_mle_cmd(MLE_DATA_RESPONSE).\ 289 filter(lambda p: { 290 NETWORK_DATA_TLV, 291 SOURCE_ADDRESS_TLV, 292 LEADER_DATA_TLV, 293 ACTIVE_TIMESTAMP_TLV 294 } <= set(p.mle.tlv.type) and\ 295 p.mle.tlv.active_tstamp == 101 and\ 296 (p.mle.tlv.leader_data.data_version - 297 _dr_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\ 298 (p.mle.tlv.leader_data.stable_data_version - 299 _dr_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 300 ).\ 301 must_next() 302 303 # Step 13: Leader MUST send a unicast MLE Data Response to Router, including 304 # the following TLVs: 305 # - Source Address TLV 306 # - Leader Data TLV 307 # - Active Operational Dataset TLV 308 # - Channel TLV 309 # - Channel Mask TLV [new value set in Step 9] 310 # - Extended PAN ID TLV [new value set in Step 9] 311 # - Network Mesh-Local Prefix TLV 312 # - Network Key TLV 313 # - Network Name TLV [new value set in Step 9] 314 # - PAN ID TLV 315 # - PSKc TLV [new value set in Step 9] 316 # - Security Policy TLV [new value set in Step 9] 317 # - Active Timestamp TLV [new value set in Step 9] 318 pkts.filter_wpan_src64(LEADER).\ 319 filter_wpan_dst64(ROUTER).\ 320 filter_mle_cmd(MLE_DATA_RESPONSE).\ 321 filter(lambda p: { 322 NETWORK_DATA_TLV, 323 SOURCE_ADDRESS_TLV, 324 LEADER_DATA_TLV, 325 ACTIVE_OPERATION_DATASET_TLV, 326 ACTIVE_TIMESTAMP_TLV 327 } <= set(p.mle.tlv.type) and\ 328 { 329 NM_CHANNEL_TLV, 330 NM_CHANNEL_MASK_TLV, 331 NM_EXTENDED_PAN_ID_TLV, 332 NM_NETWORK_MESH_LOCAL_PREFIX_TLV, 333 NM_NETWORK_KEY_TLV, 334 NM_NETWORK_NAME_TLV, 335 NM_PAN_ID_TLV, 336 NM_PSKC_TLV, 337 NM_SECURITY_POLICY_TLV 338 } <= set(p.thread_meshcop.tlv.type) and\ 339 p.mle.tlv.active_tstamp == 101 and\ 340 p.thread_meshcop.tlv.chan_mask_mask == '001fff00' and\ 341 p.thread_meshcop.tlv.xpan_id == '000db80000000003' and\ 342 p.thread_meshcop.tlv.net_name == ['TEST_3'] and\ 343 p.thread_meshcop.tlv.pskc == '08f4e9531e8efa8e852d5f4fb951b13e' 344 ).\ 345 must_next() 346 347 # Step 15: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 348 # with the following format: 349 # CoAP Response Code 350 # 2.04 Changed 351 # CoAP Payload 352 # State TLV (value = Reject (ff))) 353 pkts.filter_wpan_src64(LEADER).\ 354 filter_ipv6_dst(ROUTER_RLOC).\ 355 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 356 filter(lambda p: p.thread_meshcop.tlv.state == -1).\ 357 must_next() 358 359 # Step 16: The DUT must respond with an ICMPv6 Echo Reply 360 _pkt = pkts.filter_ping_request().\ 361 filter_ipv6_src_dst(ROUTER_RLOC, LEADER_RLOC).\ 362 must_next() 363 pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ 364 filter_ipv6_src_dst(LEADER_RLOC, ROUTER_RLOC).\ 365 must_next() 366 367 368if __name__ == '__main__': 369 unittest.main() 370