1 /*
2  *  Copyright (c) 2016-2020, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for MLE Discover Scan process.
32  */
33 
34 #ifndef DISCOVER_SCANNER_HPP_
35 #define DISCOVER_SCANNER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/callback.hpp"
40 #include "common/locator.hpp"
41 #include "common/non_copyable.hpp"
42 #include "common/tasklet.hpp"
43 #include "common/timer.hpp"
44 #include "mac/channel_mask.hpp"
45 #include "mac/mac.hpp"
46 #include "mac/mac_types.hpp"
47 #include "meshcop/meshcop.hpp"
48 #include "thread/mle.hpp"
49 
50 namespace ot {
51 
52 class MeshForwarder;
53 
54 namespace Mle {
55 
56 /**
57  * This class implements MLE Discover Scan.
58  *
59  */
60 class DiscoverScanner : public InstanceLocator, private NonCopyable
61 {
62     friend class ot::Instance;
63     friend class ot::MeshForwarder;
64     friend class Mle;
65 
66 public:
67     /**
68      * Default scan duration (per channel), in milliseconds.
69      *
70      */
71     static constexpr uint32_t kDefaultScanDuration = Mac::kScanDurationDefault;
72 
73     /**
74      * This type represents Discover Scan result.
75      *
76      */
77     typedef otActiveScanResult ScanResult;
78 
79     /**
80      * This type represents the handler function pointer called with any Discover Scan result or when the scan
81      * completes.
82      *
83      * The handler function format is `void (*oHandler)(ScanResult *aResult, void *aContext);`. End of scan is
84      * indicated by `aResult` pointer being set to `nullptr`.
85      *
86      */
87     typedef otHandleActiveScanResult Handler;
88 
89     /**
90      * This type represents the filter indexes, i.e., hash bit index values for the bloom filter (calculated from a
91      * Joiner ID).
92      *
93      * This is used when filtering is enabled during Discover Scan, i.e., received MLE Discovery Responses with steering
94      * data (bloom filter) not containing the given indexes are filtered.
95      *
96      */
97     typedef MeshCoP::SteeringData::HashBitIndexes FilterIndexes;
98 
99     /**
100      * This constructor initializes the object.
101      *
102      * @param[in]  aInstance     A reference to the OpenThread instance.
103      *
104      */
105     explicit DiscoverScanner(Instance &aInstance);
106 
107     /**
108      * This method starts a Thread Discovery Scan.
109      *
110      * @param[in]  aScanChannels      Channel mask listing channels to scan (if empty, use all supported channels).
111      * @param[in]  aPanId             The PAN ID filter (set to Broadcast PAN to disable filter).
112      * @param[in]  aJoiner            Value of the Joiner Flag in the Discovery Request TLV.
113      * @param[in]  aEnableFiltering   Enable filtering MLE Discovery Responses with steering data not containing a
114      *                                given filter indexes.
115      * @param[in]  aFilterIndexes     A pointer to `FilterIndexes` to use for filtering (when enabled).
116      *                                If set to `nullptr`, filter indexes are derived from hash of factory-assigned
117      *                                EUI64.
118      * @param[in]  aCallback          A pointer to a function that is called on receiving an MLE Discovery Response.
119      * @param[in]  aContext           A pointer to arbitrary context information.
120      *
121      * @retval kErrorNone           Successfully started a Thread Discovery Scan.
122      * @retval kErrorInvalidState   The IPv6 interface is not enabled (netif is not up).
123      * @retval kErrorNoBufs         Could not allocate message for Discovery Request.
124      * @retval kErrorBusy           Thread Discovery Scan is already in progress.
125      *
126      */
127     Error Discover(const Mac::ChannelMask &aScanChannels,
128                    Mac::PanId              aPanId,
129                    bool                    aJoiner,
130                    bool                    aEnableFiltering,
131                    const FilterIndexes    *aFilterIndexes,
132                    Handler                 aCallback,
133                    void                   *aContext);
134 
135     /**
136      * This method indicates whether or not an MLE Thread Discovery Scan is currently in progress.
137      *
138      * @returns true if an MLE Thread Discovery Scan is in progress, false otherwise.
139      *
140      */
IsInProgress(void) const141     bool IsInProgress(void) const { return (mState != kStateIdle); }
142 
143     /**
144      * This method sets Joiner Advertisement.
145      *
146      * @param[in]  aOui             The Vendor OUI for Joiner Advertisement.
147      * @param[in]  aAdvData         A pointer to AdvData for Joiner Advertisement.
148      * @param[in]  aAdvDataLength   The length of AdvData.
149      *
150      * @retval kErrorNone           Successfully set Joiner Advertisement.
151      * @retval kErrorInvalidArgs    Invalid AdvData.
152      *
153      */
154     Error SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength);
155 
156 private:
157     enum State : uint8_t
158     {
159         kStateIdle,
160         kStateScanning,
161         kStateScanDone,
162     };
163 
164     static constexpr uint32_t kMaxOui = 0xffffff;
165 
166     // Methods used by `MeshForwarder`
167     Mac::TxFrame *PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame);
168     void          HandleDiscoveryRequestFrameTxDone(Message &aMessage);
Stop(void)169     void          Stop(void) { HandleDiscoverComplete(); }
170 
171     // Methods used from `Mle`
172     void HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const;
173 
174     void HandleDiscoverComplete(void);
175     void HandleScanDoneTask(void);
176     void HandleTimer(void);
177 
178     using ScanTimer    = TimerMilliIn<DiscoverScanner, &DiscoverScanner::HandleTimer>;
179     using ScanDoneTask = TaskletIn<DiscoverScanner, &DiscoverScanner::HandleScanDoneTask>;
180 
181     Callback<Handler> mCallback;
182     ScanDoneTask      mScanDoneTask;
183     ScanTimer         mTimer;
184     FilterIndexes     mFilterIndexes;
185     Mac::ChannelMask  mScanChannels;
186     State             mState;
187     uint32_t          mOui;
188     uint8_t           mScanChannel;
189     uint8_t           mAdvDataLength;
190     uint8_t           mAdvData[MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength];
191     bool              mEnableFiltering : 1;
192     bool              mShouldRestorePanId : 1;
193 };
194 
195 } // namespace Mle
196 } // namespace ot
197 
198 #endif // DISCOVER_SCANNER_HPP_
199