Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c49d759 authored by Chris Manton's avatar Chris Manton Committed by Gerrit Code Review
Browse files

Merge changes I9d219c14,I77d03ae1 into main

* changes:
  stack::l2cap Security check uses btm_status
  stack::l2cap Explicit initialize tL2C_CONN_INFO
parents 3bb63109 6ae4e8c6
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -696,10 +696,16 @@ bool L2CA_ConnectCreditBasedRsp(const RawAddress& p_bd_addr, uint8_t id,
    return false;
  }

  tL2C_CONN_INFO conn_info;
  conn_info.lcids = accepted_lcids;
  conn_info.bd_addr = p_bd_addr;
  conn_info.l2cap_result = result;
  tL2C_CONN_INFO conn_info = {
          .bd_addr = p_bd_addr,
          .status{},
          .psm{},
          .l2cap_result = result,
          .l2cap_status{},
          .remote_cid{},
          .lcids = accepted_lcids,
          .peer_mtu{},
  };

  if (accepted_lcids.size() > 0) {
    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CREDIT_BASED_CONNECT_RSP, &conn_info);
+22 −11
Original line number Diff line number Diff line
@@ -234,7 +234,6 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
  uint8_t cmd_code, id;
  uint16_t cmd_len;
  uint16_t min_interval, max_interval, latency, timeout;
  tL2C_CONN_INFO con_info;
  uint16_t lcid = 0, rcid = 0, mtu = 0, mps = 0, initial_credit = 0;
  tL2C_CCB *p_ccb = NULL, *temp_p_ccb = NULL;
  tL2C_RCB* p_rcb;
@@ -261,8 +260,6 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {

  switch (cmd_code) {
    case L2CAP_CMD_REJECT: {
      uint16_t reason;

      if (p + 2 > p_pkt_end) {
        log::error(
                "invalid L2CAP_CMD_REJECT packet, not containing enough data for "
@@ -270,10 +267,20 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        return;
      }

      uint16_t reason{};
      STREAM_TO_UINT16(reason, p);

      if (reason == L2CAP_CMD_REJ_NOT_UNDERSTOOD && p_lcb->pending_ecoc_conn_cnt > 0) {
        con_info.l2cap_result = L2CAP_LE_RESULT_NO_PSM;
        tL2C_CONN_INFO con_info = {
                .bd_addr{},
                .status{},
                .psm{},
                .l2cap_result = L2CAP_LE_RESULT_NO_PSM,
                .l2cap_status{},
                .remote_cid{},
                .lcids{},
                .peer_mtu{},
        };
        l2cble_handle_connect_rsp_neg(p_lcb, &con_info);
      }
    } break;
@@ -336,6 +343,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        return;
      }

      tL2C_CONN_INFO con_info{};
      STREAM_TO_UINT16(con_info.psm, p);
      STREAM_TO_UINT16(mtu, p);
      STREAM_TO_UINT16(mps, p);
@@ -448,7 +456,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_REQ, NULL);
      break;
    }
    case L2CAP_CMD_CREDIT_BASED_CONN_RES:
    case L2CAP_CMD_CREDIT_BASED_CONN_RES: {
      if (p + 8 > p_pkt_end) {
        log::error("invalid L2CAP_CMD_CREDIT_BASED_CONN_RES len");
        return;
@@ -465,12 +473,14 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      }

      if (!p_ccb) {
        tL2C_CONN_INFO con_info{};
        log::verbose("Cannot find matching connection req");
        con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_SOURCE_CID;
        l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
        return;
      }

      tL2C_CONN_INFO con_info{};
      STREAM_TO_UINT16(mtu, p);
      STREAM_TO_UINT16(mps, p);
      STREAM_TO_UINT16(initial_credit, p);
@@ -571,8 +581,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
          l2c_csm_execute(temp_p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP, &con_info);
        }
      }

      break;
    } break;
    case L2CAP_CMD_CREDIT_BASED_RECONFIG_REQ: {
      if (p + 6 > p_pkt_end) {
        l2cu_send_ble_reconfig_rsp(p_lcb, id, L2CAP_RECONFIG_UNACCAPTED_PARAM);
@@ -675,7 +684,8 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      break;
    }

    case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ:
    case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ: {
      tL2C_CONN_INFO con_info{};
      if (p + 10 > p_pkt_end) {
        log::error("invalid read");
        return;
@@ -750,9 +760,10 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      p_ccb->connection_initiator = L2CAP_INITIATOR_REMOTE;

      l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
      break;
    } break;

    case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES:
    case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES: {
      tL2C_CONN_INFO con_info{};
      log::verbose("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES");
      /* For all channels, see whose identifier matches this id */
      for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb;
@@ -808,7 +819,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_SOURCE_CID;
        l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
      }
      break;
    } break;

    case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT:
      if (p + 4 > p_pkt_end) {
+1 −1
Original line number Diff line number Diff line
@@ -532,7 +532,7 @@ static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event, void* p_dat
      break;

    case L2CEVT_SEC_COMP_NEG:
      if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) {
      if (((tL2C_CONN_INFO*)p_data)->status == static_cast<tHCI_STATUS>(BTM_DELAY_CHECK)) {
        /* start a timer - encryption change not received before L2CAP connect
         * req */
        alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS,
+36 −16
Original line number Diff line number Diff line
@@ -62,13 +62,20 @@ static void l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf, tL2C_TX_COMPL
static BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb, tL2C_TX_COMPLETE_CB_INFO* p_cbi);

void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, const RawAddress& p_bda) {
  tL2C_CONN_INFO ci;
  tL2C_LCB* p_lcb;
  tL2C_CCB* p_ccb;

  /* Save the parameters */
  ci.status = status;
  ci.bd_addr = p_bda;
  tL2C_CONN_INFO ci = {
          .bd_addr = p_bda,
          .status = status,
          .psm{},
          .l2cap_result{},
          .l2cap_status{},
          .remote_cid{},
          .lcids{},
          .peer_mtu{},
  };

  /* See if we have a link control block for the remote device */
  p_lcb = l2cu_find_lcb_by_bd_addr(ci.bd_addr, BT_TRANSPORT_BR_EDR);
@@ -180,22 +187,29 @@ void l2c_link_hci_conn_comp(tHCI_STATUS status, uint16_t handle, const RawAddres
 *
 ******************************************************************************/
void l2c_link_sec_comp(RawAddress p_bda, tBT_TRANSPORT transport, void* p_ref_data,
                       tBTM_STATUS status) {
  tL2C_CONN_INFO ci;
                       tBTM_STATUS btm_status) {
  tL2C_LCB* p_lcb;
  tL2C_CCB* p_ccb;
  tL2C_CCB* p_next_ccb;

  log::debug("btm_status={}, BD_ADDR={}, transport={}", btm_status_text(status), p_bda,
  log::debug("btm_status={}, BD_ADDR={}, transport={}", btm_status_text(btm_status), p_bda,
             bt_transport_text(transport));

  if (status == BTM_SUCCESS_NO_SECURITY) {
    status = BTM_SUCCESS;
  if (btm_status == BTM_SUCCESS_NO_SECURITY) {
    btm_status = BTM_SUCCESS;
  }

  /* Save the parameters */
  ci.status = status;
  ci.bd_addr = p_bda;
  tL2C_CONN_INFO ci = {
          .bd_addr = p_bda,
          .status = static_cast<tHCI_STATUS>(btm_status),
          .psm{},
          .l2cap_result{},
          .l2cap_status{},
          .remote_cid{},
          .lcids{},
          .peer_mtu{},
  };

  p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, transport);

@@ -219,7 +233,7 @@ void l2c_link_sec_comp(RawAddress p_bda, tBT_TRANSPORT transport, void* p_ref_da
      return;
    }

    switch (status) {
    switch (btm_status) {
      case BTM_SUCCESS:
        l2c_csm_execute(p_ccb, L2CEVT_SEC_COMP, &ci);
        break;
@@ -241,7 +255,7 @@ void l2c_link_sec_comp(RawAddress p_bda, tBT_TRANSPORT transport, void* p_ref_da
      p_next_ccb = p_ccb->p_next_ccb;

      if (p_ccb == p_ref_data) {
        switch (status) {
        switch (btm_status) {
          case BTM_SUCCESS:
            l2c_csm_execute(p_ccb, L2CEVT_SEC_COMP, &ci);
            break;
@@ -508,7 +522,6 @@ void l2c_link_timeout(tL2C_LCB* p_lcb) {
void l2c_info_resp_timer_timeout(void* data) {
  tL2C_LCB* p_lcb = (tL2C_LCB*)data;
  tL2C_CCB* p_ccb;
  tL2C_CONN_INFO ci;

  /* If we timed out waiting for info response, just continue using basic if
   * allowed */
@@ -529,9 +542,16 @@ void l2c_info_resp_timer_timeout(void* data) {
    if ((p_lcb->link_state != LST_DISCONNECTED) && (p_lcb->link_state != LST_DISCONNECTING)) {
      /* Notify active channels that peer info is finished */
      if (p_lcb->ccb_queue.p_first_ccb) {
        ci.status = HCI_SUCCESS;
        ci.bd_addr = p_lcb->remote_bd_addr;

        tL2C_CONN_INFO ci = {
                .bd_addr = p_lcb->remote_bd_addr,
                .status = HCI_SUCCESS,
                .psm{},
                .l2cap_result{},
                .l2cap_status{},
                .remote_cid{},
                .lcids{},
                .peer_mtu{},
        };
        for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
          l2c_csm_execute(p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci);
        }
+28 −11
Original line number Diff line number Diff line
@@ -221,7 +221,6 @@ void l2c_rcv_acl_data(BT_HDR* p_msg) {
 *
 ******************************************************************************/
static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
  tL2C_CONN_INFO con_info;
  tL2C_RCB* p_rcb;

  /* if l2cap command received in CID 1 on top of an LE link, ignore this
@@ -346,9 +345,16 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
          alarm_cancel(p_lcb->info_resp_timer);

          p_lcb->w4_info_rsp = false;
          tL2C_CONN_INFO ci;
          ci.status = HCI_SUCCESS;
          ci.bd_addr = p_lcb->remote_bd_addr;
          tL2C_CONN_INFO ci = {
                  .bd_addr = p_lcb->remote_bd_addr,
                  .status = HCI_SUCCESS,
                  .psm{},
                  .l2cap_result{},
                  .l2cap_status{},
                  .remote_cid{},
                  .lcids{},
                  .peer_mtu{},
          };

          /* For all channels, send the event through their FSMs */
          for (tL2C_CCB* p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
@@ -358,7 +364,8 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        break;

      case L2CAP_CMD_CONN_REQ: {
        uint16_t rcid;
        tL2C_CONN_INFO con_info{};
        uint16_t rcid{};
        if (p + 4 > p_next_cmd) {
          log::warn("Not enough data for L2CAP_CMD_CONN_REQ");
          return;
@@ -401,7 +408,8 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      }

      case L2CAP_CMD_CONN_RSP: {
        uint16_t lcid;
        tL2C_CONN_INFO con_info{};
        uint16_t lcid{};
        if (p + 8 > p_next_cmd) {
          log::warn("Not enough data for L2CAP_CMD_CONN_REQ");
          return;
@@ -702,7 +710,7 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      }

      case L2CAP_CMD_DISC_REQ: {
        uint16_t lcid, rcid;
        uint16_t lcid{}, rcid{};
        if (p + 4 > p_next_cmd) {
          log::warn("Not enough data for L2CAP_CMD_DISC_REQ");
          return;
@@ -713,6 +721,7 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
        if (p_ccb) {
          if (p_ccb->remote_cid == rcid) {
            tL2C_CONN_INFO con_info{};
            p_ccb->remote_id = id;
            l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, &con_info);
          }
@@ -724,7 +733,7 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      }

      case L2CAP_CMD_DISC_RSP: {
        uint16_t lcid, rcid;
        uint16_t lcid{}, rcid{};
        if (p + 4 > p_next_cmd) {
          log::warn("Not enough data for L2CAP_CMD_DISC_RSP");
          return;
@@ -735,6 +744,7 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
        if (p_ccb) {
          if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id)) {
            tL2C_CONN_INFO con_info{};
            l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, &con_info);
          }
        }
@@ -798,9 +808,16 @@ static void process_l2cap_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
          l2cu_process_fixed_chnl_resp(p_lcb);
        }
        {
          tL2C_CONN_INFO ci;
          ci.status = HCI_SUCCESS;
          ci.bd_addr = p_lcb->remote_bd_addr;
          tL2C_CONN_INFO ci = {
                  .bd_addr = p_lcb->remote_bd_addr,
                  .status = HCI_SUCCESS,
                  .psm{},
                  .l2cap_result{},
                  .l2cap_status{},
                  .remote_cid{},
                  .lcids{},
                  .peer_mtu{},
          };
          for (tL2C_CCB* p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
            l2c_csm_execute(p_ccb, L2CEVT_L2CAP_INFO_RSP, &ci);
          }