OSDN Git Service

BNEP: Fix OOB access in bnep_data_ind
[android-x86/system-bt.git] / stack / bnep / bnep_main.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 2001-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18
19 /******************************************************************************
20  *
21  *  this file contains the main BNEP functions
22  *
23  ******************************************************************************/
24
25 #include "bt_target.h"
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 #include "gki.h"
31 #include "bt_types.h"
32 #include "l2cdefs.h"
33 #include "hcidefs.h"
34 #include "hcimsgs.h"
35
36 #include "l2c_api.h"
37 #include "l2cdefs.h"
38 #include "log/log.h"
39
40 #include "btu.h"
41 #include "btm_api.h"
42
43 #include "bnep_api.h"
44 #include "bnep_int.h"
45 #include "bt_utils.h"
46
47 #include "device/include/controller.h"
48
49
50 /********************************************************************************/
51 /*                       G L O B A L    B N E P       D A T A                   */
52 /********************************************************************************/
53 #if BNEP_DYNAMIC_MEMORY == FALSE
54 tBNEP_CB   bnep_cb;
55 #endif
56
57 const UINT16 bnep_frame_hdr_sizes[] = {14, 1, 2, 8, 8};
58
59 /********************************************************************************/
60 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
61 /********************************************************************************/
62 static void bnep_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
63 static void bnep_connect_cfm (UINT16 l2cap_cid, UINT16 result);
64 static void bnep_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
65 static void bnep_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
66 static void bnep_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
67 static void bnep_disconnect_cfm (UINT16 l2cap_cid, UINT16 result);
68 static void bnep_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
69 static void bnep_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
70
71
72 /*******************************************************************************
73 **
74 ** Function         bnep_register_with_l2cap
75 **
76 ** Description      This function registers BNEP PSM with L2CAP
77 **
78 ** Returns          void
79 **
80 *******************************************************************************/
81 tBNEP_RESULT bnep_register_with_l2cap (void)
82 {
83     /* Initialize the L2CAP configuration. We only care about MTU and flush */
84     memset(&bnep_cb.l2cap_my_cfg, 0, sizeof(tL2CAP_CFG_INFO));
85
86     bnep_cb.l2cap_my_cfg.mtu_present            = TRUE;
87     bnep_cb.l2cap_my_cfg.mtu                    = BNEP_MTU_SIZE;
88     bnep_cb.l2cap_my_cfg.flush_to_present       = TRUE;
89     bnep_cb.l2cap_my_cfg.flush_to               = BNEP_FLUSH_TO;
90
91     bnep_cb.reg_info.pL2CA_ConnectInd_Cb        = bnep_connect_ind;
92     bnep_cb.reg_info.pL2CA_ConnectCfm_Cb        = bnep_connect_cfm;
93     bnep_cb.reg_info.pL2CA_ConfigInd_Cb         = bnep_config_ind;
94     bnep_cb.reg_info.pL2CA_ConfigCfm_Cb         = bnep_config_cfm;
95     bnep_cb.reg_info.pL2CA_DisconnectInd_Cb     = bnep_disconnect_ind;
96     bnep_cb.reg_info.pL2CA_DisconnectCfm_Cb     = bnep_disconnect_cfm;
97     bnep_cb.reg_info.pL2CA_DataInd_Cb           = bnep_data_ind;
98     bnep_cb.reg_info.pL2CA_CongestionStatus_Cb  = bnep_congestion_ind;
99
100     /* Now, register with L2CAP */
101     if (!L2CA_Register (BT_PSM_BNEP, &bnep_cb.reg_info))
102     {
103         BNEP_TRACE_ERROR ("BNEP - Registration failed");
104         return BNEP_SECURITY_FAIL;
105     }
106
107     return BNEP_SUCCESS;
108 }
109
110
111 /*******************************************************************************
112 **
113 ** Function         bnep_connect_ind
114 **
115 ** Description      This function handles an inbound connection indication
116 **                  from L2CAP. This is the case where we are acting as a
117 **                  server.
118 **
119 ** Returns          void
120 **
121 *******************************************************************************/
122 static void bnep_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
123 {
124     tBNEP_CONN    *p_bcb = bnepu_find_bcb_by_bd_addr (bd_addr);
125     UNUSED(psm);
126
127     /* If we are not acting as server, or already have a connection, or have */
128     /* no more resources to handle the connection, reject the connection.    */
129     if (!(bnep_cb.profile_registered) || (p_bcb)
130      || ((p_bcb = bnepu_allocate_bcb(bd_addr)) == NULL))
131     {
132         L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0);
133         return;
134     }
135
136     /* Transition to the next appropriate state, waiting for config setup. */
137     p_bcb->con_state = BNEP_STATE_CFG_SETUP;
138
139     /* Save the L2CAP Channel ID. */
140     p_bcb->l2cap_cid = l2cap_cid;
141
142     /* Send response to the L2CAP layer. */
143     L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
144
145     /* Send a Configuration Request. */
146     L2CA_ConfigReq (l2cap_cid, &bnep_cb.l2cap_my_cfg);
147
148     /* Start timer waiting for config setup */
149     btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
150
151     BNEP_TRACE_EVENT("BNEP - Rcvd L2CAP conn ind, CID: 0x%x", p_bcb->l2cap_cid);
152
153 }
154
155
156 /*******************************************************************************
157 **
158 ** Function         bnep_connect_cfm
159 **
160 ** Description      This function handles the connect confirm events
161 **                  from L2CAP. This is the case when we are acting as a
162 **                  client and have sent a connect request.
163 **
164 ** Returns          void
165 **
166 *******************************************************************************/
167 static void bnep_connect_cfm (UINT16 l2cap_cid, UINT16 result)
168 {
169     tBNEP_CONN    *bcb;
170
171     /* Find CCB based on CID */
172     if ((bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
173     {
174         BNEP_TRACE_WARNING ("BNEP - Rcvd conn cnf for unknown CID 0x%x", l2cap_cid);
175         return;
176     }
177
178     /* If the connection response contains success status, then */
179     /* Transition to the next state and startup the timer.      */
180     if ((result == L2CAP_CONN_OK) && (bcb->con_state == BNEP_STATE_CONN_START))
181     {
182         bcb->con_state = BNEP_STATE_CFG_SETUP;
183
184         /* Send a Configuration Request. */
185         L2CA_ConfigReq (l2cap_cid, &bnep_cb.l2cap_my_cfg);
186
187         /* Start timer waiting for config results */
188         btu_start_timer (&bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
189
190         BNEP_TRACE_EVENT ("BNEP - got conn cnf, sent cfg req, CID: 0x%x", bcb->l2cap_cid);
191     }
192     else
193     {
194         BNEP_TRACE_WARNING ("BNEP - Rcvd conn cnf with error: 0x%x  CID 0x%x", result, bcb->l2cap_cid);
195
196         /* Tell the upper layer, if he has a callback */
197         if (bnep_cb.p_conn_state_cb &&
198             bcb->con_flags & BNEP_FLAGS_IS_ORIG)
199         {
200             (*bnep_cb.p_conn_state_cb) (bcb->handle, bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
201         }
202
203         bnepu_release_bcb (bcb);
204     }
205 }
206
207 /*******************************************************************************
208 **
209 ** Function         bnep_config_ind
210 **
211 ** Description      This function processes the L2CAP configuration indication
212 **                  event.
213 **
214 ** Returns          void
215 **
216 *******************************************************************************/
217 static void bnep_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
218 {
219     tBNEP_CONN    *p_bcb;
220     UINT16        result, mtu = 0;
221
222     /* Find CCB based on CID */
223     if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
224     {
225         BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
226         return;
227     }
228
229     BNEP_TRACE_EVENT ("BNEP - Rcvd cfg ind, CID: 0x%x", l2cap_cid);
230
231     /* Remember the remote MTU size */
232     if ((!p_cfg->mtu_present) || (p_cfg->mtu < BNEP_MIN_MTU_SIZE))
233     {
234         mtu                     = p_cfg->mtu;
235         p_cfg->flush_to_present = FALSE;
236         p_cfg->mtu_present      = TRUE;
237         p_cfg->mtu              = BNEP_MIN_MTU_SIZE;
238         p_cfg->result           = result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
239     }
240     else
241     {
242         if (p_cfg->mtu > BNEP_MTU_SIZE)
243             p_bcb->rem_mtu_size = BNEP_MTU_SIZE;
244         else
245             p_bcb->rem_mtu_size = p_cfg->mtu;
246
247         /* For now, always accept configuration from the other side */
248         p_cfg->flush_to_present = FALSE;
249         p_cfg->mtu_present      = FALSE;
250         p_cfg->result           = result = L2CAP_CFG_OK;
251     }
252
253     L2CA_ConfigRsp (l2cap_cid, p_cfg);
254
255     if (result != L2CAP_CFG_OK)
256     {
257         BNEP_TRACE_EVENT ("BNEP - Rcvd cfg ind with bad MTU %d, CID: 0x%x", mtu, l2cap_cid);
258         return;
259     }
260
261     p_bcb->con_flags |= BNEP_FLAGS_HIS_CFG_DONE;
262
263     if (p_bcb->con_flags & BNEP_FLAGS_MY_CFG_DONE)
264     {
265         p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
266
267         /* Start timer waiting for setup or response */
268         btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_HOST_TIMEOUT);
269
270         if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)
271         {
272             btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
273                                        BTM_SEC_PROTO_BNEP,
274                                        bnep_get_uuid32(&(p_bcb->src_uuid)),
275                                        &bnep_sec_check_complete, p_bcb);
276         }
277     }
278 }
279
280
281 /*******************************************************************************
282 **
283 ** Function         bnep_config_cfm
284 **
285 ** Description      This function processes the L2CAP configuration confirmation
286 **                  event.
287 **
288 ** Returns          void
289 **
290 *******************************************************************************/
291 static void bnep_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
292 {
293     tBNEP_CONN    *p_bcb;
294
295     BNEP_TRACE_EVENT ("BNEP - Rcvd cfg cfm, CID: 0x%x  Result: %d", l2cap_cid, p_cfg->result);
296
297     /* Find CCB based on CID */
298     if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
299     {
300         BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
301         return;
302     }
303
304     /* For now, always accept configuration from the other side */
305     if (p_cfg->result == L2CAP_CFG_OK)
306     {
307         p_bcb->con_flags |= BNEP_FLAGS_MY_CFG_DONE;
308
309         if (p_bcb->con_flags & BNEP_FLAGS_HIS_CFG_DONE)
310         {
311             p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
312
313             /* Start timer waiting for setup or response */
314             btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_HOST_TIMEOUT);
315
316             if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)
317             {
318                 btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, TRUE,
319                                            BTM_SEC_PROTO_BNEP,
320                                            bnep_get_uuid32(&(p_bcb->src_uuid)),
321                                            &bnep_sec_check_complete, p_bcb);
322             }
323         }
324     }
325     else
326     {
327         /* Tell the upper layer, if he has a callback */
328         if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
329         {
330             (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED_CFG, FALSE);
331         }
332
333         L2CA_DisconnectReq (p_bcb->l2cap_cid);
334
335         bnepu_release_bcb (p_bcb);
336     }
337 }
338
339
340 /*******************************************************************************
341 **
342 ** Function         bnep_disconnect_ind
343 **
344 ** Description      This function handles a disconnect event from L2CAP. If
345 **                  requested to, we ack the disconnect before dropping the CCB
346 **
347 ** Returns          void
348 **
349 *******************************************************************************/
350 static void bnep_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
351 {
352     tBNEP_CONN    *p_bcb;
353
354     if (ack_needed)
355         L2CA_DisconnectRsp (l2cap_cid);
356
357     /* Find CCB based on CID */
358     if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
359     {
360         BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
361         return;
362     }
363
364     BNEP_TRACE_EVENT ("BNEP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
365
366     /* Tell the user if he has a callback */
367     if (p_bcb->con_state == BNEP_STATE_CONNECTED)
368     {
369         if (bnep_cb.p_conn_state_cb)
370             (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_DISCONNECTED, FALSE);
371     }
372     else
373     {
374         if ((bnep_cb.p_conn_state_cb) && ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) ||
375             (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
376             (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
377     }
378
379     bnepu_release_bcb (p_bcb);
380 }
381
382
383
384 /*******************************************************************************
385 **
386 ** Function         bnep_disconnect_cfm
387 **
388 ** Description      This function gets the disconnect confirm event from L2CAP
389 **
390 ** Returns          void
391 **
392 *******************************************************************************/
393 static void bnep_disconnect_cfm (UINT16 l2cap_cid, UINT16 result)
394 {
395     BNEP_TRACE_EVENT ("BNEP - Rcvd L2CAP disc cfm, CID: 0x%x, Result 0x%x", l2cap_cid, result);
396 }
397
398
399
400 /*******************************************************************************
401 **
402 ** Function         bnep_congestion_ind
403 **
404 ** Description      This is a callback function called by L2CAP when
405 **                  congestion status changes
406 **
407 *******************************************************************************/
408 static void bnep_congestion_ind (UINT16 l2cap_cid, BOOLEAN is_congested)
409 {
410     tBNEP_CONN    *p_bcb;
411
412     /* Find BCB based on CID */
413     if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
414     {
415         BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP cong, unknown CID: 0x%x", l2cap_cid);
416         return;
417     }
418
419     if (is_congested)
420    {
421         p_bcb->con_flags |= BNEP_FLAGS_L2CAP_CONGESTED;
422        if(bnep_cb.p_tx_data_flow_cb)
423        {
424            bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_OFF);
425        }
426    }
427     else
428     {
429         p_bcb->con_flags &= ~BNEP_FLAGS_L2CAP_CONGESTED;
430
431        if(bnep_cb.p_tx_data_flow_cb)
432        {
433            bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_ON);
434        }
435
436         /* While not congested, send as many buffers as we can */
437         while (!(p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED))
438         {
439             BT_HDR   *p_buf = (BT_HDR *)GKI_dequeue (&p_bcb->xmit_q);
440
441             if (!p_buf)
442                 break;
443
444             L2CA_DataWrite (l2cap_cid, p_buf);
445         }
446     }
447 }
448
449
450
451 /*******************************************************************************
452 **
453 ** Function         bnep_data_ind
454 **
455 ** Description      This function is called when data is received from L2CAP.
456 **                  if we are the originator of the connection, we are the SDP
457 **                  client, and the received message is queued up for the client.
458 **
459 **                  If we are the destination of the connection, we are the SDP
460 **                  server, so the message is passed to the server processing
461 **                  function.
462 **
463 ** Returns          void
464 **
465 *******************************************************************************/
466 static void bnep_data_ind (UINT16 l2cap_cid, BT_HDR *p_buf)
467 {
468     tBNEP_CONN    *p_bcb;
469     UINT8         *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
470     UINT16        rem_len = p_buf->len;
471     UINT8         type, ctrl_type, ext_type = 0;
472     BOOLEAN       extension_present, fw_ext_present;
473     UINT16        protocol = 0;
474     UINT8         *p_src_addr, *p_dst_addr;
475
476     if (rem_len == 0)
477     {
478         android_errorWriteLog(0x534e4554, "78286118");
479         GKI_freebuf(p_buf);
480         return;
481     }
482
483
484     /* Find CCB based on CID */
485     if ((p_bcb = bnepu_find_bcb_by_cid (l2cap_cid)) == NULL)
486     {
487         BNEP_TRACE_WARNING ("BNEP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid);
488         GKI_freebuf (p_buf);
489         return;
490     }
491
492     /* Get the type and extension bits */
493     type = *p++;
494     extension_present = type >> 7;
495     type &= 0x7f;
496     if (type >= sizeof(bnep_frame_hdr_sizes) / sizeof(bnep_frame_hdr_sizes[0])) {
497         BNEP_TRACE_EVENT("BNEP - rcvd frame, bad type: 0x%02x", type);
498         android_errorWriteLog(0x534e4554, "68818034");
499         GKI_freebuf (p_buf);
500         return;
501     }
502     if ((rem_len <= bnep_frame_hdr_sizes[type]) || (rem_len > BNEP_MTU_SIZE))
503     {
504         BNEP_TRACE_EVENT ("BNEP - rcvd frame, bad len: %d  type: 0x%02x", p_buf->len, type);
505         GKI_freebuf (p_buf);
506         return;
507     }
508
509     rem_len--;
510
511     if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
512         (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)) &&
513         (type != BNEP_FRAME_CONTROL))
514     {
515         BNEP_TRACE_WARNING ("BNEP - Ignored L2CAP data while in state: %d, CID: 0x%x",
516                             p_bcb->con_state, l2cap_cid);
517
518         if (extension_present)
519         {
520             /*
521             ** When there is no connection if a data packet is received
522             ** with unknown control extension headers then those should be processed
523             ** according to complain/ignore law
524             */
525             UINT8       ext, length;
526             UINT16      org_len, new_len;
527             /* parse the extension headers and process unknown control headers */
528             org_len = rem_len;
529             do {
530                 if (org_len < 2) {
531                     android_errorWriteLog(0x534e4554, "67863755");
532                     break;
533                 }
534                 ext     = *p++;
535                 length  = *p++;
536
537                 new_len = (length + 2);
538                 if (new_len > org_len) {
539                     android_errorWriteLog(0x534e4554, "67863755");
540                     break;
541                 }
542
543                 if ((ext & 0x7F) == BNEP_EXTENSION_FILTER_CONTROL) {
544                     if (length == 0) {
545                         android_errorWriteLog(0x534e4554, "79164722");
546                         break;
547                     }
548                     if (*p > BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG) {
549                         bnep_send_command_not_understood(p_bcb, *p);
550                     }
551                 }
552
553                 p += length;
554
555                 org_len -= new_len;
556
557             } while (ext & 0x80);
558         }
559
560         GKI_freebuf (p_buf);
561         return;
562     }
563
564     if (type > BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY)
565     {
566         BNEP_TRACE_EVENT ("BNEP - rcvd frame, unknown type: 0x%02x", type);
567         GKI_freebuf (p_buf);
568         return;
569     }
570
571     BNEP_TRACE_DEBUG ("BNEP - rcv frame, type: %d len: %d Ext: %d", type, p_buf->len, extension_present);
572
573     /* Initialize addresses to 'not supplied' */
574     p_src_addr = p_dst_addr = NULL;
575
576     switch (type)
577     {
578     case BNEP_FRAME_GENERAL_ETHERNET:
579         p_dst_addr = p;
580         p += BD_ADDR_LEN;
581         p_src_addr = p;
582         p += BD_ADDR_LEN;
583         BE_STREAM_TO_UINT16 (protocol, p);
584         rem_len -= 14;
585         break;
586
587     case BNEP_FRAME_CONTROL:
588         ctrl_type = *p;
589         p = bnep_process_control_packet (p_bcb, p, &rem_len, FALSE);
590
591         if (ctrl_type == BNEP_SETUP_CONNECTION_REQUEST_MSG &&
592             p_bcb->con_state != BNEP_STATE_CONNECTED &&
593             extension_present && p && rem_len)
594         {
595             if (p_bcb->p_pending_data)
596                 GKI_freebuf (p_bcb->p_pending_data);
597             p_bcb->p_pending_data = (BT_HDR *)GKI_getbuf (rem_len + sizeof(BT_HDR));
598             if (p_bcb->p_pending_data)
599             {
600                 memcpy ((UINT8 *)(p_bcb->p_pending_data + 1), p, rem_len);
601                 p_bcb->p_pending_data->len    = rem_len;
602                 p_bcb->p_pending_data->offset = 0;
603             }
604         }
605         else
606         {
607             while (extension_present && p && rem_len)
608             {
609                 ext_type = *p++;
610                 rem_len--;
611                 extension_present = ext_type >> 7;
612                 ext_type &= 0x7F;
613
614                 /* if unknown extension present stop processing */
615                 if (ext_type != BNEP_EXTENSION_FILTER_CONTROL) break;
616
617                 android_errorWriteLog(0x534e4554, "69271284");
618                 p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
619             }
620         }
621         GKI_freebuf (p_buf);
622         return;
623
624     case BNEP_FRAME_COMPRESSED_ETHERNET:
625         BE_STREAM_TO_UINT16 (protocol, p);
626         rem_len -= 2;
627         break;
628
629     case BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY:
630         p_src_addr = p;
631         p += BD_ADDR_LEN;
632         BE_STREAM_TO_UINT16 (protocol, p);
633         rem_len -= 8;
634         break;
635
636     case BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY:
637         p_dst_addr = p;
638         p += BD_ADDR_LEN;
639         BE_STREAM_TO_UINT16 (protocol, p);
640         rem_len -= 8;
641         break;
642     }
643
644     /* Process the header extension if there is one */
645     while (extension_present && p && rem_len)
646     {
647         ext_type = *p;
648         extension_present = ext_type >> 7;
649         ext_type &= 0x7F;
650
651         /* if unknown extension present stop processing */
652         if (ext_type)
653         {
654             BNEP_TRACE_EVENT ("Data extension type 0x%x found", ext_type);
655             break;
656         }
657
658         p++;
659         rem_len--;
660         p = bnep_process_control_packet (p_bcb, p, &rem_len, TRUE);
661     }
662
663     p_buf->offset += p_buf->len - rem_len;
664     p_buf->len     = rem_len;
665
666     /* Always give the upper layer MAC addresses */
667     if (!p_src_addr)
668         p_src_addr = (UINT8 *) p_bcb->rem_bda;
669
670     if (!p_dst_addr)
671         p_dst_addr = (UINT8 *) controller_get_interface()->get_address();
672
673     /* check whether there are any extensions to be forwarded */
674     if (ext_type)
675         fw_ext_present = TRUE;
676     else
677         fw_ext_present = FALSE;
678
679     if (bnep_cb.p_data_buf_cb)
680     {
681         (*bnep_cb.p_data_buf_cb)(p_bcb->handle, p_src_addr, p_dst_addr, protocol, p_buf, fw_ext_present);
682     }
683     else if (bnep_cb.p_data_ind_cb)
684     {
685         (*bnep_cb.p_data_ind_cb)(p_bcb->handle, p_src_addr, p_dst_addr, protocol, p, rem_len, fw_ext_present);
686         GKI_freebuf (p_buf);
687     }
688 }
689
690
691
692 /*******************************************************************************
693 **
694 ** Function         bnep_process_timeout
695 **
696 ** Description      This function processes a timeout. If it is a startup
697 **                  timeout, we check for reading our BD address. If it
698 **                  is an L2CAP timeout, we send a disconnect req to L2CAP.
699 **
700 ** Returns          void
701 **
702 *******************************************************************************/
703 void bnep_process_timeout (TIMER_LIST_ENT  *p_tle)
704 {
705     tBNEP_CONN *p_bcb;
706
707     if (!p_tle->param)
708     {
709         return;
710     }
711
712     p_bcb = (tBNEP_CONN *)p_tle->param;
713
714     BNEP_TRACE_EVENT ("BNEP - CCB timeout in state: %d  CID: 0x%x flags %x, re_transmit %d",
715                        p_bcb->con_state, p_bcb->l2cap_cid, p_bcb->con_flags, p_bcb->re_transmits);
716
717     if (p_bcb->con_state == BNEP_STATE_CONN_SETUP)
718     {
719         BNEP_TRACE_EVENT ("BNEP - CCB timeout in state: %d  CID: 0x%x",
720                            p_bcb->con_state, p_bcb->l2cap_cid);
721
722         if (!(p_bcb->con_flags & BNEP_FLAGS_IS_ORIG))
723         {
724             L2CA_DisconnectReq (p_bcb->l2cap_cid);
725
726             bnepu_release_bcb (p_bcb);
727             return;
728         }
729
730         if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS)
731         {
732             bnep_send_conn_req (p_bcb);
733             btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
734         }
735         else
736         {
737             L2CA_DisconnectReq (p_bcb->l2cap_cid);
738
739             if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
740                 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
741
742             bnepu_release_bcb (p_bcb);
743             return;
744         }
745     }
746     else if (p_bcb->con_state != BNEP_STATE_CONNECTED)
747     {
748         BNEP_TRACE_EVENT ("BNEP - CCB timeout in state: %d  CID: 0x%x",
749                            p_bcb->con_state, p_bcb->l2cap_cid);
750
751         L2CA_DisconnectReq (p_bcb->l2cap_cid);
752
753         /* Tell the user if he has a callback */
754         if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
755             (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, FALSE);
756
757         bnepu_release_bcb (p_bcb);
758     }
759     else if (p_bcb->con_flags & BNEP_FLAGS_FILTER_RESP_PEND)
760     {
761         if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS)
762         {
763             bnepu_send_peer_our_filters (p_bcb);
764             btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT);
765         }
766         else
767         {
768             L2CA_DisconnectReq (p_bcb->l2cap_cid);
769
770             /* Tell the user if he has a callback */
771             if (bnep_cb.p_conn_state_cb)
772                 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, FALSE);
773
774             bnepu_release_bcb (p_bcb);
775             return;
776         }
777     }
778     else if (p_bcb->con_flags & BNEP_FLAGS_MULTI_RESP_PEND)
779     {
780         if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS)
781         {
782             bnepu_send_peer_our_multi_filters (p_bcb);
783             btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT);
784         }
785         else
786         {
787             L2CA_DisconnectReq (p_bcb->l2cap_cid);
788
789             /* Tell the user if he has a callback */
790             if (bnep_cb.p_conn_state_cb)
791                 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, FALSE);
792
793             bnepu_release_bcb (p_bcb);
794             return;
795         }
796     }
797 }
798
799
800 /*******************************************************************************
801 **
802 ** Function         bnep_connected
803 **
804 ** Description      This function is called when a connection is established
805 **                  (after config).
806 **
807 ** Returns          void
808 **
809 *******************************************************************************/
810 void bnep_connected (tBNEP_CONN *p_bcb)
811 {
812     BOOLEAN     is_role_change;
813
814     if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
815         is_role_change = TRUE;
816     else
817         is_role_change = FALSE;
818
819     p_bcb->con_state = BNEP_STATE_CONNECTED;
820     p_bcb->con_flags |= BNEP_FLAGS_CONN_COMPLETED;
821     p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
822
823     /* Ensure timer is stopped */
824     btu_stop_timer (&p_bcb->conn_tle);
825     p_bcb->re_transmits = 0;
826
827     /* Tell the upper layer, if he has a callback */
828     if (bnep_cb.p_conn_state_cb)
829         (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SUCCESS, is_role_change);
830 }