1 /******************************************************************************
2  *
3  *  Copyright 1999-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 main functions to support PAN profile
22  *  commands and events.
23  *
24  *****************************************************************************/
25 
26 #define LOG_TAG "pan"
27 
28 #include <bluetooth/log.h>
29 
30 #include <cstddef>
31 #include <cstdint>
32 #include <cstring>
33 
34 #include "bnep_api.h"
35 #include "internal_include/bt_target.h"
36 #include "stack/include/bt_types.h"
37 #include "stack/include/bt_uuid16.h"
38 #include "stack/include/sdp_api.h"
39 #include "stack/include/sdpdefs.h"
40 #include "stack/pan/pan_int.h"
41 #include "types/raw_address.h"
42 
43 using namespace bluetooth;
44 using namespace bluetooth::legacy::stack::sdp;
45 
46 static const uint8_t pan_proto_elem_data[] = {
47         0x35, 0x18, /* data element sequence of length 0x18 bytes */
48         0x35, 0x06, /* data element sequence for L2CAP descriptor */
49         0x19, 0x01,
50         0x00, /* UUID for L2CAP - 0x0100 */
51         0x09, 0x00,
52         0x0F,       /* PSM for BNEP - 0x000F */
53         0x35, 0x0E, /* data element seqence for BNEP descriptor */
54         0x19, 0x00,
55         0x0F, /* UUID for BNEP - 0x000F */
56         0x09, 0x01,
57         0x00,       /* BNEP specific parameter 0 -- Version of BNEP = version 1 = 0x0001
58                      */
59         0x35, 0x06, /* BNEP specific parameter 1 -- Supported network packet type list */
60         0x09, 0x08,
61         0x00, /* network packet type IPv4 = 0x0800 */
62         0x09, 0x08,
63         0x06 /* network packet type ARP  = 0x0806 */
64 };
65 
66 /*******************************************************************************
67  *
68  * Function         pan_register_with_sdp
69  *
70  * Description
71  *
72  * Returns
73  *
74  ******************************************************************************/
pan_register_with_sdp(uint16_t uuid,const char * p_name,const char * p_desc)75 uint32_t pan_register_with_sdp(uint16_t uuid, const char* p_name, const char* p_desc) {
76   uint32_t sdp_handle;
77   uint16_t browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
78   uint16_t security = 0;
79   uint32_t proto_len = (uint32_t)pan_proto_elem_data[1];
80 
81   /* Create a record */
82   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
83 
84   if (sdp_handle == 0) {
85     log::error("PAN_SetRole - could not create SDP record");
86     return 0;
87   }
88 
89   /* Service Class ID List */
90   if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(sdp_handle, 1, &uuid)) {
91     log::warn("Unable to add SDP class id list handle:{}", sdp_handle);
92   }
93 
94   /* Add protocol element sequence from the constant string */
95   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST,
96                                                            DATA_ELE_SEQ_DESC_TYPE, proto_len,
97                                                            (uint8_t*)(pan_proto_elem_data + 2))) {
98     log::warn("Unable to add SDP PAN profile attribute handle:{}", sdp_handle);
99   }
100 
101   /* Language base */
102   if (!get_legacy_stack_sdp_api()->handle.SDP_AddLanguageBaseAttrIDList(
103               sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID)) {
104     log::warn("Unable to add SDP language base attribute");
105   }
106 
107   /* Profile descriptor list */
108   if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(sdp_handle, uuid,
109                                                                        PAN_PROFILE_VERSION)) {
110     log::warn("Unable to add SDP PAN profile version");
111   }
112 
113   /* Service Name */
114   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
115               sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, (uint8_t)(strlen(p_name) + 1),
116               (uint8_t*)p_name)) {
117     log::warn("Unable to add SDP service name attribute handle:{}", sdp_handle);
118   }
119 
120   /* Service description */
121   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
122               sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
123               (uint8_t)(strlen(p_desc) + 1), (uint8_t*)p_desc)) {
124     log::warn("Unable to add SDP service description attribute handle:{}", sdp_handle);
125   }
126 
127   /* Security description */
128   // Only NAP and PANU has service level security; GN has no security
129   if (uuid == UUID_SERVCLASS_NAP || uuid == UUID_SERVCLASS_PANU) {
130     UINT16_TO_BE_FIELD(&security, 0x0001);
131   }
132   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
133               sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2, (uint8_t*)&security)) {
134     log::warn("Unable to add SDP security description attribute handle:{}", sdp_handle);
135   }
136 
137   if (uuid == UUID_SERVCLASS_NAP) {
138     uint16_t NetAccessType = 0x0005;      /* Ethernet */
139     uint32_t NetAccessRate = 0x0001312D0; /* 10Mb/sec */
140     uint8_t array[10], *p;
141 
142     /* Net access type. */
143     p = array;
144     UINT16_TO_BE_STREAM(p, NetAccessType);
145     if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(sdp_handle, ATTR_ID_NET_ACCESS_TYPE,
146                                                              UINT_DESC_TYPE, 2, array)) {
147       log::warn("Unable to add SDP attribute net access type handle:{}", sdp_handle);
148     }
149 
150     /* Net access rate. */
151     p = array;
152     UINT32_TO_BE_STREAM(p, NetAccessRate);
153     if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
154                 sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4, array)) {
155       log::warn("Unable to add SDP attribute net access rate handle:{}", sdp_handle);
156     }
157   }
158 
159   /* Make the service browsable */
160   if (!get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
161                                                               1, &browse_list)) {
162     log::warn("Unable to add SDP uuid sequence browse group list handle:{}", sdp_handle);
163   }
164 
165   return sdp_handle;
166 }
167 
168 /*******************************************************************************
169  *
170  * Function         pan_allocate_pcb
171  *
172  * Description
173  *
174  * Returns
175  *
176  ******************************************************************************/
pan_allocate_pcb(const RawAddress & p_bda,uint16_t handle)177 tPAN_CONN* pan_allocate_pcb(const RawAddress& p_bda, uint16_t handle) {
178   uint16_t i;
179 
180   for (i = 0; i < MAX_PAN_CONNS; i++) {
181     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE && pan_cb.pcb[i].handle == handle) {
182       return NULL;
183     }
184   }
185 
186   for (i = 0; i < MAX_PAN_CONNS; i++) {
187     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE && pan_cb.pcb[i].rem_bda == p_bda) {
188       return NULL;
189     }
190   }
191 
192   for (i = 0; i < MAX_PAN_CONNS; i++) {
193     if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) {
194       memset(&(pan_cb.pcb[i]), 0, sizeof(tPAN_CONN));
195       pan_cb.pcb[i].rem_bda = p_bda;
196       pan_cb.pcb[i].handle = handle;
197       return &(pan_cb.pcb[i]);
198     }
199   }
200   return NULL;
201 }
202 
203 /*******************************************************************************
204  *
205  * Function         pan_get_pcb_by_handle
206  *
207  * Description
208  *
209  * Returns
210  *
211  ******************************************************************************/
pan_get_pcb_by_handle(uint16_t handle)212 tPAN_CONN* pan_get_pcb_by_handle(uint16_t handle) {
213   uint16_t i;
214 
215   for (i = 0; i < MAX_PAN_CONNS; i++) {
216     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE && pan_cb.pcb[i].handle == handle) {
217       return &(pan_cb.pcb[i]);
218     }
219   }
220 
221   return NULL;
222 }
223 
224 /*******************************************************************************
225  *
226  * Function         pan_get_pcb_by_addr
227  *
228  * Description
229  *
230  * Returns
231  *
232  ******************************************************************************/
pan_get_pcb_by_addr(const RawAddress & p_bda)233 tPAN_CONN* pan_get_pcb_by_addr(const RawAddress& p_bda) {
234   uint16_t i;
235 
236   for (i = 0; i < MAX_PAN_CONNS; i++) {
237     if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) {
238       continue;
239     }
240 
241     if (pan_cb.pcb[i].rem_bda == p_bda) {
242       return &(pan_cb.pcb[i]);
243     }
244 
245     /*
246     if (pan_cb.pcb[i].mfilter_present &&
247         p_bda == pan_cb.pcb[i].multi_cast_bridge)
248         return &(pan_cb.pcb[i]);
249     */
250   }
251 
252   return NULL;
253 }
254 
255 /*******************************************************************************
256  *
257  * Function         pan_close_all_connections
258  *
259  * Description
260  *
261  * Returns          void
262  *
263  ******************************************************************************/
pan_close_all_connections(void)264 void pan_close_all_connections(void) {
265   uint16_t i;
266 
267   for (i = 0; i < MAX_PAN_CONNS; i++) {
268     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE) {
269       BNEP_Disconnect(pan_cb.pcb[i].handle);
270       pan_cb.pcb[i].con_state = PAN_STATE_IDLE;
271     }
272   }
273 
274   pan_cb.active_role = PAN_ROLE_INACTIVE;
275   pan_cb.num_conns = 0;
276   return;
277 }
278 
279 /*******************************************************************************
280  *
281  * Function         pan_release_pcb
282  *
283  * Description      This function releases a PCB.
284  *
285  * Returns          void
286  *
287  ******************************************************************************/
pan_release_pcb(tPAN_CONN * p_pcb)288 void pan_release_pcb(tPAN_CONN* p_pcb) {
289   /* Drop any response pointer we may be holding */
290   memset(p_pcb, 0, sizeof(tPAN_CONN));
291   p_pcb->con_state = PAN_STATE_IDLE;
292 }
293 
294 /*******************************************************************************
295  *
296  * Function         pan_dump_status
297  *
298  * Description      This function dumps the pan control block and connection
299  *                  blocks information
300  *
301  * Returns          none
302  *
303  ******************************************************************************/
pan_dump_status(void)304 void pan_dump_status(void) {
305 #if (PAN_SUPPORTS_DEBUG_DUMP == TRUE)
306   uint16_t i;
307   tPAN_CONN* p_pcb;
308 
309   log::verbose("PAN role {:x}, active role {}, num_conns {}", pan_cb.role, pan_cb.active_role,
310                pan_cb.num_conns);
311 
312   for (i = 0, p_pcb = pan_cb.pcb; i < MAX_PAN_CONNS; i++, p_pcb++) {
313     log::verbose("{} state:{}, handle:{}, src{}, BD:{}", i, p_pcb->con_state, p_pcb->handle,
314                  p_pcb->src_uuid, p_pcb->rem_bda);
315   }
316 #endif
317 }
318