3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
6 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include <sys/socket.h>
34 #include <sys/ioctl.h>
36 #include <bluetooth/bluetooth.h>
37 #include <bluetooth/bnep.h>
39 #include <netinet/in.h>
45 /* Compatibility with old ioctls */
46 #define OLD_BNEPCONADD 1
47 #define OLD_BNEPCONDEL 2
48 #define OLD_BNEPGETCONLIST 3
49 #define OLD_BNEPGETCONINFO 4
51 static unsigned long bnepconnadd;
52 static unsigned long bnepconndel;
53 static unsigned long bnepgetconnlist;
54 static unsigned long bnepgetconninfo;
60 { "PANU", BNEP_SVC_PANU },
61 { "NAP", BNEP_SVC_NAP },
62 { "GN", BNEP_SVC_GN },
66 int bnep_str2svc(char *svc, uint16_t *uuid)
69 for (i = 0; __svc[i].str; i++)
70 if (!strcasecmp(svc, __svc[i].str)) {
71 *uuid = __svc[i].uuid;
77 char *bnep_svc2str(uint16_t uuid)
80 for (i = 0; __svc[i].str; i++)
81 if (__svc[i].uuid == uuid)
88 ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
90 perror("Failed to open control socket");
94 /* Temporary ioctl compatibility hack */
96 struct bnep_connlist_req req;
97 struct bnep_conninfo ci[1];
102 if (!ioctl(ctl, BNEPGETCONNLIST, &req)) {
104 bnepconnadd = BNEPCONNADD;
105 bnepconndel = BNEPCONNDEL;
106 bnepgetconnlist = BNEPGETCONNLIST;
107 bnepgetconninfo = BNEPGETCONNINFO;
110 bnepconnadd = OLD_BNEPCONADD;
111 bnepconndel = OLD_BNEPCONDEL;
112 bnepgetconnlist = OLD_BNEPGETCONLIST;
113 bnepgetconninfo = OLD_BNEPGETCONINFO;
120 int bnep_cleanup(void)
126 int bnep_show_connections(void)
128 struct bnep_connlist_req req;
129 struct bnep_conninfo ci[48];
134 if (ioctl(ctl, bnepgetconnlist, &req)) {
135 perror("Failed to get connection list");
139 for (i = 0; i < req.cnum; i++) {
141 ba2str((bdaddr_t *) ci[i].dst, addr);
142 printf("%s %s %s\n", ci[i].device,
143 addr, bnep_svc2str(ci[i].role));
148 int bnep_kill_connection(uint8_t *dst)
150 struct bnep_conndel_req req;
152 memcpy(req.dst, dst, ETH_ALEN);
154 if (ioctl(ctl, bnepconndel, &req)) {
155 perror("Failed to kill connection");
161 int bnep_kill_all_connections(void)
163 struct bnep_connlist_req req;
164 struct bnep_conninfo ci[48];
169 if (ioctl(ctl, bnepgetconnlist, &req)) {
170 perror("Failed to get connection list");
174 for (i = 0; i < req.cnum; i++) {
175 struct bnep_conndel_req req;
176 memcpy(req.dst, ci[i].dst, ETH_ALEN);
178 ioctl(ctl, bnepconndel, &req);
183 static int bnep_connadd(int sk, uint16_t role, char *dev)
185 struct bnep_connadd_req req;
187 strncpy(req.device, dev, 16);
188 req.device[15] = '\0';
191 if (ioctl(ctl, bnepconnadd, &req))
193 strncpy(dev, req.device, 16);
197 struct __service_16 {
200 } __attribute__ ((packed));
202 struct __service_32 {
207 } __attribute__ ((packed));
209 struct __service_128 {
215 } __attribute__ ((packed));
217 int bnep_accept_connection(int sk, uint16_t role, char *dev)
219 struct bnep_setup_conn_req *req;
220 struct bnep_control_rsp *rsp;
221 unsigned char pkt[BNEP_MTU];
224 r = recv(sk, pkt, BNEP_MTU, 0);
230 if ((size_t) r < sizeof(*req))
235 /* Highest known Control command ID
236 * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
237 if (req->type == BNEP_CONTROL &&
238 req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
241 pkt[0] = BNEP_CONTROL;
242 pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
245 send(sk, pkt, sizeof(pkt), 0);
250 if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
253 /* FIXME: Check role UUIDs */
256 rsp->type = BNEP_CONTROL;
257 rsp->ctrl = BNEP_SETUP_CONN_RSP;
258 rsp->resp = htons(BNEP_SUCCESS);
259 if (send(sk, rsp, sizeof(*rsp), 0) < 0)
262 return bnep_connadd(sk, role, dev);
265 /* Create BNEP connection
266 * sk - Connect L2CAP socket
268 * service - Remote service
269 * dev - Network device (contains actual dev name on return)
271 int bnep_create_connection(int sk, uint16_t role, uint16_t svc, char *dev)
273 struct bnep_setup_conn_req *req;
274 struct bnep_control_rsp *rsp;
275 struct __service_16 *s;
276 struct timeval timeo;
277 unsigned char pkt[BNEP_MTU];
282 req->type = BNEP_CONTROL;
283 req->ctrl = BNEP_SETUP_CONN_REQ;
284 req->uuid_size = 2; /* 16bit UUID */
286 s = (void *) req->service;
288 s->src = htons(role);
290 memset(&timeo, 0, sizeof(timeo));
293 setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
295 if (send(sk, pkt, sizeof(*req) + sizeof(*s), 0) < 0)
300 r = recv(sk, pkt, BNEP_MTU, 0);
304 memset(&timeo, 0, sizeof(timeo));
307 setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
311 if ((size_t) r < sizeof(*rsp))
315 if (rsp->type != BNEP_CONTROL)
318 if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
321 r = ntohs(rsp->resp);
327 case BNEP_CONN_INVALID_DST:
328 case BNEP_CONN_INVALID_SRC:
329 case BNEP_CONN_INVALID_SVC:
333 case BNEP_CONN_NOT_ALLOWED:
338 return bnep_connadd(sk, role, dev);