• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
6  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
7  *
8  *
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.
13  *
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.
18  *
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
22  *
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <signal.h>
37 #include <getopt.h>
38 
39 #include <sys/socket.h>
40 
41 #include <bluetooth/bluetooth.h>
42 #include <bluetooth/hci.h>
43 #include <bluetooth/hci_lib.h>
44 #include <bluetooth/rfcomm.h>
45 #include <bluetooth/hidp.h>
46 
47 #include "sdp.h"
48 #include "dund.h"
49 #include "lib.h"
50 
51 volatile sig_atomic_t __io_canceled;
52 
53 /* MS dialup networking support (i.e. CLIENT / CLIENTSERVER thing) */
54 static int msdun = 0;
55 
56 static char *pppd = "/usr/sbin/pppd";
57 static char *pppd_opts[DUN_MAX_PPP_OPTS] =
58 	{
59 		/* First 3 are reserved */
60 		"", "", "",
61 		"noauth",
62 		"noipdefault",
63 		NULL
64 	};
65 
66 static int  detach = 1;
67 static int  persist;
68 static int  use_sdp = 1;
69 static int  auth;
70 static int  encrypt;
71 static int  secure;
72 static int  master;
73 static int  type = LANACCESS;
74 static int  search_duration = 10;
75 static uint use_cache;
76 
77 static int  channel;
78 
79 static struct {
80 	uint     valid;
81 	char     dst[40];
82 	bdaddr_t bdaddr;
83 	int      channel;
84 } cache;
85 
86 static bdaddr_t src_addr = *BDADDR_ANY;
87 static int src_dev = -1;
88 
89 volatile int terminate;
90 
91 enum {
92 	NONE,
93 	SHOW,
94 	LISTEN,
95 	CONNECT,
96 	KILL
97 } modes;
98 
99 static int create_connection(char *dst, bdaddr_t *bdaddr, int mrouter);
100 
do_listen(void)101 static int do_listen(void)
102 {
103 	struct sockaddr_rc sa;
104 	int sk, lm;
105 
106 	if (type == MROUTER) {
107 		if (!cache.valid)
108 			return -1;
109 
110 		if (create_connection(cache.dst, &cache.bdaddr, type) < 0) {
111 			syslog(LOG_ERR, "Cannot connect to mRouter device. %s(%d)",
112 								strerror(errno), errno);
113 			return -1;
114 		}
115 	}
116 
117 	if (!channel)
118 		channel = DUN_DEFAULT_CHANNEL;
119 
120 	if (use_sdp)
121 		dun_sdp_register(&src_addr, channel, type);
122 
123 	if (type == MROUTER)
124 		syslog(LOG_INFO, "Waiting for mRouter callback on channel %d", channel);
125 
126 	/* Create RFCOMM socket */
127 	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
128 	if (sk < 0) {
129 		syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)",
130 				strerror(errno), errno);
131 		return -1;
132 	}
133 
134 	sa.rc_family  = AF_BLUETOOTH;
135 	sa.rc_channel = channel;
136 	sa.rc_bdaddr  = src_addr;
137 
138 	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) {
139 		syslog(LOG_ERR, "Bind failed. %s(%d)", strerror(errno), errno);
140 		return -1;
141 	}
142 
143 	/* Set link mode */
144 	lm = 0;
145 	if (master)
146 		lm |= RFCOMM_LM_MASTER;
147 	if (auth)
148 		lm |= RFCOMM_LM_AUTH;
149 	if (encrypt)
150 		lm |= RFCOMM_LM_ENCRYPT;
151 	if (secure)
152 		lm |= RFCOMM_LM_SECURE;
153 
154 	if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
155 		syslog(LOG_ERR, "Failed to set link mode. %s(%d)", strerror(errno), errno);
156 		return -1;
157 	}
158 
159 	listen(sk, 10);
160 
161 	while (!terminate) {
162 		socklen_t alen = sizeof(sa);
163 		int nsk;
164 		char ba[40];
165 		char ch[10];
166 
167 		nsk = accept(sk, (struct sockaddr *) &sa, &alen);
168 		if (nsk < 0) {
169 			syslog(LOG_ERR, "Accept failed. %s(%d)", strerror(errno), errno);
170 			continue;
171 		}
172 
173 		switch (fork()) {
174 		case 0:
175 			break;
176 		case -1:
177 			syslog(LOG_ERR, "Fork failed. %s(%d)", strerror(errno), errno);
178 		default:
179 			close(nsk);
180 			if (type == MROUTER) {
181 				close(sk);
182 				terminate = 1;
183 			}
184 			continue;
185 		}
186 
187 		close(sk);
188 
189 		if (msdun && ms_dun(nsk, 1, msdun) < 0) {
190 			syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno);
191 			exit(0);
192 		}
193 
194 		ba2str(&sa.rc_bdaddr, ba);
195 		snprintf(ch, sizeof(ch), "%d", channel);
196 
197 		/* Setup environment */
198 		setenv("DUN_BDADDR",  ba, 1);
199 		setenv("DUN_CHANNEL", ch, 1);
200 
201 		if (!dun_open_connection(nsk, pppd, pppd_opts, 0))
202 			syslog(LOG_INFO, "New connection from %s", ba);
203 
204 		close(nsk);
205 		exit(0);
206 	}
207 
208 	if (use_sdp)
209 		dun_sdp_unregister();
210 	return 0;
211 }
212 
213 /* Connect and initiate RFCOMM session
214  * Returns:
215  *   -1 - critical error (exit persist mode)
216  *   1  - non critical error
217  *   0  - success
218  */
create_connection(char * dst,bdaddr_t * bdaddr,int mrouter)219 static int create_connection(char *dst, bdaddr_t *bdaddr, int mrouter)
220 {
221 	struct sockaddr_rc sa;
222 	int sk, err = 0, ch;
223 
224 	if (use_cache && cache.valid && cache.channel) {
225 		/* Use cached channel */
226 		ch = cache.channel;
227 
228 	} else if (!channel) {
229 		syslog(LOG_INFO, "Searching for %s on %s", mrouter ? "SP" : "LAP", dst);
230 
231 		if (dun_sdp_search(&src_addr, bdaddr, &ch, mrouter) <= 0)
232 			return 0;
233 	} else
234 		ch = channel;
235 
236 	syslog(LOG_INFO, "Connecting to %s channel %d", dst, ch);
237 
238 	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
239 	if (sk < 0) {
240 		syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)",
241 		     strerror(errno), errno);
242 		return -1;
243 	}
244 
245 	sa.rc_family  = AF_BLUETOOTH;
246 	sa.rc_channel = 0;
247 	sa.rc_bdaddr  = src_addr;
248 
249 	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)))
250 		syslog(LOG_ERR, "Bind failed. %s(%d)",
251 			strerror(errno), errno);
252 
253 	sa.rc_channel = ch;
254 	sa.rc_bdaddr  = *bdaddr;
255 
256 	if (!connect(sk, (struct sockaddr *) &sa, sizeof(sa)) ) {
257 		if (mrouter) {
258 			sleep(1);
259 			close(sk);
260 			return 0;
261 		}
262 
263 		syslog(LOG_INFO, "Connection established");
264 
265 		if (msdun && ms_dun(sk, 0, msdun) < 0) {
266 			syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno);
267 			err = 1;
268 			goto out;
269 		}
270 
271 		if (!dun_open_connection(sk, pppd, pppd_opts, (persist > 0)))
272 			err = 0;
273 		else
274 			err = 1;
275 	} else {
276 		syslog(LOG_ERR, "Connect to %s failed. %s(%d)",
277 				dst, strerror(errno), errno);
278 		err = 1;
279 	}
280 
281 out:
282 	if (use_cache) {
283 		if (!err) {
284 			/* Succesesful connection, validate cache */
285 			strcpy(cache.dst, dst);
286 			bacpy(&cache.bdaddr, bdaddr);
287 			cache.channel = ch;
288 			cache.valid   = use_cache;
289 		} else {
290 			cache.channel = 0;
291 			cache.valid--;
292 		}
293 	}
294 
295 	close(sk);
296 	return err;
297 }
298 
299 /* Search and connect
300  * Returns:
301  *   -1 - critical error (exit persist mode)
302  *   1  - non critical error
303  *   0  - success
304  */
do_connect(void)305 static int do_connect(void)
306 {
307 	inquiry_info *ii;
308 	int reconnect = 0;
309 	int i, n, r = 0;
310 
311 	do {
312 		if (reconnect)
313 			sleep(persist);
314 		reconnect = 1;
315 
316 		if (cache.valid) {
317 			/* Use cached bdaddr */
318 			r = create_connection(cache.dst, &cache.bdaddr, 0);
319 			if (r < 0) {
320 				terminate = 1;
321 				break;
322 			}
323 			continue;
324 		}
325 
326 		syslog(LOG_INFO, "Inquiring");
327 
328 		/* FIXME: Should we use non general LAP here ? */
329 
330 		ii = NULL;
331 		n  = hci_inquiry(src_dev, search_duration, 0, NULL, &ii, 0);
332 		if (n < 0) {
333 			syslog(LOG_ERR, "Inquiry failed. %s(%d)", strerror(errno), errno);
334 			continue;
335 		}
336 
337 		for (i = 0; i < n; i++) {
338 			char dst[40];
339 			ba2str(&ii[i].bdaddr, dst);
340 
341 			r = create_connection(dst, &ii[i].bdaddr, 0);
342 			if (r < 0) {
343 				terminate = 1;
344 				break;
345 			}
346 		}
347 		bt_free(ii);
348 	} while (!terminate && persist);
349 
350 	return r;
351 }
352 
do_show(void)353 static void do_show(void)
354 {
355 	dun_show_connections();
356 }
357 
do_kill(char * dst)358 static void do_kill(char *dst)
359 {
360 	if (dst) {
361 		bdaddr_t ba;
362 		str2ba(dst, &ba);
363 		dun_kill_connection((void *) &ba);
364 	} else
365 		dun_kill_all_connections();
366 }
367 
sig_hup(int sig)368 static void sig_hup(int sig)
369 {
370 	return;
371 }
372 
sig_term(int sig)373 static void sig_term(int sig)
374 {
375 	io_cancel();
376 	terminate = 1;
377 }
378 
379 static struct option main_lopts[] = {
380 	{ "help",	0, 0, 'h' },
381 	{ "listen",	0, 0, 's' },
382 	{ "connect",	1, 0, 'c' },
383 	{ "search",	2, 0, 'Q' },
384 	{ "kill",	1, 0, 'k' },
385 	{ "killall",	0, 0, 'K' },
386 	{ "channel",	1, 0, 'P' },
387 	{ "device",	1, 0, 'i' },
388 	{ "nosdp",	0, 0, 'D' },
389 	{ "list",	0, 0, 'l' },
390 	{ "show",	0, 0, 'l' },
391 	{ "nodetach",	0, 0, 'n' },
392 	{ "persist",	2, 0, 'p' },
393 	{ "auth",	0, 0, 'A' },
394 	{ "encrypt",	0, 0, 'E' },
395 	{ "secure",	0, 0, 'S' },
396 	{ "master",	0, 0, 'M' },
397 	{ "cache",	0, 0, 'C' },
398 	{ "pppd",	1, 0, 'd' },
399 	{ "msdun",	2, 0, 'X' },
400 	{ "activesync",	0, 0, 'a' },
401 	{ "mrouter",	1, 0, 'm' },
402 	{ "dialup",	0, 0, 'u' },
403 	{ 0, 0, 0, 0 }
404 };
405 
406 static const char *main_sopts = "hsc:k:Kr:i:lnp::DQ::AESMP:C::P:Xam:u";
407 
408 static const char *main_help =
409 	"Bluetooth LAP (LAN Access over PPP) daemon version %s\n"
410 	"Usage:\n"
411 	"\tdund <options> [pppd options]\n"
412 	"Options:\n"
413 	"\t--show --list -l          Show active LAP connections\n"
414 	"\t--listen -s               Listen for LAP connections\n"
415 	"\t--dialup -u               Pretend to be a dialup/telephone\n"
416 	"\t--connect -c <bdaddr>     Create LAP connection\n"
417 	"\t--mrouter -m <bdaddr>     Create mRouter connection\n"
418 	"\t--search -Q[duration]     Search and connect\n"
419 	"\t--kill -k <bdaddr>        Kill LAP connection\n"
420 	"\t--killall -K              Kill all LAP connections\n"
421 	"\t--channel -P <channel>    RFCOMM channel\n"
422 	"\t--device -i <bdaddr>      Source bdaddr\n"
423 	"\t--nosdp -D                Disable SDP\n"
424 	"\t--auth -A                 Enable authentication\n"
425 	"\t--encrypt -E              Enable encryption\n"
426 	"\t--secure -S               Secure connection\n"
427 	"\t--master -M               Become the master of a piconet\n"
428 	"\t--nodetach -n             Do not become a daemon\n"
429 	"\t--persist -p[interval]    Persist mode\n"
430 	"\t--pppd -d <pppd>          Location of the PPP daemon (pppd)\n"
431 	"\t--msdun -X[timeo]         Enable Microsoft dialup networking support\n"
432 	"\t--activesync -a           Enable Microsoft ActiveSync networking\n"
433 	"\t--cache -C[valid]         Enable address cache\n";
434 
main(int argc,char * argv[])435 int main(int argc, char *argv[])
436 {
437 	char *dst = NULL, *src = NULL;
438 	struct sigaction sa;
439 	int mode = NONE;
440 	int opt;
441 
442 	while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) {
443 		switch(opt) {
444 		case 'l':
445 			mode = SHOW;
446 			detach = 0;
447 			break;
448 
449 		case 's':
450 			mode = LISTEN;
451 			type = LANACCESS;
452 			break;
453 
454 		case 'c':
455 			mode = CONNECT;
456 			dst  = strdup(optarg);
457 			break;
458 
459 		case 'Q':
460 			mode = CONNECT;
461 			dst  = NULL;
462 			if (optarg)
463 				search_duration = atoi(optarg);
464 			break;
465 
466 		case 'k':
467 			mode = KILL;
468 			detach = 0;
469 			dst  = strdup(optarg);
470 			break;
471 
472 		case 'K':
473 			mode = KILL;
474 			detach = 0;
475 			dst  = NULL;
476 			break;
477 
478 		case 'P':
479 			channel = atoi(optarg);
480 			break;
481 
482 		case 'i':
483 			src = strdup(optarg);
484 			break;
485 
486 		case 'D':
487 			use_sdp = 0;
488 			break;
489 
490 		case 'A':
491 			auth = 1;
492 			break;
493 
494 		case 'E':
495 			encrypt = 1;
496 			break;
497 
498 		case 'S':
499 			secure = 1;
500 			break;
501 
502 		case 'M':
503 			master = 1;
504 			break;
505 
506 		case 'n':
507 			detach = 0;
508 			break;
509 
510 		case 'p':
511 			if (optarg)
512 				persist = atoi(optarg);
513 			else
514 				persist = 5;
515 			break;
516 
517 		case 'C':
518 			if (optarg)
519 				use_cache = atoi(optarg);
520 			else
521 				use_cache = 2;
522 			break;
523 
524 		case 'd':
525 			pppd  = strdup(optarg);
526 			break;
527 
528 		case 'X':
529 			if (optarg)
530 				msdun = atoi(optarg);
531 			else
532 				msdun = 10;
533 			break;
534 
535 		case 'a':
536 			msdun = 10;
537 			type = ACTIVESYNC;
538 			break;
539 
540 		case 'm':
541 			mode = LISTEN;
542 			dst  = strdup(optarg);
543 			type = MROUTER;
544 			break;
545 
546 		case 'u':
547 			mode = LISTEN;
548 			type = DIALUP;
549 			break;
550 
551 		case 'h':
552 		default:
553 			printf(main_help, VERSION);
554 			exit(0);
555 		}
556 	}
557 
558 	argc -= optind;
559 	argv += optind;
560 
561 	/* The rest is pppd options */
562 	if (argc > 0) {
563 		for (opt = 3; argc && opt < DUN_MAX_PPP_OPTS - 1;
564 							argc--, opt++)
565 			pppd_opts[opt] = *argv++;
566 		pppd_opts[opt] = NULL;
567 	}
568 
569 	io_init();
570 
571 	if (dun_init()) {
572 		free(dst);
573 		return -1;
574 	}
575 
576 	/* Check non daemon modes first */
577 	switch (mode) {
578 	case SHOW:
579 		do_show();
580 		free(dst);
581 		return 0;
582 
583 	case KILL:
584 		do_kill(dst);
585 		free(dst);
586 		return 0;
587 
588 	case NONE:
589 		printf(main_help, VERSION);
590 		free(dst);
591 		return 0;
592 	}
593 
594 	/* Initialize signals */
595 	memset(&sa, 0, sizeof(sa));
596 	sa.sa_flags   = SA_NOCLDSTOP;
597 	sa.sa_handler = SIG_IGN;
598 	sigaction(SIGCHLD, &sa, NULL);
599 	sigaction(SIGPIPE, &sa, NULL);
600 
601 	sa.sa_handler = sig_term;
602 	sigaction(SIGTERM, &sa, NULL);
603 	sigaction(SIGINT,  &sa, NULL);
604 
605 	sa.sa_handler = sig_hup;
606 	sigaction(SIGHUP, &sa, NULL);
607 
608 	if (detach && daemon(0, 0)) {
609 		perror("Can't start daemon");
610 		exit(1);
611 	}
612 
613 	openlog("dund", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
614 	syslog(LOG_INFO, "Bluetooth DUN daemon version %s", VERSION);
615 
616 	if (src) {
617 		src_dev = hci_devid(src);
618 		if (src_dev < 0 || hci_devba(src_dev, &src_addr) < 0) {
619 			syslog(LOG_ERR, "Invalid source. %s(%d)", strerror(errno), errno);
620 			free(dst);
621 			return -1;
622 		}
623 	}
624 
625 	if (dst) {
626 		strncpy(cache.dst, dst, sizeof(cache.dst) - 1);
627 		str2ba(dst, &cache.bdaddr);
628 
629 		/* Disable cache invalidation */
630 		use_cache = cache.valid = ~0;
631 	}
632 
633 	switch (mode) {
634 	case CONNECT:
635 		do_connect();
636 		break;
637 
638 	case LISTEN:
639 		do_listen();
640 		break;
641 	}
642 
643 	free(dst);
644 	return 0;
645 }
646