1 /******************************************************************************
2 *
3 * Copyright 2022 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include <hci/hci_packets.h>
20 #include <hci/pcap_filter.h>
21 #include <packet/raw_builder.h>
22
23 using namespace bluetooth::hci;
24 using namespace bluetooth::packet;
25
26 namespace rootcanal {
27
create_packet_view(std::vector<uint8_t> const & packet)28 static PacketView<kLittleEndian> create_packet_view(
29 std::vector<uint8_t> const& packet) {
30 // Wrap the reference to the packet in a shared_ptr with created
31 // a no-op deleter. The packet view will be short lived so there is no
32 // risk of the reference leaking.
33 return PacketView<kLittleEndian>(std::shared_ptr<std::vector<uint8_t> const>(
34 &packet, [](std::vector<uint8_t> const* /* ptr */) {}));
35 }
36
37 static std::vector<uint8_t> FilterHciAcl(std::vector<uint8_t> const& packet);
38 static std::vector<uint8_t> FilterHciSco(std::vector<uint8_t> const& packet);
39 static std::vector<uint8_t> FilterHciIso(std::vector<uint8_t> const& packet);
40
FilterHciPacket(std::vector<uint8_t> const & packet,uint8_t idc)41 std::vector<uint8_t> PcapFilter::FilterHciPacket(
42 std::vector<uint8_t> const& packet, uint8_t idc) {
43 switch (idc) {
44 case 0x1:
45 return FilterHciCommand(packet);
46 case 0x2:
47 return FilterHciAcl(packet);
48 case 0x3:
49 return FilterHciSco(packet);
50 case 0x4:
51 return FilterHciEvent(packet);
52 case 0x5:
53 return FilterHciIso(packet);
54 default:
55 break;
56 }
57 return std::vector<uint8_t>(packet);
58 }
59
FilterHciCommand(std::vector<uint8_t> const & packet)60 std::vector<uint8_t> PcapFilter::FilterHciCommand(
61 std::vector<uint8_t> const& packet) {
62 auto command = CommandView::Create(create_packet_view(packet));
63 ASSERT(command.IsValid());
64 switch (command.GetOpCode()) {
65 case OpCode::WRITE_LOCAL_NAME:
66 return FilterWriteLocalName(command);
67 case OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE:
68 return FilterWriteExtendedInquiryResponse(command);
69 case OpCode::LE_SET_ADVERTISING_DATA:
70 return FilterLeSetAdvertisingData(command);
71 case OpCode::LE_SET_SCAN_RESPONSE_DATA:
72 return FilterLeSetScanResponseData(command);
73 case OpCode::LE_SET_EXTENDED_ADVERTISING_DATA:
74 return FilterLeSetExtendedAdvertisingData(command);
75 case OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA:
76 return FilterLeSetExtendedScanResponseData(command);
77 case OpCode::LE_SET_PERIODIC_ADVERTISING_DATA:
78 return FilterLeSetPeriodicAdvertisingData(command);
79 case OpCode::LE_MULTI_ADVT: {
80 auto le_multi_advt_command = LeMultiAdvtView::Create(command);
81 ASSERT(le_multi_advt_command.IsValid());
82 switch (le_multi_advt_command.GetSubCmd()) {
83 case SubOcf::SET_DATA:
84 return FilterLeMultiAdvtSetData(le_multi_advt_command);
85 case SubOcf::SET_SCAN_RESP:
86 return FilterLeMultiAdvtSetScanResp(le_multi_advt_command);
87 default:
88 break;
89 }
90 break;
91 }
92 default:
93 break;
94 }
95 return std::vector<uint8_t>(packet);
96 }
97
FilterHciEvent(std::vector<uint8_t> const & packet)98 std::vector<uint8_t> PcapFilter::FilterHciEvent(
99 std::vector<uint8_t> const& packet) {
100 auto event = EventView::Create(create_packet_view(packet));
101 ASSERT(event.IsValid());
102 switch (event.GetEventCode()) {
103 case EventCode::LE_META_EVENT: {
104 auto le_meta_event = LeMetaEventView::Create(event);
105 ASSERT(le_meta_event.IsValid());
106 switch (le_meta_event.GetSubeventCode()) {
107 case SubeventCode::ADVERTISING_REPORT:
108 return FilterLeAdvertisingReport(le_meta_event);
109 case SubeventCode::EXTENDED_ADVERTISING_REPORT:
110 return FilterLeExtendedAdvertisingReport(le_meta_event);
111 default:
112 break;
113 }
114 break;
115 }
116 case EventCode::COMMAND_COMPLETE: {
117 auto command_complete = CommandCompleteView::Create(event);
118 ASSERT(command_complete.IsValid());
119 switch (command_complete.GetCommandOpCode()) {
120 case OpCode::READ_LOCAL_NAME:
121 return FilterReadLocalNameComplete(command_complete);
122 case OpCode::READ_EXTENDED_INQUIRY_RESPONSE:
123 return FilterReadExtendedInquiryResponseComplete(command_complete);
124 default:
125 break;
126 }
127 break;
128 }
129 case EventCode::REMOTE_NAME_REQUEST_COMPLETE:
130 return FilterRemoteNameRequestComplete(event);
131 case EventCode::EXTENDED_INQUIRY_RESULT:
132 return FilterExtendedInquiryResult(event);
133 default:
134 break;
135 }
136 return std::vector<uint8_t>(packet);
137 }
138
FilterHciAcl(std::vector<uint8_t> const & packet)139 static std::vector<uint8_t> FilterHciAcl(std::vector<uint8_t> const& packet) {
140 auto acl = AclView::Create(create_packet_view(packet));
141 std::vector<uint8_t> payload;
142 payload.resize(acl.GetPayload().size());
143 ASSERT(acl.IsValid());
144 return AclBuilder::Create(acl.GetHandle(), acl.GetPacketBoundaryFlag(),
145 acl.GetBroadcastFlag(),
146 std::make_unique<RawBuilder>(payload))
147 ->SerializeToBytes();
148 }
149
FilterHciSco(std::vector<uint8_t> const & packet)150 static std::vector<uint8_t> FilterHciSco(std::vector<uint8_t> const& packet) {
151 auto sco = ScoView::Create(create_packet_view(packet));
152 std::vector<uint8_t> data;
153 data.resize(sco.GetData().size());
154 ASSERT(sco.IsValid());
155 return ScoBuilder::Create(sco.GetHandle(), sco.GetPacketStatusFlag(), data)
156 ->SerializeToBytes();
157 }
158
FilterHciIso(std::vector<uint8_t> const & packet)159 static std::vector<uint8_t> FilterHciIso(std::vector<uint8_t> const& packet) {
160 auto iso = IsoView::Create(create_packet_view(packet));
161 std::vector<uint8_t> payload;
162 payload.resize(iso.GetPayload().size());
163 ASSERT(iso.IsValid());
164 return IsoBuilder::Create(iso.GetConnectionHandle(), iso.GetPbFlag(),
165 iso.GetTsFlag(),
166 std::make_unique<RawBuilder>(payload))
167 ->SerializeToBytes();
168 }
169
170 // Replace device names in GAP entries.
FilterGapData(std::vector<GapData> & gap_data)171 void PcapFilter::FilterGapData(std::vector<GapData>& gap_data) {
172 for (GapData& entry : gap_data) {
173 switch (entry.data_type_) {
174 case GapDataType::COMPLETE_LOCAL_NAME:
175 case GapDataType::SHORTENED_LOCAL_NAME:
176 entry.data_ = ChangeDeviceName(entry.data_);
177 break;
178 default:
179 break;
180 }
181 }
182 }
183
FilterLengthAndData(std::vector<bluetooth::hci::LengthAndData> & gap_data)184 void PcapFilter::FilterLengthAndData(
185 std::vector<bluetooth::hci::LengthAndData>& gap_data) {
186 for (LengthAndData& entry : gap_data) {
187 if (entry.data_.empty()) {
188 continue;
189 }
190 switch (GapDataType(entry.data_[0])) {
191 case GapDataType::COMPLETE_LOCAL_NAME:
192 case GapDataType::SHORTENED_LOCAL_NAME: {
193 std::vector<uint8_t> device_name(entry.data_.begin() + 1,
194 entry.data_.end());
195 device_name = ChangeDeviceName(device_name);
196 entry.data_.insert(device_name.begin(), device_name.end(),
197 entry.data_.begin() + 1);
198 break;
199 }
200 default:
201 break;
202 }
203 }
204 }
205
206 // Replace the local device name.
FilterWriteLocalName(CommandView & command)207 std::vector<uint8_t> PcapFilter::FilterWriteLocalName(CommandView& command) {
208 auto parameters = WriteLocalNameView::Create(command);
209 ASSERT(parameters.IsValid());
210
211 std::array<uint8_t, 248> local_name =
212 ChangeDeviceName(parameters.GetLocalName());
213 return WriteLocalNameBuilder::Create(local_name)->SerializeToBytes();
214 }
215
216 // Replace the device names in the GAP entries of the extended inquiry response.
FilterWriteExtendedInquiryResponse(CommandView & command)217 std::vector<uint8_t> PcapFilter::FilterWriteExtendedInquiryResponse(
218 CommandView& command) {
219 auto parameters = WriteExtendedInquiryResponseView::Create(command);
220 ASSERT(parameters.IsValid());
221
222 std::vector<GapData> extended_inquiry_response =
223 parameters.GetExtendedInquiryResponse();
224 FilterGapData(extended_inquiry_response);
225 return WriteExtendedInquiryResponseBuilder::Create(
226 parameters.GetFecRequired(), extended_inquiry_response)
227 ->SerializeToBytes();
228 }
229
230 // Replace the device names in the GAP entries of the advertising data.
FilterLeSetAdvertisingData(CommandView & command)231 std::vector<uint8_t> PcapFilter::FilterLeSetAdvertisingData(
232 CommandView& command) {
233 auto parameters = LeSetAdvertisingDataView::Create(command);
234 ASSERT(parameters.IsValid());
235
236 std::vector<GapData> advertising_data = parameters.GetAdvertisingData();
237 FilterGapData(advertising_data);
238 return LeSetAdvertisingDataBuilder::Create(advertising_data)
239 ->SerializeToBytes();
240 }
241
242 // Replace the device names in the GAP entries of the scan response data.
FilterLeSetScanResponseData(CommandView & command)243 std::vector<uint8_t> PcapFilter::FilterLeSetScanResponseData(
244 CommandView& command) {
245 auto parameters = LeSetScanResponseDataView::Create(command);
246 ASSERT(parameters.IsValid());
247
248 std::vector<GapData> advertising_data = parameters.GetAdvertisingData();
249 FilterGapData(advertising_data);
250 return LeSetScanResponseDataBuilder::Create(advertising_data)
251 ->SerializeToBytes();
252 }
253
254 // Replace the device names in the GAP entries of the extended advertising data.
FilterLeSetExtendedAdvertisingData(CommandView & command)255 std::vector<uint8_t> PcapFilter::FilterLeSetExtendedAdvertisingData(
256 CommandView& command) {
257 auto parameters = LeSetExtendedAdvertisingDataView::Create(command);
258 ASSERT(parameters.IsValid());
259
260 std::vector<GapData> advertising_data = parameters.GetAdvertisingData();
261 FilterGapData(advertising_data);
262 return LeSetExtendedAdvertisingDataBuilder::Create(
263 parameters.GetAdvertisingHandle(), parameters.GetOperation(),
264 parameters.GetFragmentPreference(), advertising_data)
265 ->SerializeToBytes();
266 }
267
268 // Replace the device names in the GAP entries of the extended scan response
269 // data.
FilterLeSetExtendedScanResponseData(CommandView & command)270 std::vector<uint8_t> PcapFilter::FilterLeSetExtendedScanResponseData(
271 CommandView& command) {
272 auto parameters = LeSetExtendedScanResponseDataView::Create(command);
273 ASSERT(parameters.IsValid());
274
275 std::vector<GapData> advertising_data = parameters.GetScanResponseData();
276 FilterGapData(advertising_data);
277 return LeSetExtendedScanResponseDataBuilder::Create(
278 parameters.GetAdvertisingHandle(), parameters.GetOperation(),
279 parameters.GetFragmentPreference(), advertising_data)
280 ->SerializeToBytes();
281 }
282
283 // Replace the device names in the GAP entries of the periodic advertising
284 // data.
FilterLeSetPeriodicAdvertisingData(bluetooth::hci::CommandView & command)285 std::vector<uint8_t> PcapFilter::FilterLeSetPeriodicAdvertisingData(
286 bluetooth::hci::CommandView& command) {
287 auto parameters = LeSetPeriodicAdvertisingDataView::Create(command);
288 ASSERT(parameters.IsValid());
289
290 std::vector<GapData> advertising_data = parameters.GetAdvertisingData();
291 FilterGapData(advertising_data);
292 return LeSetPeriodicAdvertisingDataBuilder::Create(
293 parameters.GetAdvertisingHandle(), parameters.GetOperation(),
294 advertising_data)
295 ->SerializeToBytes();
296 }
297
298 // Replace the device names in the GAP entries of the advertising data.
FilterLeMultiAdvtSetData(bluetooth::hci::LeMultiAdvtView & command)299 std::vector<uint8_t> PcapFilter::FilterLeMultiAdvtSetData(
300 bluetooth::hci::LeMultiAdvtView& command) {
301 auto parameters = LeMultiAdvtSetDataView::Create(command);
302 ASSERT(parameters.IsValid());
303
304 std::vector<GapData> advertising_data = parameters.GetAdvertisingData();
305 FilterGapData(advertising_data);
306 return LeMultiAdvtSetDataBuilder::Create(advertising_data,
307 parameters.GetAdvertisingInstance())
308 ->SerializeToBytes();
309 }
310
311 // Replace the device names in the GAP entries of the scan response data.
FilterLeMultiAdvtSetScanResp(bluetooth::hci::LeMultiAdvtView & command)312 std::vector<uint8_t> PcapFilter::FilterLeMultiAdvtSetScanResp(
313 bluetooth::hci::LeMultiAdvtView& command) {
314 auto parameters = LeMultiAdvtSetScanRespView::Create(command);
315 ASSERT(parameters.IsValid());
316
317 std::vector<GapData> advertising_data = parameters.GetAdvertisingData();
318 FilterGapData(advertising_data);
319 return LeMultiAdvtSetScanRespBuilder::Create(
320 advertising_data, parameters.GetAdvertisingInstance())
321 ->SerializeToBytes();
322 }
323
324 // Replace the local device name in the read local name complete event.
FilterReadLocalNameComplete(bluetooth::hci::CommandCompleteView & command_complete)325 std::vector<uint8_t> PcapFilter::FilterReadLocalNameComplete(
326 bluetooth::hci::CommandCompleteView& command_complete) {
327 auto parameters = ReadLocalNameCompleteView::Create(command_complete);
328 ASSERT(parameters.IsValid());
329
330 std::array<uint8_t, 248> local_name = parameters.GetLocalName();
331 if (parameters.GetStatus() == ErrorCode::SUCCESS) {
332 local_name = ChangeDeviceName(local_name);
333 }
334
335 return ReadLocalNameCompleteBuilder::Create(
336 parameters.GetNumHciCommandPackets(), parameters.GetStatus(),
337 local_name)
338 ->SerializeToBytes();
339 }
340
341 // Replace the device names in the GAP entries of the extended inquiry response.
FilterReadExtendedInquiryResponseComplete(bluetooth::hci::CommandCompleteView & command_complete)342 std::vector<uint8_t> PcapFilter::FilterReadExtendedInquiryResponseComplete(
343 bluetooth::hci::CommandCompleteView& command_complete) {
344 auto parameters =
345 ReadExtendedInquiryResponseCompleteView::Create(command_complete);
346 ASSERT(parameters.IsValid());
347
348 std::vector<GapData> extended_inquiry_response =
349 parameters.GetExtendedInquiryResponse();
350 if (parameters.GetStatus() == ErrorCode::SUCCESS) {
351 FilterGapData(extended_inquiry_response);
352 }
353
354 return ReadExtendedInquiryResponseCompleteBuilder::Create(
355 parameters.GetNumHciCommandPackets(), parameters.GetStatus(),
356 parameters.GetFecRequired(), extended_inquiry_response)
357 ->SerializeToBytes();
358 }
359
360 // Replace the remote device name in the remote name request complete event.
FilterRemoteNameRequestComplete(bluetooth::hci::EventView & event)361 std::vector<uint8_t> PcapFilter::FilterRemoteNameRequestComplete(
362 bluetooth::hci::EventView& event) {
363 auto parameters = RemoteNameRequestCompleteView::Create(event);
364 ASSERT(parameters.IsValid());
365
366 std::array<uint8_t, 248> remote_name = parameters.GetRemoteName();
367 if (parameters.GetStatus() == ErrorCode::SUCCESS) {
368 remote_name = ChangeDeviceName(remote_name);
369 }
370
371 return RemoteNameRequestCompleteBuilder::Create(
372 parameters.GetStatus(), parameters.GetBdAddr(), remote_name)
373 ->SerializeToBytes();
374 }
375
376 // Replace the device names in the GAP entries in the extended inquiry result.
FilterExtendedInquiryResult(bluetooth::hci::EventView & event)377 std::vector<uint8_t> PcapFilter::FilterExtendedInquiryResult(
378 bluetooth::hci::EventView& event) {
379 auto parameters = ExtendedInquiryResultView::Create(event);
380 ASSERT(parameters.IsValid());
381
382 std::vector<GapData> extended_inquiry_response =
383 parameters.GetExtendedInquiryResponse();
384 FilterGapData(extended_inquiry_response);
385
386 return ExtendedInquiryResultBuilder::Create(
387 parameters.GetAddress(), parameters.GetPageScanRepetitionMode(),
388 parameters.GetClassOfDevice(), parameters.GetClockOffset(),
389 parameters.GetRssi(), extended_inquiry_response)
390 ->SerializeToBytes();
391 }
392
393 // Replace the device names in the GAP entries in the advertising report.
FilterLeAdvertisingReport(bluetooth::hci::LeMetaEventView & event)394 std::vector<uint8_t> PcapFilter::FilterLeAdvertisingReport(
395 bluetooth::hci::LeMetaEventView& event) {
396 auto parameters = LeAdvertisingReportView::Create(event);
397 ASSERT(parameters.IsValid());
398
399 std::vector<LeAdvertisingResponse> responses = parameters.GetResponses();
400 for (auto& response : responses) {
401 FilterLengthAndData(response.advertising_data_);
402 }
403
404 return LeAdvertisingReportBuilder::Create(responses)->SerializeToBytes();
405 }
406
407 // Replace the device names in the GAP entries in the extended advertising
408 // report.
FilterLeExtendedAdvertisingReport(bluetooth::hci::LeMetaEventView & event)409 std::vector<uint8_t> PcapFilter::FilterLeExtendedAdvertisingReport(
410 bluetooth::hci::LeMetaEventView& event) {
411 auto parameters = LeExtendedAdvertisingReportView::Create(event);
412 ASSERT(parameters.IsValid());
413
414 std::vector<LeExtendedAdvertisingResponse> responses =
415 parameters.GetResponses();
416 for (auto& response : responses) {
417 FilterLengthAndData(response.advertising_data_);
418 }
419
420 return LeExtendedAdvertisingReportBuilder::Create(responses)
421 ->SerializeToBytes();
422 }
423
424 // Generate a device name of the specified length.
425 // device_nr is a unique identifier used for the generation.
426 // padded indicates if the name should be padded to length with
427 // spaces.
generate_device_name(size_t device_nr,size_t device_name_len,bool padded)428 static std::vector<uint8_t> generate_device_name(size_t device_nr,
429 size_t device_name_len,
430 bool padded) {
431 std::vector<uint8_t> output;
432 output.resize(device_name_len + 1);
433 int written_len = std::snprintf(reinterpret_cast<char*>(output.data()),
434 output.size(), "#%02zu device", device_nr);
435 // Remove the null terminator, not used for the device name
436 // since it is framed in most cases.
437 output.resize(device_name_len);
438 // Pad the device name with spaces.
439 if (padded && written_len >= 0 && written_len < (int)output.size()) {
440 std::memset(&output[written_len], ' ', output.size() - written_len);
441 }
442 return output;
443 }
444
ChangeDeviceName(std::vector<uint8_t> const & device_name)445 std::vector<uint8_t> PcapFilter::ChangeDeviceName(
446 std::vector<uint8_t> const& device_name) {
447 for (auto const& [old_device_name, new_device_name] : device_name_map) {
448 if (old_device_name == device_name) {
449 return std::vector<uint8_t>(new_device_name);
450 }
451 }
452
453 std::vector<uint8_t> new_device_name =
454 generate_device_name(device_name_map.size(), device_name.size(), true);
455 device_name_map.push_back(std::pair{
456 std::vector<uint8_t>(device_name),
457 new_device_name,
458 });
459 return new_device_name;
460 }
461
ChangeDeviceName(std::array<uint8_t,248> const & device_name)462 std::array<uint8_t, 248> PcapFilter::ChangeDeviceName(
463 std::array<uint8_t, 248> const& device_name) {
464 for (auto const& [old_device_name, new_device_name] : device_name_map) {
465 if (std::equal(old_device_name.begin(), old_device_name.end(),
466 device_name.begin(), device_name.end())) {
467 std::array<uint8_t, 248> out_device_name{};
468 std::copy(new_device_name.begin(), new_device_name.end(),
469 out_device_name.begin());
470 return out_device_name;
471 }
472 }
473
474 std::vector<uint8_t> new_device_name =
475 generate_device_name(device_name_map.size(), device_name.size(), false);
476 std::array<uint8_t, 248> out_device_name{};
477 std::copy(new_device_name.begin(), new_device_name.end(),
478 out_device_name.begin());
479 device_name_map.push_back(std::pair{
480 std::vector<uint8_t>(device_name.begin(), device_name.end()),
481 std::move(new_device_name),
482 });
483 return out_device_name;
484 }
485
486 } // namespace rootcanal
487