• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_command_handler.h"
16 
17 #include <endian.h>
18 
19 #include <type_traits>
20 
21 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/packet_view.h"
24 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_configuration.h"
25 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
26 
27 namespace bt::l2cap::internal {
28 
Decode(const ByteBuffer & payload_buf)29 bool BrEdrCommandHandler::ConnectionResponse::Decode(
30     const ByteBuffer& payload_buf) {
31   auto conn_rsp_payload = payload_buf.To<PayloadT>();
32   remote_cid_ = le16toh(conn_rsp_payload.dst_cid);
33   local_cid_ = le16toh(conn_rsp_payload.src_cid);
34   result_ = static_cast<ConnectionResult>(
35       le16toh(static_cast<uint16_t>(conn_rsp_payload.result)));
36   conn_status_ = static_cast<ConnectionStatus>(
37       le16toh(static_cast<uint16_t>(conn_rsp_payload.status)));
38   return true;
39 }
40 
Decode(const ByteBuffer & payload_buf)41 bool BrEdrCommandHandler::ConfigurationResponse::Decode(
42     const ByteBuffer& payload_buf) {
43   PacketView<PayloadT> config_rsp(&payload_buf,
44                                   payload_buf.size() - sizeof(PayloadT));
45   local_cid_ = le16toh(config_rsp.header().src_cid);
46   flags_ = le16toh(config_rsp.header().flags);
47   result_ = static_cast<ConfigurationResult>(
48       le16toh(static_cast<uint16_t>(config_rsp.header().result)));
49 
50   if (!config_.ReadOptions(config_rsp.payload_data())) {
51     bt_log(WARN,
52            "l2cap",
53            "could not decode channel configuration response option");
54     return false;
55   }
56   return true;
57 }
58 
Decode(const ByteBuffer & payload_buf)59 bool BrEdrCommandHandler::InformationResponse::Decode(
60     const ByteBuffer& payload_buf) {
61   PacketView<InformationResponsePayload> info_rsp(
62       &payload_buf, payload_buf.size() - sizeof(InformationResponsePayload));
63   type_ =
64       InformationType{le16toh(static_cast<uint16_t>(info_rsp.header().type))};
65   result_ = InformationResult{
66       le16toh(static_cast<uint16_t>(info_rsp.header().result))};
67   if (result_ != InformationResult::kSuccess) {
68     return true;
69   }
70 
71   size_t expected_size = 0;
72   switch (type_) {
73     case InformationType::kConnectionlessMTU:
74       expected_size = sizeof(uint16_t);
75       break;
76     case InformationType::kExtendedFeaturesSupported:
77       expected_size = sizeof(ExtendedFeatures);
78       break;
79     case InformationType::kFixedChannelsSupported:
80       expected_size = sizeof(FixedChannelsSupported);
81       break;
82     default:
83       bt_log(DEBUG,
84              "l2cap-bredr",
85              "cmd: passing Information Response with unknown type %#.4hx with "
86              "%zu data bytes",
87              static_cast<unsigned short>(type_),
88              info_rsp.payload_size());
89   }
90   if (info_rsp.payload_size() < expected_size) {
91     bt_log(DEBUG,
92            "l2cap-bredr",
93            "cmd: ignoring malformed Information Response, type %#.4hx with %zu "
94            "data bytes",
95            static_cast<unsigned short>(type_),
96            info_rsp.payload_size());
97     return false;
98   }
99   data_ = info_rsp.payload_data();
100   return true;
101 }
102 
ConnectionResponder(SignalingChannel::Responder * sig_responder,ChannelId remote_cid)103 BrEdrCommandHandler::ConnectionResponder::ConnectionResponder(
104     SignalingChannel::Responder* sig_responder, ChannelId remote_cid)
105     : Responder(sig_responder, kInvalidChannelId, remote_cid) {}
106 
Send(ChannelId local_cid,ConnectionResult result,ConnectionStatus status)107 void BrEdrCommandHandler::ConnectionResponder::Send(ChannelId local_cid,
108                                                     ConnectionResult result,
109                                                     ConnectionStatus status) {
110   ConnectionResponsePayload conn_rsp = {
111       htole16(local_cid),
112       htole16(remote_cid()),
113       static_cast<ConnectionResult>(htole16(static_cast<uint16_t>(result))),
114       static_cast<ConnectionStatus>(htole16(static_cast<uint16_t>(status)))};
115   sig_responder_->Send(BufferView(&conn_rsp, sizeof(conn_rsp)));
116 }
117 
ConfigurationResponder(SignalingChannel::Responder * sig_responder,ChannelId local_cid)118 BrEdrCommandHandler::ConfigurationResponder::ConfigurationResponder(
119     SignalingChannel::Responder* sig_responder, ChannelId local_cid)
120     : Responder(sig_responder, local_cid) {}
121 
Send(ChannelId remote_cid,uint16_t flags,ConfigurationResult result,ChannelConfiguration::ConfigurationOptions options)122 void BrEdrCommandHandler::ConfigurationResponder::Send(
123     ChannelId remote_cid,
124     uint16_t flags,
125     ConfigurationResult result,
126     ChannelConfiguration::ConfigurationOptions options) {
127   size_t options_size = 0;
128   for (auto& option : options) {
129     options_size += option->size();
130   }
131 
132   DynamicByteBuffer config_rsp_buf(sizeof(ConfigurationResponsePayload) +
133                                    options_size);
134   MutablePacketView<ConfigurationResponsePayload> config_rsp(&config_rsp_buf,
135                                                              options_size);
136   config_rsp.mutable_header()->src_cid = htole16(remote_cid);
137   config_rsp.mutable_header()->flags = htole16(flags);
138   config_rsp.mutable_header()->result =
139       static_cast<ConfigurationResult>(htole16(static_cast<uint16_t>(result)));
140 
141   auto payload_view = config_rsp.mutable_payload_data().mutable_view();
142   for (auto& option : options) {
143     auto encoded = option->Encode();
144     payload_view.Write(encoded.data(), encoded.size());
145     payload_view = payload_view.mutable_view(encoded.size());
146   }
147 
148   sig_responder_->Send(config_rsp.data());
149 }
150 
DisconnectionResponder(SignalingChannel::Responder * sig_responder,ChannelId local_cid,ChannelId remote_cid)151 BrEdrCommandHandler::DisconnectionResponder::DisconnectionResponder(
152     SignalingChannel::Responder* sig_responder,
153     ChannelId local_cid,
154     ChannelId remote_cid)
155     : Responder(sig_responder, local_cid, remote_cid) {}
156 
Send()157 void BrEdrCommandHandler::DisconnectionResponder::Send() {
158   DisconnectionResponsePayload discon_rsp = {htole16(local_cid()),
159                                              htole16(remote_cid())};
160   sig_responder_->Send(BufferView(&discon_rsp, sizeof(discon_rsp)));
161 }
162 
InformationResponder(SignalingChannel::Responder * sig_responder,InformationType type)163 BrEdrCommandHandler::InformationResponder::InformationResponder(
164     SignalingChannel::Responder* sig_responder, InformationType type)
165     : Responder(sig_responder), type_(type) {}
166 
SendNotSupported()167 void BrEdrCommandHandler::InformationResponder::SendNotSupported() {
168   Send(InformationResult::kNotSupported, BufferView());
169 }
170 
SendConnectionlessMtu(uint16_t mtu)171 void BrEdrCommandHandler::InformationResponder::SendConnectionlessMtu(
172     uint16_t mtu) {
173   mtu = htole16(mtu);
174   Send(InformationResult::kSuccess, BufferView(&mtu, sizeof(mtu)));
175 }
176 
SendExtendedFeaturesSupported(ExtendedFeatures extended_features)177 void BrEdrCommandHandler::InformationResponder::SendExtendedFeaturesSupported(
178     ExtendedFeatures extended_features) {
179   extended_features = htole32(extended_features);
180   Send(InformationResult::kSuccess,
181        BufferView(&extended_features, sizeof(extended_features)));
182 }
183 
SendFixedChannelsSupported(FixedChannelsSupported channels_supported)184 void BrEdrCommandHandler::InformationResponder::SendFixedChannelsSupported(
185     FixedChannelsSupported channels_supported) {
186   channels_supported = htole64(channels_supported);
187   Send(InformationResult::kSuccess,
188        BufferView(&channels_supported, sizeof(channels_supported)));
189 }
190 
Send(InformationResult result,const ByteBuffer & data)191 void BrEdrCommandHandler::InformationResponder::Send(InformationResult result,
192                                                      const ByteBuffer& data) {
193   constexpr size_t kMaxPayloadLength =
194       sizeof(InformationResponsePayload) + sizeof(uint64_t);
195   StaticByteBuffer<kMaxPayloadLength> info_rsp_buf;
196   MutablePacketView<InformationResponsePayload> info_rsp_view(&info_rsp_buf,
197                                                               data.size());
198 
199   info_rsp_view.mutable_header()->type =
200       static_cast<InformationType>(htole16(static_cast<uint16_t>(type_)));
201   info_rsp_view.mutable_header()->result =
202       static_cast<InformationResult>(htole16(static_cast<uint16_t>(result)));
203   info_rsp_view.mutable_payload_data().Write(data);
204   sig_responder_->Send(info_rsp_view.data());
205 }
206 
BrEdrCommandHandler(SignalingChannelInterface * sig,fit::closure request_fail_callback)207 BrEdrCommandHandler::BrEdrCommandHandler(SignalingChannelInterface* sig,
208                                          fit::closure request_fail_callback)
209     : CommandHandler(sig, std::move(request_fail_callback)) {}
210 
SendConnectionRequest(uint16_t psm,ChannelId local_cid,ConnectionResponseCallback cb)211 bool BrEdrCommandHandler::SendConnectionRequest(uint16_t psm,
212                                                 ChannelId local_cid,
213                                                 ConnectionResponseCallback cb) {
214   auto on_conn_rsp = BuildResponseHandler<ConnectionResponse>(std::move(cb));
215 
216   ConnectionRequestPayload payload = {htole16(psm), htole16(local_cid)};
217   return sig()->SendRequest(kConnectionRequest,
218                             BufferView(&payload, sizeof(payload)),
219                             std::move(on_conn_rsp));
220 }
221 
SendConfigurationRequest(ChannelId remote_cid,uint16_t flags,ChannelConfiguration::ConfigurationOptions options,ConfigurationResponseCallback cb)222 bool BrEdrCommandHandler::SendConfigurationRequest(
223     ChannelId remote_cid,
224     uint16_t flags,
225     ChannelConfiguration::ConfigurationOptions options,
226     ConfigurationResponseCallback cb) {
227   auto on_config_rsp =
228       BuildResponseHandler<ConfigurationResponse>(std::move(cb));
229 
230   size_t options_size = 0;
231   for (auto& option : options) {
232     options_size += option->size();
233   }
234 
235   DynamicByteBuffer config_req_buf(sizeof(ConfigurationRequestPayload) +
236                                    options_size);
237   MutablePacketView<ConfigurationRequestPayload> config_req(&config_req_buf,
238                                                             options_size);
239   config_req.mutable_header()->dst_cid = htole16(remote_cid);
240   config_req.mutable_header()->flags = htole16(flags);
241 
242   auto payload_view = config_req.mutable_payload_data().mutable_view();
243   for (auto& option : options) {
244     auto encoded = option->Encode();
245     payload_view.Write(encoded.data(), encoded.size());
246     payload_view = payload_view.mutable_view(encoded.size());
247   }
248 
249   return sig()->SendRequest(
250       kConfigurationRequest, config_req_buf, std::move(on_config_rsp));
251 }
252 
SendInformationRequest(InformationType type,InformationResponseCallback cb)253 bool BrEdrCommandHandler::SendInformationRequest(
254     InformationType type, InformationResponseCallback cb) {
255   auto on_info_rsp = BuildResponseHandler<InformationResponse>(std::move(cb));
256 
257   InformationRequestPayload payload = {
258       InformationType{htole16(static_cast<uint16_t>(type))}};
259   return sig()->SendRequest(kInformationRequest,
260                             BufferView(&payload, sizeof(payload)),
261                             std::move(on_info_rsp));
262 }
263 
ServeConnectionRequest(ConnectionRequestCallback cb)264 void BrEdrCommandHandler::ServeConnectionRequest(ConnectionRequestCallback cb) {
265   auto on_conn_req = [cb = std::move(cb)](
266                          const ByteBuffer& request_payload,
267                          SignalingChannel::Responder* sig_responder) {
268     if (request_payload.size() != sizeof(ConnectionRequestPayload)) {
269       bt_log(DEBUG,
270              "l2cap-bredr",
271              "cmd: rejecting malformed Connection Request, size %zu",
272              request_payload.size());
273       sig_responder->RejectNotUnderstood();
274       return;
275     }
276 
277     const auto& conn_req = request_payload.To<ConnectionRequestPayload>();
278     const Psm psm = le16toh(conn_req.psm);
279     const ChannelId remote_cid = le16toh(conn_req.src_cid);
280 
281     ConnectionResponder responder(sig_responder, remote_cid);
282 
283     // v5.0 Vol 3, Part A, Sec 4.2: PSMs shall be odd and the least significant
284     // bit of the most significant byte shall be zero
285     if (((psm & 0x0001) != 0x0001) || ((psm & 0x0100) != 0x0000)) {
286       bt_log(DEBUG,
287              "l2cap-bredr",
288              "Rejecting connection for invalid PSM %#.4x from channel %#.4x",
289              psm,
290              remote_cid);
291       responder.Send(kInvalidChannelId,
292                      ConnectionResult::kPsmNotSupported,
293                      ConnectionStatus::kNoInfoAvailable);
294       return;
295     }
296 
297     // Check that source channel ID is in range (v5.0 Vol 3, Part A, Sec 2.1)
298     if (remote_cid < kFirstDynamicChannelId) {
299       bt_log(DEBUG,
300              "l2cap-bredr",
301              "Rejecting connection for PSM %#.4x from invalid channel %#.4x",
302              psm,
303              remote_cid);
304       responder.Send(kInvalidChannelId,
305                      ConnectionResult::kInvalidSourceCID,
306                      ConnectionStatus::kNoInfoAvailable);
307       return;
308     }
309 
310     cb(psm, remote_cid, &responder);
311   };
312 
313   sig()->ServeRequest(kConnectionRequest, std::move(on_conn_req));
314 }
315 
ServeConfigurationRequest(ConfigurationRequestCallback cb)316 void BrEdrCommandHandler::ServeConfigurationRequest(
317     ConfigurationRequestCallback cb) {
318   auto on_config_req = [cb = std::move(cb)](
319                            const ByteBuffer& request_payload,
320                            SignalingChannel::Responder* sig_responder) {
321     if (request_payload.size() < sizeof(ConfigurationRequestPayload)) {
322       bt_log(DEBUG,
323              "l2cap-bredr",
324              "cmd: rejecting malformed Configuration Request, size %zu",
325              request_payload.size());
326       sig_responder->RejectNotUnderstood();
327       return;
328     }
329 
330     PacketView<ConfigurationRequestPayload> config_req(
331         &request_payload,
332         request_payload.size() - sizeof(ConfigurationRequestPayload));
333     const auto local_cid =
334         static_cast<ChannelId>(le16toh(config_req.header().dst_cid));
335     const uint16_t flags = le16toh(config_req.header().flags);
336     ConfigurationResponder responder(sig_responder, local_cid);
337 
338     ChannelConfiguration config;
339     if (!config.ReadOptions(config_req.payload_data())) {
340       bt_log(WARN,
341              "l2cap",
342              "could not decode configuration option in configuration request");
343     }
344 
345     cb(local_cid, flags, std::move(config), &responder);
346   };
347 
348   sig()->ServeRequest(kConfigurationRequest, std::move(on_config_req));
349 }
350 
ServeInformationRequest(InformationRequestCallback cb)351 void BrEdrCommandHandler::ServeInformationRequest(
352     InformationRequestCallback cb) {
353   auto on_info_req = [cb = std::move(cb)](
354                          const ByteBuffer& request_payload,
355                          SignalingChannel::Responder* sig_responder) {
356     if (request_payload.size() != sizeof(InformationRequestPayload)) {
357       bt_log(DEBUG,
358              "l2cap-bredr",
359              "cmd: rejecting malformed Information Request, size %zu",
360              request_payload.size());
361       sig_responder->RejectNotUnderstood();
362       return;
363     }
364 
365     const auto& info_req = request_payload.To<InformationRequestPayload>();
366     const auto type = static_cast<InformationType>(
367         le16toh(static_cast<uint16_t>(info_req.type)));
368     InformationResponder responder(sig_responder, type);
369     cb(type, &responder);
370   };
371 
372   sig()->ServeRequest(kInformationRequest, std::move(on_info_req));
373 }
374 
375 }  // namespace bt::l2cap::internal
376