• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <linux/kthread.h>
39 #include <net/sock.h>
40 
41 #include <linux/isdn/capilli.h>
42 
43 #include <net/bluetooth/bluetooth.h>
44 #include <net/bluetooth/l2cap.h>
45 
46 #include "cmtp.h"
47 
48 #define VERSION "1.0"
49 
50 static DECLARE_RWSEM(cmtp_session_sem);
51 static LIST_HEAD(cmtp_session_list);
52 
__cmtp_get_session(bdaddr_t * bdaddr)53 static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
54 {
55 	struct cmtp_session *session;
56 
57 	BT_DBG("");
58 
59 	list_for_each_entry(session, &cmtp_session_list, list)
60 		if (!bacmp(bdaddr, &session->bdaddr))
61 			return session;
62 
63 	return NULL;
64 }
65 
__cmtp_link_session(struct cmtp_session * session)66 static void __cmtp_link_session(struct cmtp_session *session)
67 {
68 	list_add(&session->list, &cmtp_session_list);
69 }
70 
__cmtp_unlink_session(struct cmtp_session * session)71 static void __cmtp_unlink_session(struct cmtp_session *session)
72 {
73 	list_del(&session->list);
74 }
75 
__cmtp_copy_session(struct cmtp_session * session,struct cmtp_conninfo * ci)76 static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
77 {
78 	memset(ci, 0, sizeof(*ci));
79 	bacpy(&ci->bdaddr, &session->bdaddr);
80 
81 	ci->flags = session->flags;
82 	ci->state = session->state;
83 
84 	ci->num = session->num;
85 }
86 
87 
cmtp_alloc_block_id(struct cmtp_session * session)88 static inline int cmtp_alloc_block_id(struct cmtp_session *session)
89 {
90 	int i, id = -1;
91 
92 	for (i = 0; i < 16; i++)
93 		if (!test_and_set_bit(i, &session->blockids)) {
94 			id = i;
95 			break;
96 		}
97 
98 	return id;
99 }
100 
cmtp_free_block_id(struct cmtp_session * session,int id)101 static inline void cmtp_free_block_id(struct cmtp_session *session, int id)
102 {
103 	clear_bit(id, &session->blockids);
104 }
105 
cmtp_add_msgpart(struct cmtp_session * session,int id,const unsigned char * buf,int count)106 static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const unsigned char *buf, int count)
107 {
108 	struct sk_buff *skb = session->reassembly[id], *nskb;
109 	int size;
110 
111 	BT_DBG("session %p buf %p count %d", session, buf, count);
112 
113 	size = (skb) ? skb->len + count : count;
114 
115 	nskb = alloc_skb(size, GFP_ATOMIC);
116 	if (!nskb) {
117 		BT_ERR("Can't allocate memory for CAPI message");
118 		return;
119 	}
120 
121 	if (skb && (skb->len > 0))
122 		skb_copy_from_linear_data(skb, skb_put(nskb, skb->len), skb->len);
123 
124 	memcpy(skb_put(nskb, count), buf, count);
125 
126 	session->reassembly[id] = nskb;
127 
128 	kfree_skb(skb);
129 }
130 
cmtp_recv_frame(struct cmtp_session * session,struct sk_buff * skb)131 static inline int cmtp_recv_frame(struct cmtp_session *session, struct sk_buff *skb)
132 {
133 	__u8 hdr, hdrlen, id;
134 	__u16 len;
135 
136 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
137 
138 	while (skb->len > 0) {
139 		hdr = skb->data[0];
140 
141 		switch (hdr & 0xc0) {
142 		case 0x40:
143 			hdrlen = 2;
144 			len = skb->data[1];
145 			break;
146 		case 0x80:
147 			hdrlen = 3;
148 			len = skb->data[1] | (skb->data[2] << 8);
149 			break;
150 		default:
151 			hdrlen = 1;
152 			len = 0;
153 			break;
154 		}
155 
156 		id = (hdr & 0x3c) >> 2;
157 
158 		BT_DBG("hdr 0x%02x hdrlen %d len %d id %d", hdr, hdrlen, len, id);
159 
160 		if (hdrlen + len > skb->len) {
161 			BT_ERR("Wrong size or header information in CMTP frame");
162 			break;
163 		}
164 
165 		if (len == 0) {
166 			skb_pull(skb, hdrlen);
167 			continue;
168 		}
169 
170 		switch (hdr & 0x03) {
171 		case 0x00:
172 			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
173 			cmtp_recv_capimsg(session, session->reassembly[id]);
174 			session->reassembly[id] = NULL;
175 			break;
176 		case 0x01:
177 			cmtp_add_msgpart(session, id, skb->data + hdrlen, len);
178 			break;
179 		default:
180 			if (session->reassembly[id] != NULL)
181 				kfree_skb(session->reassembly[id]);
182 			session->reassembly[id] = NULL;
183 			break;
184 		}
185 
186 		skb_pull(skb, hdrlen + len);
187 	}
188 
189 	kfree_skb(skb);
190 	return 0;
191 }
192 
cmtp_send_frame(struct cmtp_session * session,unsigned char * data,int len)193 static int cmtp_send_frame(struct cmtp_session *session, unsigned char *data, int len)
194 {
195 	struct socket *sock = session->sock;
196 	struct kvec iv = { data, len };
197 	struct msghdr msg;
198 
199 	BT_DBG("session %p data %p len %d", session, data, len);
200 
201 	if (!len)
202 		return 0;
203 
204 	memset(&msg, 0, sizeof(msg));
205 
206 	return kernel_sendmsg(sock, &msg, &iv, 1, len);
207 }
208 
cmtp_process_transmit(struct cmtp_session * session)209 static void cmtp_process_transmit(struct cmtp_session *session)
210 {
211 	struct sk_buff *skb, *nskb;
212 	unsigned char *hdr;
213 	unsigned int size, tail;
214 
215 	BT_DBG("session %p", session);
216 
217 	nskb = alloc_skb(session->mtu, GFP_ATOMIC);
218 	if (!nskb) {
219 		BT_ERR("Can't allocate memory for new frame");
220 		return;
221 	}
222 
223 	while ((skb = skb_dequeue(&session->transmit))) {
224 		struct cmtp_scb *scb = (void *) skb->cb;
225 
226 		tail = session->mtu - nskb->len;
227 		if (tail < 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) {
236 			scb->id = cmtp_alloc_block_id(session);
237 			if (scb->id < 0) {
238 				skb_queue_head(&session->transmit, skb);
239 				break;
240 			}
241 		}
242 
243 		if (size < 256) {
244 			hdr = skb_put(nskb, 2);
245 			hdr[0] = 0x40
246 				| ((scb->id << 2) & 0x3c)
247 				| ((skb->len == size) ? 0x00 : 0x01);
248 			hdr[1] = size;
249 		} else {
250 			hdr = skb_put(nskb, 3);
251 			hdr[0] = 0x80
252 				| ((scb->id << 2) & 0x3c)
253 				| ((skb->len == size) ? 0x00 : 0x01);
254 			hdr[1] = size & 0xff;
255 			hdr[2] = size >> 8;
256 		}
257 
258 		skb_copy_from_linear_data(skb, skb_put(nskb, size), size);
259 		skb_pull(skb, size);
260 
261 		if (skb->len > 0) {
262 			skb_queue_head(&session->transmit, skb);
263 		} else {
264 			cmtp_free_block_id(session, scb->id);
265 			if (scb->data) {
266 				cmtp_send_frame(session, nskb->data, nskb->len);
267 				skb_trim(nskb, 0);
268 			}
269 			kfree_skb(skb);
270 		}
271 	}
272 
273 	cmtp_send_frame(session, nskb->data, nskb->len);
274 
275 	kfree_skb(nskb);
276 }
277 
cmtp_session(void * arg)278 static int cmtp_session(void *arg)
279 {
280 	struct cmtp_session *session = arg;
281 	struct sock *sk = session->sock->sk;
282 	struct sk_buff *skb;
283 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
284 
285 	BT_DBG("session %p", session);
286 
287 	set_user_nice(current, -15);
288 
289 	add_wait_queue(sk_sleep(sk), &wait);
290 	while (1) {
291 		/* Ensure session->terminate is updated */
292 		smp_mb__before_atomic();
293 
294 		if (atomic_read(&session->terminate))
295 			break;
296 		if (sk->sk_state != BT_CONNECTED)
297 			break;
298 
299 		while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
300 			skb_orphan(skb);
301 			if (!skb_linearize(skb))
302 				cmtp_recv_frame(session, skb);
303 			else
304 				kfree_skb(skb);
305 		}
306 
307 		cmtp_process_transmit(session);
308 
309 		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
310 	}
311 	remove_wait_queue(sk_sleep(sk), &wait);
312 
313 	down_write(&cmtp_session_sem);
314 
315 	if (!(session->flags & (1 << CMTP_LOOPBACK)))
316 		cmtp_detach_device(session);
317 
318 	fput(session->sock->file);
319 
320 	__cmtp_unlink_session(session);
321 
322 	up_write(&cmtp_session_sem);
323 
324 	kfree(session);
325 	module_put_and_exit(0);
326 	return 0;
327 }
328 
cmtp_add_connection(struct cmtp_connadd_req * req,struct socket * sock)329 int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
330 {
331 	struct cmtp_session *session, *s;
332 	int i, err;
333 
334 	BT_DBG("");
335 
336 	if (!l2cap_is_socket(sock))
337 		return -EBADFD;
338 
339 	session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
340 	if (!session)
341 		return -ENOMEM;
342 
343 	down_write(&cmtp_session_sem);
344 
345 	s = __cmtp_get_session(&l2cap_pi(sock->sk)->chan->dst);
346 	if (s && s->state == BT_CONNECTED) {
347 		err = -EEXIST;
348 		goto failed;
349 	}
350 
351 	bacpy(&session->bdaddr, &l2cap_pi(sock->sk)->chan->dst);
352 
353 	session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu,
354 					l2cap_pi(sock->sk)->chan->imtu);
355 
356 	BT_DBG("mtu %d", session->mtu);
357 
358 	sprintf(session->name, "%pMR", &session->bdaddr);
359 
360 	session->sock  = sock;
361 	session->state = BT_CONFIG;
362 
363 	init_waitqueue_head(&session->wait);
364 
365 	session->msgnum = CMTP_INITIAL_MSGNUM;
366 
367 	INIT_LIST_HEAD(&session->applications);
368 
369 	skb_queue_head_init(&session->transmit);
370 
371 	for (i = 0; i < 16; i++)
372 		session->reassembly[i] = NULL;
373 
374 	session->flags = req->flags;
375 
376 	__cmtp_link_session(session);
377 
378 	__module_get(THIS_MODULE);
379 	session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d",
380 								session->num);
381 	if (IS_ERR(session->task)) {
382 		module_put(THIS_MODULE);
383 		err = PTR_ERR(session->task);
384 		goto unlink;
385 	}
386 
387 	if (!(session->flags & (1 << CMTP_LOOPBACK))) {
388 		err = cmtp_attach_device(session);
389 		if (err < 0) {
390 			atomic_inc(&session->terminate);
391 			wake_up_interruptible(sk_sleep(session->sock->sk));
392 			up_write(&cmtp_session_sem);
393 			return err;
394 		}
395 	}
396 
397 	up_write(&cmtp_session_sem);
398 	return 0;
399 
400 unlink:
401 	__cmtp_unlink_session(session);
402 
403 failed:
404 	up_write(&cmtp_session_sem);
405 	kfree(session);
406 	return err;
407 }
408 
cmtp_del_connection(struct cmtp_conndel_req * req)409 int cmtp_del_connection(struct cmtp_conndel_req *req)
410 {
411 	struct cmtp_session *session;
412 	int err = 0;
413 
414 	BT_DBG("");
415 
416 	down_read(&cmtp_session_sem);
417 
418 	session = __cmtp_get_session(&req->bdaddr);
419 	if (session) {
420 		/* Flush the transmit queue */
421 		skb_queue_purge(&session->transmit);
422 
423 		/* Stop session thread */
424 		atomic_inc(&session->terminate);
425 
426 		/* Ensure session->terminate is updated */
427 		smp_mb__after_atomic();
428 
429 		wake_up_interruptible(sk_sleep(session->sock->sk));
430 	} else
431 		err = -ENOENT;
432 
433 	up_read(&cmtp_session_sem);
434 	return err;
435 }
436 
cmtp_get_connlist(struct cmtp_connlist_req * req)437 int cmtp_get_connlist(struct cmtp_connlist_req *req)
438 {
439 	struct cmtp_session *session;
440 	int err = 0, n = 0;
441 
442 	BT_DBG("");
443 
444 	down_read(&cmtp_session_sem);
445 
446 	list_for_each_entry(session, &cmtp_session_list, list) {
447 		struct cmtp_conninfo ci;
448 
449 		__cmtp_copy_session(session, &ci);
450 
451 		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
452 			err = -EFAULT;
453 			break;
454 		}
455 
456 		if (++n >= req->cnum)
457 			break;
458 
459 		req->ci++;
460 	}
461 	req->cnum = n;
462 
463 	up_read(&cmtp_session_sem);
464 	return err;
465 }
466 
cmtp_get_conninfo(struct cmtp_conninfo * ci)467 int cmtp_get_conninfo(struct cmtp_conninfo *ci)
468 {
469 	struct cmtp_session *session;
470 	int err = 0;
471 
472 	down_read(&cmtp_session_sem);
473 
474 	session = __cmtp_get_session(&ci->bdaddr);
475 	if (session)
476 		__cmtp_copy_session(session, ci);
477 	else
478 		err = -ENOENT;
479 
480 	up_read(&cmtp_session_sem);
481 	return err;
482 }
483 
484 
cmtp_init(void)485 static int __init cmtp_init(void)
486 {
487 	BT_INFO("CMTP (CAPI Emulation) ver %s", VERSION);
488 
489 	cmtp_init_sockets();
490 
491 	return 0;
492 }
493 
cmtp_exit(void)494 static void __exit cmtp_exit(void)
495 {
496 	cmtp_cleanup_sockets();
497 }
498 
499 module_init(cmtp_init);
500 module_exit(cmtp_exit);
501 
502 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
503 MODULE_DESCRIPTION("Bluetooth CMTP ver " VERSION);
504 MODULE_VERSION(VERSION);
505 MODULE_LICENSE("GPL");
506 MODULE_ALIAS("bt-proto-5");
507