1 ///! Rule group for tracking connection related issues.
2 use chrono::NaiveDateTime;
3 use std::collections::{HashMap, HashSet, VecDeque};
4 use std::convert::Into;
5 use std::io::Write;
6 use std::slice::Iter;
7 
8 use crate::engine::{Rule, RuleGroup, Signal};
9 use crate::parser::{Packet, PacketChild};
10 use hcidoc_packets::hci::{
11     Acl, Address, AuthenticatedPayloadTimeoutExpired, CommandChild, DisconnectReason, Enable,
12     ErrorCode, EventChild, InitiatorFilterPolicy, LeMetaEventChild, NumberOfCompletedPackets,
13     OpCode,
14 };
15 
16 enum ConnectionSignal {
17     LinkKeyMismatch,     // Peer forgets the link key or it mismatches ours. (b/284802375)
18     LongTermKeyMismatch, // Like LinkKeyMismatch but for LE cases. (b/303600602)
19     NocpDisconnect,      // Peer is disconnected when NOCP packet isn't yet received. (b/249295604)
20     NocpTimeout, // Host doesn't receive NOCP packet 5 seconds after ACL is sent. (b/249295604)
21     ApteDisconnect, // Host doesn't receive a packet with valid MIC for a while. (b/299850738)
22     RemoteFeatureNoReply, // Host doesn't receive a response for a remote feature request. (b/300851411)
23     RemoteFeatureError,   // Controller replies error for remote feature request. (b/292116133)
24     SecurityMode3,        // Peer uses the unsupported legacy security mode 3. (b/260625799)
25 }
26 
27 impl Into<&'static str> for ConnectionSignal {
into(self) -> &'static str28     fn into(self) -> &'static str {
29         match self {
30             ConnectionSignal::LinkKeyMismatch => "LinkKeyMismatch",
31             ConnectionSignal::LongTermKeyMismatch => "LongTermKeyMismatch",
32             ConnectionSignal::NocpDisconnect => "Nocp",
33             ConnectionSignal::NocpTimeout => "Nocp",
34             ConnectionSignal::ApteDisconnect => "AuthenticatedPayloadTimeoutExpired",
35             ConnectionSignal::RemoteFeatureError => "RemoteFeatureError",
36             ConnectionSignal::RemoteFeatureNoReply => "RemoteFeatureNoReply",
37             ConnectionSignal::SecurityMode3 => "UnsupportedSecurityMode3",
38         }
39     }
40 }
41 
42 /// Valid values are in the range 0x0000-0x0EFF.
43 pub type ConnectionHandle = u16;
44 
45 /// When we attempt to create a sco connection on an unknown handle, use this address as
46 /// a placeholder.
47 pub const UNKNOWN_SCO_ADDRESS: [u8; 6] = [0xdeu8, 0xad, 0xbe, 0xef, 0x00, 0x00];
48 
49 /// The tolerance duration of not receiving an expected reply. If 5s elapsed and timeout occurs,
50 /// we blame the pending event for causing timeout. This is used to detect NOCP and others.
51 pub const TIMEOUT_TOLERANCE_TIME_MS: i64 = 5000;
52 
53 pub(crate) struct NocpData {
54     /// Number of in-flight packets without a corresponding NOCP.
55     pub inflight_acl_ts: VecDeque<NaiveDateTime>,
56 }
57 
58 impl NocpData {
new() -> Self59     fn new() -> Self {
60         Self { inflight_acl_ts: VecDeque::new() }
61     }
62 }
63 
64 #[derive(Debug, Eq, PartialEq, Hash)]
65 enum PendingRemoteFeature {
66     Supported,
67     Extended,
68     Le,
69 }
70 
71 impl PendingRemoteFeature {
iterate_all() -> Iter<'static, PendingRemoteFeature>72     fn iterate_all() -> Iter<'static, PendingRemoteFeature> {
73         static FEATS: [PendingRemoteFeature; 3] = [
74             PendingRemoteFeature::Supported,
75             PendingRemoteFeature::Extended,
76             PendingRemoteFeature::Le,
77         ];
78         FEATS.iter()
79     }
80 }
81 
82 /// Keeps track of connections and identifies odd disconnections.
83 struct OddDisconnectionsRule {
84     /// Handles that had successful complete connections. The value has the timestamp of the
85     /// connection completion and the address of the device.
86     active_handles: HashMap<ConnectionHandle, (NaiveDateTime, Address)>,
87 
88     connection_attempt: HashMap<Address, Packet>,
89     last_connection_attempt: Option<Address>,
90 
91     le_connection_attempt: HashMap<Address, Packet>,
92     last_le_connection_attempt: Option<Address>,
93     last_le_connection_filter_policy: Option<InitiatorFilterPolicy>,
94 
95     sco_connection_attempt: HashMap<Address, Packet>,
96     last_sco_connection_attempt: Option<Address>,
97 
98     accept_list: HashSet<Address>,
99 
100     /// Keep track of some number of |Number of Completed Packets| and filter to
101     /// identify bursts.
102     nocp_by_handle: HashMap<ConnectionHandle, NocpData>,
103 
104     /// Number of |Authenticated Payload Timeout Expired| events hapened.
105     apte_by_handle: HashMap<ConnectionHandle, u32>,
106 
107     /// Pending handles for read remote features.
108     pending_supported_feat: HashMap<ConnectionHandle, NaiveDateTime>,
109     pending_extended_feat: HashMap<ConnectionHandle, NaiveDateTime>,
110     pending_le_feat: HashMap<ConnectionHandle, NaiveDateTime>,
111     last_feat_handle: HashMap<PendingRemoteFeature, ConnectionHandle>,
112 
113     /// When powering off, the controller might or might not reply disconnection request. Therefore
114     /// make this a special case.
115     pending_disconnect_due_to_host_power_off: HashSet<ConnectionHandle>,
116 
117     /// Pre-defined signals discovered in the logs.
118     signals: Vec<Signal>,
119 
120     /// Interesting occurrences surfaced by this rule.
121     reportable: Vec<(NaiveDateTime, String)>,
122 }
123 
124 impl OddDisconnectionsRule {
new() -> Self125     pub fn new() -> Self {
126         OddDisconnectionsRule {
127             active_handles: HashMap::new(),
128             connection_attempt: HashMap::new(),
129             last_connection_attempt: None,
130             le_connection_attempt: HashMap::new(),
131             last_le_connection_attempt: None,
132             last_le_connection_filter_policy: None,
133             sco_connection_attempt: HashMap::new(),
134             last_sco_connection_attempt: None,
135             accept_list: HashSet::new(),
136             nocp_by_handle: HashMap::new(),
137             apte_by_handle: HashMap::new(),
138             pending_supported_feat: HashMap::new(),
139             pending_extended_feat: HashMap::new(),
140             pending_le_feat: HashMap::new(),
141             last_feat_handle: HashMap::new(),
142             pending_disconnect_due_to_host_power_off: HashSet::new(),
143             signals: vec![],
144             reportable: vec![],
145         }
146     }
147 
process_classic_connection(&mut self, address: Address, packet: &Packet)148     fn process_classic_connection(&mut self, address: Address, packet: &Packet) {
149         self.last_connection_attempt = Some(address);
150         if let Some(p) = self.connection_attempt.insert(address, packet.clone()) {
151             self.reportable.push((
152                 p.ts,
153                 format!("Dangling connection attempt at {:?} replaced with {:?}", p, packet),
154             ));
155         }
156     }
157 
convert_sco_handle_to_address(&self, handle: ConnectionHandle) -> Address158     fn convert_sco_handle_to_address(&self, handle: ConnectionHandle) -> Address {
159         match self.active_handles.get(&handle).as_ref() {
160             Some((_ts, address)) => address.clone(),
161             None => Address::from(&UNKNOWN_SCO_ADDRESS),
162         }
163     }
164 
process_sync_connection(&mut self, address: Address, packet: &Packet)165     fn process_sync_connection(&mut self, address: Address, packet: &Packet) {
166         self.last_sco_connection_attempt = Some(address);
167         if let Some(p) = self.sco_connection_attempt.insert(address, packet.clone()) {
168             self.reportable.push((
169                 p.ts,
170                 format!("Dangling sco connection attempt at {:?} replaced with {:?}", p, packet),
171             ));
172         }
173     }
174 
process_le_create_connection( &mut self, address: Address, policy: InitiatorFilterPolicy, packet: &Packet, )175     fn process_le_create_connection(
176         &mut self,
177         address: Address,
178         policy: InitiatorFilterPolicy,
179         packet: &Packet,
180     ) {
181         self.last_le_connection_attempt = Some(address);
182         self.last_le_connection_filter_policy = Some(policy);
183         if let Some(p) = self.le_connection_attempt.insert(address, packet.clone()) {
184             self.reportable.push((
185                 p.ts,
186                 format!("Dangling LE connection attempt at {:?} replaced with {:?}", p, packet),
187             ));
188         }
189     }
190 
process_add_accept_list(&mut self, address: Address, _packet: &Packet)191     fn process_add_accept_list(&mut self, address: Address, _packet: &Packet) {
192         self.accept_list.insert(address);
193     }
194 
process_remove_accept_list(&mut self, address: Address, _packet: &Packet)195     fn process_remove_accept_list(&mut self, address: Address, _packet: &Packet) {
196         self.accept_list.remove(&address);
197     }
198 
process_clear_accept_list(&mut self, _packet: &Packet)199     fn process_clear_accept_list(&mut self, _packet: &Packet) {
200         self.accept_list.clear();
201     }
202 
get_feature_pending_map( &mut self, pending_type: &PendingRemoteFeature, ) -> &mut HashMap<ConnectionHandle, NaiveDateTime>203     fn get_feature_pending_map(
204         &mut self,
205         pending_type: &PendingRemoteFeature,
206     ) -> &mut HashMap<ConnectionHandle, NaiveDateTime> {
207         match pending_type {
208             PendingRemoteFeature::Supported => &mut self.pending_supported_feat,
209             PendingRemoteFeature::Extended => &mut self.pending_extended_feat,
210             PendingRemoteFeature::Le => &mut self.pending_le_feat,
211         }
212     }
213 
process_remote_feat_cmd( &mut self, feat_type: PendingRemoteFeature, handle: &ConnectionHandle, packet: &Packet, )214     fn process_remote_feat_cmd(
215         &mut self,
216         feat_type: PendingRemoteFeature,
217         handle: &ConnectionHandle,
218         packet: &Packet,
219     ) {
220         self.get_feature_pending_map(&feat_type).insert(*handle, packet.ts);
221         self.last_feat_handle.insert(feat_type, *handle);
222     }
223 
process_disconnect_cmd( &mut self, reason: DisconnectReason, handle: ConnectionHandle, packet: &Packet, )224     fn process_disconnect_cmd(
225         &mut self,
226         reason: DisconnectReason,
227         handle: ConnectionHandle,
228         packet: &Packet,
229     ) {
230         // If reason is power off, the host might not wait for connection complete event
231         if reason == DisconnectReason::RemoteDeviceTerminatedConnectionPowerOff {
232             self.process_disconn_complete_ev(handle, packet);
233             self.pending_disconnect_due_to_host_power_off.insert(handle);
234         }
235     }
236 
process_command_status(&mut self, status: ErrorCode, opcode: OpCode, packet: &Packet)237     fn process_command_status(&mut self, status: ErrorCode, opcode: OpCode, packet: &Packet) {
238         match opcode {
239             OpCode::CreateConnection
240             | OpCode::AcceptConnectionRequest
241             | OpCode::SetupSynchronousConnection
242             | OpCode::AcceptSynchronousConnection
243             | OpCode::EnhancedSetupSynchronousConnection
244             | OpCode::EnhancedAcceptSynchronousConnection
245             | OpCode::LeCreateConnection
246             | OpCode::LeExtendedCreateConnection => {
247                 self.process_command_status_conn(status, opcode, packet);
248             }
249 
250             OpCode::ReadRemoteSupportedFeatures
251             | OpCode::ReadRemoteExtendedFeatures
252             | OpCode::LeReadRemoteFeatures => {
253                 self.process_command_status_feat(status, opcode, packet);
254             }
255 
256             _ => {}
257         }
258     }
259 
process_command_status_conn(&mut self, status: ErrorCode, opcode: OpCode, packet: &Packet)260     fn process_command_status_conn(&mut self, status: ErrorCode, opcode: OpCode, packet: &Packet) {
261         // Clear last connection attempt since it was successful.
262         let last_address = match opcode {
263             OpCode::CreateConnection | OpCode::AcceptConnectionRequest => {
264                 self.last_connection_attempt.take()
265             }
266 
267             OpCode::SetupSynchronousConnection
268             | OpCode::AcceptSynchronousConnection
269             | OpCode::EnhancedSetupSynchronousConnection
270             | OpCode::EnhancedAcceptSynchronousConnection => {
271                 self.last_sco_connection_attempt.take()
272             }
273 
274             OpCode::LeCreateConnection | OpCode::LeExtendedCreateConnection => {
275                 self.last_le_connection_attempt.take()
276             }
277 
278             _ => return,
279         };
280 
281         if let Some(address) = last_address {
282             if status != ErrorCode::Success {
283                 self.reportable.push((
284                     packet.ts,
285                     format!("Failing command status on [{}]: {:?}", address, opcode),
286                 ));
287 
288                 // Also remove the connection attempt.
289                 match opcode {
290                     OpCode::CreateConnection | OpCode::AcceptConnectionRequest => {
291                         self.connection_attempt.remove(&address);
292                     }
293 
294                     OpCode::SetupSynchronousConnection
295                     | OpCode::AcceptSynchronousConnection
296                     | OpCode::EnhancedSetupSynchronousConnection
297                     | OpCode::EnhancedAcceptSynchronousConnection => {
298                         self.sco_connection_attempt.remove(&address);
299                     }
300 
301                     OpCode::LeCreateConnection | OpCode::LeExtendedCreateConnection => {
302                         self.le_connection_attempt.remove(&address);
303                         self.last_le_connection_filter_policy = None;
304                     }
305 
306                     _ => (),
307                 }
308             }
309         } else {
310             if status != ErrorCode::Success {
311                 self.reportable.push((
312                     packet.ts,
313                     format!("Failing command status on unknown address: {:?}", opcode),
314                 ));
315             }
316         }
317     }
318 
process_command_status_feat(&mut self, status: ErrorCode, opcode: OpCode, packet: &Packet)319     fn process_command_status_feat(&mut self, status: ErrorCode, opcode: OpCode, packet: &Packet) {
320         let feat_type = match opcode {
321             OpCode::ReadRemoteSupportedFeatures => PendingRemoteFeature::Supported,
322             OpCode::ReadRemoteExtendedFeatures => PendingRemoteFeature::Extended,
323             OpCode::LeReadRemoteFeatures => PendingRemoteFeature::Le,
324             _ => return,
325         };
326 
327         // If handle is not known, probably the request comes before btsnoop starts. In any case,
328         // the command complete event will still complain. So let's just return here.
329         let handle = match self.last_feat_handle.remove(&feat_type) {
330             Some(handle) => handle,
331             None => return,
332         };
333 
334         // If failed, there won't be a following command complete event. So treat this as the
335         // command complete.
336         if status != ErrorCode::Success {
337             self.process_remote_feat_ev(feat_type, status, handle, packet);
338         }
339     }
340 
process_conn_complete_ev( &mut self, status: ErrorCode, handle: ConnectionHandle, address: Address, packet: &Packet, )341     fn process_conn_complete_ev(
342         &mut self,
343         status: ErrorCode,
344         handle: ConnectionHandle,
345         address: Address,
346         packet: &Packet,
347     ) {
348         if let Some(_) = self.connection_attempt.remove(&address) {
349             if status == ErrorCode::Success {
350                 self.active_handles.insert(handle, (packet.ts, address));
351                 self.pending_disconnect_due_to_host_power_off.remove(&handle);
352             } else {
353                 self.reportable.push((
354                     packet.ts,
355                     format!(
356                         "ConnectionComplete error {:?} for addr {} (handle={})",
357                         status, address, handle
358                     ),
359                 ));
360             }
361         } else {
362             self.reportable.push((
363                 packet.ts,
364                 format!(
365                     "ConnectionComplete with status {:?} for unknown addr {} (handle={})",
366                     status, address, handle
367                 ),
368             ));
369         }
370     }
371 
process_disconn_complete_ev(&mut self, handle: ConnectionHandle, packet: &Packet)372     fn process_disconn_complete_ev(&mut self, handle: ConnectionHandle, packet: &Packet) {
373         // If previously host send disconnect with power off reason, disconnection has been handled.
374         if self.pending_disconnect_due_to_host_power_off.remove(&handle) {
375             return;
376         }
377 
378         self.active_handles.remove(&handle);
379 
380         // Check if this is a NOCP type disconnection and flag it.
381         if let Some(nocp_data) = self.nocp_by_handle.get_mut(&handle) {
382             if let Some(acl_front_ts) = nocp_data.inflight_acl_ts.pop_front() {
383                 let duration_since_acl = packet.ts.signed_duration_since(acl_front_ts);
384                 if duration_since_acl.num_milliseconds() > TIMEOUT_TOLERANCE_TIME_MS {
385                     self.signals.push(Signal {
386                         index: packet.index,
387                         ts: packet.ts,
388                         tag: ConnectionSignal::NocpDisconnect.into(),
389                     });
390 
391                     self.reportable.push((
392                         packet.ts,
393                         format!("DisconnectionComplete for handle({}) showed incomplete in-flight ACL at {}",
394                         handle, acl_front_ts)));
395                 }
396             }
397         }
398         // Remove nocp information for handles that were removed.
399         self.nocp_by_handle.remove(&handle);
400 
401         // Check if auth payload timeout happened.
402         if let Some(apte_count) = self.apte_by_handle.remove(&handle) {
403             self.signals.push(Signal {
404                 index: packet.index,
405                 ts: packet.ts,
406                 tag: ConnectionSignal::ApteDisconnect.into(),
407             });
408 
409             self.reportable.push((
410                 packet.ts,
411                 format!("DisconnectionComplete with {} Authenticated Payload Timeout Expired (handle={})",
412                 apte_count, handle))
413             );
414         }
415 
416         // Check if remote feature request is pending
417         for feat_type in PendingRemoteFeature::iterate_all() {
418             if let Some(ts) = self.get_feature_pending_map(feat_type).remove(&handle) {
419                 let elapsed_time_ms = packet.ts.signed_duration_since(ts).num_milliseconds();
420                 if elapsed_time_ms > TIMEOUT_TOLERANCE_TIME_MS {
421                     self.signals.push(Signal {
422                         index: packet.index,
423                         ts: packet.ts,
424                         tag: ConnectionSignal::RemoteFeatureNoReply.into(),
425                     });
426 
427                     self.reportable.push((
428                         packet.ts,
429                         format!(
430                             "Handle {} doesn't respond to {:?} feature request at {}.",
431                             handle,
432                             feat_type,
433                             ts.time()
434                         ),
435                     ));
436                 }
437             }
438         }
439     }
440 
process_sync_conn_complete_ev( &mut self, status: ErrorCode, handle: ConnectionHandle, address: Address, packet: &Packet, )441     fn process_sync_conn_complete_ev(
442         &mut self,
443         status: ErrorCode,
444         handle: ConnectionHandle,
445         address: Address,
446         packet: &Packet,
447     ) {
448         if let Some(_) = self.sco_connection_attempt.remove(&address) {
449             if status == ErrorCode::Success {
450                 self.active_handles.insert(handle, (packet.ts, address));
451                 self.pending_disconnect_due_to_host_power_off.remove(&handle);
452             } else {
453                 self.reportable.push((
454                     packet.ts,
455                     format!(
456                         "SynchronousConnectionComplete error {:?} for addr {} (handle={})",
457                         status, address, handle
458                     ),
459                 ));
460             }
461         } else {
462             self.reportable.push((
463                 packet.ts,
464                 format!(
465                     "SynchronousConnectionComplete with status {:?} for unknown addr {} (handle={})",
466                     status,
467                     address,
468                     handle
469                 ),
470             ));
471         }
472     }
473 
process_le_conn_complete_ev( &mut self, status: ErrorCode, handle: ConnectionHandle, address: Address, packet: &Packet, )474     fn process_le_conn_complete_ev(
475         &mut self,
476         status: ErrorCode,
477         handle: ConnectionHandle,
478         address: Address,
479         packet: &Packet,
480     ) {
481         let use_accept_list = self
482             .last_le_connection_filter_policy
483             .map_or(false, |policy| policy == InitiatorFilterPolicy::UseFilterAcceptList);
484         let addr_to_remove =
485             if use_accept_list { hcidoc_packets::hci::EMPTY_ADDRESS } else { address };
486 
487         if let Some(_) = self.le_connection_attempt.remove(&addr_to_remove) {
488             if status == ErrorCode::Success {
489                 self.active_handles.insert(handle, (packet.ts, address));
490                 self.pending_disconnect_due_to_host_power_off.remove(&handle);
491             } else {
492                 let message = if use_accept_list {
493                     format!("LeConnectionComplete error {:?} for accept list", status)
494                 } else {
495                     format!(
496                         "LeConnectionComplete error {:?} for addr {} (handle={})",
497                         status, address, handle
498                     )
499                 };
500                 self.reportable.push((packet.ts, message));
501             }
502         } else {
503             self.reportable.push((
504                 packet.ts,
505                 format!(
506                     "LeConnectionComplete with status {:?} for unknown addr {} (handle={})",
507                     status, address, handle
508                 ),
509             ));
510         }
511     }
512 
process_acl_tx(&mut self, acl_tx: &Acl, packet: &Packet)513     fn process_acl_tx(&mut self, acl_tx: &Acl, packet: &Packet) {
514         let handle = acl_tx.get_handle();
515 
516         // Insert empty Nocp data for handle if it doesn't exist.
517         if !self.nocp_by_handle.contains_key(&handle) {
518             self.nocp_by_handle.insert(handle, NocpData::new());
519         }
520 
521         if let Some(nocp_data) = self.nocp_by_handle.get_mut(&handle) {
522             nocp_data.inflight_acl_ts.push_back(packet.ts);
523         }
524     }
525 
process_nocp(&mut self, nocp: &NumberOfCompletedPackets, packet: &Packet)526     fn process_nocp(&mut self, nocp: &NumberOfCompletedPackets, packet: &Packet) {
527         let ts = &packet.ts;
528         for completed_packet in nocp.get_completed_packets() {
529             let handle = completed_packet.connection_handle;
530             let num = completed_packet.host_num_of_completed_packets;
531             if !self.nocp_by_handle.contains_key(&handle) {
532                 self.nocp_by_handle.insert(handle, NocpData::new());
533             }
534 
535             if let Some(nocp_data) = self.nocp_by_handle.get_mut(&handle) {
536                 for _i in 0..num {
537                     if let Some(acl_front_ts) = nocp_data.inflight_acl_ts.pop_front() {
538                         let duration_since_acl = ts.signed_duration_since(acl_front_ts);
539                         if duration_since_acl.num_milliseconds() > TIMEOUT_TOLERANCE_TIME_MS {
540                             self.signals.push(Signal {
541                                 index: packet.index,
542                                 ts: packet.ts,
543                                 tag: ConnectionSignal::NocpTimeout.into(),
544                             });
545                             self.reportable.push((
546                                 packet.ts,
547                                 format!(
548                                     "Nocp sent {} ms after ACL on handle({}).",
549                                     duration_since_acl.num_milliseconds(),
550                                     handle
551                                 ),
552                             ));
553                         }
554                     }
555                 }
556             }
557         }
558     }
559 
process_apte(&mut self, apte: &AuthenticatedPayloadTimeoutExpired, _packet: &Packet)560     fn process_apte(&mut self, apte: &AuthenticatedPayloadTimeoutExpired, _packet: &Packet) {
561         let handle = apte.get_connection_handle();
562         *self.apte_by_handle.entry(handle).or_insert(0) += 1;
563     }
564 
process_remote_feat_ev( &mut self, feat_type: PendingRemoteFeature, status: ErrorCode, handle: ConnectionHandle, packet: &Packet, )565     fn process_remote_feat_ev(
566         &mut self,
567         feat_type: PendingRemoteFeature,
568         status: ErrorCode,
569         handle: ConnectionHandle,
570         packet: &Packet,
571     ) {
572         let feat_map = self.get_feature_pending_map(&feat_type);
573 
574         if feat_map.remove(&handle) == None {
575             self.reportable.push((
576                 packet.ts,
577                 format!("Got remote {:?} for unknown handle {}", feat_type, handle),
578             ));
579         }
580 
581         if status != ErrorCode::Success {
582             self.signals.push(Signal {
583                 index: packet.index,
584                 ts: packet.ts,
585                 tag: ConnectionSignal::RemoteFeatureError.into(),
586             });
587 
588             self.reportable.push((
589                 packet.ts,
590                 format!("Got {:?} for remote {:?} feature, handle {}", status, feat_type, handle),
591             ));
592         }
593     }
594 
process_reset(&mut self)595     fn process_reset(&mut self) {
596         self.active_handles.clear();
597         self.connection_attempt.clear();
598         self.last_connection_attempt = None;
599         self.le_connection_attempt.clear();
600         self.last_le_connection_attempt = None;
601         self.last_le_connection_filter_policy = None;
602         self.sco_connection_attempt.clear();
603         self.last_sco_connection_attempt = None;
604         self.accept_list.clear();
605         self.nocp_by_handle.clear();
606         self.apte_by_handle.clear();
607         self.pending_supported_feat.clear();
608         self.pending_extended_feat.clear();
609         self.pending_le_feat.clear();
610         self.last_feat_handle.clear();
611         self.pending_disconnect_due_to_host_power_off.clear();
612     }
613 
process_system_note(&mut self, note: &String)614     fn process_system_note(&mut self, note: &String) {
615         // Carryover section doesn't contain the NOCP from the controller.
616         // The note may contain zero bytes, so don't check for exact string.
617         if note.contains("END OF CARRYOVER SECTION") {
618             self.nocp_by_handle.clear();
619         }
620     }
621 }
622 
623 impl Rule for OddDisconnectionsRule {
process(&mut self, packet: &Packet)624     fn process(&mut self, packet: &Packet) {
625         match &packet.inner {
626             PacketChild::HciCommand(cmd) => match cmd.specialize() {
627                 CommandChild::CreateConnection(cc) => {
628                     self.process_classic_connection(cc.get_bd_addr(), packet);
629                 }
630                 CommandChild::AcceptConnectionRequest(ac) => {
631                     self.process_classic_connection(ac.get_bd_addr(), packet);
632                 }
633                 CommandChild::ReadRemoteSupportedFeatures(rrsf) => {
634                     self.process_remote_feat_cmd(
635                         PendingRemoteFeature::Supported,
636                         &rrsf.get_connection_handle(),
637                         packet,
638                     );
639                 }
640                 CommandChild::ReadRemoteExtendedFeatures(rref) => {
641                     self.process_remote_feat_cmd(
642                         PendingRemoteFeature::Extended,
643                         &rref.get_connection_handle(),
644                         packet,
645                     );
646                 }
647                 CommandChild::SetupSynchronousConnection(ssc) => {
648                     let address = self.convert_sco_handle_to_address(ssc.get_connection_handle());
649                     self.process_sync_connection(address, packet);
650                 }
651                 CommandChild::EnhancedSetupSynchronousConnection(esc) => {
652                     let address = self.convert_sco_handle_to_address(esc.get_connection_handle());
653                     self.process_sync_connection(address, packet);
654                 }
655                 CommandChild::AcceptSynchronousConnection(asc) => {
656                     self.process_sync_connection(asc.get_bd_addr(), packet);
657                 }
658                 CommandChild::EnhancedAcceptSynchronousConnection(easc) => {
659                     self.process_sync_connection(easc.get_bd_addr(), packet);
660                 }
661                 CommandChild::LeCreateConnection(lcc) => {
662                     self.process_le_create_connection(
663                         lcc.get_peer_address(),
664                         lcc.get_initiator_filter_policy(),
665                         packet,
666                     );
667                 }
668                 CommandChild::LeExtendedCreateConnection(lecc) => {
669                     self.process_le_create_connection(
670                         lecc.get_peer_address(),
671                         lecc.get_initiator_filter_policy(),
672                         packet,
673                     );
674                 }
675                 CommandChild::LeAddDeviceToFilterAcceptList(laac) => {
676                     self.process_add_accept_list(laac.get_address(), packet);
677                 }
678                 CommandChild::LeRemoveDeviceFromFilterAcceptList(lrac) => {
679                     self.process_remove_accept_list(lrac.get_address(), packet);
680                 }
681                 CommandChild::LeClearFilterAcceptList(_lcac) => {
682                     self.process_clear_accept_list(packet);
683                 }
684                 CommandChild::LeReadRemoteFeatures(lrrf) => {
685                     self.process_remote_feat_cmd(
686                         PendingRemoteFeature::Le,
687                         &lrrf.get_connection_handle(),
688                         packet,
689                     );
690                 }
691                 CommandChild::Disconnect(dc_conn) => {
692                     self.process_disconnect_cmd(
693                         dc_conn.get_reason(),
694                         dc_conn.get_connection_handle(),
695                         packet,
696                     );
697                 }
698                 CommandChild::Reset(_) => {
699                     self.process_reset();
700                 }
701 
702                 // End HciCommand.specialize()
703                 _ => (),
704             },
705 
706             PacketChild::HciEvent(ev) => match ev.specialize() {
707                 EventChild::CommandStatus(cs) => {
708                     self.process_command_status(cs.get_status(), cs.get_command_op_code(), packet);
709                 }
710                 EventChild::ConnectionComplete(cc) => {
711                     self.process_conn_complete_ev(
712                         cc.get_status(),
713                         cc.get_connection_handle(),
714                         cc.get_bd_addr(),
715                         packet,
716                     );
717                 }
718                 EventChild::DisconnectionComplete(dsc) => {
719                     self.process_disconn_complete_ev(dsc.get_connection_handle(), packet);
720                 }
721                 EventChild::SynchronousConnectionComplete(scc) => {
722                     self.process_sync_conn_complete_ev(
723                         scc.get_status(),
724                         scc.get_connection_handle(),
725                         scc.get_bd_addr(),
726                         packet,
727                     );
728                 }
729                 EventChild::NumberOfCompletedPackets(nocp) => {
730                     self.process_nocp(&nocp, packet);
731                 }
732 
733                 EventChild::AuthenticatedPayloadTimeoutExpired(apte) => {
734                     self.process_apte(&apte, packet);
735                 }
736                 EventChild::ReadRemoteSupportedFeaturesComplete(rsfc) => {
737                     self.process_remote_feat_ev(
738                         PendingRemoteFeature::Supported,
739                         rsfc.get_status(),
740                         rsfc.get_connection_handle(),
741                         packet,
742                     );
743                 }
744                 EventChild::ReadRemoteExtendedFeaturesComplete(refc) => {
745                     self.process_remote_feat_ev(
746                         PendingRemoteFeature::Extended,
747                         refc.get_status(),
748                         refc.get_connection_handle(),
749                         packet,
750                     );
751                 }
752                 EventChild::LeMetaEvent(lme) => match lme.specialize() {
753                     LeMetaEventChild::LeConnectionComplete(lcc) => {
754                         self.process_le_conn_complete_ev(
755                             lcc.get_status(),
756                             lcc.get_connection_handle(),
757                             lcc.get_peer_address(),
758                             packet,
759                         );
760                     }
761                     LeMetaEventChild::LeEnhancedConnectionComplete(lecc) => {
762                         self.process_le_conn_complete_ev(
763                             lecc.get_status(),
764                             lecc.get_connection_handle(),
765                             lecc.get_peer_address(),
766                             packet,
767                         );
768                     }
769                     LeMetaEventChild::LeReadRemoteFeaturesComplete(lrrfc) => {
770                         self.process_remote_feat_ev(
771                             PendingRemoteFeature::Le,
772                             lrrfc.get_status(),
773                             lrrfc.get_connection_handle(),
774                             packet,
775                         );
776                     }
777                     // End LeMetaEvent.specialize()
778                     _ => {}
779                 },
780 
781                 // End HciEvent.specialize()
782                 _ => (),
783             },
784 
785             // Use tx packets for nocp tracking.
786             PacketChild::AclTx(tx) => {
787                 self.process_acl_tx(&tx, packet);
788             }
789 
790             // We don't do anything with RX packets yet.
791             PacketChild::AclRx(_) => (),
792 
793             PacketChild::SystemNote(note) => {
794                 self.process_system_note(note);
795             }
796 
797             // End packet.inner match
798             _ => (),
799         }
800     }
801 
report(&self, writer: &mut dyn Write)802     fn report(&self, writer: &mut dyn Write) {
803         if self.reportable.len() > 0 {
804             let _ = writeln!(writer, "OddDisconnectionsRule report:");
805             for (ts, message) in self.reportable.iter() {
806                 let _ = writeln!(writer, "[{:?}] {}", ts, message);
807             }
808         }
809     }
810 
report_signals(&self) -> &[Signal]811     fn report_signals(&self) -> &[Signal] {
812         self.signals.as_slice()
813     }
814 }
815 
816 // What state are we in for the LinkKeyMismatchRule state?
817 #[derive(Debug, PartialEq)]
818 enum LinkKeyMismatchState {
819     Requested, // Controller requested link key to the host
820     Replied,   // Host replied the link key
821 }
822 
823 /// Identifies instances when the peer forgets the link key or it mismatches with ours.
824 /// For classic connections, first the controller asks for the link key via Link Key Request, then
825 /// the host replies with Link Key Request Reply, finally the controller will report the result,
826 /// usually via AuthenticationComplete.
827 /// For LE connections, the host passes the Long Term Key (LTK) via LE Start Encryption, then the
828 /// controller reports the result via Encryption Change event. There are also LE Long Term Key
829 /// Requests from the controller, but that is only used when the device is a peripheral.
830 struct LinkKeyMismatchRule {
831     /// Addresses in authenticating process
832     states: HashMap<Address, LinkKeyMismatchState>,
833 
834     /// Active handles
835     handles: HashMap<ConnectionHandle, Address>,
836 
837     /// Handles pending for LE encryption
838     pending_le_encrypt: HashSet<ConnectionHandle>,
839 
840     /// Pre-defined signals discovered in the logs.
841     signals: Vec<Signal>,
842 
843     /// Interesting occurrences surfaced by this rule.
844     reportable: Vec<(NaiveDateTime, String)>,
845 }
846 
847 impl LinkKeyMismatchRule {
new() -> Self848     pub fn new() -> Self {
849         LinkKeyMismatchRule {
850             states: HashMap::new(),
851             handles: HashMap::new(),
852             pending_le_encrypt: HashSet::new(),
853             signals: vec![],
854             reportable: vec![],
855         }
856     }
857 
process_address_auth(&mut self, status: ErrorCode, address: Address, packet: &Packet)858     fn process_address_auth(&mut self, status: ErrorCode, address: Address, packet: &Packet) {
859         if status == ErrorCode::AuthenticationFailure {
860             if let Some(LinkKeyMismatchState::Replied) = self.states.get(&address) {
861                 self.signals.push(Signal {
862                     index: packet.index,
863                     ts: packet.ts,
864                     tag: ConnectionSignal::LinkKeyMismatch.into(),
865                 });
866 
867                 self.reportable.push((
868                     packet.ts,
869                     format!("Peer {} forgets the link key, or it mismatches with ours.", address),
870                 ));
871             }
872         }
873         self.states.remove(&address);
874     }
875 
process_handle_auth( &mut self, status: ErrorCode, handle: ConnectionHandle, packet: &Packet, )876     fn process_handle_auth(
877         &mut self,
878         status: ErrorCode,
879         handle: ConnectionHandle,
880         packet: &Packet,
881     ) {
882         if let Some(address) = self.handles.get(&handle) {
883             self.process_address_auth(status, *address, packet);
884         }
885     }
886 
process_request_link_key(&mut self, address: Address)887     fn process_request_link_key(&mut self, address: Address) {
888         self.states.insert(address, LinkKeyMismatchState::Requested);
889     }
890 
process_reply_link_key(&mut self, address: Address, key_exist: bool)891     fn process_reply_link_key(&mut self, address: Address, key_exist: bool) {
892         if !key_exist {
893             self.states.remove(&address);
894             return;
895         }
896 
897         if let Some(LinkKeyMismatchState::Requested) = self.states.get(&address) {
898             self.states.insert(address, LinkKeyMismatchState::Replied);
899         }
900     }
901 
process_encryption_change( &mut self, status: ErrorCode, handle: ConnectionHandle, packet: &Packet, )902     fn process_encryption_change(
903         &mut self,
904         status: ErrorCode,
905         handle: ConnectionHandle,
906         packet: &Packet,
907     ) {
908         if status != ErrorCode::Success {
909             let address_format = self
910                 .handles
911                 .get(&handle)
912                 .map_or(format!("handle {}", handle), |addr| format!("{}", addr));
913             self.reportable.push((
914                 packet.ts,
915                 format!("Encryption failure with {:?} for {}", status, address_format),
916             ));
917 
918             if self.pending_le_encrypt.contains(&handle) {
919                 self.signals.push(Signal {
920                     index: packet.index,
921                     ts: packet.ts,
922                     tag: ConnectionSignal::LongTermKeyMismatch.into(),
923                 });
924             }
925         }
926 
927         self.pending_le_encrypt.remove(&handle);
928     }
929 
process_reset(&mut self)930     fn process_reset(&mut self) {
931         self.states.clear();
932         self.handles.clear();
933         self.pending_le_encrypt.clear();
934     }
935 }
936 
937 impl Rule for LinkKeyMismatchRule {
process(&mut self, packet: &Packet)938     fn process(&mut self, packet: &Packet) {
939         match &packet.inner {
940             PacketChild::HciEvent(ev) => match ev.specialize() {
941                 EventChild::ConnectionComplete(ev) => {
942                     if ev.get_status() == ErrorCode::Success {
943                         self.handles.insert(ev.get_connection_handle(), ev.get_bd_addr());
944                     }
945                 }
946                 EventChild::LinkKeyRequest(ev) => {
947                     self.process_request_link_key(ev.get_bd_addr());
948                 }
949                 EventChild::SimplePairingComplete(ev) => {
950                     self.process_address_auth(ev.get_status(), ev.get_bd_addr(), &packet);
951                 }
952                 EventChild::AuthenticationComplete(ev) => {
953                     self.process_handle_auth(ev.get_status(), ev.get_connection_handle(), &packet);
954                 }
955                 EventChild::DisconnectionComplete(ev) => {
956                     self.process_handle_auth(ev.get_status(), ev.get_connection_handle(), &packet);
957                     self.handles.remove(&ev.get_connection_handle());
958                 }
959                 EventChild::EncryptionChange(ev) => {
960                     self.process_encryption_change(
961                         ev.get_status(),
962                         ev.get_connection_handle(),
963                         &packet,
964                     );
965                 }
966                 EventChild::LeMetaEvent(ev) => match ev.specialize() {
967                     LeMetaEventChild::LeConnectionComplete(ev) => {
968                         if ev.get_status() == ErrorCode::Success {
969                             self.handles.insert(ev.get_connection_handle(), ev.get_peer_address());
970                         }
971                     }
972                     LeMetaEventChild::LeEnhancedConnectionComplete(ev) => {
973                         if ev.get_status() == ErrorCode::Success {
974                             self.handles.insert(ev.get_connection_handle(), ev.get_peer_address());
975                         }
976                     }
977 
978                     // EventChild::LeMetaEvent(ev).specialize()
979                     _ => {}
980                 },
981 
982                 // PacketChild::HciEvent(ev).specialize()
983                 _ => {}
984             },
985 
986             PacketChild::HciCommand(cmd) => match cmd.specialize() {
987                 // Have an arm for Disconnect since sometimes we don't receive disconnect
988                 // event when powering off. However, no need to actually match the reason
989                 // since we just clean the handle in both cases.
990                 CommandChild::Disconnect(cmd) => {
991                     self.process_handle_auth(
992                         ErrorCode::Success,
993                         cmd.get_connection_handle(),
994                         &packet,
995                     );
996                     self.handles.remove(&cmd.get_connection_handle());
997                 }
998                 CommandChild::LinkKeyRequestReply(cmd) => {
999                     self.process_reply_link_key(cmd.get_bd_addr(), true);
1000                 }
1001                 CommandChild::LinkKeyRequestNegativeReply(cmd) => {
1002                     self.process_reply_link_key(cmd.get_bd_addr(), false);
1003                 }
1004                 CommandChild::LeStartEncryption(cmd) => {
1005                     self.pending_le_encrypt.insert(cmd.get_connection_handle());
1006                 }
1007                 CommandChild::Reset(_) => {
1008                     self.process_reset();
1009                 }
1010 
1011                 // PacketChild::HciCommand(cmd).specialize()
1012                 _ => {}
1013             },
1014 
1015             // packet.inner
1016             _ => {}
1017         }
1018     }
1019 
report(&self, writer: &mut dyn Write)1020     fn report(&self, writer: &mut dyn Write) {
1021         if self.reportable.len() > 0 {
1022             let _ = writeln!(writer, "LinkKeyMismatchRule report:");
1023             for (ts, message) in self.reportable.iter() {
1024                 let _ = writeln!(writer, "[{:?}] {}", ts, message);
1025             }
1026         }
1027     }
1028 
report_signals(&self) -> &[Signal]1029     fn report_signals(&self) -> &[Signal] {
1030         self.signals.as_slice()
1031     }
1032 }
1033 
1034 struct SecurityMode3Rule {
1035     /// Pre-defined signals discovered in the logs.
1036     signals: Vec<Signal>,
1037 
1038     /// Interesting occurrences surfaced by this rule.
1039     reportable: Vec<(NaiveDateTime, String)>,
1040 }
1041 
1042 impl SecurityMode3Rule {
new() -> Self1043     pub fn new() -> Self {
1044         SecurityMode3Rule { signals: vec![], reportable: vec![] }
1045     }
1046 
process_connect_complete( &mut self, status: ErrorCode, address: Address, encryption_enabled: Enable, packet: &Packet, )1047     fn process_connect_complete(
1048         &mut self,
1049         status: ErrorCode,
1050         address: Address,
1051         encryption_enabled: Enable,
1052         packet: &Packet,
1053     ) {
1054         // See figure 5.2 and 5.3 in BT spec v5.4 Vol 3 Part C 5.2 for security mode 3 explanation.
1055         // It is indicated by encryption before the link setup is complete.
1056         // Therefore we just need to observe the encryption_enabled parameter in conn complete evt.
1057         if status == ErrorCode::Success && encryption_enabled == Enable::Enabled {
1058             self.signals.push(Signal {
1059                 index: packet.index,
1060                 ts: packet.ts,
1061                 tag: ConnectionSignal::SecurityMode3.into(),
1062             });
1063 
1064             self.reportable.push((
1065                 packet.ts,
1066                 format!("Device {} uses unsupported legacy security mode 3 (b/260625799)", address),
1067             ));
1068         }
1069     }
1070 }
1071 
1072 impl Rule for SecurityMode3Rule {
process(&mut self, packet: &Packet)1073     fn process(&mut self, packet: &Packet) {
1074         match &packet.inner {
1075             PacketChild::HciEvent(ev) => match ev.specialize() {
1076                 EventChild::ConnectionComplete(ev) => {
1077                     self.process_connect_complete(
1078                         ev.get_status(),
1079                         ev.get_bd_addr(),
1080                         ev.get_encryption_enabled(),
1081                         packet,
1082                     );
1083                 }
1084                 _ => {}
1085             },
1086             _ => {}
1087         }
1088     }
1089 
report(&self, writer: &mut dyn Write)1090     fn report(&self, writer: &mut dyn Write) {
1091         if self.reportable.len() > 0 {
1092             let _ = writeln!(writer, "SecurityMode3Rule report:");
1093             for (ts, message) in self.reportable.iter() {
1094                 let _ = writeln!(writer, "[{:?}] {}", ts, message);
1095             }
1096         }
1097     }
1098 
report_signals(&self) -> &[Signal]1099     fn report_signals(&self) -> &[Signal] {
1100         self.signals.as_slice()
1101     }
1102 }
1103 
1104 /// Get a rule group with connection rules.
get_connections_group() -> RuleGroup1105 pub fn get_connections_group() -> RuleGroup {
1106     let mut group = RuleGroup::new();
1107     group.add_rule(Box::new(LinkKeyMismatchRule::new()));
1108     group.add_rule(Box::new(OddDisconnectionsRule::new()));
1109     group.add_rule(Box::new(SecurityMode3Rule::new()));
1110 
1111     group
1112 }
1113