/src/openthread/src/core/meshcop/border_agent.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2018, 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 the BorderAgent service. |
32 | | */ |
33 | | |
34 | | #include "border_agent.hpp" |
35 | | |
36 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE |
37 | | |
38 | | #include "instance/instance.hpp" |
39 | | |
40 | | namespace ot { |
41 | | namespace MeshCoP { |
42 | | |
43 | | RegisterLogModule("BorderAgent"); |
44 | | |
45 | | //---------------------------------------------------------------------------------------------------------------------- |
46 | | // `BorderAgent` |
47 | | |
48 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
49 | | const char BorderAgent::kServiceType[] = "_meshcop._udp"; |
50 | | const char BorderAgent::kDefaultBaseServiceName[] = OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME; |
51 | | #endif |
52 | | |
53 | | BorderAgent::BorderAgent(Instance &aInstance) |
54 | 21.3k | : InstanceLocator(aInstance) |
55 | 21.3k | , mEnabled(true) |
56 | 21.3k | , mIsRunning(false) |
57 | 21.3k | , mDtlsTransport(aInstance, kNoLinkSecurity) |
58 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE |
59 | 21.3k | , mIdInitialized(false) |
60 | | #endif |
61 | 21.3k | , mServiceTask(aInstance) |
62 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
63 | | , mEphemeralKeyManager(aInstance) |
64 | | #endif |
65 | 21.3k | { |
66 | 21.3k | ClearAllBytes(mCounters); |
67 | | |
68 | 21.3k | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
69 | 21.3k | ClearAllBytes(mServiceName); |
70 | 21.3k | PostServiceTask(); |
71 | | |
72 | 21.3k | static_assert(sizeof(kDefaultBaseServiceName) - 1 <= kBaseServiceNameMaxLen, |
73 | 21.3k | "OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME is too long"); |
74 | 21.3k | #endif |
75 | 21.3k | } |
76 | | |
77 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE |
78 | | Error BorderAgent::GetId(Id &aId) |
79 | 3.77k | { |
80 | 3.77k | Error error = kErrorNone; |
81 | | |
82 | 3.77k | if (mIdInitialized) |
83 | 3.69k | { |
84 | 3.69k | aId = mId; |
85 | 3.69k | ExitNow(); |
86 | 3.69k | } |
87 | | |
88 | 78 | if (Get<Settings>().Read<Settings::BorderAgentId>(mId) != kErrorNone) |
89 | 78 | { |
90 | 78 | mId.GenerateRandom(); |
91 | 78 | SuccessOrExit(error = Get<Settings>().Save<Settings::BorderAgentId>(mId)); |
92 | 78 | } |
93 | | |
94 | 78 | mIdInitialized = true; |
95 | 78 | aId = mId; |
96 | | |
97 | 3.77k | exit: |
98 | 3.77k | return error; |
99 | 78 | } |
100 | | |
101 | | Error BorderAgent::SetId(const Id &aId) |
102 | 0 | { |
103 | 0 | Error error = kErrorNone; |
104 | |
|
105 | 0 | if (mIdInitialized) |
106 | 0 | { |
107 | 0 | VerifyOrExit(aId != mId); |
108 | 0 | } |
109 | | |
110 | 0 | SuccessOrExit(error = Get<Settings>().Save<Settings::BorderAgentId>(aId)); |
111 | 0 | mId = aId; |
112 | 0 | mIdInitialized = true; |
113 | 0 | PostServiceTask(); |
114 | |
|
115 | 0 | exit: |
116 | 0 | return error; |
117 | 0 | } |
118 | | #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE |
119 | | |
120 | | void BorderAgent::SetEnabled(bool aEnabled) |
121 | 0 | { |
122 | 0 | VerifyOrExit(mEnabled != aEnabled); |
123 | 0 | mEnabled = aEnabled; |
124 | 0 | LogInfo("%sabling Border Agent", mEnabled ? "En" : "Dis"); |
125 | 0 | UpdateState(); |
126 | |
|
127 | 0 | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
128 | 0 | if (!mEnabled) |
129 | 0 | { |
130 | 0 | UnregisterService(); |
131 | 0 | } |
132 | 0 | #endif |
133 | |
|
134 | 0 | exit: |
135 | 0 | return; |
136 | 0 | } |
137 | | |
138 | | void BorderAgent::UpdateState(void) |
139 | 21.3k | { |
140 | 21.3k | if (mEnabled && Get<Mle::Mle>().IsAttached()) |
141 | 0 | { |
142 | 0 | Start(); |
143 | 0 | } |
144 | 21.3k | else |
145 | 21.3k | { |
146 | 21.3k | Stop(); |
147 | 21.3k | } |
148 | 21.3k | } |
149 | | |
150 | | void BorderAgent::Start(void) |
151 | 0 | { |
152 | 0 | Error error = kErrorNone; |
153 | 0 | Pskc pskc; |
154 | |
|
155 | 0 | VerifyOrExit(!mIsRunning); |
156 | | |
157 | 0 | mDtlsTransport.SetAcceptCallback(BorderAgent::HandleAcceptSession, this); |
158 | 0 | mDtlsTransport.SetRemoveSessionCallback(BorderAgent::HandleRemoveSession, this); |
159 | |
|
160 | 0 | SuccessOrExit(error = mDtlsTransport.Open()); |
161 | 0 | SuccessOrExit(error = mDtlsTransport.Bind(kUdpPort)); |
162 | | |
163 | 0 | Get<KeyManager>().GetPskc(pskc); |
164 | 0 | SuccessOrExit(error = mDtlsTransport.SetPsk(pskc.m8, Pskc::kSize)); |
165 | 0 | pskc.Clear(); |
166 | |
|
167 | 0 | mIsRunning = true; |
168 | 0 | PostServiceTask(); |
169 | |
|
170 | 0 | LogInfo("Border Agent start listening on port %u", GetUdpPort()); |
171 | |
|
172 | 0 | exit: |
173 | 0 | if (!mIsRunning) |
174 | 0 | { |
175 | 0 | mDtlsTransport.Close(); |
176 | 0 | } |
177 | |
|
178 | 0 | LogWarnOnError(error, "start agent"); |
179 | 0 | } |
180 | | |
181 | | void BorderAgent::Stop(void) |
182 | 21.3k | { |
183 | 21.3k | VerifyOrExit(mIsRunning); |
184 | | |
185 | 0 | mDtlsTransport.Close(); |
186 | 0 | mIsRunning = false; |
187 | 0 | PostServiceTask(); |
188 | |
|
189 | 0 | LogInfo("Border Agent stopped"); |
190 | |
|
191 | 21.3k | exit: |
192 | 21.3k | return; |
193 | 0 | } |
194 | | |
195 | 3.58k | uint16_t BorderAgent::GetUdpPort(void) const { return mDtlsTransport.GetUdpPort(); } |
196 | | |
197 | | void BorderAgent::SetServiceChangedCallback(ServiceChangedCallback aCallback, void *aContext) |
198 | 21.3k | { |
199 | 21.3k | mServiceChangedCallback.Set(aCallback, aContext); |
200 | | |
201 | 21.3k | PostServiceTask(); |
202 | 21.3k | } |
203 | | |
204 | | void BorderAgent::HandleNotifierEvents(Events aEvents) |
205 | 21.3k | { |
206 | 21.3k | if (aEvents.Contains(kEventThreadRoleChanged)) |
207 | 21.3k | { |
208 | 21.3k | UpdateState(); |
209 | 21.3k | } |
210 | | |
211 | 21.3k | VerifyOrExit(mEnabled); |
212 | | |
213 | 21.3k | if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadExtPanIdChanged | kEventThreadNetworkNameChanged | |
214 | 21.3k | kEventThreadBackboneRouterStateChanged | kEventActiveDatasetChanged)) |
215 | 21.3k | { |
216 | 21.3k | PostServiceTask(); |
217 | 21.3k | } |
218 | | |
219 | 21.3k | if (aEvents.ContainsAny(kEventPskcChanged)) |
220 | 0 | { |
221 | 0 | Pskc pskc; |
222 | |
|
223 | 0 | VerifyOrExit(mIsRunning); |
224 | | |
225 | 0 | Get<KeyManager>().GetPskc(pskc); |
226 | | |
227 | | // If there is secure session already established, it won't be impacted, |
228 | | // new pskc will be applied for next connection. |
229 | 0 | SuccessOrExit(mDtlsTransport.SetPsk(pskc.m8, Pskc::kSize)); |
230 | 0 | pskc.Clear(); |
231 | 0 | } |
232 | | |
233 | 21.3k | exit: |
234 | 21.3k | return; |
235 | 21.3k | } |
236 | | |
237 | | SecureSession *BorderAgent::HandleAcceptSession(void *aContext, const Ip6::MessageInfo &aMessageInfo) |
238 | 0 | { |
239 | 0 | OT_UNUSED_VARIABLE(aMessageInfo); |
240 | |
|
241 | 0 | return static_cast<BorderAgent *>(aContext)->HandleAcceptSession(); |
242 | 0 | } |
243 | | |
244 | | BorderAgent::CoapDtlsSession *BorderAgent::HandleAcceptSession(void) |
245 | 0 | { |
246 | 0 | return CoapDtlsSession::Allocate(GetInstance(), mDtlsTransport); |
247 | 0 | } |
248 | | |
249 | | void BorderAgent::HandleRemoveSession(void *aContext, SecureSession &aSession) |
250 | 0 | { |
251 | 0 | static_cast<BorderAgent *>(aContext)->HandleRemoveSession(aSession); |
252 | 0 | } |
253 | | |
254 | | void BorderAgent::HandleRemoveSession(SecureSession &aSession) |
255 | 0 | { |
256 | 0 | CoapDtlsSession &coapSession = static_cast<CoapDtlsSession &>(aSession); |
257 | |
|
258 | 0 | coapSession.Cleanup(); |
259 | 0 | coapSession.Free(); |
260 | 0 | } |
261 | | |
262 | | void BorderAgent::HandleSessionConnected(CoapDtlsSession &aSession) |
263 | 0 | { |
264 | 0 | OT_UNUSED_VARIABLE(aSession); |
265 | |
|
266 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
267 | | if (mEphemeralKeyManager.OwnsSession(aSession)) |
268 | | { |
269 | | mEphemeralKeyManager.HandleSessionConnected(); |
270 | | } |
271 | | else |
272 | | #endif |
273 | 0 | { |
274 | 0 | mCounters.mPskcSecureSessionSuccesses++; |
275 | 0 | } |
276 | 0 | } |
277 | | |
278 | | void BorderAgent::HandleSessionDisconnected(CoapDtlsSession &aSession, CoapDtlsSession::ConnectEvent aEvent) |
279 | 0 | { |
280 | 0 | OT_UNUSED_VARIABLE(aSession); |
281 | |
|
282 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
283 | | if (mEphemeralKeyManager.OwnsSession(aSession)) |
284 | | { |
285 | | mEphemeralKeyManager.HandleSessionDisconnected(aEvent); |
286 | | } |
287 | | else |
288 | | #endif |
289 | 0 | { |
290 | 0 | if (aEvent == CoapDtlsSession::kDisconnectedError) |
291 | 0 | { |
292 | 0 | mCounters.mPskcSecureSessionFailures++; |
293 | 0 | } |
294 | 0 | } |
295 | 0 | } |
296 | | |
297 | | void BorderAgent::HandleCommissionerPetitionAccepted(CoapDtlsSession &aSession) |
298 | 0 | { |
299 | 0 | OT_UNUSED_VARIABLE(aSession); |
300 | |
|
301 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
302 | | if (mEphemeralKeyManager.OwnsSession(aSession)) |
303 | | { |
304 | | mEphemeralKeyManager.HandleCommissionerPetitionAccepted(); |
305 | | } |
306 | | else |
307 | | #endif |
308 | 0 | { |
309 | 0 | mCounters.mPskcCommissionerPetitions++; |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | | BorderAgent::CoapDtlsSession *BorderAgent::FindActiveCommissionerSession(void) |
314 | 0 | { |
315 | 0 | CoapDtlsSession *commissionerSession = nullptr; |
316 | |
|
317 | 0 | for (SecureSession &session : mDtlsTransport.GetSessions()) |
318 | 0 | { |
319 | 0 | CoapDtlsSession &coapSession = static_cast<CoapDtlsSession &>(session); |
320 | |
|
321 | 0 | if (coapSession.IsActiveCommissioner()) |
322 | 0 | { |
323 | 0 | commissionerSession = &coapSession; |
324 | 0 | break; |
325 | 0 | } |
326 | 0 | } |
327 | |
|
328 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
329 | | if ((mEphemeralKeyManager.mCoapDtlsSession != nullptr) && |
330 | | mEphemeralKeyManager.mCoapDtlsSession->IsActiveCommissioner()) |
331 | | { |
332 | | commissionerSession = mEphemeralKeyManager.mCoapDtlsSession; |
333 | | } |
334 | | #endif |
335 | |
|
336 | 0 | return commissionerSession; |
337 | 0 | } |
338 | | |
339 | | Coap::Message::Code BorderAgent::CoapCodeFromError(Error aError) |
340 | 0 | { |
341 | 0 | Coap::Message::Code code; |
342 | |
|
343 | 0 | switch (aError) |
344 | 0 | { |
345 | 0 | case kErrorNone: |
346 | 0 | code = Coap::kCodeChanged; |
347 | 0 | break; |
348 | | |
349 | 0 | case kErrorParse: |
350 | 0 | code = Coap::kCodeBadRequest; |
351 | 0 | break; |
352 | | |
353 | 0 | default: |
354 | 0 | code = Coap::kCodeInternalError; |
355 | 0 | break; |
356 | 0 | } |
357 | | |
358 | 0 | return code; |
359 | 0 | } |
360 | | |
361 | | template <> void BorderAgent::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) |
362 | 196 | { |
363 | | // This is from TMF agent. |
364 | | |
365 | 196 | OT_UNUSED_VARIABLE(aMessageInfo); |
366 | | |
367 | 196 | Coap::Message *message = nullptr; |
368 | 196 | Error error = kErrorNone; |
369 | 196 | CoapDtlsSession *session; |
370 | | |
371 | 196 | VerifyOrExit(mIsRunning); |
372 | | |
373 | 0 | VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorDrop); |
374 | | |
375 | 0 | session = FindActiveCommissionerSession(); |
376 | 0 | VerifyOrExit(session != nullptr); |
377 | | |
378 | 0 | message = session->NewPriorityNonConfirmablePostMessage(kUriRelayRx); |
379 | 0 | VerifyOrExit(message != nullptr, error = kErrorNoBufs); |
380 | | |
381 | 0 | SuccessOrExit(error = session->ForwardToCommissioner(*message, aMessage)); |
382 | 0 | LogInfo("Sent to commissioner on RelayRx (c/rx)"); |
383 | |
|
384 | 196 | exit: |
385 | 196 | FreeMessageOnError(message, error); |
386 | 196 | } |
387 | | |
388 | | void BorderAgent::PostServiceTask(void) |
389 | 63.9k | { |
390 | 63.9k | VerifyOrExit(mEnabled); |
391 | | |
392 | | #if !OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
393 | | VerifyOrExit(mServiceChangedCallback.IsSet()); |
394 | | #endif |
395 | | |
396 | 63.9k | mServiceTask.Post(); |
397 | | |
398 | 63.9k | exit: |
399 | 63.9k | return; |
400 | 63.9k | } |
401 | | |
402 | | void BorderAgent::HandleServiceTask(void) |
403 | 21.3k | { |
404 | 21.3k | VerifyOrExit(mEnabled); |
405 | | |
406 | 21.3k | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
407 | 21.3k | RegisterService(); |
408 | 21.3k | #endif |
409 | 21.3k | mServiceChangedCallback.InvokeIfSet(); |
410 | | |
411 | 21.3k | exit: |
412 | 21.3k | return; |
413 | 21.3k | } |
414 | | |
415 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
416 | | |
417 | | Error BorderAgent::SetServiceBaseName(const char *aBaseName) |
418 | 0 | { |
419 | 0 | Error error = kErrorNone; |
420 | 0 | Dns::Name::LabelBuffer newName; |
421 | |
|
422 | 0 | VerifyOrExit(StringLength(aBaseName, kBaseServiceNameMaxLen + 1) <= kBaseServiceNameMaxLen, |
423 | 0 | error = kErrorInvalidArgs); |
424 | | |
425 | 0 | ConstrcutServiceName(aBaseName, newName); |
426 | |
|
427 | 0 | VerifyOrExit(!StringMatch(newName, mServiceName)); |
428 | | |
429 | 0 | UnregisterService(); |
430 | 0 | IgnoreError(StringCopy(mServiceName, newName)); |
431 | 0 | RegisterService(); |
432 | |
|
433 | 0 | exit: |
434 | 0 | return error; |
435 | 0 | } |
436 | | |
437 | | const char *BorderAgent::GetServiceName(void) |
438 | 0 | { |
439 | 0 | if (IsServiceNameEmpty()) |
440 | 0 | { |
441 | 0 | ConstrcutServiceName(kDefaultBaseServiceName, mServiceName); |
442 | 0 | } |
443 | |
|
444 | 0 | return mServiceName; |
445 | 0 | } |
446 | | |
447 | | void BorderAgent::ConstrcutServiceName(const char *aBaseName, Dns::Name::LabelBuffer &aNameBuffer) |
448 | 0 | { |
449 | 0 | StringWriter writer(aNameBuffer, sizeof(Dns::Name::LabelBuffer)); |
450 | |
|
451 | 0 | writer.Append("%.*s%s", kBaseServiceNameMaxLen, aBaseName, Get<Mac::Mac>().GetExtAddress().ToString().AsCString()); |
452 | 0 | } |
453 | | |
454 | | void BorderAgent::RegisterService(void) |
455 | 21.3k | { |
456 | 21.3k | ServiceTxtData txtData; |
457 | 21.3k | Dnssd::Service service; |
458 | | |
459 | 21.3k | VerifyOrExit(Get<Dnssd>().IsReady()); |
460 | | |
461 | 0 | SuccessOrAssert(PrepareServiceTxtData(txtData)); |
462 | | |
463 | 0 | service.Clear(); |
464 | 0 | service.mServiceInstance = GetServiceName(); |
465 | 0 | service.mServiceType = kServiceType; |
466 | 0 | service.mPort = IsRunning() ? GetUdpPort() : kDummyUdpPort; |
467 | 0 | service.mTxtData = txtData.mData; |
468 | 0 | service.mTxtDataLength = txtData.mLength; |
469 | |
|
470 | 0 | Get<Dnssd>().RegisterService(service, /* aRequestId */ 0, /* aCallback */ nullptr); |
471 | |
|
472 | 21.3k | exit: |
473 | 21.3k | return; |
474 | 0 | } |
475 | | |
476 | | void BorderAgent::UnregisterService(void) |
477 | 0 | { |
478 | 0 | Dnssd::Service service; |
479 | |
|
480 | 0 | VerifyOrExit(Get<Dnssd>().IsReady()); |
481 | 0 | VerifyOrExit(!IsServiceNameEmpty()); |
482 | | |
483 | 0 | service.Clear(); |
484 | 0 | service.mServiceInstance = GetServiceName(); |
485 | 0 | service.mServiceType = kServiceType; |
486 | |
|
487 | 0 | Get<Dnssd>().UnregisterService(service, /* aRequestId */ 0, /* aCallback */ nullptr); |
488 | |
|
489 | 0 | exit: |
490 | 0 | return; |
491 | 0 | } |
492 | | |
493 | | #endif // OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
494 | | |
495 | | Error BorderAgent::PrepareServiceTxtData(ServiceTxtData &aTxtData) |
496 | 3.77k | { |
497 | 3.77k | Error error = kErrorNone; |
498 | 3.77k | Dns::TxtDataEncoder encoder(aTxtData.mData, sizeof(aTxtData.mData)); |
499 | | |
500 | 3.77k | #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE |
501 | 3.77k | { |
502 | 3.77k | Id id; |
503 | | |
504 | 3.77k | if (GetId(id) == kErrorNone) |
505 | 3.77k | { |
506 | 3.77k | SuccessOrExit(error = encoder.AppendEntry("id", id)); |
507 | 3.77k | } |
508 | 3.77k | } |
509 | 3.77k | #endif |
510 | 3.77k | SuccessOrExit(error = encoder.AppendNameEntry("nn", Get<NetworkNameManager>().GetNetworkName().GetAsData())); |
511 | 3.77k | SuccessOrExit(error = encoder.AppendEntry("xp", Get<ExtendedPanIdManager>().GetExtPanId())); |
512 | 3.77k | SuccessOrExit(error = encoder.AppendStringEntry("tv", kThreadVersionString)); |
513 | 3.77k | SuccessOrExit(error = encoder.AppendEntry("xa", Get<Mac::Mac>().GetExtAddress())); |
514 | 3.77k | SuccessOrExit(error = encoder.AppendBigEndianUintEntry("sb", DetermineStateBitmap())); |
515 | | |
516 | 3.77k | if (Get<Mle::Mle>().IsAttached()) |
517 | 0 | { |
518 | 0 | SuccessOrExit(error = encoder.AppendBigEndianUintEntry("pt", Get<Mle::Mle>().GetLeaderData().GetPartitionId())); |
519 | | |
520 | 0 | if (Get<MeshCoP::ActiveDatasetManager>().GetTimestamp().IsValid()) |
521 | 0 | { |
522 | 0 | SuccessOrExit(error = encoder.AppendEntry("at", Get<MeshCoP::ActiveDatasetManager>().GetTimestamp())); |
523 | 0 | } |
524 | 0 | } |
525 | | |
526 | | #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE |
527 | | if (Get<Mle::Mle>().IsAttached() && Get<BackboneRouter::Local>().IsEnabled()) |
528 | | { |
529 | | BackboneRouter::Config bbrConfig; |
530 | | |
531 | | Get<BackboneRouter::Local>().GetConfig(bbrConfig); |
532 | | SuccessOrExit(error = encoder.AppendEntry("sq", bbrConfig.mSequenceNumber)); |
533 | | SuccessOrExit(error = encoder.AppendBigEndianUintEntry("bb", BackboneRouter::kBackboneUdpPort)); |
534 | | } |
535 | | |
536 | | SuccessOrExit(error = |
537 | | encoder.AppendNameEntry("dn", Get<MeshCoP::NetworkNameManager>().GetDomainName().GetAsData())); |
538 | | #endif |
539 | | |
540 | 3.77k | #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE |
541 | 3.77k | { |
542 | 3.77k | Ip6::Prefix prefix; |
543 | 3.77k | BorderRouter::RoutingManager::RoutePreference preference; |
544 | | |
545 | 3.77k | if (Get<BorderRouter::RoutingManager>().GetFavoredOmrPrefix(prefix, preference) == kErrorNone && |
546 | 3.77k | prefix.GetLength() > 0) |
547 | 0 | { |
548 | 0 | uint8_t omrData[Ip6::NetworkPrefix::kSize + 1]; |
549 | |
|
550 | 0 | omrData[0] = prefix.GetLength(); |
551 | 0 | memcpy(omrData + 1, prefix.GetBytes(), prefix.GetBytesSize()); |
552 | |
|
553 | 0 | SuccessOrExit(error = encoder.AppendEntry("omr", omrData)); |
554 | 0 | } |
555 | 3.77k | } |
556 | 3.77k | #endif |
557 | | |
558 | 3.77k | aTxtData.mLength = encoder.GetLength(); |
559 | | |
560 | 3.77k | exit: |
561 | 3.77k | return error; |
562 | 3.77k | } |
563 | | |
564 | | uint32_t BorderAgent::DetermineStateBitmap(void) const |
565 | 3.77k | { |
566 | 3.77k | uint32_t bitmap = 0; |
567 | | |
568 | 3.77k | bitmap |= (IsRunning() ? StateBitmap::kConnectionModePskc : StateBitmap::kConnectionModeDisabled); |
569 | 3.77k | bitmap |= StateBitmap::kAvailabilityHigh; |
570 | | |
571 | 3.77k | switch (Get<Mle::Mle>().GetRole()) |
572 | 3.77k | { |
573 | 420 | case Mle::DeviceRole::kRoleDisabled: |
574 | 420 | bitmap |= (StateBitmap::kThreadIfStatusNotInitialized | StateBitmap::kThreadRoleDisabledOrDetached); |
575 | 420 | break; |
576 | 3.35k | case Mle::DeviceRole::kRoleDetached: |
577 | 3.35k | bitmap |= (StateBitmap::kThreadIfStatusInitialized | StateBitmap::kThreadRoleDisabledOrDetached); |
578 | 3.35k | break; |
579 | 0 | case Mle::DeviceRole::kRoleChild: |
580 | 0 | bitmap |= (StateBitmap::kThreadIfStatusActive | StateBitmap::kThreadRoleChild); |
581 | 0 | break; |
582 | 0 | case Mle::DeviceRole::kRoleRouter: |
583 | 0 | bitmap |= (StateBitmap::kThreadIfStatusActive | StateBitmap::kThreadRoleRouter); |
584 | 0 | break; |
585 | 0 | case Mle::DeviceRole::kRoleLeader: |
586 | 0 | bitmap |= (StateBitmap::kThreadIfStatusActive | StateBitmap::kThreadRoleLeader); |
587 | 0 | break; |
588 | 3.77k | } |
589 | | |
590 | | #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE |
591 | | if (Get<Mle::Mle>().IsAttached()) |
592 | | { |
593 | | bitmap |= (Get<BackboneRouter::Local>().IsEnabled() ? StateBitmap::kFlagBbrIsActive : 0); |
594 | | bitmap |= (Get<BackboneRouter::Local>().IsPrimary() ? StateBitmap::kFlagBbrIsPrimary : 0); |
595 | | } |
596 | | #endif |
597 | | |
598 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
599 | | if (mEphemeralKeyManager.GetState() != EphemeralKeyManager::kStateDisabled) |
600 | | { |
601 | | bitmap |= StateBitmap::kFlagEpskcSupported; |
602 | | } |
603 | | #endif |
604 | | |
605 | 3.77k | return bitmap; |
606 | 3.77k | } |
607 | | |
608 | | //---------------------------------------------------------------------------------------------------------------------- |
609 | | // BorderAgent::SessionIterator |
610 | | |
611 | | void BorderAgent::SessionIterator::Init(Instance &aInstance) |
612 | 0 | { |
613 | 0 | SetSession(static_cast<CoapDtlsSession *>(aInstance.Get<BorderAgent>().mDtlsTransport.GetSessions().GetHead())); |
614 | 0 | SetInitTime(aInstance.Get<Uptime>().GetUptime()); |
615 | 0 | } |
616 | | |
617 | | Error BorderAgent::SessionIterator::GetNextSessionInfo(SessionInfo &aSessionInfo) |
618 | 0 | { |
619 | 0 | Error error = kErrorNone; |
620 | 0 | CoapDtlsSession *session = GetSession(); |
621 | |
|
622 | 0 | VerifyOrExit(session != nullptr, error = kErrorNotFound); |
623 | | |
624 | 0 | SetSession(static_cast<CoapDtlsSession *>(session->GetNext())); |
625 | |
|
626 | 0 | aSessionInfo.mPeerSockAddr.mAddress = session->GetMessageInfo().GetPeerAddr(); |
627 | 0 | aSessionInfo.mPeerSockAddr.mPort = session->GetMessageInfo().GetPeerPort(); |
628 | 0 | aSessionInfo.mIsConnected = session->IsConnected(); |
629 | 0 | aSessionInfo.mIsCommissioner = session->IsActiveCommissioner(); |
630 | 0 | aSessionInfo.mLifetime = GetInitTime() - session->GetAllocationTime(); |
631 | |
|
632 | 0 | exit: |
633 | 0 | return error; |
634 | 0 | } |
635 | | |
636 | | //---------------------------------------------------------------------------------------------------------------------- |
637 | | // BorderAgent::EphemeralKeyManager |
638 | | |
639 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
640 | | |
641 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
642 | | const char BorderAgent::EphemeralKeyManager::kServiceType[] = "_meshcop-e._udp"; |
643 | | #endif |
644 | | |
645 | | BorderAgent::EphemeralKeyManager::EphemeralKeyManager(Instance &aInstance) |
646 | | : InstanceLocator(aInstance) |
647 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_FEATURE_ENABLED_BY_DEFAULT |
648 | | , mState(kStateStopped) |
649 | | #else |
650 | | , mState(kStateDisabled) |
651 | | #endif |
652 | | , mDtlsTransport(aInstance, kNoLinkSecurity) |
653 | | , mCoapDtlsSession(nullptr) |
654 | | , mTimer(aInstance) |
655 | | , mCallbackTask(aInstance) |
656 | | { |
657 | | } |
658 | | |
659 | | void BorderAgent::EphemeralKeyManager::SetEnabled(bool aEnabled) |
660 | | { |
661 | | if (aEnabled) |
662 | | { |
663 | | VerifyOrExit(mState == kStateDisabled); |
664 | | SetState(kStateStopped); |
665 | | Get<BorderAgent>().PostServiceTask(); |
666 | | } |
667 | | else |
668 | | { |
669 | | VerifyOrExit(mState != kStateDisabled); |
670 | | Stop(); |
671 | | SetState(kStateDisabled); |
672 | | Get<BorderAgent>().PostServiceTask(); |
673 | | } |
674 | | |
675 | | exit: |
676 | | return; |
677 | | } |
678 | | |
679 | | Error BorderAgent::EphemeralKeyManager::Start(const char *aKeyString, uint32_t aTimeout, uint16_t aUdpPort) |
680 | | { |
681 | | Error error = kErrorNone; |
682 | | uint16_t length; |
683 | | |
684 | | VerifyOrExit(mState == kStateStopped, error = kErrorInvalidState); |
685 | | |
686 | | length = StringLength(aKeyString, kMaxKeyLength + 1); |
687 | | VerifyOrExit((length >= kMinKeyLength) && (length <= kMaxKeyLength), error = kErrorInvalidArgs); |
688 | | |
689 | | IgnoreError(mDtlsTransport.SetMaxConnectionAttempts(kMaxConnectionAttempts, HandleTransportClosed, this)); |
690 | | |
691 | | mDtlsTransport.SetAcceptCallback(EphemeralKeyManager::HandleAcceptSession, this); |
692 | | mDtlsTransport.SetRemoveSessionCallback(EphemeralKeyManager::HandleRemoveSession, this); |
693 | | |
694 | | SuccessOrExit(error = mDtlsTransport.Open()); |
695 | | SuccessOrExit(error = mDtlsTransport.Bind(aUdpPort)); |
696 | | |
697 | | SuccessOrExit( |
698 | | error = mDtlsTransport.SetPsk(reinterpret_cast<const uint8_t *>(aKeyString), static_cast<uint8_t>(length))); |
699 | | |
700 | | aTimeout = Min((aTimeout == 0) ? kDefaultTimeout : aTimeout, kMaxTimeout); |
701 | | mTimer.Start(aTimeout); |
702 | | |
703 | | LogInfo("Allow ephemeral key for %lu msec on port %u", ToUlong(aTimeout), GetUdpPort()); |
704 | | |
705 | | SetState(kStateStarted); |
706 | | |
707 | | exit: |
708 | | switch (error) |
709 | | { |
710 | | case kErrorNone: |
711 | | Get<BorderAgent>().mCounters.mEpskcActivations++; |
712 | | break; |
713 | | case kErrorInvalidState: |
714 | | Get<BorderAgent>().mCounters.mEpskcInvalidBaStateErrors++; |
715 | | break; |
716 | | case kErrorInvalidArgs: |
717 | | Get<BorderAgent>().mCounters.mEpskcInvalidArgsErrors++; |
718 | | break; |
719 | | default: |
720 | | Get<BorderAgent>().mCounters.mEpskcStartSecureSessionErrors++; |
721 | | break; |
722 | | } |
723 | | |
724 | | return error; |
725 | | } |
726 | | |
727 | | void BorderAgent::EphemeralKeyManager::Stop(void) { Stop(kReasonLocalDisconnect); } |
728 | | |
729 | | void BorderAgent::EphemeralKeyManager::Stop(StopReason aReason) |
730 | | { |
731 | | switch (mState) |
732 | | { |
733 | | case kStateStarted: |
734 | | case kStateConnected: |
735 | | case kStateAccepted: |
736 | | break; |
737 | | case kStateDisabled: |
738 | | case kStateStopped: |
739 | | ExitNow(); |
740 | | } |
741 | | |
742 | | LogInfo("Stopping ephemeral key use - reason: %s", StopReasonToString(aReason)); |
743 | | SetState(kStateStopped); |
744 | | |
745 | | mTimer.Stop(); |
746 | | mDtlsTransport.Close(); |
747 | | |
748 | | switch (aReason) |
749 | | { |
750 | | case kReasonLocalDisconnect: |
751 | | Get<BorderAgent>().mCounters.mEpskcDeactivationClears++; |
752 | | break; |
753 | | case kReasonPeerDisconnect: |
754 | | Get<BorderAgent>().mCounters.mEpskcDeactivationDisconnects++; |
755 | | break; |
756 | | case kReasonSessionError: |
757 | | Get<BorderAgent>().mCounters.mEpskcStartSecureSessionErrors++; |
758 | | break; |
759 | | case kReasonMaxFailedAttempts: |
760 | | Get<BorderAgent>().mCounters.mEpskcDeactivationMaxAttempts++; |
761 | | break; |
762 | | case kReasonTimeout: |
763 | | Get<BorderAgent>().mCounters.mEpskcDeactivationTimeouts++; |
764 | | break; |
765 | | case kReasonUnknown: |
766 | | break; |
767 | | } |
768 | | |
769 | | exit: |
770 | | return; |
771 | | } |
772 | | |
773 | | void BorderAgent::EphemeralKeyManager::SetState(State aState) |
774 | | { |
775 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
776 | | bool isServiceRegistered = ShouldRegisterService(); |
777 | | #endif |
778 | | |
779 | | VerifyOrExit(mState != aState); |
780 | | LogInfo("Ephemeral key - state: %s -> %s", StateToString(mState), StateToString(aState)); |
781 | | mState = aState; |
782 | | mCallbackTask.Post(); |
783 | | |
784 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
785 | | VerifyOrExit(isServiceRegistered != ShouldRegisterService()); |
786 | | RegisterOrUnregisterService(); |
787 | | #endif |
788 | | |
789 | | exit: |
790 | | return; |
791 | | } |
792 | | |
793 | | SecureSession *BorderAgent::EphemeralKeyManager::HandleAcceptSession(void *aContext, |
794 | | const Ip6::MessageInfo &aMessageInfo) |
795 | | { |
796 | | OT_UNUSED_VARIABLE(aMessageInfo); |
797 | | |
798 | | return static_cast<EphemeralKeyManager *>(aContext)->HandleAcceptSession(); |
799 | | } |
800 | | |
801 | | BorderAgent::CoapDtlsSession *BorderAgent::EphemeralKeyManager::HandleAcceptSession(void) |
802 | | { |
803 | | CoapDtlsSession *session = nullptr; |
804 | | |
805 | | VerifyOrExit(mCoapDtlsSession == nullptr); |
806 | | |
807 | | session = CoapDtlsSession::Allocate(GetInstance(), mDtlsTransport); |
808 | | VerifyOrExit(session != nullptr); |
809 | | |
810 | | mCoapDtlsSession = session; |
811 | | |
812 | | exit: |
813 | | return session; |
814 | | } |
815 | | |
816 | | void BorderAgent::EphemeralKeyManager::HandleRemoveSession(void *aContext, SecureSession &aSession) |
817 | | { |
818 | | static_cast<EphemeralKeyManager *>(aContext)->HandleRemoveSession(aSession); |
819 | | } |
820 | | |
821 | | void BorderAgent::EphemeralKeyManager::HandleRemoveSession(SecureSession &aSession) |
822 | | { |
823 | | CoapDtlsSession &coapSession = static_cast<CoapDtlsSession &>(aSession); |
824 | | |
825 | | coapSession.Cleanup(); |
826 | | coapSession.Free(); |
827 | | mCoapDtlsSession = nullptr; |
828 | | } |
829 | | |
830 | | void BorderAgent::EphemeralKeyManager::HandleSessionConnected(void) |
831 | | { |
832 | | SetState(kStateConnected); |
833 | | Get<BorderAgent>().mCounters.mEpskcSecureSessionSuccesses++; |
834 | | } |
835 | | |
836 | | void BorderAgent::EphemeralKeyManager::HandleSessionDisconnected(SecureSession::ConnectEvent aEvent) |
837 | | { |
838 | | StopReason reason = kReasonUnknown; |
839 | | |
840 | | // The ephemeral key can be used once |
841 | | |
842 | | VerifyOrExit((mState == kStateConnected) || (mState == kStateAccepted)); |
843 | | |
844 | | switch (aEvent) |
845 | | { |
846 | | case SecureSession::kDisconnectedError: |
847 | | reason = kReasonSessionError; |
848 | | break; |
849 | | case SecureSession::kDisconnectedPeerClosed: |
850 | | reason = kReasonPeerDisconnect; |
851 | | break; |
852 | | case SecureSession::kDisconnectedMaxAttempts: |
853 | | reason = kReasonMaxFailedAttempts; |
854 | | break; |
855 | | default: |
856 | | break; |
857 | | } |
858 | | |
859 | | Stop(reason); |
860 | | |
861 | | exit: |
862 | | return; |
863 | | } |
864 | | |
865 | | void BorderAgent::EphemeralKeyManager::HandleCommissionerPetitionAccepted(void) |
866 | | { |
867 | | SetState(kStateAccepted); |
868 | | Get<BorderAgent>().mCounters.mEpskcCommissionerPetitions++; |
869 | | } |
870 | | |
871 | | void BorderAgent::EphemeralKeyManager::HandleTimer(void) { Stop(kReasonTimeout); } |
872 | | |
873 | | void BorderAgent::EphemeralKeyManager::HandleTask(void) { mCallback.InvokeIfSet(); } |
874 | | |
875 | | void BorderAgent::EphemeralKeyManager::HandleTransportClosed(void *aContext) |
876 | | { |
877 | | reinterpret_cast<EphemeralKeyManager *>(aContext)->HandleTransportClosed(); |
878 | | } |
879 | | |
880 | | void BorderAgent::EphemeralKeyManager::HandleTransportClosed(void) |
881 | | { |
882 | | Stop(kReasonMaxFailedAttempts); |
883 | | ; |
884 | | } |
885 | | |
886 | | #if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
887 | | |
888 | | bool BorderAgent::EphemeralKeyManager::ShouldRegisterService(void) const |
889 | | { |
890 | | bool shouldRegister = false; |
891 | | |
892 | | switch (mState) |
893 | | { |
894 | | case kStateDisabled: |
895 | | case kStateStopped: |
896 | | break; |
897 | | case kStateStarted: |
898 | | case kStateConnected: |
899 | | case kStateAccepted: |
900 | | shouldRegister = true; |
901 | | break; |
902 | | } |
903 | | |
904 | | return shouldRegister; |
905 | | } |
906 | | |
907 | | void BorderAgent::EphemeralKeyManager::RegisterOrUnregisterService(void) |
908 | | { |
909 | | Dnssd::Service service; |
910 | | |
911 | | VerifyOrExit(Get<Dnssd>().IsReady()); |
912 | | |
913 | | service.Clear(); |
914 | | service.mServiceInstance = Get<BorderAgent>().GetServiceName(); |
915 | | service.mServiceType = kServiceType; |
916 | | service.mPort = GetUdpPort(); |
917 | | |
918 | | if (ShouldRegisterService()) |
919 | | { |
920 | | Get<Dnssd>().RegisterService(service, /* aRequestId */ 0, /* aCallback */ nullptr); |
921 | | } |
922 | | else |
923 | | { |
924 | | Get<Dnssd>().UnregisterService(service, /* aRequestId */ 0, /* aCallback */ nullptr); |
925 | | } |
926 | | |
927 | | exit: |
928 | | return; |
929 | | } |
930 | | |
931 | | #endif // OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE |
932 | | |
933 | | const char *BorderAgent::EphemeralKeyManager::StateToString(State aState) |
934 | | { |
935 | | static const char *const kStateStrings[] = { |
936 | | "Disabled", // (0) kStateDisabled |
937 | | "Stopped", // (1) kStateStopped |
938 | | "Started", // (2) kStateStarted |
939 | | "Connected", // (3) kStateConnected |
940 | | "Accepted", // (4) kStateAccepted |
941 | | }; |
942 | | |
943 | | struct EnumCheck |
944 | | { |
945 | | InitEnumValidatorCounter(); |
946 | | ValidateNextEnum(kStateDisabled); |
947 | | ValidateNextEnum(kStateStopped); |
948 | | ValidateNextEnum(kStateStarted); |
949 | | ValidateNextEnum(kStateConnected); |
950 | | ValidateNextEnum(kStateAccepted); |
951 | | }; |
952 | | |
953 | | return kStateStrings[aState]; |
954 | | } |
955 | | |
956 | | #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) |
957 | | |
958 | | const char *BorderAgent::EphemeralKeyManager::StopReasonToString(StopReason aReason) |
959 | | { |
960 | | static const char *const kReasonStrings[] = { |
961 | | "LocalDisconnect", // (0) kReasonLocalDisconnect |
962 | | "PeerDisconnect", // (1) kReasonPeerDisconnect |
963 | | "SessionError", // (2) kReasonSessionError |
964 | | "MaxFailedAttempts", // (3) kReasonMaxFailedAttempts |
965 | | "Timeout", // (4) kReasonTimeout |
966 | | "Unknown", // (5) kReasonUnknown |
967 | | }; |
968 | | |
969 | | struct EnumCheck |
970 | | { |
971 | | InitEnumValidatorCounter(); |
972 | | ValidateNextEnum(kReasonLocalDisconnect); |
973 | | ValidateNextEnum(kReasonPeerDisconnect); |
974 | | ValidateNextEnum(kReasonSessionError); |
975 | | ValidateNextEnum(kReasonMaxFailedAttempts); |
976 | | ValidateNextEnum(kReasonTimeout); |
977 | | ValidateNextEnum(kReasonUnknown); |
978 | | }; |
979 | | |
980 | | return kReasonStrings[aReason]; |
981 | | } |
982 | | |
983 | | #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) |
984 | | |
985 | | #endif // OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE |
986 | | |
987 | | //---------------------------------------------------------------------------------------------------------------------- |
988 | | // `BorderAgent::CoapDtlsSession |
989 | | |
990 | | BorderAgent::CoapDtlsSession::CoapDtlsSession(Instance &aInstance, Dtls::Transport &aDtlsTransport) |
991 | 0 | : Coap::SecureSession(aInstance, aDtlsTransport) |
992 | 0 | , mIsActiveCommissioner(false) |
993 | 0 | , mTimer(aInstance, HandleTimer, this) |
994 | 0 | , mUdpReceiver(HandleUdpReceive, this) |
995 | 0 | , mAllocationTime(aInstance.Get<Uptime>().GetUptime()) |
996 | 0 | { |
997 | 0 | mCommissionerAloc.InitAsThreadOriginMeshLocal(); |
998 | |
|
999 | 0 | SetResourceHandler(&HandleResource); |
1000 | 0 | SetConnectCallback(&HandleConnected, this); |
1001 | 0 | } |
1002 | | |
1003 | | void BorderAgent::CoapDtlsSession::Cleanup(void) |
1004 | 0 | { |
1005 | 0 | while (!mForwardContexts.IsEmpty()) |
1006 | 0 | { |
1007 | 0 | ForwardContext *forwardContext = mForwardContexts.Pop(); |
1008 | |
|
1009 | 0 | IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleCoapResponse, forwardContext)); |
1010 | 0 | } |
1011 | |
|
1012 | 0 | mTimer.Stop(); |
1013 | 0 | IgnoreError(Get<Ip6::Udp>().RemoveReceiver(mUdpReceiver)); |
1014 | 0 | Get<ThreadNetif>().RemoveUnicastAddress(mCommissionerAloc); |
1015 | |
|
1016 | 0 | Coap::SecureSession::Cleanup(); |
1017 | 0 | } |
1018 | | |
1019 | | bool BorderAgent::CoapDtlsSession::HandleResource(CoapBase &aCoapBase, |
1020 | | const char *aUriPath, |
1021 | | Coap::Message &aMessage, |
1022 | | const Ip6::MessageInfo &aMessageInfo) |
1023 | 0 | { |
1024 | 0 | return static_cast<CoapDtlsSession &>(aCoapBase).HandleResource(aUriPath, aMessage, aMessageInfo); |
1025 | 0 | } |
1026 | | |
1027 | | bool BorderAgent::CoapDtlsSession::HandleResource(const char *aUriPath, |
1028 | | Coap::Message &aMessage, |
1029 | | const Ip6::MessageInfo &aMessageInfo) |
1030 | 0 | { |
1031 | 0 | bool didHandle = true; |
1032 | 0 | Uri uri = UriFromPath(aUriPath); |
1033 | |
|
1034 | 0 | switch (uri) |
1035 | 0 | { |
1036 | 0 | case kUriCommissionerPetition: |
1037 | 0 | IgnoreError(ForwardToLeader(aMessage, aMessageInfo, kUriLeaderPetition)); |
1038 | 0 | break; |
1039 | 0 | case kUriCommissionerKeepAlive: |
1040 | 0 | HandleTmfCommissionerKeepAlive(aMessage, aMessageInfo); |
1041 | 0 | break; |
1042 | 0 | case kUriRelayTx: |
1043 | 0 | HandleTmfRelayTx(aMessage); |
1044 | 0 | break; |
1045 | 0 | case kUriCommissionerGet: |
1046 | 0 | case kUriActiveGet: |
1047 | 0 | case kUriPendingGet: |
1048 | 0 | HandleTmfDatasetGet(aMessage, uri); |
1049 | 0 | break; |
1050 | 0 | case kUriProxyTx: |
1051 | 0 | HandleTmfProxyTx(aMessage); |
1052 | 0 | break; |
1053 | 0 | default: |
1054 | 0 | didHandle = false; |
1055 | 0 | break; |
1056 | 0 | } |
1057 | | |
1058 | 0 | return didHandle; |
1059 | 0 | } |
1060 | | |
1061 | | void BorderAgent::CoapDtlsSession::HandleConnected(ConnectEvent aEvent, void *aContext) |
1062 | 0 | { |
1063 | 0 | static_cast<CoapDtlsSession *>(aContext)->HandleConnected(aEvent); |
1064 | 0 | } |
1065 | | |
1066 | | void BorderAgent::CoapDtlsSession::HandleConnected(ConnectEvent aEvent) |
1067 | 0 | { |
1068 | 0 | if (aEvent == kConnected) |
1069 | 0 | { |
1070 | 0 | LogInfo("SecureSession connected"); |
1071 | 0 | mTimer.Start(kKeepAliveTimeout); |
1072 | 0 | Get<BorderAgent>().HandleSessionConnected(*this); |
1073 | 0 | } |
1074 | 0 | else |
1075 | 0 | { |
1076 | 0 | LogInfo("SecureSession disconnected"); |
1077 | 0 | IgnoreError(Get<Ip6::Udp>().RemoveReceiver(mUdpReceiver)); |
1078 | 0 | Get<ThreadNetif>().RemoveUnicastAddress(mCommissionerAloc); |
1079 | |
|
1080 | 0 | Get<BorderAgent>().HandleSessionDisconnected(*this, aEvent); |
1081 | 0 | } |
1082 | 0 | } |
1083 | | |
1084 | | void BorderAgent::CoapDtlsSession::HandleTmfCommissionerKeepAlive(Coap::Message &aMessage, |
1085 | | const Ip6::MessageInfo &aMessageInfo) |
1086 | 0 | { |
1087 | 0 | VerifyOrExit(mIsActiveCommissioner); |
1088 | 0 | SuccessOrExit(ForwardToLeader(aMessage, aMessageInfo, kUriLeaderKeepAlive)); |
1089 | 0 | mTimer.Start(kKeepAliveTimeout); |
1090 | |
|
1091 | 0 | exit: |
1092 | 0 | return; |
1093 | 0 | } |
1094 | | |
1095 | | Error BorderAgent::CoapDtlsSession::ForwardToLeader(const Coap::Message &aMessage, |
1096 | | const Ip6::MessageInfo &aMessageInfo, |
1097 | | Uri aUri) |
1098 | 0 | { |
1099 | 0 | Error error = kErrorNone; |
1100 | 0 | OwnedPtr<ForwardContext> forwardContext; |
1101 | 0 | Tmf::MessageInfo messageInfo(GetInstance()); |
1102 | 0 | Coap::Message *message = nullptr; |
1103 | 0 | bool petition = false; |
1104 | 0 | bool separate = false; |
1105 | 0 | OffsetRange offsetRange; |
1106 | |
|
1107 | 0 | switch (aUri) |
1108 | 0 | { |
1109 | 0 | case kUriLeaderPetition: |
1110 | 0 | petition = true; |
1111 | 0 | separate = true; |
1112 | 0 | break; |
1113 | 0 | case kUriLeaderKeepAlive: |
1114 | 0 | separate = true; |
1115 | 0 | break; |
1116 | 0 | default: |
1117 | 0 | break; |
1118 | 0 | } |
1119 | | |
1120 | 0 | if (separate) |
1121 | 0 | { |
1122 | 0 | SuccessOrExit(error = SendAck(aMessage, aMessageInfo)); |
1123 | 0 | } |
1124 | | |
1125 | 0 | forwardContext.Reset(ForwardContext::Allocate(*this, aMessage, petition, separate)); |
1126 | 0 | VerifyOrExit(!forwardContext.IsNull(), error = kErrorNoBufs); |
1127 | | |
1128 | 0 | message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(aUri); |
1129 | 0 | VerifyOrExit(message != nullptr, error = kErrorNoBufs); |
1130 | | |
1131 | 0 | offsetRange.InitFromMessageOffsetToEnd(aMessage); |
1132 | 0 | SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange)); |
1133 | | |
1134 | 0 | messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc(); |
1135 | 0 | messageInfo.SetSockPortToTmf(); |
1136 | |
|
1137 | 0 | SuccessOrExit(error = |
1138 | 0 | Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleCoapResponse, forwardContext.Get())); |
1139 | | |
1140 | | // Release the ownership of `forwardContext` since `SendMessage()` |
1141 | | // will own it. We take back ownership from `HandleCoapResponse()` |
1142 | | // callback. |
1143 | | |
1144 | 0 | mForwardContexts.Push(*forwardContext.Release()); |
1145 | |
|
1146 | 0 | LogInfo("Forwarded request to leader on %s", PathForUri(aUri)); |
1147 | |
|
1148 | 0 | exit: |
1149 | 0 | LogWarnOnError(error, "forward to leader"); |
1150 | |
|
1151 | 0 | if (error != kErrorNone) |
1152 | 0 | { |
1153 | 0 | FreeMessage(message); |
1154 | 0 | SendErrorMessage(aMessage, separate, error); |
1155 | 0 | } |
1156 | |
|
1157 | 0 | return error; |
1158 | 0 | } |
1159 | | |
1160 | | void BorderAgent::CoapDtlsSession::HandleCoapResponse(void *aContext, |
1161 | | otMessage *aMessage, |
1162 | | const otMessageInfo *aMessageInfo, |
1163 | | otError aResult) |
1164 | 0 | { |
1165 | 0 | OT_UNUSED_VARIABLE(aMessageInfo); |
1166 | |
|
1167 | 0 | OwnedPtr<ForwardContext> forwardContext(static_cast<ForwardContext *>(aContext)); |
1168 | |
|
1169 | 0 | forwardContext->mSession.HandleCoapResponse(*forwardContext.Get(), AsCoapMessagePtr(aMessage), aResult); |
1170 | 0 | } |
1171 | | |
1172 | | void BorderAgent::CoapDtlsSession::HandleCoapResponse(const ForwardContext &aForwardContext, |
1173 | | const Coap::Message *aResponse, |
1174 | | Error aResult) |
1175 | 0 | { |
1176 | 0 | Coap::Message *message = nullptr; |
1177 | 0 | Error error; |
1178 | |
|
1179 | 0 | IgnoreError(mForwardContexts.Remove(aForwardContext)); |
1180 | |
|
1181 | 0 | SuccessOrExit(error = aResult); |
1182 | 0 | VerifyOrExit((message = NewPriorityMessage()) != nullptr, error = kErrorNoBufs); |
1183 | | |
1184 | 0 | if (aForwardContext.mPetition && aResponse->GetCode() == Coap::kCodeChanged) |
1185 | 0 | { |
1186 | 0 | uint8_t state; |
1187 | |
|
1188 | 0 | SuccessOrExit(error = Tlv::Find<StateTlv>(*aResponse, state)); |
1189 | | |
1190 | 0 | if (state == StateTlv::kAccept) |
1191 | 0 | { |
1192 | 0 | uint16_t sessionId; |
1193 | |
|
1194 | 0 | SuccessOrExit(error = Tlv::Find<CommissionerSessionIdTlv>(*aResponse, sessionId)); |
1195 | | |
1196 | 0 | Get<Mle::Mle>().GetCommissionerAloc(sessionId, mCommissionerAloc.GetAddress()); |
1197 | 0 | Get<ThreadNetif>().AddUnicastAddress(mCommissionerAloc); |
1198 | 0 | IgnoreError(Get<Ip6::Udp>().AddReceiver(mUdpReceiver)); |
1199 | 0 | mIsActiveCommissioner = true; |
1200 | 0 | Get<BorderAgent>().HandleCommissionerPetitionAccepted(*this); |
1201 | |
|
1202 | 0 | LogInfo("Commissioner accepted - SessionId:%u ALOC:%s", sessionId, |
1203 | 0 | mCommissionerAloc.GetAddress().ToString().AsCString()); |
1204 | 0 | } |
1205 | 0 | else |
1206 | 0 | { |
1207 | 0 | LogInfo("Commissioner rejected"); |
1208 | 0 | } |
1209 | 0 | } |
1210 | | |
1211 | 0 | SuccessOrExit(error = aForwardContext.ToHeader(*message, aResponse->GetCode())); |
1212 | | |
1213 | 0 | if (aResponse->GetLength() > aResponse->GetOffset()) |
1214 | 0 | { |
1215 | 0 | SuccessOrExit(error = message->SetPayloadMarker()); |
1216 | 0 | } |
1217 | | |
1218 | 0 | SuccessOrExit(error = ForwardToCommissioner(*message, *aResponse)); |
1219 | | |
1220 | 0 | exit: |
1221 | |
|
1222 | 0 | if (error != kErrorNone) |
1223 | 0 | { |
1224 | 0 | FreeMessage(message); |
1225 | |
|
1226 | 0 | LogWarn("Commissioner request[%u] failed: %s", aForwardContext.mMessageId, ErrorToString(error)); |
1227 | |
|
1228 | 0 | SendErrorMessage(aForwardContext, error); |
1229 | 0 | } |
1230 | 0 | } |
1231 | | |
1232 | | bool BorderAgent::CoapDtlsSession::HandleUdpReceive(void *aContext, |
1233 | | const otMessage *aMessage, |
1234 | | const otMessageInfo *aMessageInfo) |
1235 | 0 | { |
1236 | 0 | return static_cast<CoapDtlsSession *>(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo)); |
1237 | 0 | } |
1238 | | |
1239 | | bool BorderAgent::CoapDtlsSession::HandleUdpReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) |
1240 | 0 | { |
1241 | 0 | Error error = kErrorNone; |
1242 | 0 | Coap::Message *message = nullptr; |
1243 | 0 | bool didHandle = false; |
1244 | 0 | ExtendedTlv extTlv; |
1245 | 0 | UdpEncapsulationTlvHeader udpEncapHeader; |
1246 | 0 | OffsetRange offsetRange; |
1247 | |
|
1248 | 0 | VerifyOrExit(aMessageInfo.GetSockAddr() == mCommissionerAloc.GetAddress()); |
1249 | | |
1250 | 0 | didHandle = true; |
1251 | |
|
1252 | 0 | VerifyOrExit(aMessage.GetLength() > 0); |
1253 | | |
1254 | 0 | message = NewPriorityNonConfirmablePostMessage(kUriProxyRx); |
1255 | 0 | VerifyOrExit(message != nullptr, error = kErrorNoBufs); |
1256 | | |
1257 | 0 | offsetRange.InitFromMessageOffsetToEnd(aMessage); |
1258 | |
|
1259 | 0 | extTlv.SetType(Tlv::kUdpEncapsulation); |
1260 | 0 | extTlv.SetLength(sizeof(UdpEncapsulationTlvHeader) + offsetRange.GetLength()); |
1261 | |
|
1262 | 0 | udpEncapHeader.SetSourcePort(aMessageInfo.GetPeerPort()); |
1263 | 0 | udpEncapHeader.SetDestinationPort(aMessageInfo.GetSockPort()); |
1264 | |
|
1265 | 0 | SuccessOrExit(error = message->Append(extTlv)); |
1266 | 0 | SuccessOrExit(error = message->Append(udpEncapHeader)); |
1267 | 0 | SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange)); |
1268 | | |
1269 | 0 | SuccessOrExit(error = Tlv::Append<Ip6AddressTlv>(*message, aMessageInfo.GetPeerAddr())); |
1270 | | |
1271 | 0 | SuccessOrExit(error = SendMessage(*message)); |
1272 | | |
1273 | 0 | LogInfo("Sent ProxyRx (c/ur) to commissioner"); |
1274 | |
|
1275 | 0 | exit: |
1276 | 0 | FreeMessageOnError(message, error); |
1277 | 0 | LogWarnOnError(error, "send ProxyRx (c/ur)"); |
1278 | |
|
1279 | 0 | return didHandle; |
1280 | 0 | } |
1281 | | |
1282 | | Error BorderAgent::CoapDtlsSession::ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage) |
1283 | 0 | { |
1284 | 0 | Error error = kErrorNone; |
1285 | 0 | OffsetRange offsetRange; |
1286 | |
|
1287 | 0 | offsetRange.InitFromMessageOffsetToEnd(aMessage); |
1288 | 0 | SuccessOrExit(error = aForwardMessage.AppendBytesFromMessage(aMessage, offsetRange)); |
1289 | | |
1290 | 0 | SuccessOrExit(error = SendMessage(aForwardMessage)); |
1291 | | |
1292 | 0 | LogInfo("Sent to commissioner"); |
1293 | |
|
1294 | 0 | exit: |
1295 | 0 | LogWarnOnError(error, "send to commissioner"); |
1296 | 0 | return error; |
1297 | 0 | } |
1298 | | |
1299 | | void BorderAgent::CoapDtlsSession::SendErrorMessage(const ForwardContext &aForwardContext, Error aError) |
1300 | 0 | { |
1301 | 0 | Error error = kErrorNone; |
1302 | 0 | Coap::Message *message = nullptr; |
1303 | |
|
1304 | 0 | VerifyOrExit((message = NewPriorityMessage()) != nullptr, error = kErrorNoBufs); |
1305 | 0 | SuccessOrExit(error = aForwardContext.ToHeader(*message, CoapCodeFromError(aError))); |
1306 | 0 | SuccessOrExit(error = SendMessage(*message)); |
1307 | | |
1308 | 0 | exit: |
1309 | 0 | FreeMessageOnError(message, error); |
1310 | 0 | LogWarnOnError(error, "send error CoAP message"); |
1311 | 0 | } |
1312 | | |
1313 | | void BorderAgent::CoapDtlsSession::SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, Error aError) |
1314 | 0 | { |
1315 | 0 | Error error = kErrorNone; |
1316 | 0 | Coap::Message *message = nullptr; |
1317 | |
|
1318 | 0 | VerifyOrExit((message = NewPriorityMessage()) != nullptr, error = kErrorNoBufs); |
1319 | | |
1320 | 0 | if (aRequest.IsNonConfirmable() || aSeparate) |
1321 | 0 | { |
1322 | 0 | message->Init(Coap::kTypeNonConfirmable, CoapCodeFromError(aError)); |
1323 | 0 | } |
1324 | 0 | else |
1325 | 0 | { |
1326 | 0 | message->Init(Coap::kTypeAck, CoapCodeFromError(aError)); |
1327 | 0 | } |
1328 | |
|
1329 | 0 | if (!aSeparate) |
1330 | 0 | { |
1331 | 0 | message->SetMessageId(aRequest.GetMessageId()); |
1332 | 0 | } |
1333 | |
|
1334 | 0 | SuccessOrExit(error = message->SetTokenFromMessage(aRequest)); |
1335 | | |
1336 | 0 | SuccessOrExit(error = SendMessage(*message)); |
1337 | | |
1338 | 0 | exit: |
1339 | 0 | FreeMessageOnError(message, error); |
1340 | 0 | LogWarnOnError(error, "send error CoAP message"); |
1341 | 0 | } |
1342 | | |
1343 | | void BorderAgent::CoapDtlsSession::HandleTmfProxyTx(Coap::Message &aMessage) |
1344 | 0 | { |
1345 | 0 | Error error = kErrorNone; |
1346 | 0 | Message *message = nullptr; |
1347 | 0 | Ip6::MessageInfo messageInfo; |
1348 | 0 | OffsetRange offsetRange; |
1349 | 0 | UdpEncapsulationTlvHeader udpEncapHeader; |
1350 | |
|
1351 | 0 | SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kUdpEncapsulation, offsetRange)); |
1352 | | |
1353 | 0 | SuccessOrExit(error = aMessage.Read(offsetRange, udpEncapHeader)); |
1354 | 0 | offsetRange.AdvanceOffset(sizeof(UdpEncapsulationTlvHeader)); |
1355 | |
|
1356 | 0 | VerifyOrExit(udpEncapHeader.GetSourcePort() > 0 && udpEncapHeader.GetDestinationPort() > 0, error = kErrorDrop); |
1357 | | |
1358 | 0 | VerifyOrExit((message = Get<Ip6::Udp>().NewMessage()) != nullptr, error = kErrorNoBufs); |
1359 | 0 | SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange)); |
1360 | | |
1361 | 0 | messageInfo.SetSockPort(udpEncapHeader.GetSourcePort()); |
1362 | 0 | messageInfo.SetSockAddr(mCommissionerAloc.GetAddress()); |
1363 | 0 | messageInfo.SetPeerPort(udpEncapHeader.GetDestinationPort()); |
1364 | |
|
1365 | 0 | SuccessOrExit(error = Tlv::Find<Ip6AddressTlv>(aMessage, messageInfo.GetPeerAddr())); |
1366 | | |
1367 | 0 | SuccessOrExit(error = Get<Ip6::Udp>().SendDatagram(*message, messageInfo)); |
1368 | | |
1369 | 0 | LogInfo("Proxy transmit sent to %s", messageInfo.GetPeerAddr().ToString().AsCString()); |
1370 | |
|
1371 | 0 | exit: |
1372 | 0 | FreeMessageOnError(message, error); |
1373 | 0 | LogWarnOnError(error, "send proxy stream"); |
1374 | 0 | } |
1375 | | |
1376 | | void BorderAgent::CoapDtlsSession::HandleTmfRelayTx(Coap::Message &aMessage) |
1377 | 0 | { |
1378 | 0 | Error error = kErrorNone; |
1379 | 0 | uint16_t joinerRouterRloc; |
1380 | 0 | Coap::Message *message = nullptr; |
1381 | 0 | Tmf::MessageInfo messageInfo(GetInstance()); |
1382 | 0 | OffsetRange offsetRange; |
1383 | |
|
1384 | 0 | VerifyOrExit(aMessage.IsNonConfirmablePostRequest()); |
1385 | | |
1386 | 0 | SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRouterRloc)); |
1387 | | |
1388 | 0 | message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(kUriRelayTx); |
1389 | 0 | VerifyOrExit(message != nullptr, error = kErrorNoBufs); |
1390 | | |
1391 | 0 | offsetRange.InitFromMessageOffsetToEnd(aMessage); |
1392 | 0 | SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange)); |
1393 | | |
1394 | 0 | messageInfo.SetSockAddrToRlocPeerAddrTo(joinerRouterRloc); |
1395 | 0 | messageInfo.SetSockPortToTmf(); |
1396 | |
|
1397 | 0 | SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo)); |
1398 | | |
1399 | 0 | LogInfo("Sent to joiner router request on RelayTx (c/tx)"); |
1400 | |
|
1401 | 0 | exit: |
1402 | 0 | FreeMessageOnError(message, error); |
1403 | 0 | LogWarnOnError(error, "send to joiner router request RelayTx (c/tx)"); |
1404 | 0 | } |
1405 | | |
1406 | | void BorderAgent::CoapDtlsSession::HandleTmfDatasetGet(Coap::Message &aMessage, Uri aUri) |
1407 | 0 | { |
1408 | 0 | Error error = kErrorNone; |
1409 | 0 | Coap::Message *response = nullptr; |
1410 | | |
1411 | | // When processing `MGMT_GET` request directly on Border Agent, |
1412 | | // the Security Policy flags (O-bit) should be ignored to allow |
1413 | | // the commissioner candidate to get the full Operational Dataset. |
1414 | |
|
1415 | 0 | switch (aUri) |
1416 | 0 | { |
1417 | 0 | case kUriActiveGet: |
1418 | 0 | response = Get<ActiveDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags); |
1419 | 0 | Get<BorderAgent>().mCounters.mMgmtActiveGets++; |
1420 | 0 | break; |
1421 | | |
1422 | 0 | case kUriPendingGet: |
1423 | 0 | response = Get<PendingDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags); |
1424 | 0 | Get<BorderAgent>().mCounters.mMgmtPendingGets++; |
1425 | 0 | break; |
1426 | | |
1427 | 0 | case kUriCommissionerGet: |
1428 | 0 | response = Get<NetworkData::Leader>().ProcessCommissionerGetRequest(aMessage); |
1429 | 0 | break; |
1430 | | |
1431 | 0 | default: |
1432 | 0 | break; |
1433 | 0 | } |
1434 | | |
1435 | 0 | VerifyOrExit(response != nullptr, error = kErrorParse); |
1436 | | |
1437 | 0 | SuccessOrExit(error = SendMessage(*response)); |
1438 | | |
1439 | 0 | LogInfo("Sent %s response to non-active commissioner", PathForUri(aUri)); |
1440 | |
|
1441 | 0 | exit: |
1442 | 0 | LogWarnOnError(error, "send Active/Pending/CommissionerGet response"); |
1443 | 0 | FreeMessageOnError(response, error); |
1444 | 0 | } |
1445 | | |
1446 | | void BorderAgent::CoapDtlsSession::HandleTimer(Timer &aTimer) |
1447 | 0 | { |
1448 | 0 | static_cast<CoapDtlsSession *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer(); |
1449 | 0 | } |
1450 | | |
1451 | | void BorderAgent::CoapDtlsSession::HandleTimer(void) |
1452 | 0 | { |
1453 | 0 | if (IsConnected()) |
1454 | 0 | { |
1455 | 0 | LogInfo("Session timed out - disconnecting"); |
1456 | 0 | Disconnect(); |
1457 | 0 | } |
1458 | 0 | } |
1459 | | |
1460 | | //---------------------------------------------------------------------------------------------------------------------- |
1461 | | // `BorderAgent::CoapDtlsSession::ForwardContext` |
1462 | | |
1463 | | BorderAgent::CoapDtlsSession::ForwardContext::ForwardContext(CoapDtlsSession &aSession, |
1464 | | const Coap::Message &aMessage, |
1465 | | bool aPetition, |
1466 | | bool aSeparate) |
1467 | 0 | : mSession(aSession) |
1468 | 0 | , mMessageId(aMessage.GetMessageId()) |
1469 | 0 | , mPetition(aPetition) |
1470 | 0 | , mSeparate(aSeparate) |
1471 | 0 | , mTokenLength(aMessage.GetTokenLength()) |
1472 | 0 | , mType(aMessage.GetType()) |
1473 | 0 | { |
1474 | 0 | memcpy(mToken, aMessage.GetToken(), mTokenLength); |
1475 | 0 | } |
1476 | | |
1477 | | Error BorderAgent::CoapDtlsSession::ForwardContext::ToHeader(Coap::Message &aMessage, uint8_t aCode) const |
1478 | 0 | { |
1479 | 0 | if ((mType == Coap::kTypeNonConfirmable) || mSeparate) |
1480 | 0 | { |
1481 | 0 | aMessage.Init(Coap::kTypeNonConfirmable, static_cast<Coap::Code>(aCode)); |
1482 | 0 | } |
1483 | 0 | else |
1484 | 0 | { |
1485 | 0 | aMessage.Init(Coap::kTypeAck, static_cast<Coap::Code>(aCode)); |
1486 | 0 | } |
1487 | |
|
1488 | 0 | if (!mSeparate) |
1489 | 0 | { |
1490 | 0 | aMessage.SetMessageId(mMessageId); |
1491 | 0 | } |
1492 | |
|
1493 | 0 | return aMessage.SetToken(mToken, mTokenLength); |
1494 | 0 | } |
1495 | | |
1496 | | } // namespace MeshCoP |
1497 | | } // namespace ot |
1498 | | |
1499 | | #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE |