1 /******************************************************************************
3 * Copyright 2001-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * This file contains BNEP utility functions
23 ******************************************************************************/
30 #include "bt_common.h"
35 #include "device/include/controller.h"
36 #include "osi/include/osi.h"
38 using bluetooth::Uuid;
40 /******************************************************************************/
41 /* L O C A L F U N C T I O N P R O T O T Y P E S */
42 /******************************************************************************/
43 static uint8_t* bnepu_init_hdr(BT_HDR* p_buf, uint16_t hdr_len,
46 void bnepu_process_peer_multicast_filter_set(tBNEP_CONN* p_bcb,
47 uint8_t* p_filters, uint16_t len);
48 void bnepu_send_peer_multicast_filter_rsp(tBNEP_CONN* p_bcb,
49 uint16_t response_code);
51 /*******************************************************************************
53 * Function bnepu_find_bcb_by_cid
55 * Description This function searches the bcb table for an entry with the
58 * Returns the BCB address, or NULL if not found.
60 ******************************************************************************/
61 tBNEP_CONN* bnepu_find_bcb_by_cid(uint16_t cid) {
65 /* Look through each connection control block */
66 for (xx = 0, p_bcb = bnep_cb.bcb; xx < BNEP_MAX_CONNECTIONS; xx++, p_bcb++) {
67 if ((p_bcb->con_state != BNEP_STATE_IDLE) && (p_bcb->l2cap_cid == cid))
71 /* If here, not found */
75 /*******************************************************************************
77 * Function bnepu_find_bcb_by_bd_addr
79 * Description This function searches the BCB table for an entry with the
80 * passed Bluetooth Address.
82 * Returns the BCB address, or NULL if not found.
84 ******************************************************************************/
85 tBNEP_CONN* bnepu_find_bcb_by_bd_addr(const RawAddress& p_bda) {
89 /* Look through each connection control block */
90 for (xx = 0, p_bcb = bnep_cb.bcb; xx < BNEP_MAX_CONNECTIONS; xx++, p_bcb++) {
91 if (p_bcb->con_state != BNEP_STATE_IDLE) {
92 if (p_bcb->rem_bda == p_bda) return (p_bcb);
96 /* If here, not found */
100 /*******************************************************************************
102 * Function bnepu_allocate_bcb
104 * Description This function allocates a new BCB.
106 * Returns BCB address, or NULL if none available.
108 ******************************************************************************/
109 tBNEP_CONN* bnepu_allocate_bcb(const RawAddress& p_rem_bda) {
113 /* Look through each connection control block for a free one */
114 for (xx = 0, p_bcb = bnep_cb.bcb; xx < BNEP_MAX_CONNECTIONS; xx++, p_bcb++) {
115 if (p_bcb->con_state == BNEP_STATE_IDLE) {
116 alarm_free(p_bcb->conn_timer);
117 memset((uint8_t*)p_bcb, 0, sizeof(tBNEP_CONN));
118 p_bcb->conn_timer = alarm_new("bnep.conn_timer");
120 p_bcb->rem_bda = p_rem_bda;
121 p_bcb->handle = xx + 1;
122 p_bcb->xmit_q = fixed_queue_new(SIZE_MAX);
128 /* If here, no free BCB found */
132 /*******************************************************************************
134 * Function bnepu_release_bcb
136 * Description This function releases a BCB.
140 ******************************************************************************/
141 void bnepu_release_bcb(tBNEP_CONN* p_bcb) {
142 /* Ensure timer is stopped */
143 alarm_free(p_bcb->conn_timer);
144 p_bcb->conn_timer = NULL;
146 /* Drop any response pointer we may be holding */
147 p_bcb->con_state = BNEP_STATE_IDLE;
148 osi_free_and_reset((void**)&p_bcb->p_pending_data);
150 /* Free transmit queue */
151 while (!fixed_queue_is_empty(p_bcb->xmit_q)) {
152 osi_free(fixed_queue_try_dequeue(p_bcb->xmit_q));
154 fixed_queue_free(p_bcb->xmit_q, NULL);
155 p_bcb->xmit_q = NULL;
158 /*******************************************************************************
160 * Function bnep_send_conn_req
162 * Description This function sends a BNEP connection request to peer
166 ******************************************************************************/
167 void bnep_send_conn_req(tBNEP_CONN* p_bcb) {
168 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
169 uint8_t *p, *p_start;
171 BNEP_TRACE_DEBUG("%s: sending setup req with dst uuid %s", __func__,
172 p_bcb->dst_uuid.ToString().c_str());
174 p_buf->offset = L2CAP_MIN_OFFSET;
175 p = p_start = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
177 /* Put in BNEP frame type - filter control */
178 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
180 /* Put in filter message type - set filters */
181 UINT8_TO_BE_STREAM(p, BNEP_SETUP_CONNECTION_REQUEST_MSG);
183 int len = std::max(p_bcb->dst_uuid.GetShortestRepresentationSize(),
184 p_bcb->src_uuid.GetShortestRepresentationSize());
186 UINT8_TO_BE_STREAM(p, len);
188 if (len == Uuid::kNumBytes16) {
189 UINT16_TO_BE_STREAM(p, p_bcb->dst_uuid.As16Bit());
190 UINT16_TO_BE_STREAM(p, p_bcb->src_uuid.As16Bit());
191 } else if (len == Uuid::kNumBytes32) {
192 UINT32_TO_BE_STREAM(p, p_bcb->dst_uuid.As32Bit());
193 UINT32_TO_BE_STREAM(p, p_bcb->src_uuid.As32Bit());
194 } else if (len == Uuid::kNumBytes128) {
195 memcpy(p, p_bcb->dst_uuid.To128BitBE().data(), Uuid::kNumBytes128);
196 p += Uuid::kNumBytes128;
197 memcpy(p, p_bcb->src_uuid.To128BitBE().data(), Uuid::kNumBytes128);
198 p += Uuid::kNumBytes128;
200 BNEP_TRACE_ERROR("%s: uuid: %s, invalid length: %zu", __func__,
201 p_bcb->dst_uuid.ToString().c_str(),
202 p_bcb->dst_uuid.GetShortestRepresentationSize());
205 p_buf->len = (uint16_t)(p - p_start);
207 bnepu_check_send_packet(p_bcb, p_buf);
210 /*******************************************************************************
212 * Function bnep_send_conn_responce
214 * Description This function sends a BNEP setup response to peer
218 ******************************************************************************/
219 void bnep_send_conn_responce(tBNEP_CONN* p_bcb, uint16_t resp_code) {
220 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
223 BNEP_TRACE_EVENT("BNEP - bnep_send_conn_responce for CID: 0x%x",
226 p_buf->offset = L2CAP_MIN_OFFSET;
227 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
229 /* Put in BNEP frame type - filter control */
230 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
232 /* Put in filter message type - set filters */
233 UINT8_TO_BE_STREAM(p, BNEP_SETUP_CONNECTION_RESPONSE_MSG);
235 UINT16_TO_BE_STREAM(p, resp_code);
239 bnepu_check_send_packet(p_bcb, p_buf);
242 /*******************************************************************************
244 * Function bnepu_send_peer_our_filters
246 * Description This function sends our filters to a peer
250 ******************************************************************************/
251 void bnepu_send_peer_our_filters(tBNEP_CONN* p_bcb) {
252 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
256 BNEP_TRACE_DEBUG("BNEP sending peer our filters");
258 p_buf->offset = L2CAP_MIN_OFFSET;
259 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
261 /* Put in BNEP frame type - filter control */
262 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
264 /* Put in filter message type - set filters */
265 UINT8_TO_BE_STREAM(p, BNEP_FILTER_NET_TYPE_SET_MSG);
267 UINT16_TO_BE_STREAM(p, (4 * p_bcb->sent_num_filters));
268 for (xx = 0; xx < p_bcb->sent_num_filters; xx++) {
269 UINT16_TO_BE_STREAM(p, p_bcb->sent_prot_filter_start[xx]);
270 UINT16_TO_BE_STREAM(p, p_bcb->sent_prot_filter_end[xx]);
273 p_buf->len = 4 + (4 * p_bcb->sent_num_filters);
275 bnepu_check_send_packet(p_bcb, p_buf);
277 p_bcb->con_flags |= BNEP_FLAGS_FILTER_RESP_PEND;
279 /* Start timer waiting for setup response */
280 alarm_set_on_mloop(p_bcb->conn_timer, BNEP_FILTER_SET_TIMEOUT_MS,
281 bnep_conn_timer_timeout, p_bcb);
284 /*******************************************************************************
286 * Function bnepu_send_peer_our_multi_filters
288 * Description This function sends our multicast filters to a peer
292 ******************************************************************************/
293 void bnepu_send_peer_our_multi_filters(tBNEP_CONN* p_bcb) {
294 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
298 BNEP_TRACE_DEBUG("BNEP sending peer our multicast filters");
300 p_buf->offset = L2CAP_MIN_OFFSET;
301 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
303 /* Put in BNEP frame type - filter control */
304 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
306 /* Put in filter message type - set filters */
307 UINT8_TO_BE_STREAM(p, BNEP_FILTER_MULTI_ADDR_SET_MSG);
309 UINT16_TO_BE_STREAM(p, (2 * BD_ADDR_LEN * p_bcb->sent_mcast_filters));
310 for (xx = 0; xx < p_bcb->sent_mcast_filters; xx++) {
311 memcpy(p, p_bcb->sent_mcast_filter_start[xx].address, BD_ADDR_LEN);
313 memcpy(p, p_bcb->sent_mcast_filter_end[xx].address, BD_ADDR_LEN);
317 p_buf->len = 4 + (2 * BD_ADDR_LEN * p_bcb->sent_mcast_filters);
319 bnepu_check_send_packet(p_bcb, p_buf);
321 p_bcb->con_flags |= BNEP_FLAGS_MULTI_RESP_PEND;
323 /* Start timer waiting for setup response */
324 alarm_set_on_mloop(p_bcb->conn_timer, BNEP_FILTER_SET_TIMEOUT_MS,
325 bnep_conn_timer_timeout, p_bcb);
328 /*******************************************************************************
330 * Function bnepu_send_peer_filter_rsp
332 * Description This function sends a filter response to a peer
336 ******************************************************************************/
337 void bnepu_send_peer_filter_rsp(tBNEP_CONN* p_bcb, uint16_t response_code) {
338 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
341 BNEP_TRACE_DEBUG("BNEP sending filter response");
343 p_buf->offset = L2CAP_MIN_OFFSET;
344 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
346 /* Put in BNEP frame type - filter control */
347 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
349 /* Put in filter message type - set filters */
350 UINT8_TO_BE_STREAM(p, BNEP_FILTER_NET_TYPE_RESPONSE_MSG);
352 UINT16_TO_BE_STREAM(p, response_code);
356 bnepu_check_send_packet(p_bcb, p_buf);
359 /*******************************************************************************
361 * Function bnep_send_command_not_understood
363 * Description This function sends a BNEP command not understood message
367 ******************************************************************************/
368 void bnep_send_command_not_understood(tBNEP_CONN* p_bcb, uint8_t cmd_code) {
369 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
373 "BNEP - bnep_send_command_not_understood for CID: 0x%x, cmd 0x%x",
374 p_bcb->l2cap_cid, cmd_code);
376 p_buf->offset = L2CAP_MIN_OFFSET;
377 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
379 /* Put in BNEP frame type - filter control */
380 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
382 /* Put in filter message type - set filters */
383 UINT8_TO_BE_STREAM(p, BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD);
385 UINT8_TO_BE_STREAM(p, cmd_code);
389 bnepu_check_send_packet(p_bcb, p_buf);
392 /*******************************************************************************
394 * Function bnepu_check_send_packet
396 * Description This function tries to send a packet to L2CAP.
397 * If L2CAP is flow controlled, it enqueues the
398 * packet to the transmit queue
402 ******************************************************************************/
403 void bnepu_check_send_packet(tBNEP_CONN* p_bcb, BT_HDR* p_buf) {
404 BNEP_TRACE_EVENT("BNEP - bnepu_check_send_packet for CID: 0x%x",
406 if (p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED) {
407 if (fixed_queue_length(p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH) {
408 BNEP_TRACE_EVENT("BNEP - congested, dropping buf, CID: 0x%x",
413 fixed_queue_enqueue(p_bcb->xmit_q, p_buf);
416 L2CA_DataWrite(p_bcb->l2cap_cid, p_buf);
420 /*******************************************************************************
422 * Function bnepu_build_bnep_hdr
424 * Description This function builds the BNEP header for a packet
425 * Extension headers are not sent yet, so there is no
430 ******************************************************************************/
431 void bnepu_build_bnep_hdr(tBNEP_CONN* p_bcb, BT_HDR* p_buf, uint16_t protocol,
432 const RawAddress* p_src_addr,
433 const RawAddress* p_dest_addr, bool fw_ext_present) {
434 const controller_t* controller = controller_get_interface();
435 uint8_t ext_bit, *p = (uint8_t*)NULL;
436 uint8_t type = BNEP_FRAME_COMPRESSED_ETHERNET;
438 ext_bit = fw_ext_present ? 0x80 : 0x00;
440 if (p_src_addr && *p_src_addr != *controller->get_address())
441 type = BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY;
443 if (*p_dest_addr != p_bcb->rem_bda)
444 type = (type == BNEP_FRAME_COMPRESSED_ETHERNET)
445 ? BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY
446 : BNEP_FRAME_GENERAL_ETHERNET;
448 if (!p_src_addr) p_src_addr = controller->get_address();
451 case BNEP_FRAME_GENERAL_ETHERNET:
452 p = bnepu_init_hdr(p_buf, 15,
453 (uint8_t)(ext_bit | BNEP_FRAME_GENERAL_ETHERNET));
455 memcpy(p, p_dest_addr->address, BD_ADDR_LEN);
458 memcpy(p, p_src_addr->address, BD_ADDR_LEN);
462 case BNEP_FRAME_COMPRESSED_ETHERNET:
463 p = bnepu_init_hdr(p_buf, 3,
464 (uint8_t)(ext_bit | BNEP_FRAME_COMPRESSED_ETHERNET));
467 case BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY:
470 (uint8_t)(ext_bit | BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY));
472 memcpy(p, p_src_addr->address, BD_ADDR_LEN);
476 case BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY:
479 (uint8_t)(ext_bit | BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY));
481 memcpy(p, p_dest_addr->address, BD_ADDR_LEN);
486 UINT16_TO_BE_STREAM(p, protocol);
489 /*******************************************************************************
491 * Function bnepu_init_hdr
493 * Description This function initializes the BNEP header
495 * Returns pointer to header in buffer
497 ******************************************************************************/
498 static uint8_t* bnepu_init_hdr(BT_HDR* p_buf, uint16_t hdr_len,
500 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
502 /* See if we need to make space in the buffer */
503 if (p_buf->offset < (hdr_len + L2CAP_MIN_OFFSET)) {
504 uint16_t xx, diff = BNEP_MINIMUM_OFFSET - p_buf->offset;
505 p = p + p_buf->len - 1;
506 for (xx = 0; xx < p_buf->len; xx++, p--) p[diff] = *p;
508 p_buf->offset = BNEP_MINIMUM_OFFSET;
509 p = (uint8_t*)(p_buf + 1) + p_buf->offset;
512 p_buf->len += hdr_len;
513 p_buf->offset -= hdr_len;
521 /*******************************************************************************
523 * Function bnep_process_setup_conn_req
525 * Description This function processes a peer's setup connection request
526 * message. The destination UUID is verified and response sent
527 * Connection open indication will be given to PAN profile
531 ******************************************************************************/
532 void bnep_process_setup_conn_req(tBNEP_CONN* p_bcb, uint8_t* p_setup,
534 BNEP_TRACE_EVENT("BNEP - %s for CID: 0x%x", __func__, p_bcb->l2cap_cid);
536 if (p_bcb->con_state != BNEP_STATE_CONN_SETUP &&
537 p_bcb->con_state != BNEP_STATE_SEC_CHECKING &&
538 p_bcb->con_state != BNEP_STATE_CONNECTED) {
539 BNEP_TRACE_ERROR("BNEP - setup request in bad state %d", p_bcb->con_state);
540 bnep_send_conn_responce(p_bcb, BNEP_SETUP_CONN_NOT_ALLOWED);
544 /* Check if we already initiated security check or if waiting for user
546 if (p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD) {
548 "BNEP - Duplicate Setup message received while doing security check");
552 /* Check if peer is the originator */
553 if (p_bcb->con_state != BNEP_STATE_CONNECTED &&
554 (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)) &&
555 (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)) {
556 BNEP_TRACE_ERROR("BNEP - setup request when we are originator",
558 bnep_send_conn_responce(p_bcb, BNEP_SETUP_CONN_NOT_ALLOWED);
562 if (p_bcb->con_state == BNEP_STATE_CONNECTED) {
563 p_bcb->prv_src_uuid = p_bcb->src_uuid;
564 p_bcb->prv_dst_uuid = p_bcb->dst_uuid;
567 if (len == Uuid::kNumBytes16) {
568 /* because peer initiated connection keep src uuid as dst uuid */
571 BE_STREAM_TO_UINT16(tmp, p_setup);
572 p_bcb->src_uuid = Uuid::From16Bit(tmp);
574 BE_STREAM_TO_UINT16(tmp, p_setup);
575 p_bcb->dst_uuid = Uuid::From16Bit(tmp);
577 /* If nothing has changed don't bother the profile */
578 if (p_bcb->con_state == BNEP_STATE_CONNECTED &&
579 p_bcb->src_uuid == p_bcb->prv_src_uuid &&
580 p_bcb->dst_uuid == p_bcb->prv_dst_uuid) {
581 bnep_send_conn_responce(p_bcb, BNEP_SETUP_CONN_OK);
584 } else if (len == Uuid::kNumBytes32) {
587 BE_STREAM_TO_UINT32(tmp, p_setup);
588 p_bcb->src_uuid = Uuid::From32Bit(tmp);
590 BE_STREAM_TO_UINT32(tmp, p_setup);
591 p_bcb->dst_uuid = Uuid::From32Bit(tmp);
592 } else if (len == Uuid::kNumBytes128) {
593 p_bcb->src_uuid = Uuid::From128BitBE(p_setup);
596 p_bcb->dst_uuid = Uuid::From128BitBE(p_setup);
599 BNEP_TRACE_ERROR("BNEP - Bad UID len %d in ConnReq", len);
600 bnep_send_conn_responce(p_bcb, BNEP_SETUP_INVALID_UUID_SIZE);
604 p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
605 p_bcb->con_flags |= BNEP_FLAGS_SETUP_RCVD;
608 "BNEP initiating security check for incoming call for uuid %s",
609 p_bcb->src_uuid.ToString().c_str());
610 #if (BNEP_DO_AUTH_FOR_ROLE_SWITCH == FALSE)
611 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
612 bnep_sec_check_complete(p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
615 btm_sec_mx_access_request(p_bcb->rem_bda, BT_PSM_BNEP, false,
616 BTM_SEC_PROTO_BNEP, p_bcb->src_uuid.As32Bit(),
617 &bnep_sec_check_complete, p_bcb);
622 /*******************************************************************************
624 * Function bnep_process_setup_conn_responce
626 * Description This function processes a peer's setup connection response
627 * message. The response code is verified and
628 * Connection open indication will be given to PAN profile
632 ******************************************************************************/
633 void bnep_process_setup_conn_responce(tBNEP_CONN* p_bcb, uint8_t* p_setup) {
637 BNEP_TRACE_DEBUG("BNEP received setup responce");
638 /* The state should be either SETUP or CONNECTED */
639 if (p_bcb->con_state != BNEP_STATE_CONN_SETUP) {
640 /* Should we disconnect ? */
641 BNEP_TRACE_ERROR("BNEP - setup response in bad state %d", p_bcb->con_state);
645 /* Check if we are the originator */
646 if (!(p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)) {
647 BNEP_TRACE_ERROR("BNEP - setup response when we are not originator",
652 BE_STREAM_TO_UINT16(resp_code, p_setup);
655 case BNEP_SETUP_INVALID_SRC_UUID:
656 resp = BNEP_CONN_FAILED_SRC_UUID;
659 case BNEP_SETUP_INVALID_DEST_UUID:
660 resp = BNEP_CONN_FAILED_DST_UUID;
663 case BNEP_SETUP_INVALID_UUID_SIZE:
664 resp = BNEP_CONN_FAILED_UUID_SIZE;
667 case BNEP_SETUP_CONN_NOT_ALLOWED:
669 resp = BNEP_CONN_FAILED;
673 /* Check the responce code */
674 if (resp_code != BNEP_SETUP_CONN_OK) {
675 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) {
676 BNEP_TRACE_EVENT("BNEP - role change response is %d", resp_code);
678 /* Restore the earlier BNEP status */
679 p_bcb->con_state = BNEP_STATE_CONNECTED;
680 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
681 p_bcb->src_uuid = p_bcb->prv_src_uuid;
682 p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
684 /* Ensure timer is stopped */
685 alarm_cancel(p_bcb->conn_timer);
686 p_bcb->re_transmits = 0;
688 /* Tell the user if he has a callback */
689 if (bnep_cb.p_conn_state_cb)
690 (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, resp, true);
694 BNEP_TRACE_ERROR("BNEP - setup response %d is not OK", resp_code);
696 L2CA_DisconnectReq(p_bcb->l2cap_cid);
698 /* Tell the user if he has a callback */
699 if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
700 (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, resp, false);
702 bnepu_release_bcb(p_bcb);
707 /* Received successful responce */
708 bnep_connected(p_bcb);
711 /*******************************************************************************
713 * Function bnep_process_control_packet
715 * Description This function processes a peer's setup connection request
716 * message. The destination UUID is verified and response sent
717 * Connection open indication will be given to PAN profile
721 ******************************************************************************/
722 uint8_t* bnep_process_control_packet(tBNEP_CONN* p_bcb, uint8_t* p,
723 uint16_t* rem_len, bool is_ext) {
724 uint8_t control_type;
725 uint16_t len, ext_len = 0;
727 if (p == NULL || rem_len == NULL) {
728 if (rem_len != NULL) *rem_len = 0;
729 BNEP_TRACE_DEBUG("%s: invalid packet: p = %p rem_len = %p", __func__, p,
733 uint16_t rem_len_orig = *rem_len;
736 if (*rem_len < 1) goto bad_packet_length;
738 *rem_len = *rem_len - 1;
741 if (*rem_len < 1) goto bad_packet_length;
743 *rem_len = *rem_len - 1;
746 "%s: BNEP processing control packet rem_len %d, is_ext %d, ctrl_type %d",
747 __func__, *rem_len, is_ext, control_type);
749 switch (control_type) {
750 case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD:
753 "%s: Received BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD with bad length",
755 goto bad_packet_length;
758 "%s: Received BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD for pkt type: %d",
761 *rem_len = *rem_len - 1;
764 case BNEP_SETUP_CONNECTION_REQUEST_MSG:
767 "%s: Received BNEP_SETUP_CONNECTION_REQUEST_MSG with bad length",
769 android_errorWriteLog(0x534e4554, "69177292");
770 goto bad_packet_length;
773 if (*rem_len < ((2 * len) + 1)) {
775 "%s: Received BNEP_SETUP_CONNECTION_REQUEST_MSG with bad length",
777 goto bad_packet_length;
779 if (!is_ext) bnep_process_setup_conn_req(p_bcb, p, (uint8_t)len);
781 *rem_len = *rem_len - (2 * len) - 1;
784 case BNEP_SETUP_CONNECTION_RESPONSE_MSG:
787 "%s: Received BNEP_SETUP_CONNECTION_RESPONSE_MSG with bad length",
789 goto bad_packet_length;
791 if (!is_ext) bnep_process_setup_conn_responce(p_bcb, p);
793 *rem_len = *rem_len - 2;
796 case BNEP_FILTER_NET_TYPE_SET_MSG:
799 "%s: Received BNEP_FILTER_NET_TYPE_SET_MSG with bad length",
801 android_errorWriteLog(0x534e4554, "69177292");
802 goto bad_packet_length;
804 BE_STREAM_TO_UINT16(len, p);
805 if (*rem_len < (len + 2)) {
807 "%s: Received BNEP_FILTER_NET_TYPE_SET_MSG with bad length",
809 goto bad_packet_length;
811 bnepu_process_peer_filter_set(p_bcb, p, len);
813 *rem_len = *rem_len - len - 2;
816 case BNEP_FILTER_NET_TYPE_RESPONSE_MSG:
819 "%s: Received BNEP_FILTER_NET_TYPE_RESPONSE_MSG with bad length",
821 goto bad_packet_length;
823 bnepu_process_peer_filter_rsp(p_bcb, p);
825 *rem_len = *rem_len - 2;
828 case BNEP_FILTER_MULTI_ADDR_SET_MSG:
831 "%s: Received BNEP_FILTER_MULTI_ADDR_SET_MSG with bad length",
833 android_errorWriteLog(0x534e4554, "69177292");
834 goto bad_packet_length;
836 BE_STREAM_TO_UINT16(len, p);
837 if (*rem_len < (len + 2)) {
839 "%s: Received BNEP_FILTER_MULTI_ADDR_SET_MSG with bad length",
841 goto bad_packet_length;
843 bnepu_process_peer_multicast_filter_set(p_bcb, p, len);
845 *rem_len = *rem_len - len - 2;
848 case BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG:
851 "%s: Received BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG with bad length",
853 goto bad_packet_length;
855 bnepu_process_multicast_filter_rsp(p_bcb, p);
857 *rem_len = *rem_len - 2;
861 BNEP_TRACE_ERROR("%s: BNEP - bad ctl pkt type: %d", __func__,
863 bnep_send_command_not_understood(p_bcb, control_type);
864 if (is_ext && (ext_len > 0)) {
865 if (*rem_len < (ext_len - 1)) {
866 goto bad_packet_length;
869 *rem_len -= (ext_len - 1);
876 BNEP_TRACE_ERROR("%s: bad control packet length: original=%d remaining=%d",
877 __func__, rem_len_orig, *rem_len);
882 /*******************************************************************************
884 * Function bnepu_process_peer_filter_set
886 * Description This function processes a peer's filter control
887 * 'set' message. The filters are stored in the BCB,
888 * and an appropriate filter response message sent.
892 ******************************************************************************/
893 void bnepu_process_peer_filter_set(tBNEP_CONN* p_bcb, uint8_t* p_filters,
895 uint16_t num_filters = 0;
896 uint16_t xx, resp_code = BNEP_FILTER_CRL_OK;
898 uint8_t* p_temp_filters;
900 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
901 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED))) {
903 "BNEP received filter set from peer when there is no connection");
907 BNEP_TRACE_DEBUG("BNEP received filter set from peer");
908 /* Check for length not a multiple of 4 */
910 BNEP_TRACE_EVENT("BNEP - bad filter len: %d", len);
911 bnepu_send_peer_filter_rsp(p_bcb, BNEP_FILTER_CRL_BAD_RANGE);
915 if (len) num_filters = (uint16_t)(len >> 2);
917 /* Validate filter values */
918 if (num_filters <= BNEP_MAX_PROT_FILTERS) {
919 p_temp_filters = p_filters;
920 for (xx = 0; xx < num_filters; xx++) {
921 BE_STREAM_TO_UINT16(start, p_temp_filters);
922 BE_STREAM_TO_UINT16(end, p_temp_filters);
925 resp_code = BNEP_FILTER_CRL_BAD_RANGE;
930 resp_code = BNEP_FILTER_CRL_MAX_REACHED;
932 if (resp_code != BNEP_FILTER_CRL_OK) {
933 bnepu_send_peer_filter_rsp(p_bcb, resp_code);
937 if (bnep_cb.p_filter_ind_cb)
938 (*bnep_cb.p_filter_ind_cb)(p_bcb->handle, true, 0, len, p_filters);
940 p_bcb->rcvd_num_filters = num_filters;
941 for (xx = 0; xx < num_filters; xx++) {
942 BE_STREAM_TO_UINT16(start, p_filters);
943 BE_STREAM_TO_UINT16(end, p_filters);
945 p_bcb->rcvd_prot_filter_start[xx] = start;
946 p_bcb->rcvd_prot_filter_end[xx] = end;
949 bnepu_send_peer_filter_rsp(p_bcb, resp_code);
952 /*******************************************************************************
954 * Function bnepu_process_peer_filter_rsp
956 * Description This function processes a peer's filter control
957 * 'response' message.
961 ******************************************************************************/
962 void bnepu_process_peer_filter_rsp(tBNEP_CONN* p_bcb, uint8_t* p_data) {
966 BNEP_TRACE_DEBUG("BNEP received filter responce");
967 /* The state should be CONNECTED */
968 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
969 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED))) {
970 BNEP_TRACE_ERROR("BNEP - filter response in bad state %d",
975 /* Check if we are the originator */
976 if (!(p_bcb->con_flags & BNEP_FLAGS_FILTER_RESP_PEND)) {
977 BNEP_TRACE_ERROR("BNEP - filter response when not expecting");
981 /* Ensure timer is stopped */
982 alarm_cancel(p_bcb->conn_timer);
983 p_bcb->con_flags &= ~BNEP_FLAGS_FILTER_RESP_PEND;
984 p_bcb->re_transmits = 0;
986 BE_STREAM_TO_UINT16(resp_code, p_data);
988 result = BNEP_SUCCESS;
989 if (resp_code != BNEP_FILTER_CRL_OK) result = BNEP_SET_FILTER_FAIL;
991 if (bnep_cb.p_filter_ind_cb)
992 (*bnep_cb.p_filter_ind_cb)(p_bcb->handle, false, result, 0, NULL);
995 /*******************************************************************************
997 * Function bnepu_process_multicast_filter_rsp
999 * Description This function processes multicast filter control
1000 * 'response' message.
1004 ******************************************************************************/
1005 void bnepu_process_multicast_filter_rsp(tBNEP_CONN* p_bcb, uint8_t* p_data) {
1007 tBNEP_RESULT result;
1009 BNEP_TRACE_DEBUG("BNEP received multicast filter responce");
1010 /* The state should be CONNECTED */
1011 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
1012 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED))) {
1013 BNEP_TRACE_ERROR("BNEP - multicast filter response in bad state %d",
1018 /* Check if we are the originator */
1019 if (!(p_bcb->con_flags & BNEP_FLAGS_MULTI_RESP_PEND)) {
1020 BNEP_TRACE_ERROR("BNEP - multicast filter response when not expecting");
1024 /* Ensure timer is stopped */
1025 alarm_cancel(p_bcb->conn_timer);
1026 p_bcb->con_flags &= ~BNEP_FLAGS_MULTI_RESP_PEND;
1027 p_bcb->re_transmits = 0;
1029 BE_STREAM_TO_UINT16(resp_code, p_data);
1031 result = BNEP_SUCCESS;
1032 if (resp_code != BNEP_FILTER_CRL_OK) result = BNEP_SET_FILTER_FAIL;
1034 if (bnep_cb.p_mfilter_ind_cb)
1035 (*bnep_cb.p_mfilter_ind_cb)(p_bcb->handle, false, result, 0, NULL);
1038 /*******************************************************************************
1040 * Function bnepu_process_peer_multicast_filter_set
1042 * Description This function processes a peer's filter control
1043 * 'set' message. The filters are stored in the BCB,
1044 * and an appropriate filter response message sent.
1048 ******************************************************************************/
1049 void bnepu_process_peer_multicast_filter_set(tBNEP_CONN* p_bcb,
1050 uint8_t* p_filters, uint16_t len) {
1051 uint16_t resp_code = BNEP_FILTER_CRL_OK;
1052 uint16_t num_filters, xx;
1053 uint8_t *p_temp_filters, null_bda[BD_ADDR_LEN] = {0, 0, 0, 0, 0, 0};
1055 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
1056 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED))) {
1058 "BNEP received multicast filter set from peer when there is no "
1064 BNEP_TRACE_EVENT("BNEP - bad filter len: %d", len);
1065 bnepu_send_peer_multicast_filter_rsp(p_bcb, BNEP_FILTER_CRL_BAD_RANGE);
1069 if (len > (BNEP_MAX_MULTI_FILTERS * 2 * BD_ADDR_LEN)) {
1070 BNEP_TRACE_EVENT("BNEP - Too many filters");
1071 bnepu_send_peer_multicast_filter_rsp(p_bcb, BNEP_FILTER_CRL_MAX_REACHED);
1076 if (len) num_filters = (uint16_t)(len / 12);
1078 /* Validate filter values */
1079 if (num_filters <= BNEP_MAX_MULTI_FILTERS) {
1080 p_temp_filters = p_filters;
1081 for (xx = 0; xx < num_filters; xx++) {
1082 if (memcmp(p_temp_filters, p_temp_filters + BD_ADDR_LEN, BD_ADDR_LEN) >
1084 bnepu_send_peer_multicast_filter_rsp(p_bcb, BNEP_FILTER_CRL_BAD_RANGE);
1088 p_temp_filters += (BD_ADDR_LEN * 2);
1092 p_bcb->rcvd_mcast_filters = num_filters;
1093 for (xx = 0; xx < num_filters; xx++) {
1094 memcpy(p_bcb->rcvd_mcast_filter_start[xx].address, p_filters, BD_ADDR_LEN);
1095 memcpy(p_bcb->rcvd_mcast_filter_end[xx].address, p_filters + BD_ADDR_LEN,
1097 p_filters += (BD_ADDR_LEN * 2);
1099 /* Check if any of the ranges have all zeros as both starting and ending
1101 if ((memcmp(null_bda, p_bcb->rcvd_mcast_filter_start[xx].address,
1102 BD_ADDR_LEN) == 0) &&
1103 (memcmp(null_bda, p_bcb->rcvd_mcast_filter_end[xx].address,
1104 BD_ADDR_LEN) == 0)) {
1105 p_bcb->rcvd_mcast_filters = 0xFFFF;
1110 BNEP_TRACE_EVENT("BNEP multicast filters %d", p_bcb->rcvd_mcast_filters);
1111 bnepu_send_peer_multicast_filter_rsp(p_bcb, resp_code);
1113 if (bnep_cb.p_mfilter_ind_cb)
1114 (*bnep_cb.p_mfilter_ind_cb)(p_bcb->handle, true, 0, len, p_filters);
1117 /*******************************************************************************
1119 * Function bnepu_send_peer_multicast_filter_rsp
1121 * Description This function sends a filter response to a peer
1125 ******************************************************************************/
1126 void bnepu_send_peer_multicast_filter_rsp(tBNEP_CONN* p_bcb,
1127 uint16_t response_code) {
1128 BT_HDR* p_buf = (BT_HDR*)osi_malloc(BNEP_BUF_SIZE);
1131 BNEP_TRACE_DEBUG("BNEP sending multicast filter response %d", response_code);
1133 p_buf->offset = L2CAP_MIN_OFFSET;
1134 p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
1136 /* Put in BNEP frame type - filter control */
1137 UINT8_TO_BE_STREAM(p, BNEP_FRAME_CONTROL);
1139 /* Put in filter message type - set filters */
1140 UINT8_TO_BE_STREAM(p, BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG);
1142 UINT16_TO_BE_STREAM(p, response_code);
1146 bnepu_check_send_packet(p_bcb, p_buf);
1149 /*******************************************************************************
1151 * Function bnep_sec_check_complete
1153 * Description This function is registered with BTM and will be called
1154 * after completing the security procedures
1158 ******************************************************************************/
1159 void bnep_sec_check_complete(UNUSED_ATTR const RawAddress* bd_addr,
1160 UNUSED_ATTR tBT_TRANSPORT trasnport,
1161 void* p_ref_data, uint8_t result) {
1162 tBNEP_CONN* p_bcb = (tBNEP_CONN*)p_ref_data;
1163 uint16_t resp_code = BNEP_SETUP_CONN_OK;
1164 bool is_role_change;
1166 BNEP_TRACE_EVENT("BNEP security callback returned result %d", result);
1167 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
1168 is_role_change = true;
1170 is_role_change = false;
1172 /* check if the port is still waiting for security to complete */
1173 if (p_bcb->con_state != BNEP_STATE_SEC_CHECKING) {
1175 "BNEP Connection in wrong state %d when security is completed",
1180 /* if it is outgoing call and result is FAILURE return security fail error */
1181 if (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)) {
1182 if (result != BTM_SUCCESS) {
1183 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) {
1184 /* Tell the user that role change is failed because of security */
1185 if (bnep_cb.p_conn_state_cb)
1186 (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda,
1187 BNEP_SECURITY_FAIL, is_role_change);
1189 p_bcb->con_state = BNEP_STATE_CONNECTED;
1190 p_bcb->src_uuid = p_bcb->prv_src_uuid;
1191 p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
1195 L2CA_DisconnectReq(p_bcb->l2cap_cid);
1197 /* Tell the user if he has a callback */
1198 if (bnep_cb.p_conn_state_cb)
1199 (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda,
1200 BNEP_SECURITY_FAIL, is_role_change);
1202 bnepu_release_bcb(p_bcb);
1206 /* Transition to the next appropriate state, waiting for connection confirm.
1208 p_bcb->con_state = BNEP_STATE_CONN_SETUP;
1210 bnep_send_conn_req(p_bcb);
1211 alarm_set_on_mloop(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS,
1212 bnep_conn_timer_timeout, p_bcb);
1216 /* it is an incoming call respond appropriately */
1217 if (result != BTM_SUCCESS) {
1218 bnep_send_conn_responce(p_bcb, BNEP_SETUP_CONN_NOT_ALLOWED);
1219 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) {
1220 /* Role change is failed because of security. Revert back to connected
1222 p_bcb->con_state = BNEP_STATE_CONNECTED;
1223 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
1224 p_bcb->src_uuid = p_bcb->prv_src_uuid;
1225 p_bcb->dst_uuid = p_bcb->prv_dst_uuid;
1229 L2CA_DisconnectReq(p_bcb->l2cap_cid);
1231 bnepu_release_bcb(p_bcb);
1235 if (bnep_cb.p_conn_ind_cb) {
1236 p_bcb->con_state = BNEP_STATE_CONN_SETUP;
1237 (*bnep_cb.p_conn_ind_cb)(p_bcb->handle, p_bcb->rem_bda, p_bcb->dst_uuid,
1238 p_bcb->src_uuid, is_role_change);
1240 /* Profile didn't register connection indication call back */
1241 bnep_send_conn_responce(p_bcb, resp_code);
1242 bnep_connected(p_bcb);
1248 /*******************************************************************************
1250 * Function bnep_is_packet_allowed
1252 * Description This function verifies whether the protocol passes through
1253 * the protocol filters set by the peer
1255 * Returns BNEP_SUCCESS - if the protocol is allowed
1256 * BNEP_IGNORE_CMD - if the protocol is filtered out
1258 ******************************************************************************/
1259 tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
1260 const RawAddress& p_dest_addr,
1261 uint16_t protocol, bool fw_ext_present,
1263 if (p_bcb->rcvd_num_filters) {
1266 /* Findout the actual protocol to check for the filtering */
1268 if (proto == BNEP_802_1_P_PROTOCOL) {
1269 if (fw_ext_present) {
1271 /* parse the extension headers and findout actual protocol */
1277 } while (ext & 0x80);
1280 BE_STREAM_TO_UINT16(proto, p_data);
1283 for (i = 0; i < p_bcb->rcvd_num_filters; i++) {
1284 if ((p_bcb->rcvd_prot_filter_start[i] <= proto) &&
1285 (proto <= p_bcb->rcvd_prot_filter_end[i]))
1289 if (i == p_bcb->rcvd_num_filters) {
1290 BNEP_TRACE_DEBUG("Ignoring protocol 0x%x in BNEP data write", proto);
1291 return BNEP_IGNORE_CMD;
1295 /* Ckeck for multicast address filtering */
1296 if ((p_dest_addr.address[0] & 0x01) && p_bcb->rcvd_mcast_filters) {
1299 /* Check if every multicast should be filtered */
1300 if (p_bcb->rcvd_mcast_filters != 0xFFFF) {
1301 /* Check if the address is mentioned in the filter range */
1302 for (i = 0; i < p_bcb->rcvd_mcast_filters; i++) {
1303 if ((memcmp(p_bcb->rcvd_mcast_filter_start[i].address,
1304 p_dest_addr.address, BD_ADDR_LEN) <= 0) &&
1305 (memcmp(p_bcb->rcvd_mcast_filter_end[i].address,
1306 p_dest_addr.address, BD_ADDR_LEN) >= 0))
1312 ** If every multicast should be filtered or the address is not in the filter
1316 if ((p_bcb->rcvd_mcast_filters == 0xFFFF) ||
1317 (i == p_bcb->rcvd_mcast_filters)) {
1318 VLOG(1) << "Ignoring multicast address " << p_dest_addr
1319 << " in BNEP data write";
1320 return BNEP_IGNORE_CMD;
1324 return BNEP_SUCCESS;