1 /*
2 * Copyright (c) 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 implements Thread Management Framework (TMF) functionalities.
32 */
33
34 #include "thread/tmf.hpp"
35
36 #include "common/locator_getters.hpp"
37 #include "net/ip6_types.hpp"
38
39 namespace ot {
40 namespace Tmf {
41
42 //----------------------------------------------------------------------------------------------------------------------
43 // MessageInfo
44
SetSockAddrToRloc(void)45 void MessageInfo::SetSockAddrToRloc(void) { SetSockAddr(Get<Mle::MleRouter>().GetMeshLocalRloc()); }
46
SetSockAddrToRlocPeerAddrToLeaderAloc(void)47 void MessageInfo::SetSockAddrToRlocPeerAddrToLeaderAloc(void)
48 {
49 SetSockAddrToRloc();
50 Get<Mle::MleRouter>().GetLeaderAloc(GetPeerAddr());
51 }
52
SetSockAddrToRlocPeerAddrToLeaderRloc(void)53 void MessageInfo::SetSockAddrToRlocPeerAddrToLeaderRloc(void)
54 {
55 SetSockAddrToRloc();
56 Get<Mle::MleRouter>().GetLeaderRloc(GetPeerAddr());
57 }
58
SetSockAddrToRlocPeerAddrToRealmLocalAllRoutersMulticast(void)59 void MessageInfo::SetSockAddrToRlocPeerAddrToRealmLocalAllRoutersMulticast(void)
60 {
61 SetSockAddrToRloc();
62 GetPeerAddr().SetToRealmLocalAllRoutersMulticast();
63 }
64
SetSockAddrToRlocPeerAddrTo(uint16_t aRloc16)65 void MessageInfo::SetSockAddrToRlocPeerAddrTo(uint16_t aRloc16)
66 {
67 SetSockAddrToRloc();
68 GetPeerAddr().SetToRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(), aRloc16);
69 }
70
SetSockAddrToRlocPeerAddrTo(const Ip6::Address & aPeerAddress)71 void MessageInfo::SetSockAddrToRlocPeerAddrTo(const Ip6::Address &aPeerAddress)
72 {
73 SetSockAddrToRloc();
74 SetPeerAddr(aPeerAddress);
75 }
76
77 //----------------------------------------------------------------------------------------------------------------------
78 // Agent
79
Agent(Instance & aInstance)80 Agent::Agent(Instance &aInstance)
81 : Coap::Coap(aInstance)
82 {
83 SetInterceptor(&Filter, this);
84 SetResourceHandler(&HandleResource);
85 }
86
Start(void)87 Error Agent::Start(void) { return Coap::Start(kUdpPort, Ip6::kNetifThread); }
88
HandleTmf(Message & aMessage,const Ip6::MessageInfo & aMessageInfo)89 template <> void Agent::HandleTmf<kUriRelayRx>(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
90 {
91 OT_UNUSED_VARIABLE(aMessage);
92 OT_UNUSED_VARIABLE(aMessageInfo);
93
94 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE)
95 Get<MeshCoP::Commissioner>().HandleTmf<kUriRelayRx>(aMessage, aMessageInfo);
96 #endif
97 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
98 Get<MeshCoP::BorderAgent>().HandleTmf<kUriRelayRx>(aMessage, aMessageInfo);
99 #endif
100 }
101
HandleResource(CoapBase & aCoapBase,const char * aUriPath,Message & aMessage,const Ip6::MessageInfo & aMessageInfo)102 bool Agent::HandleResource(CoapBase &aCoapBase,
103 const char *aUriPath,
104 Message &aMessage,
105 const Ip6::MessageInfo &aMessageInfo)
106 {
107 return static_cast<Agent &>(aCoapBase).HandleResource(aUriPath, aMessage, aMessageInfo);
108 }
109
HandleResource(const char * aUriPath,Message & aMessage,const Ip6::MessageInfo & aMessageInfo)110 bool Agent::HandleResource(const char *aUriPath, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
111 {
112 bool didHandle = true;
113 Uri uri = UriFromPath(aUriPath);
114
115 #define Case(kUri, Type) \
116 case kUri: \
117 Get<Type>().HandleTmf<kUri>(aMessage, aMessageInfo); \
118 break
119
120 switch (uri)
121 {
122 Case(kUriAddressError, AddressResolver);
123 Case(kUriEnergyScan, EnergyScanServer);
124 Case(kUriActiveGet, MeshCoP::ActiveDatasetManager);
125 Case(kUriPendingGet, MeshCoP::PendingDatasetManager);
126 Case(kUriPanIdQuery, PanIdQueryServer);
127
128 #if OPENTHREAD_FTD
129 Case(kUriAddressQuery, AddressResolver);
130 Case(kUriAddressNotify, AddressResolver);
131 Case(kUriAddressSolicit, Mle::MleRouter);
132 Case(kUriAddressRelease, Mle::MleRouter);
133 Case(kUriActiveSet, MeshCoP::ActiveDatasetManager);
134 Case(kUriActiveReplace, MeshCoP::ActiveDatasetManager);
135 Case(kUriPendingSet, MeshCoP::PendingDatasetManager);
136 Case(kUriLeaderPetition, MeshCoP::Leader);
137 Case(kUriLeaderKeepAlive, MeshCoP::Leader);
138 Case(kUriServerData, NetworkData::Leader);
139 Case(kUriCommissionerGet, NetworkData::Leader);
140 Case(kUriCommissionerSet, NetworkData::Leader);
141 Case(kUriAnnounceBegin, AnnounceBeginServer);
142 Case(kUriRelayTx, MeshCoP::JoinerRouter);
143 #endif
144
145 #if OPENTHREAD_CONFIG_JOINER_ENABLE
146 Case(kUriJoinerEntrust, MeshCoP::Joiner);
147 #endif
148
149 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
150 Case(kUriPanIdConflict, PanIdQueryClient);
151 Case(kUriEnergyReport, EnergyScanClient);
152 Case(kUriDatasetChanged, MeshCoP::Commissioner);
153 // kUriRelayRx is handled below
154 #endif
155
156 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE)
157 Case(kUriRelayRx, Agent);
158 #endif
159
160 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
161 Case(kUriDuaRegistrationNotify, DuaManager);
162 #endif
163
164 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
165 Case(kUriAnycastLocate, AnycastLocator);
166 #endif
167
168 Case(kUriDiagnosticGetRequest, NetworkDiagnostic::Server);
169 Case(kUriDiagnosticGetQuery, NetworkDiagnostic::Server);
170 Case(kUriDiagnosticReset, NetworkDiagnostic::Server);
171
172 #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE
173 Case(kUriDiagnosticGetAnswer, NetworkDiagnostic::Client);
174 #endif
175
176 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
177 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
178 Case(kUriMlr, BackboneRouter::Manager);
179 #endif
180 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
181 Case(kUriDuaRegistrationRequest, BackboneRouter::Manager);
182 #endif
183 #endif
184
185 default:
186 didHandle = false;
187 break;
188 }
189
190 #undef Case
191
192 return didHandle;
193 }
194
Filter(const Message & aMessage,const Ip6::MessageInfo & aMessageInfo,void * aContext)195 Error Agent::Filter(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
196 {
197 OT_UNUSED_VARIABLE(aMessage);
198
199 return static_cast<Agent *>(aContext)->IsTmfMessage(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(),
200 aMessageInfo.GetSockPort())
201 ? kErrorNone
202 : kErrorNotTmf;
203 }
204
IsTmfMessage(const Ip6::Address & aSourceAddress,const Ip6::Address & aDestAddress,uint16_t aDestPort) const205 bool Agent::IsTmfMessage(const Ip6::Address &aSourceAddress, const Ip6::Address &aDestAddress, uint16_t aDestPort) const
206 {
207 bool isTmf = false;
208
209 VerifyOrExit(aDestPort == kUdpPort);
210
211 if (aSourceAddress.IsLinkLocalUnicast())
212 {
213 isTmf = aDestAddress.IsLinkLocalUnicastOrMulticast();
214 ExitNow();
215 }
216
217 VerifyOrExit(Get<Mle::Mle>().IsMeshLocalAddress(aSourceAddress));
218 VerifyOrExit(Get<Mle::Mle>().IsMeshLocalAddress(aDestAddress) || aDestAddress.IsLinkLocalMulticast() ||
219 aDestAddress.IsRealmLocalMulticast());
220
221 isTmf = true;
222
223 exit:
224 return isTmf;
225 }
226
PriorityToDscp(Message::Priority aPriority)227 uint8_t Agent::PriorityToDscp(Message::Priority aPriority)
228 {
229 uint8_t dscp = Ip6::kDscpTmfNormalPriority;
230
231 switch (aPriority)
232 {
233 case Message::kPriorityNet:
234 dscp = Ip6::kDscpTmfNetPriority;
235 break;
236
237 case Message::kPriorityHigh:
238 case Message::kPriorityNormal:
239 break;
240
241 case Message::kPriorityLow:
242 dscp = Ip6::kDscpTmfLowPriority;
243 break;
244 }
245
246 return dscp;
247 }
248
DscpToPriority(uint8_t aDscp)249 Message::Priority Agent::DscpToPriority(uint8_t aDscp)
250 {
251 Message::Priority priority = Message::kPriorityNet;
252
253 // If the sender does not use TMF specific DSCP value, we use
254 // `kPriorityNet`. This ensures that senders that do not use the
255 // new value (older firmware) experience the same behavior as
256 // before where all TMF message were treated as `kPriorityNet`.
257
258 switch (aDscp)
259 {
260 case Ip6::kDscpTmfNetPriority:
261 default:
262 break;
263 case Ip6::kDscpTmfNormalPriority:
264 priority = Message::kPriorityNormal;
265 break;
266 case Ip6::kDscpTmfLowPriority:
267 priority = Message::kPriorityLow;
268 break;
269 }
270
271 return priority;
272 }
273
274 #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
275
SecureAgent(Instance & aInstance)276 SecureAgent::SecureAgent(Instance &aInstance)
277 : Coap::CoapSecure(aInstance)
278 {
279 SetResourceHandler(&HandleResource);
280 }
281
HandleResource(CoapBase & aCoapBase,const char * aUriPath,Message & aMessage,const Ip6::MessageInfo & aMessageInfo)282 bool SecureAgent::HandleResource(CoapBase &aCoapBase,
283 const char *aUriPath,
284 Message &aMessage,
285 const Ip6::MessageInfo &aMessageInfo)
286 {
287 return static_cast<SecureAgent &>(aCoapBase).HandleResource(aUriPath, aMessage, aMessageInfo);
288 }
289
HandleResource(const char * aUriPath,Message & aMessage,const Ip6::MessageInfo & aMessageInfo)290 bool SecureAgent::HandleResource(const char *aUriPath, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
291 {
292 OT_UNUSED_VARIABLE(aMessage);
293 OT_UNUSED_VARIABLE(aMessageInfo);
294
295 bool didHandle = true;
296 Uri uri = UriFromPath(aUriPath);
297
298 #define Case(kUri, Type) \
299 case kUri: \
300 Get<Type>().HandleTmf<kUri>(aMessage, aMessageInfo); \
301 break
302
303 switch (uri)
304 {
305 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
306 Case(kUriJoinerFinalize, MeshCoP::Commissioner);
307 #endif
308
309 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
310 Case(kUriCommissionerPetition, MeshCoP::BorderAgent);
311 Case(kUriCommissionerKeepAlive, MeshCoP::BorderAgent);
312 Case(kUriRelayTx, MeshCoP::BorderAgent);
313 Case(kUriCommissionerGet, MeshCoP::BorderAgent);
314 Case(kUriActiveGet, MeshCoP::BorderAgent);
315 Case(kUriPendingGet, MeshCoP::BorderAgent);
316 Case(kUriProxyTx, MeshCoP::BorderAgent);
317 #endif
318
319 default:
320 didHandle = false;
321 break;
322 }
323
324 #undef Case
325
326 return didHandle;
327 }
328
329 #endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
330
331 } // namespace Tmf
332 } // namespace ot
333