Introduction
Introduction Statistics Contact Development Disclaimer Help
rfcommd.c - rfcommd - RFCOMM daemon to run filters on clients.
git clone git://bitreich.org/rfcommd/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinw…
Log
Files
Refs
Tags
README
LICENSE
---
rfcommd.c (12906B)
---
1 /*
2 * See LICENSE for copyright details.
3 *
4 * Logic copied from rfcomm.c in bluez.
5 * SDP code from pybluez.
6 *
7 * Copy me if you can.
8 * by 20h
9 */
10
11 #include <stdio.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <getopt.h>
18 #include <signal.h>
19 #include <libgen.h>
20 #include <termios.h>
21 #include <stdint.h>
22 #include <poll.h>
23 #include <stdarg.h>
24 #include <sys/poll.h>
25 #include <sys/param.h>
26 #include <sys/ioctl.h>
27 #include <sys/socket.h>
28 #include <sys/wait.h>
29
30 #include <bluetooth/bluetooth.h>
31 #include <bluetooth/hci.h>
32 #include <bluetooth/hci_lib.h>
33 #include <bluetooth/rfcomm.h>
34 #include <bluetooth/sdp.h>
35 #include <bluetooth/sdp_lib.h>
36
37 #include "arg.h"
38
39 volatile sig_atomic_t __io_canceled = 0;
40
41 int dodebug = 0;
42
43 void
44 debug(char *fmt, ...)
45 {
46 va_list fmtargs;
47
48 if (!dodebug)
49 return;
50
51 va_start(fmtargs, fmt);
52 vfprintf(stderr, fmt, fmtargs);
53 va_end(fmtargs);
54 }
55
56 void
57 sig_hup(int sig)
58 {
59 return;
60 }
61
62 void
63 sig_term(int sig)
64 {
65 __io_canceled = 1;
66 }
67
68 void
69 setup_signals(void)
70 {
71 struct sigaction sa;
72
73 memset(&sa, 0, sizeof(sa));
74 sa.sa_flags = SA_NOCLDSTOP;
75 sa.sa_handler = SIG_IGN;
76 sigaction(SIGCHLD, &sa, NULL);
77 sigaction(SIGPIPE, &sa, NULL);
78
79 sa.sa_handler = sig_term;
80 sigaction(SIGTERM, &sa, NULL);
81 sigaction(SIGINT, &sa, NULL);
82
83 sa.sa_handler = sig_hup;
84 sigaction(SIGHUP, &sa, NULL);
85 }
86
87 int
88 _adv_available(struct hci_dev_info *di)
89 {
90 uint32_t *flags = &di->flags;
91 int dd;
92
93 if (hci_test_bit(HCI_RAW, &flags) && !bacmp(&di->bdaddr, BDADDR_…
94 dd = hci_open_dev(di->dev_id);
95
96 if (dd < 0)
97 return -1;
98 hci_read_bd_addr(dd, &di->bdaddr, 1000);
99 hci_close_dev(dd);
100 }
101
102 return (hci_test_bit(HCI_UP, flags) &&
103 hci_test_bit(HCI_RUNNING, flags) &&
104 hci_test_bit(HCI_PSCAN, flags) &&
105 hci_test_bit(HCI_ISCAN, flags)) != 0 ? 0 : -1;
106 }
107
108 int
109 _any_adv_available(void)
110 {
111 struct hci_dev_list_req *dl = NULL;
112 struct hci_dev_req *dr = NULL;
113 struct hci_dev_info di = {0, };
114 int result = -1;
115 int ctl = -1;
116 int i;
117
118 if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0)
119 return -1;
120
121 if (!(dl = malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) +
122 sizeof(uint16_t)))) {
123 goto CLEAN_UP_RETURN;
124 }
125 dl->dev_num = HCI_MAX_DEV;
126 dr = dl->dev_req;
127
128 if (ioctl(ctl, HCIGETDEVLIST, (void *)dl) < 0)
129 goto CLEAN_UP_RETURN;
130
131 for (i = 0; i < dl->dev_num; i++) {
132 di.dev_id = (dr+i)->dev_id;
133 if (ioctl(ctl, HCIGETDEVINFO, (void *)&di) < 0)
134 continue;
135
136 if (_adv_available(&di) == 0) {
137 result = 0;
138 goto CLEAN_UP_RETURN;
139 }
140 }
141
142 CLEAN_UP_RETURN:
143 close(ctl);
144 free(dl);
145
146 return result;
147 }
148
149 int
150 adv_available(int sock)
151 {
152 bdaddr_t ba = {{0, }};
153 struct sockaddr addr = {0, };
154 int dev_id = -1;
155 socklen_t alen = sizeof(addr);
156 struct sockaddr_rc const *addr_rc = (struct sockaddr_rc const *)…
157 struct hci_dev_info di;
158
159 if (getsockname(sock, &addr, &alen) < 0)
160 return -1;
161
162 ba = addr_rc->rc_bdaddr;
163
164 if (bacmp(&ba, BDADDR_ANY) == 0) {
165 dev_id = -1;
166 } else {
167 dev_id = hci_get_route(&ba);
168 }
169
170 if (dev_id == -1) {
171 return _any_adv_available();
172 } else {
173 if (hci_devinfo(dev_id, &di))
174 return -1;
175 return _adv_available(&di);
176 }
177 }
178
179 int
180 str2uuid(char *uuidstr, uuid_t *uuid)
181 {
182 uint32_t uuid_int[4];
183 int i;
184 char *endptr, buf[9] = { 0 };
185
186 if (strlen(uuidstr) == 36) {
187 if (uuidstr[8] != '-' && uuidstr[13] != '-' &&
188 uuidstr[18] != '-' && uuidstr[23] != '-'…
189 return 1;
190 }
191
192 strncpy(buf, uuidstr, 8);
193 uuid_int[0] = htonl(strtoul(buf, &endptr, 16));
194 if (endptr != buf+8)
195 return 1;
196
197 strncpy(buf, uuidstr+9, 4);
198 strncpy(buf+4, uuidstr+14, 4);
199 uuid_int[1] = htonl(strtoul(buf, &endptr, 16));
200 if (endptr != buf+8)
201 return 1;
202
203 strncpy(buf, uuidstr+19, 4);
204 strncpy(buf+4, uuidstr+24, 4);
205 uuid_int[2] = htonl(strtoul(buf, &endptr, 16));
206 if (endptr != buf+8)
207 return 1;
208
209 strncpy(buf, uuidstr+28, 4);
210 uuid_int[3] = htonl(strtoul(buf, &endptr, 16));
211 if (endptr != buf+8)
212 return 1;
213
214 if (uuid != NULL)
215 sdp_uuid128_create(uuid, uuid_int);
216 } else if (strlen(uuidstr) == 8) {
217 uuid_int[0] = strtoul(uuidstr, &endptr, 16);
218 if (endptr != uuidstr+8)
219 return 1;
220 if (uuid != NULL)
221 sdp_uuid32_create(uuid, uuid_int[0]);
222 } else if (strlen(uuidstr) == 4) {
223 i = strtol(uuidstr, &endptr, 16);
224 if (endptr != uuidstr+4)
225 return 1;
226 if (uuid != NULL)
227 sdp_uuid16_create(uuid, i);
228 } else {
229 return 1;
230 }
231
232 return 0;
233 }
234
235 int
236 sdp_advertise_service(int sock, char *svcname,
237 char *svcid, int svc_class, int profiles,
238 char *svcprovider, char *svcdescription)
239 {
240 char addrbuf[256];
241 int res, err = 0;
242 struct sockaddr *sockaddr;
243 uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_class_uuid,
244 svc_uuid;
245 sdp_profile_desc_t *profile_desc;
246 sdp_list_t *l2cap_list = NULL, *rfcomm_list = NULL, *root_list =…
247 *proto_list = NULL, *profile_list = NULL,
248 *svc_class_list = NULL, *access_proto_list = NULL;
249 sdp_data_t *channel = 0;
250 sdp_record_t record;
251 sdp_session_t *session = 0;
252 uint8_t rfcomm_channel;
253 socklen_t addrlen = sizeof(struct sockaddr_rc);
254
255 str2uuid(svcid, &svc_uuid);
256 sdp_uuid16_create(&svc_class_uuid, svc_class);
257
258 memset(addrbuf, 0, sizeof(addrbuf));
259
260 if (adv_available(sock) < 0)
261 return -1;
262
263 res = getsockname(sock, (struct sockaddr *)addrbuf, &addrlen);
264 if (res < 0)
265 return -1;
266 sockaddr = (struct sockaddr *)addrbuf;
267
268 memset(&record, 0, sizeof(record));
269 memset(&record.handle, 0xff, sizeof(record.handle));
270
271 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
272 root_list = sdp_list_append(0, &root_uuid);
273 sdp_set_browse_groups(&record, root_list);
274 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
275 l2cap_list = sdp_list_append(0, &l2cap_uuid);
276 proto_list = sdp_list_append(0, l2cap_list);
277 rfcomm_channel = ((struct sockaddr_rc *)sockaddr)->rc_channel;
278 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
279 channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
280 rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
281 sdp_list_append(rfcomm_list, channel);
282 sdp_list_append(proto_list, rfcomm_list);
283 access_proto_list = sdp_list_append(0, proto_list);
284 sdp_set_access_protos(&record, access_proto_list);
285 svc_class_list = sdp_list_append(svc_class_list, &svc_class_uuid…
286 sdp_set_service_classes(&record, svc_class_list);
287
288 profile_desc = (sdp_profile_desc_t *)malloc(sizeof(sdp_profile_d…
289 if (profile_desc == NULL)
290 return -1;
291 sdp_uuid16_create(&profile_desc->uuid, profiles);
292 profile_list = sdp_list_append(profile_list, profile_desc);
293 sdp_set_profile_descs(&record, profile_list);
294
295 sdp_set_info_attr(&record, svcname, svcprovider, svcdescription);
296 sdp_set_service_id(&record, svc_uuid);
297
298 session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
299 if (!session)
300 return -1;
301 err = sdp_record_register(session, &record, 0);
302
303 if (channel)
304 sdp_data_free(channel);
305 sdp_list_free(l2cap_list, 0);
306 sdp_list_free(rfcomm_list, 0);
307 sdp_list_free(root_list, 0);
308 sdp_list_free(access_proto_list, 0);
309 sdp_list_free(svc_class_list, 0);
310 sdp_list_free(profile_list, free);
311
312 if (err)
313 return -1;
314
315 return 0;
316 }
317
318 void
319 usage(char *argv0)
320 {
321 fprintf(stderr, "%s [-dhrAESM] [-i hciX|bdaddr] [-L linger] [-c …
322 basename(argv0));
323 exit(1);
324 }
325
326 int
327 main(int argc, char *argv[])
328 {
329 int rfcomm_raw_tty = 0, auth = 0, encryption = 0,
330 secure = 0, master = 0, linger = 0, sk, nsk, fd, lm , tr…
331 ctl, rc_channel = 1, filteri, dev;
332 char *argv0, *optarg, dst[18], devname[MAXPATHLEN], *replace,
333 *cmd, *oldcmd, *defaultcmd = NULL, *runcmd;
334 struct sockaddr_rc laddr, raddr;
335 struct rfcomm_dev_req req;
336 struct termios ti;
337 socklen_t alen;
338 bdaddr_t bdaddr;
339 struct linger l;
340
341 char **cmds = NULL;
342 char **filteraddrs = NULL;
343 bdaddr_t **filterbds = NULL;
344 int filtern = 0;
345
346 bacpy(&bdaddr, BDADDR_ANY);
347
348 ARGBEGIN(argv0) {
349 case 'c':
350 rc_channel = atoi(EARGF(usage(argv0)));
351 break;
352 case 'd':
353 dodebug = 1;
354 break;
355 case 'i':
356 optarg = EARGF(usage(argv0));
357 if (strncmp(optarg, "hci", 3) == 0) {
358 hci_devba(atoi(optarg + 3), &bdaddr);
359 } else {
360 str2ba(optarg, &bdaddr);
361 }
362 break;
363 case 'f':
364 ++filtern;
365 filteraddrs = realloc(filteraddrs,
366 filtern * sizeof(*filteraddrs));
367 if (filteraddrs == NULL)
368 exit(1);
369
370 cmds = realloc(cmds, filtern * sizeof(*cmds));
371 if (cmds == NULL)
372 exit(1);
373
374 filterbds = realloc(filterbds, filtern * sizeof(*filterb…
375 if (filterbds == NULL)
376 exit(1);
377
378 filteraddrs[filtern-1] = EARGF(usage(argv0));
379 argv++, argc--;
380 if (argc <= 0)
381 usage(argv0);
382 cmds[filtern-1] = argv[0];
383
384 filterbds[filtern-1] = malloc(sizeof(*filterbds));
385 if (filterbds[filtern-1] == NULL)
386 exit(1);
387 str2ba(filteraddrs[filtern-1], filterbds[filtern-1]);
388 break;
389 case 'r':
390 rfcomm_raw_tty = 1;
391 break;
392 case 'A':
393 auth = 1;
394 break;
395 case 'E':
396 encryption = 1;
397 break;
398 case 'S':
399 secure = 1;
400 break;
401 case 'M':
402 master = 1;
403 break;
404 case 'L':
405 linger = atoi(EARGF(usage(argv0)));
406 break;
407 case 'h':
408 default:
409 usage(argv0);
410 } ARGEND;
411
412 if (argc > 0)
413 defaultcmd = argv[0];
414 if (defaultcmd == NULL && filtern < 0)
415 usage(argv[0]);
416
417 for (filteri = 0; filteri < filtern; filteri++) {
418 ba2str(filterbds[filteri], dst);
419 debug("filter: %s (%s) -> %s\n",
420 filteraddrs[filteri], dst, cmds[filteri]);
421 }
422 debug("defaultcmd: %s\n", defaultcmd);
423
424 setup_signals();
425
426 ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
427 if (ctl < 0) {
428 perror("Can't open RFCOMM control socket");
429 return 1;
430 }
431
432 laddr.rc_family = AF_BLUETOOTH;
433 bacpy(&laddr.rc_bdaddr, &bdaddr);
434 laddr.rc_channel = rc_channel;
435
436 sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
437 if (sk < 0) {
438 perror("Can't create RFCOMM socket");
439 return 1;
440 }
441
442 lm = 0;
443 if (master)
444 lm |= RFCOMM_LM_MASTER;
445 if (auth)
446 lm |= RFCOMM_LM_AUTH;
447 if (encryption)
448 lm |= RFCOMM_LM_ENCRYPT;
449 if (secure)
450 lm |= RFCOMM_LM_SECURE;
451
452 if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))…
453 perror("Can't set RFCOMM link mode");
454 close(sk);
455 return 1;
456 }
457
458 if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
459 perror("Can't bind RFCOMM socket");
460 close(sk);
461 return 1;
462 }
463
464 debug("Waiting for connection on channel %d\n", laddr.rc_channel…
465
466 listen(sk, 10);
467
468 sdp_advertise_service(sk,
469 "SPP Printer",
470 "00001101-0000-1000-8000-00805F9B34FB",
471 SERIAL_PORT_SVCLASS_ID,
472 SERIAL_PORT_PROFILE_ID,
473 "SPP Printer Emulation",
474 "rfcommd");
475
476 while (!__io_canceled) {
477 alen = sizeof(raddr);
478 nsk = accept(sk, (struct sockaddr *)&raddr, &alen);
479
480 if (fork() != 0)
481 continue;
482
483 ba2str(&raddr.rc_bdaddr, dst);
484 debug("Accept from %s\n", dst);
485
486 for (filteri = 0; filteri < filtern; filteri++) {
487 if (!bacmp(filterbds[filteri], &raddr.rc_bdaddr)…
488 runcmd = cmds[filteri];
489 debug("filter found: %s -> %s\n",
490 filteraddrs[filteri],
491 runcmd);
492 break;
493 }
494 }
495 if (filteri >= filtern) {
496 if (defaultcmd != NULL) {
497 debug("running defaultcmd = %s\n",
498 defaultcmd);
499 runcmd = defaultcmd;
500 } else {
501 close(nsk);
502 continue;
503 }
504 }
505
506 alen = sizeof(laddr);
507 if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) <…
508 perror("Can't get RFCOMM socket name");
509 close(nsk);
510 continue;
511 }
512
513 if (linger) {
514 l.l_onoff = 1;
515 l.l_linger = linger;
516
517 if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, s…
518 perror("Can't set linger option");
519 close(nsk);
520 continue;
521 }
522 }
523
524 memset(&req, 0, sizeof(req));
525 req.dev_id = -1;
526 req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEA…
527
528 bacpy(&req.src, &laddr.rc_bdaddr);
529 bacpy(&req.dst, &raddr.rc_bdaddr);
530 req.channel = raddr.rc_channel;
531
532 dev = ioctl(nsk, RFCOMMCREATEDEV, &req);
533 if (dev < 0) {
534 perror("Can't create RFCOMM TTY");
535 close(sk);
536 continue;
537 }
538
539 snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
540 while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
541 if (errno == EACCES) {
542 perror("Can't open RFCOMM device");
543 goto release;
544 }
545
546 snprintf(devname, MAXPATHLEN - 1, "/dev/bluetoot…
547 if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < …
548 if (try--) {
549 snprintf(devname, MAXPATHLEN - 1…
550 usleep(100 * 1000);
551 continue;
552 }
553 perror("Can't open RFCOMM device");
554 goto release;
555 }
556 }
557
558 if (rfcomm_raw_tty) {
559 tcflush(fd, TCIOFLUSH);
560
561 cfmakeraw(&ti);
562 tcsetattr(fd, TCSANOW, &ti);
563 }
564
565 ba2str(&req.dst, dst);
566 debug("Connection from %s to %s\n", dst, devname);
567
568 /* Replace all occurences of '{}' with the rfcomm device…
569 asprintf(&oldcmd, "%s", runcmd);
570 while ((replace = strstr(oldcmd, "{}"))) {
571 replace[0] = '%';
572 replace[1] = 's';
573 asprintf(&cmd, oldcmd, devname);
574 free(oldcmd);
575 oldcmd = cmd;
576 }
577
578 debug("Executing %s\n", cmd);
579
580 system(cmd);
581 free(cmd);
582
583 close(fd);
584 close(nsk);
585 release:
586 memset(&req, 0, sizeof(req));
587 req.dev_id = dev;
588 req.flags = (1 << RFCOMM_HANGUP_NOW);
589 ioctl(ctl, RFCOMMRELEASEDEV, &req);
590 }
591
592 close(sk);
593
594 return 0;
595 }
596
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.