• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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