xref: /linux/net/bluetooth/cmtp/core.c (revision b233b28eac0cc37d07c2d007ea08c86c778c5af4)
1 /*
2    CMTP implementation for Linux Bluetooth stack (BlueZ).
3    Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License version 2 as
7    published by the Free Software Foundation;
8 
9    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20    SOFTWARE IS DISCLAIMED.
21 */
22 
23 #include <linux/module.h>
24 
25 #include <linux/types.h>
26 #include <linux/errno.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/slab.h>
30 #include <linux/poll.h>
31 #include <linux/fcntl.h>
32 #include <linux/freezer.h>
33 #include <linux/skbuff.h>
34 #include <linux/socket.h>
35 #include <linux/ioctl.h>
36 #include <linux/file.h>
37 #include <linux/init.h>
38 #include <net/sock.h>
39 
40 #include <linux/isdn/capilli.h>
41 
42 #include <net/bluetooth/bluetooth.h>
43 #include <net/bluetooth/l2cap.h>
44 
45 #include "cmtp.h"
46 
47 #define VERSION "1.0"
48 
49 static DECLARE_RWSEM(cmtp_session_sem);
50 static LIST_HEAD(cmtp_session_list);
51 
52 static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
53 {
54 	struct cmtp_session *session;
55 	struct list_head *p;
56 
57 	BT_DBG("");
58 
59 	list_for_each(p, &cmtp_session_list) {
60 		session = list_entry(p, struct cmtp_session, list);
61 		if (!bacmp(bdaddr, &session->bdaddr))
62 			return session;
63 	}
64 	return NULL;
65 }
66 
67 static void __cmtp_link_session(struct cmtp_session *session)
68 {
69 	__module_get(THIS_MODULE);
70 	list_add(&session->list, &cmtp_session_list);
71 }
72 
73 static void __cmtp_unlink_session(struct cmtp_session *session)
74 {
75 	list_del(&session->list);
76 	module_put(THIS_MODULE);
77 }
78 
79 static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
80 {
81 	bacpy(&ci->bdaddr, &session->bdaddr);
82 
83 	ci->flags = session->flags;
84 	ci->state = session->state;
85 
86 	ci->num = session->num;
87 }
88 
89 
90 static inline int cmtp_alloc_block_id(struct cmtp_session *session)
91 {
92 	int i, id = -1;
93 
94 	for (i = 0; i < 16; i++)
95 		if (!test_and_set_bit(i, &session->blockids)) {
96 			id = i;
97 			break;
98 		}
99 
100 	return id;
101 }
102 
103 static inline void cmtp_free_block_id(struct cmtp_session *session, int id)
104 {
105 	clear_bit(id, &session->blockids);
106 }
107 
108 static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const unsigned char *buf, int count)
109 {
110 	struct sk_buff *skb = session->reassembly[id], *nskb;
111 	int size;
112 
113 	BT_DBG("session %p buf %p count %d", session, buf, count);
114 
115 	size = (skb) ? skb->len + count : count;
116 
117 	if (!(nskb = alloc_skb(size, GFP_ATOMIC))) {
118 		BT_ERR("Can't allocate memory for CAPI message");
119 		return;
120 	}
121 
122 	if (skb && (skb->len > 0))
123 		skb_copy_from_linear_data(skb, skb_put(nskb, skb->len), skb->len);
124 
125 	memcpy(skb_put(nskb, count), buf, count);
126 
127 	session->reassembly[id] = nskb;
128 
129 	if (skb)
130 		kfree_skb(skb);
131 }
132 
133 static inline int cmtp_recv_frame(struct cmtp_session *session, struct sk_buff *skb)
134 {
135 	__u8 hdr, hdrlen, id;
136 	__u16 len;
137 
138 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
139 
140 	while (skb->len > 0) {
141 		hdr = skb->data[0];
142 
143 		switch (hdr & 0xc0) {
144 		case 0x40:
145 			hdrlen = 2;
146 			len = skb->data[1];
147 			break;
148 		case 0x80:
149 			hdrlen = 3;
150 			len = skb->data[1] | (skb->data[2] << 8);
151 			break;
152 		default:
153 			hdrlen = 1;
154 			len = 0;
155 			break;
156 		}
157 
158 		id = (hdr & 0x3c) >> 2;
159 
160 		BT_DBG("hdr 0x%02x hdrlen %d len %d id %d", hdr, hdrlen, len, id);
161 
162 		if (hdrlen + len > skb->len) {
163 			BT_ERR("Wrong size or header information in CMTP frame");
164 			break;
165 		}
166 
167 		if (len == 0) {
168 			skb_pull(skb, hdrlen);
169 			continue;
170 		}
171 
172 		switch (hdr & 0x03) {
173 		case 0x00:
174 			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
175 			cmtp_recv_capimsg(session, session->reassembly[id]);
176 			session->reassembly[id] = NULL;
177 			break;
178 		case 0x01:
179 			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
180 			break;
181 		default:
182 			if (session->reassembly[id] != NULL)
183 				kfree_skb(session->reassembly[id]);
184 			session->reassembly[id] = NULL;
185 			break;
186 		}
187 
188 		skb_pull(skb, hdrlen + len);
189 	}
190 
191 	kfree_skb(skb);
192 	return 0;
193 }
194 
195 static int cmtp_send_frame(struct cmtp_session *session, unsigned char *data, int len)
196 {
197 	struct socket *sock = session->sock;
198 	struct kvec iv = { data, len };
199 	struct msghdr msg;
200 
201 	BT_DBG("session %p data %p len %d", session, data, len);
202 
203 	if (!len)
204 		return 0;
205 
206 	memset(&msg, 0, sizeof(msg));
207 
208 	return kernel_sendmsg(sock, &msg, &iv, 1, len);
209 }
210 
211 static void cmtp_process_transmit(struct cmtp_session *session)
212 {
213 	struct sk_buff *skb, *nskb;
214 	unsigned char *hdr;
215 	unsigned int size, tail;
216 
217 	BT_DBG("session %p", session);
218 
219 	if (!(nskb = alloc_skb(session->mtu, GFP_ATOMIC))) {
220 		BT_ERR("Can't allocate memory for new frame");
221 		return;
222 	}
223 
224 	while ((skb = skb_dequeue(&session->transmit))) {
225 		struct cmtp_scb *scb = (void *) skb->cb;
226 
227 		if ((tail = (session->mtu - nskb->len)) < 5) {
228 			cmtp_send_frame(session, nskb->data, nskb->len);
229 			skb_trim(nskb, 0);
230 			tail = session->mtu;
231 		}
232 
233 		size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len);
234 
235 		if ((scb->id < 0) && ((scb->id = cmtp_alloc_block_id(session)) < 0)) {
236 			skb_queue_head(&session->transmit, skb);
237 			break;
238 		}
239 
240 		if (size < 256) {
241 			hdr = skb_put(nskb, 2);
242 			hdr[0] = 0x40
243 				| ((scb->id << 2) & 0x3c)
244 				| ((skb->len == size) ? 0x00 : 0x01);
245 			hdr[1] = size;
246 		} else {
247 			hdr = skb_put(nskb, 3);
248 			hdr[0] = 0x80
249 				| ((scb->id << 2) & 0x3c)
250 				| ((skb->len == size) ? 0x00 : 0x01);
251 			hdr[1] = size & 0xff;
252 			hdr[2] = size >> 8;
253 		}
254 
255 		skb_copy_from_linear_data(skb, skb_put(nskb, size), size);
256 		skb_pull(skb, size);
257 
258 		if (skb->len > 0) {
259 			skb_queue_head(&session->transmit, skb);
260 		} else {
261 			cmtp_free_block_id(session, scb->id);
262 			if (scb->data) {
263 				cmtp_send_frame(session, nskb->data, nskb->len);
264 				skb_trim(nskb, 0);
265 			}
266 			kfree_skb(skb);
267 		}
268 	}
269 
270 	cmtp_send_frame(session, nskb->data, nskb->len);
271 
272 	kfree_skb(nskb);
273 }
274 
275 static int cmtp_session(void *arg)
276 {
277 	struct cmtp_session *session = arg;
278 	struct sock *sk = session->sock->sk;
279 	struct sk_buff *skb;
280 	wait_queue_t wait;
281 
282 	BT_DBG("session %p", session);
283 
284 	daemonize("kcmtpd_ctr_%d", session->num);
285 	set_user_nice(current, -15);
286 
287 	init_waitqueue_entry(&wait, current);
288 	add_wait_queue(sk->sk_sleep, &wait);
289 	while (!atomic_read(&session->terminate)) {
290 		set_current_state(TASK_INTERRUPTIBLE);
291 
292 		if (sk->sk_state != BT_CONNECTED)
293 			break;
294 
295 		while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
296 			skb_orphan(skb);
297 			cmtp_recv_frame(session, skb);
298 		}
299 
300 		cmtp_process_transmit(session);
301 
302 		schedule();
303 	}
304 	set_current_state(TASK_RUNNING);
305 	remove_wait_queue(sk->sk_sleep, &wait);
306 
307 	down_write(&cmtp_session_sem);
308 
309 	if (!(session->flags & (1 << CMTP_LOOPBACK)))
310 		cmtp_detach_device(session);
311 
312 	fput(session->sock->file);
313 
314 	__cmtp_unlink_session(session);
315 
316 	up_write(&cmtp_session_sem);
317 
318 	kfree(session);
319 	return 0;
320 }
321 
322 int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
323 {
324 	struct cmtp_session *session, *s;
325 	bdaddr_t src, dst;
326 	int i, err;
327 
328 	BT_DBG("");
329 
330 	baswap(&src, &bt_sk(sock->sk)->src);
331 	baswap(&dst, &bt_sk(sock->sk)->dst);
332 
333 	session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
334 	if (!session)
335 		return -ENOMEM;
336 
337 	down_write(&cmtp_session_sem);
338 
339 	s = __cmtp_get_session(&bt_sk(sock->sk)->dst);
340 	if (s && s->state == BT_CONNECTED) {
341 		err = -EEXIST;
342 		goto failed;
343 	}
344 
345 	bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst);
346 
347 	session->mtu = min_t(uint, l2cap_pi(sock->sk)->omtu, l2cap_pi(sock->sk)->imtu);
348 
349 	BT_DBG("mtu %d", session->mtu);
350 
351 	sprintf(session->name, "%s", batostr(&dst));
352 
353 	session->sock  = sock;
354 	session->state = BT_CONFIG;
355 
356 	init_waitqueue_head(&session->wait);
357 
358 	session->msgnum = CMTP_INITIAL_MSGNUM;
359 
360 	INIT_LIST_HEAD(&session->applications);
361 
362 	skb_queue_head_init(&session->transmit);
363 
364 	for (i = 0; i < 16; i++)
365 		session->reassembly[i] = NULL;
366 
367 	session->flags = req->flags;
368 
369 	__cmtp_link_session(session);
370 
371 	err = kernel_thread(cmtp_session, session, CLONE_KERNEL);
372 	if (err < 0)
373 		goto unlink;
374 
375 	if (!(session->flags & (1 << CMTP_LOOPBACK))) {
376 		err = cmtp_attach_device(session);
377 		if (err < 0)
378 			goto detach;
379 	}
380 
381 	up_write(&cmtp_session_sem);
382 	return 0;
383 
384 detach:
385 	cmtp_detach_device(session);
386 
387 unlink:
388 	__cmtp_unlink_session(session);
389 
390 failed:
391 	up_write(&cmtp_session_sem);
392 	kfree(session);
393 	return err;
394 }
395 
396 int cmtp_del_connection(struct cmtp_conndel_req *req)
397 {
398 	struct cmtp_session *session;
399 	int err = 0;
400 
401 	BT_DBG("");
402 
403 	down_read(&cmtp_session_sem);
404 
405 	session = __cmtp_get_session(&req->bdaddr);
406 	if (session) {
407 		/* Flush the transmit queue */
408 		skb_queue_purge(&session->transmit);
409 
410 		/* Kill session thread */
411 		atomic_inc(&session->terminate);
412 		cmtp_schedule(session);
413 	} else
414 		err = -ENOENT;
415 
416 	up_read(&cmtp_session_sem);
417 	return err;
418 }
419 
420 int cmtp_get_connlist(struct cmtp_connlist_req *req)
421 {
422 	struct list_head *p;
423 	int err = 0, n = 0;
424 
425 	BT_DBG("");
426 
427 	down_read(&cmtp_session_sem);
428 
429 	list_for_each(p, &cmtp_session_list) {
430 		struct cmtp_session *session;
431 		struct cmtp_conninfo ci;
432 
433 		session = list_entry(p, struct cmtp_session, list);
434 
435 		__cmtp_copy_session(session, &ci);
436 
437 		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
438 			err = -EFAULT;
439 			break;
440 		}
441 
442 		if (++n >= req->cnum)
443 			break;
444 
445 		req->ci++;
446 	}
447 	req->cnum = n;
448 
449 	up_read(&cmtp_session_sem);
450 	return err;
451 }
452 
453 int cmtp_get_conninfo(struct cmtp_conninfo *ci)
454 {
455 	struct cmtp_session *session;
456 	int err = 0;
457 
458 	down_read(&cmtp_session_sem);
459 
460 	session = __cmtp_get_session(&ci->bdaddr);
461 	if (session)
462 		__cmtp_copy_session(session, ci);
463 	else
464 		err = -ENOENT;
465 
466 	up_read(&cmtp_session_sem);
467 	return err;
468 }
469 
470 
471 static int __init cmtp_init(void)
472 {
473 	l2cap_load();
474 
475 	BT_INFO("CMTP (CAPI Emulation) ver %s", VERSION);
476 
477 	cmtp_init_sockets();
478 
479 	return 0;
480 }
481 
482 static void __exit cmtp_exit(void)
483 {
484 	cmtp_cleanup_sockets();
485 }
486 
487 module_init(cmtp_init);
488 module_exit(cmtp_exit);
489 
490 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
491 MODULE_DESCRIPTION("Bluetooth CMTP ver " VERSION);
492 MODULE_VERSION(VERSION);
493 MODULE_LICENSE("GPL");
494 MODULE_ALIAS("bt-proto-5");
495