static int hostmode(char const *arg, int brief) { struct hostent *he = NULL; bdaddr_t ba; char bastr[32]; int reverse; if (bt_aton(arg, &ba) == 1) { reverse = 1; he = bt_gethostbyaddr((char const *) &ba, sizeof(ba), AF_BLUETOOTH); } else { reverse = 0; he = bt_gethostbyname(arg); } if (he == NULL) { herror(reverse? bt_ntoa(&ba, bastr) : arg); return (1); } if (brief) printf("%s", reverse? he->h_name : bt_ntoa((bdaddr_t *)(he->h_addr), bastr)); else printf("Host %s has %s %s\n", reverse? bt_ntoa(&ba, bastr) : arg, reverse? "name" : "address", reverse? he->h_name : bt_ntoa((bdaddr_t *)(he->h_addr), bastr)); return (0); }
int main(int argc, char *argv[]) { bdaddr_t bdaddr; int opt; hid_init(NULL); memcpy(&bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr)); while ((opt = getopt(argc, argv, "a:c:H:hv")) != -1) { switch (opt) { case 'a': /* bdaddr */ if (!bt_aton(optarg, &bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); } break; case 'c': /* config file */ config_file = optarg; break; case 'H': /* HIDs file */ hids_file = optarg; break; case 'v': /* verbose */ verbose++; break; case 'h': default: usage(); /* NOT REACHED */ } } argc -= optind; argv += optind; if (*argv == NULL) usage(); return (do_bthid_command(&bdaddr, argc, argv)); } /* main */
/* Main */ int main(int argc, char *argv[]) { char const *control = SDP_LOCAL_PATH; int n, local; bdaddr_t bdaddr; memset(&bdaddr, 0, sizeof(bdaddr)); local = 0; /* Process command line arguments */ while ((n = getopt(argc, argv, "a:c:lh")) != -1) { switch (n) { case 'a': /* bdaddr */ if (!bt_aton(optarg, &bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); } break; case 'c': /* control socket */ control = optarg; break; case 'l': /* local sdpd */ local = 1; break; case 'h': default: usage(); /* NOT REACHED */ } } argc -= optind; argv += optind; if (*argv == NULL) usage(); return (do_sdp_command(&bdaddr, control, local, argc, argv)); }
int main(int argc, char *argv[]) { int n; bdaddr_t bdaddr; memset(&bdaddr, 0, sizeof(bdaddr)); /* Process command line arguments */ while ((n = getopt(argc, argv, "a:nh")) != -1) { switch (n) { case 'a': if (!bt_aton(optarg, &bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); } break; case 'n': numeric_bdaddr = 1; break; case 'h': default: usage(); break; } } argc -= optind; argv += optind; if (*argv == NULL) usage(); return (do_l2cap_command(&bdaddr, argc, argv)); } /* main */
static int bt_open(struct voss_backend *pbe, const char *devname, int samplerate, int bufsize, int *pchannels, int *pformat, struct bt_config *cfg, int service_class, int isSink) { struct sockaddr_l2cap addr; struct l2cap_info info; socklen_t mtusize = sizeof(uint16_t); int tmpbitpool; int l2cap_psm; int temp; int err; memset(&info, 0, sizeof(info)); if (strstr(devname, "/dev/bluetooth/") != devname) { printf("Invalid device name '%s'", devname); goto error; } /* skip prefix */ devname += sizeof("/dev/bluetooth/") - 1; if (!bt_aton(devname, &info.raddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(devname)) == NULL) { DPRINTF("Could not get host by name\n"); goto error; } bdaddr_copy(&info.raddr, (bdaddr_t *)he->h_addr); } retry: switch (samplerate) { case 8000: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0x80; cfg->aacMode2 = 0x0C; break; case 11025: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0x40; cfg->aacMode2 = 0x0C; break; case 12000: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0x20; cfg->aacMode2 = 0x0C; break; case 16000: cfg->freq = FREQ_16K; cfg->aacMode1 = 0x10; cfg->aacMode2 = 0x0C; break; case 22050: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0x08; cfg->aacMode2 = 0x0C; break; case 24000: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0x04; cfg->aacMode2 = 0x0C; break; case 32000: cfg->freq = FREQ_32K; cfg->aacMode1 = 0x02; cfg->aacMode2 = 0x0C; break; case 44100: cfg->freq = FREQ_44_1K; cfg->aacMode1 = 0x01; cfg->aacMode2 = 0x0C; break; case 48000: cfg->freq = FREQ_48K; cfg->aacMode1 = 0; cfg->aacMode2 = 0x8C; break; case 64000: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0; cfg->aacMode2 = 0x4C; break; case 88200: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0; cfg->aacMode2 = 0x2C; break; case 96000: cfg->freq = FREQ_UNDEFINED; cfg->aacMode1 = 0; cfg->aacMode2 = 0x1C; break; default: DPRINTF("Invalid samplerate %d", samplerate); goto error; } cfg->bands = BANDS_8; cfg->bitpool = 0; switch (*pchannels) { case 1: cfg->aacMode2 &= 0xF8; cfg->chmode = MODE_MONO; break; default: cfg->aacMode2 &= 0xF4; cfg->chmode = MODE_STEREO; break; } cfg->allocm = ALLOC_LOUDNESS; if (cfg->chmode == MODE_MONO || cfg->chmode == MODE_DUAL) tmpbitpool = 16; else tmpbitpool = 32; if (cfg->bands == BANDS_8) tmpbitpool *= 8; else tmpbitpool *= 4; if (tmpbitpool > DEFAULT_MAXBPOOL) tmpbitpool = DEFAULT_MAXBPOOL; cfg->bitpool = tmpbitpool; if (bt_set_format(pformat)) { DPRINTF("Unsupported sample format\n"); goto error; } l2cap_psm = bt_query(&info, service_class); DPRINTF("PSM=0x%02x\n", l2cap_psm); if (l2cap_psm < 0) { DPRINTF("PSM not found\n"); goto error; } cfg->hc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); if (cfg->hc < 0) { DPRINTF("Could not create BT socket\n"); goto error; } memset(&addr, 0, sizeof(addr)); addr.l2cap_len = sizeof(addr); addr.l2cap_family = AF_BLUETOOTH; bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr); if (bind(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) { DPRINTF("Could not bind to HC\n"); goto error; } bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr); addr.l2cap_psm = l2cap_psm; if (connect(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) { DPRINTF("Could not connect to HC: %d\n", errno); goto error; } if (avdtpDiscoverAndConfig(cfg, isSink)) { DPRINTF("DISCOVER FAILED\n"); goto error; } if (avdtpOpen(cfg->hc, cfg->sep)) { DPRINTF("OPEN FAILED\n"); goto error; } cfg->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); if (cfg->fd < 0) { DPRINTF("Could not create BT socket\n"); goto error; } memset(&addr, 0, sizeof(addr)); addr.l2cap_len = sizeof(addr); addr.l2cap_family = AF_BLUETOOTH; bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr); if (bind(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { DPRINTF("Could not bind\n"); goto error; } bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr); addr.l2cap_psm = l2cap_psm; if (connect(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { DPRINTF("Could not connect: %d\n", errno); goto error; } if (isSink) { if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_OMTU, &cfg->mtu, &mtusize) == -1) { DPRINTF("Could not get MTU\n"); goto error; } temp = cfg->mtu * 2; if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDBUF, &temp, sizeof(temp)) == -1) { DPRINTF("Could not set send buffer size\n"); goto error; } temp = cfg->mtu; if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDLOWAT, &temp, sizeof(temp)) == -1) { DPRINTF("Could not set low water mark\n"); goto error; } } else { if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_IMTU, &cfg->mtu, &mtusize) == -1) { DPRINTF("Could not get MTU\n"); goto error; } temp = cfg->mtu * 16; if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVBUF, &temp, sizeof(temp)) == -1) { DPRINTF("Could not set receive buffer size\n"); goto error; } temp = 1; if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVLOWAT, &temp, sizeof(temp)) == -1) { DPRINTF("Could not set low water mark\n"); goto error; } } if (avdtpStart(cfg->hc, cfg->sep)) { DPRINTF("START FAILED\n"); goto error; } switch (cfg->chmode) { case MODE_MONO: *pchannels = 1; break; default: *pchannels = 2; break; } return (0); error: if (cfg->hc > 0) { close(cfg->hc); cfg->hc = -1; } if (cfg->fd > 0) { close(cfg->fd); cfg->fd = -1; } return (-1); }
/* Send Swith Role to the unit */ static int hci_switch_role(int s, int argc, char **argv) { int n0; char b[512]; ng_hci_switch_role_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* parse command parameters */ switch (argc) { case 2: /* bdaddr */ if (!bt_aton(argv[0], &cp.bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(argv[0])) == NULL) return (USAGE); memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); } /* role */ if (sscanf(argv[1], "%d", &n0) != 1) return (USAGE); cp.role = n0? NG_HCI_ROLE_SLAVE : NG_HCI_ROLE_MASTER; break; default: return (USAGE); } /* send request and expect status response */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_POLICY, NG_HCI_OCF_SWITCH_ROLE), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) return (ERROR); if (n0 < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_ROLE_CHANGE) { ng_hci_role_change_ep *ep = (ng_hci_role_change_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Role: %s [%#x]\n", (ep->role == NG_HCI_ROLE_MASTER)? "Master" : "Slave", ep->role); } else goto again; return (OK); } /* hci_switch_role */
/* Send Remote_Name_Request command to the unit */ static int hci_remote_name_request(int s, int argc, char **argv) { int n0; char b[512]; ng_hci_remote_name_req_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; memset(&cp, 0, sizeof(cp)); cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0; cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE; /* parse command parameters */ switch (argc) { case 4: /* clock_offset */ if (sscanf(argv[3], "%x", &n0) != 1) return (USAGE); cp.clock_offset = (n0 & 0xffff); cp.clock_offset = htole16(cp.clock_offset); case 3: /* page_scan_mode */ if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x03) return (USAGE); cp.page_scan_mode = (n0 & 0xff); case 2: /* page_scan_rep_mode */ if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x02) return (USAGE); cp.page_scan_rep_mode = (n0 & 0xff); case 1: /* BD_ADDR */ if (!bt_aton(argv[0], &cp.bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(argv[0])) == NULL) return (USAGE); memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); } break; default: return (USAGE); } /* send request and expect status response */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_REMOTE_NAME_REQ), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) return (ERROR); if (n0 < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL) { ng_hci_remote_name_req_compl_ep *ep = (ng_hci_remote_name_req_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Name: %s\n", ep->name); } else goto again; return (OK); } /* hci_remote_name_request */
int main(int ac, char *av[]) { bthcid_pin_response_t rp; struct sockaddr_un un; char *pin = NULL; int ch, s, len; memset(&rp, 0, sizeof(rp)); len = -1; memset(&un, 0, sizeof(un)); un.sun_len = sizeof(un); un.sun_family = AF_LOCAL; strlcpy(un.sun_path, BTHCID_SOCKET_NAME, sizeof(un.sun_path)); while ((ch = getopt(ac, av, "a:d:l:p:rs:")) != -1) { switch (ch) { case 'a': if (!bt_aton(optarg, &rp.raddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(optarg)) == NULL) errx(EXIT_FAILURE, "%s: %s", optarg, hstrerror(h_errno)); bdaddr_copy(&rp.raddr, (bdaddr_t *)he->h_addr); } break; case 'd': if (!bt_devaddr(optarg, &rp.laddr)) err(EXIT_FAILURE, "%s", optarg); break; case 'l': len = atoi(optarg); if (len < 1 || len > HCI_PIN_SIZE) errx(EXIT_FAILURE, "Invalid PIN length"); break; case 'p': pin = optarg; break; case 'r': if (len == -1) len = 4; break; case 's': strlcpy(un.sun_path, optarg, sizeof(un.sun_path)); break; default: usage(); } } if (bdaddr_any(&rp.raddr)) usage(); if (pin == NULL) { if (len == -1) usage(); srandom(time(NULL)); pin = (char *)rp.pin; while (len-- > 0) *pin++ = '0' + (random() % 10); printf("PIN: %.*s\n", HCI_PIN_SIZE, rp.pin); } else { if (len != -1) usage(); strncpy((char *)rp.pin, pin, HCI_PIN_SIZE); } s = socket(PF_LOCAL, SOCK_STREAM, 0); if (s < 0) err(EXIT_FAILURE, "socket"); if (connect(s, (struct sockaddr *)&un, sizeof(un)) < 0) err(EXIT_FAILURE, "connect(\"%s\")", un.sun_path); if (send(s, &rp, sizeof(rp), 0) != sizeof(rp)) err(EXIT_FAILURE, "send"); close(s); exit(EXIT_SUCCESS); }
/* Send Create_Connection command to the unit */ static int hci_create_connection(int s, int argc, char **argv) { int n0; char b[512]; ng_hci_create_con_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; /* Set defaults */ memset(&cp, 0, sizeof(cp)); cp.pkt_type = htole16( NG_HCI_PKT_DM1 | NG_HCI_PKT_DH1 | NG_HCI_PKT_DM3 | NG_HCI_PKT_DH3 | NG_HCI_PKT_DM5); cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0; cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE; cp.clock_offset = 0; cp.accept_role_switch = 1; /* parse command parameters */ switch (argc) { case 6: /* accept role switch */ if (sscanf(argv[5], "%d", &n0) != 1) return (USAGE); cp.accept_role_switch = n0 ? 1 : 0; case 5: /* clock offset */ if (sscanf(argv[4], "%d", &n0) != 1) return (USAGE); cp.clock_offset = (n0 & 0xffff); cp.clock_offset = htole16(cp.clock_offset); case 4: /* page scan mode */ if (sscanf(argv[3], "%d", &n0) != 1 || n0 < 0 || n0 > 3) return (USAGE); cp.page_scan_mode = (n0 & 0xff); case 3: /* page scan rep mode */ if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0 || n0 > 2) return (USAGE); cp.page_scan_rep_mode = (n0 & 0xff); case 2: /* packet type */ if (sscanf(argv[1], "%x", &n0) != 1) return (USAGE); n0 &= ( NG_HCI_PKT_DM1 | NG_HCI_PKT_DH1 | NG_HCI_PKT_DM3 | NG_HCI_PKT_DH3 | NG_HCI_PKT_DM5); if (n0 == 0) return (USAGE); cp.pkt_type = (n0 & 0xffff); cp.pkt_type = htole16(cp.pkt_type); case 1: /* BD_ADDR */ if (!bt_aton(argv[0], &cp.bdaddr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(argv[0])) == NULL) return (USAGE); memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); } break; default: return (USAGE); } /* send request and expect status response */ n0 = sizeof(b); if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_CREATE_CON), (char const *) &cp, sizeof(cp), b, &n0) == ERROR) return (ERROR); if (*b != 0x00) return (FAILED); /* wait for event */ again: n0 = sizeof(b); if (hci_recv(s, b, &n0) == ERROR) return (ERROR); if (n0 < sizeof(*e)) { errno = EIO; return (ERROR); } if (e->event == NG_HCI_EVENT_CON_COMPL) { ng_hci_con_compl_ep *ep = (ng_hci_con_compl_ep *)(e + 1); if (ep->status != 0x00) { fprintf(stdout, "Status: %s [%#02x]\n", hci_status2str(ep->status), ep->status); return (FAILED); } fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", hci_encrypt2str(ep->encryption_mode, 0), ep->encryption_mode); } else goto again; return (OK); } /* hci_create_connection */
/* Main */ int main(int argc, char *argv[]) { struct sockaddr_rfcomm sock_addr; char *label = NULL, *unit = NULL, *ep = NULL; bdaddr_t addr; int s, channel, detach, server, service, regdun, regsp; pid_t pid; memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)); channel = 0; detach = 1; server = 0; service = 0; regdun = 0; regsp = 0; /* Parse command line arguments */ while ((s = getopt(argc, argv, "a:cC:dDhl:sSu:")) != -1) { switch (s) { case 'a': /* BDADDR */ if (!bt_aton(optarg, &addr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&addr, he->h_addr, sizeof(addr)); } break; case 'c': /* client */ server = 0; break; case 'C': /* RFCOMM channel */ channel = strtoul(optarg, &ep, 10); if (*ep != '\0') { channel = 0; switch (tolower(optarg[0])) { case 'd': /* DialUp Networking */ service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; break; case 'l': /* LAN Access Using PPP */ service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; break; } } break; case 'd': /* do not detach */ detach = 0; break; case 'D': /* Register DUN service as well as LAN service */ regdun = 1; break; case 'l': /* PPP label */ label = optarg; break; case 's': /* server */ server = 1; break; case 'S': /* Register SP service as well as LAN service */ regsp = 1; break; case 'u': /* PPP -unit option */ strtoul(optarg, &ep, 10); if (*ep != '\0') usage(); /* NOT REACHED */ unit = optarg; break; case 'h': default: usage(); /* NOT REACHED */ } } /* Check if we got everything we wanted */ if (label == NULL) errx(1, "Must specify PPP label"); if (!server) { if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0) errx(1, "Must specify server BD_ADDR"); /* Check channel, if was not set then obtain it via SDP */ if (channel == 0 && service != 0) if (rfcomm_channel_lookup(NULL, &addr, service, &channel, &s) != 0) errc(1, s, "Could not obtain RFCOMM channel"); } if (channel <= 0 || channel > 30) errx(1, "Invalid RFCOMM channel number %d", channel); openlog(RFCOMM_PPPD, LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_USER); if (detach && daemon(0, 0) < 0) { syslog(LOG_ERR, "Could not daemon(0, 0). %s (%d)", strerror(errno), errno); exit(1); } s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM); if (s < 0) { syslog(LOG_ERR, "Could not create socket. %s (%d)", strerror(errno), errno); exit(1); } if (server) { struct sigaction sa; void *ss = NULL; sdp_lan_profile_t lan; /* Install signal handler */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = sighandler; if (sigaction(SIGTERM, &sa, NULL) < 0) { syslog(LOG_ERR, "Could not sigaction(SIGTERM). %s (%d)", strerror(errno), errno); exit(1); } if (sigaction(SIGHUP, &sa, NULL) < 0) { syslog(LOG_ERR, "Could not sigaction(SIGHUP). %s (%d)", strerror(errno), errno); exit(1); } if (sigaction(SIGINT, &sa, NULL) < 0) { syslog(LOG_ERR, "Could not sigaction(SIGINT). %s (%d)", strerror(errno), errno); exit(1); } sa.sa_handler = SIG_IGN; sa.sa_flags = SA_NOCLDWAIT; if (sigaction(SIGCHLD, &sa, NULL) < 0) { syslog(LOG_ERR, "Could not sigaction(SIGCHLD). %s (%d)", strerror(errno), errno); exit(1); } /* bind socket and listen for incoming connections */ sock_addr.rfcomm_len = sizeof(sock_addr); sock_addr.rfcomm_family = AF_BLUETOOTH; memcpy(&sock_addr.rfcomm_bdaddr, &addr, sizeof(sock_addr.rfcomm_bdaddr)); sock_addr.rfcomm_channel = channel; if (bind(s, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0) { syslog(LOG_ERR, "Could not bind socket. %s (%d)", strerror(errno), errno); exit(1); } if (listen(s, 10) < 0) { syslog(LOG_ERR, "Could not listen on socket. %s (%d)", strerror(errno), errno); exit(1); } ss = sdp_open_local(NULL); if (ss == NULL) { syslog(LOG_ERR, "Unable to create local SDP session"); exit(1); } if (sdp_error(ss) != 0) { syslog(LOG_ERR, "Unable to open local SDP session. " \ "%s (%d)", strerror(sdp_error(ss)), sdp_error(ss)); exit(1); } memset(&lan, 0, sizeof(lan)); lan.server_channel = channel; if (sdp_register_service(ss, SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP, &addr, (void *) &lan, sizeof(lan), NULL) != 0) { syslog(LOG_ERR, "Unable to register LAN service with " \ "local SDP daemon. %s (%d)", strerror(sdp_error(ss)), sdp_error(ss)); exit(1); } /* * Register DUN (Dial-Up Networking) service on the same * RFCOMM channel if requested. There is really no good reason * to not to support this. AT-command exchange can be faked * with chat script in ppp.conf */ if (regdun) { sdp_dun_profile_t dun; memset(&dun, 0, sizeof(dun)); dun.server_channel = channel; if (sdp_register_service(ss, SDP_SERVICE_CLASS_DIALUP_NETWORKING, &addr, (void *) &dun, sizeof(dun), NULL) != 0) { syslog(LOG_ERR, "Unable to register DUN " \ "service with local SDP daemon. " \ "%s (%d)", strerror(sdp_error(ss)), sdp_error(ss)); exit(1); } } /* * Register SP (Serial Port) service on the same RFCOMM channel * if requested. It appears that some cell phones are using so * called "callback mechanism". In this scenario user is trying * to connect his cell phone to the Internet, and, user's host * computer is acting as the gateway server. It seems that it * is not possible to tell the phone to just connect and start * using the LAN service. Instead the user's host computer must * "jump start" the phone by connecting to the phone's SP * service. What happens next is the phone kills the existing * connection and opens another connection back to the user's * host computer. The phone really wants to use LAN service, * but for whatever reason it looks for SP service on the * user's host computer. This brain damaged behavior was * reported for Nokia 6600 and Sony/Ericsson P900. Both phones * are Symbian-based phones. Perhaps this is a Symbian problem? */ if (regsp) { sdp_sp_profile_t sp; memset(&sp, 0, sizeof(sp)); sp.server_channel = channel; if (sdp_register_service(ss, SDP_SERVICE_CLASS_SERIAL_PORT, &addr, (void *) &sp, sizeof(sp), NULL) != 0) { syslog(LOG_ERR, "Unable to register SP " \ "service with local SDP daemon. " \ "%s (%d)", strerror(sdp_error(ss)), sdp_error(ss)); exit(1); } } for (done = 0; !done; ) { socklen_t len = sizeof(sock_addr); int s1 = accept(s, (struct sockaddr *) &sock_addr, &len); if (s1 < 0) { syslog(LOG_ERR, "Could not accept connection " \ "on socket. %s (%d)", strerror(errno), errno); exit(1); } pid = fork(); if (pid == (pid_t) -1) { syslog(LOG_ERR, "Could not fork(). %s (%d)", strerror(errno), errno); exit(1); } if (pid == 0) { sdp_close(ss); close(s); /* Reset signal handler */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; sigaction(SIGTERM, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGCHLD, &sa, NULL); /* Become daemon */ daemon(0, 0); /* * XXX Make sure user does not shoot himself * in the foot. Do not pass unit option to the * PPP when operating in the server mode. */ exec_ppp(s1, NULL, label); } else close(s1); } } else { sock_addr.rfcomm_len = sizeof(sock_addr); sock_addr.rfcomm_family = AF_BLUETOOTH; memcpy(&sock_addr.rfcomm_bdaddr, NG_HCI_BDADDR_ANY, sizeof(sock_addr.rfcomm_bdaddr)); sock_addr.rfcomm_channel = 0; if (bind(s, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0) { syslog(LOG_ERR, "Could not bind socket. %s (%d)", strerror(errno), errno); exit(1); } memcpy(&sock_addr.rfcomm_bdaddr, &addr, sizeof(sock_addr.rfcomm_bdaddr)); sock_addr.rfcomm_channel = channel; if (connect(s, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0) { syslog(LOG_ERR, "Could not connect socket. %s (%d)", strerror(errno), errno); exit(1); } exec_ppp(s, unit, label); } exit(0); } /* main */
int main(int argc, char *argv[]) { bdaddr_t src, dst; struct hostent *he; uint8_t *echo_data; struct sockaddr_l2cap sa; int32_t n, s, count, wait, flood, echo_size, numeric; char *endp, *rname; /* Set defaults */ memcpy(&src, NG_HCI_BDADDR_ANY, sizeof(src)); memcpy(&dst, NG_HCI_BDADDR_ANY, sizeof(dst)); echo_data = (uint8_t *) calloc(NG_L2CAP_MAX_ECHO_SIZE, sizeof(uint8_t)); if (echo_data == NULL) { fprintf(stderr, "Failed to allocate echo data buffer"); exit(1); } /* * Set default echo size to the NG_L2CAP_MTU_MINIMUM minus * the size of the L2CAP signalling command header. */ echo_size = NG_L2CAP_MTU_MINIMUM - sizeof(ng_l2cap_cmd_hdr_t); count = -1; /* unimited */ wait = 1; /* sec */ flood = 0; numeric = 0; /* Parse command line arguments */ while ((n = getopt(argc, argv, "a:c:fi:nS:s:h")) != -1) { switch (n) { case 'a': if (!bt_aton(optarg, &dst)) { if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&dst, he->h_addr, sizeof(dst)); } break; case 'c': count = strtol(optarg, &endp, 10); if (count <= 0 || *endp != '\0') usage(); break; case 'f': flood = 1; break; case 'i': wait = strtol(optarg, &endp, 10); if (wait <= 0 || *endp != '\0') usage(); break; case 'n': numeric = 1; break; case 'S': if (!bt_aton(optarg, &src)) { if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&src, he->h_addr, sizeof(src)); } break; case 's': echo_size = strtol(optarg, &endp, 10); if (echo_size < sizeof(int32_t) || echo_size > NG_L2CAP_MAX_ECHO_SIZE || *endp != '\0') usage(); break; case 'h': default: usage(); break; } } if (memcmp(&dst, NG_HCI_BDADDR_ANY, sizeof(dst)) == 0) usage(); he = bt_gethostbyaddr((const char *)&dst, sizeof(dst), AF_BLUETOOTH); if (he == NULL || he->h_name == NULL || he->h_name[0] == '\0' || numeric) asprintf(&rname, "%s", bt_ntoa(&dst, NULL)); else rname = strdup(he->h_name); if (rname == NULL) errx(1, "Failed to create remote hostname"); s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_L2CAP); if (s < 0) err(2, "Could not create socket"); memset(&sa, 0, sizeof(sa)); sa.l2cap_len = sizeof(sa); sa.l2cap_family = AF_BLUETOOTH; memcpy(&sa.l2cap_bdaddr, &src, sizeof(sa.l2cap_bdaddr)); if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(3, "Could not bind socket, src bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); memset(&sa, 0, sizeof(sa)); sa.l2cap_len = sizeof(sa); sa.l2cap_family = AF_BLUETOOTH; memcpy(&sa.l2cap_bdaddr, &dst, sizeof(sa.l2cap_bdaddr)); if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(4, "Could not connect socket, dst bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); /* Fill pattern */ for (n = 0; n < echo_size; ) { int32_t avail = min(echo_size - n, PATTERN_SIZE); memcpy(echo_data + n, pattern, avail); n += avail; } /* Start ping'ing */ for (n = 0; count == -1 || count > 0; n ++) { struct ng_btsocket_l2cap_raw_ping r; struct timeval a, b; int32_t fail; if (gettimeofday(&a, NULL) < 0) err(5, "Could not gettimeofday(a)"); fail = 0; *((int32_t *) echo_data) = htonl(n); r.result = 0; r.echo_size = echo_size; r.echo_data = echo_data; if (ioctl(s, SIOC_L2CAP_L2CA_PING, &r, sizeof(r)) < 0) { r.result = errno; fail = 1; /* warn("Could not ping, dst bdaddr=%s", bt_ntoa(&r.echo_dst, NULL)); */ } if (gettimeofday(&b, NULL) < 0) err(7, "Could not gettimeofday(b)"); tv_sub(&b, &a); fprintf(stdout, "%d bytes from %s seq_no=%d time=%.3f ms result=%#x %s\n", r.echo_size, rname, ntohl(*((int32_t *)(r.echo_data))), tv2msec(&b), r.result, ((fail == 0)? "" : strerror(errno))); if (!flood) { /* Wait */ a.tv_sec = wait; a.tv_usec = 0; select(0, NULL, NULL, NULL, &a); } if (count != -1) count --; } free(rname); free(echo_data); close(s); return (0); } /* main */
int32_t main(int32_t argc, char *argv[]) { struct bthid_server srv; struct sigaction sa; char const *pid_file = BTHIDD_PIDFILE; char *ep; int32_t opt, detach, tval; memset(&srv, 0, sizeof(srv)); memset(&srv.bdaddr, 0, sizeof(srv.bdaddr)); detach = 1; tval = 10; /* sec */ while ((opt = getopt(argc, argv, "a:c:dH:hp:t:")) != -1) { switch (opt) { case 'a': /* BDADDR */ if (!bt_aton(optarg, &srv.bdaddr)) { struct hostent *he; if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&srv.bdaddr, he->h_addr, sizeof(srv.bdaddr)); } break; case 'c': /* config file */ config_file = optarg; break; case 'd': /* do not detach */ detach = 0; break; case 'H': /* hids file */ hids_file = optarg; break; case 'p': /* pid file */ pid_file = optarg; break; case 't': /* rescan interval */ tval = strtol(optarg, (char **) &ep, 10); if (*ep != '\0' || tval <= 0) usage(); break; case 'h': default: usage(); /* NOT REACHED */ } } openlog(BTHIDD_IDENT, LOG_PID|LOG_PERROR|LOG_NDELAY, LOG_USER); /* Become daemon if required */ if (detach && daemon(0, 0) < 0) { syslog(LOG_CRIT, "Could not become daemon. %s (%d)", strerror(errno), errno); exit(1); } /* Install signal handler */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = sighandler; if (sigaction(SIGTERM, &sa, NULL) < 0 || sigaction(SIGHUP, &sa, NULL) < 0 || sigaction(SIGINT, &sa, NULL) < 0) { syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)", strerror(errno), errno); exit(1); } sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL) < 0) { syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)", strerror(errno), errno); exit(1); } sa.sa_handler = SIG_IGN; sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT; if (sigaction(SIGCHLD, &sa, NULL) < 0) { syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)", strerror(errno), errno); exit(1); } if (read_config_file() < 0 || read_hids_file() < 0 || server_init(&srv) < 0 || write_pid_file(pid_file) < 0) exit(1); for (done = 0; !done; ) { if (elapsed(tval)) client_rescan(&srv); if (server_do(&srv) < 0) break; } server_shutdown(&srv); remove_pid_file(pid_file); clean_config(); closelog(); return (0); }
/* Main */ int main(int argc, char *argv[]) { struct sigaction sa; struct sockaddr_rfcomm ra; bdaddr_t addr; int n, background, channel, service, s, amaster, aslave, fd, doserver, dopty; fd_set rfd; char *tty = NULL, *ep = NULL, buf[SPPD_BUFFER_SIZE]; memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)); background = channel = 0; service = SDP_SERVICE_CLASS_SERIAL_PORT; doserver = 0; dopty = 0; /* Parse command line options */ while ((n = getopt(argc, argv, "a:bc:thS")) != -1) { switch (n) { case 'a': /* BDADDR */ if (!bt_aton(optarg, &addr)) { struct hostent *he = NULL; if ((he = bt_gethostbyname(optarg)) == NULL) errx(1, "%s: %s", optarg, hstrerror(h_errno)); memcpy(&addr, he->h_addr, sizeof(addr)); } break; case 'c': /* RFCOMM channel */ channel = strtoul(optarg, &ep, 10); if (*ep != '\0') { channel = 0; switch (tolower(optarg[0])) { case 'd': /* DialUp Networking */ service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; break; case 'f': /* Fax */ service = SDP_SERVICE_CLASS_FAX; break; case 'l': /* LAN */ service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; break; case 's': /* Serial Port */ service = SDP_SERVICE_CLASS_SERIAL_PORT; break; default: errx(1, "Unknown service name: %s", optarg); /* NOT REACHED */ } } break; case 'b': /* Run in background */ background = 1; break; case 't': /* Open pseudo TTY */ dopty = 1; break; case 'S': doserver = 1; break; case 'h': default: usage(); /* NOT REACHED */ } } /* Check if we have everything we need */ if (!doserver && memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0) usage(); /* NOT REACHED */ /* Set signal handlers */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = sppd_sighandler; if (sigaction(SIGTERM, &sa, NULL) < 0) err(1, "Could not sigaction(SIGTERM)"); if (sigaction(SIGHUP, &sa, NULL) < 0) err(1, "Could not sigaction(SIGHUP)"); if (sigaction(SIGINT, &sa, NULL) < 0) err(1, "Could not sigaction(SIGINT)"); sa.sa_handler = SIG_IGN; sa.sa_flags = SA_NOCLDWAIT; if (sigaction(SIGCHLD, &sa, NULL) < 0) err(1, "Could not sigaction(SIGCHLD)"); /* Open TTYs */ if (dopty) { if (sppd_ttys_open(&tty, &amaster, &aslave) < 0) exit(1); fd = amaster; } else { if (background) usage(); amaster = STDIN_FILENO; fd = STDOUT_FILENO; } /* Open RFCOMM connection */ if (doserver) { struct sockaddr_rfcomm ma; bdaddr_t bt_addr_any; sdp_sp_profile_t sp; void *ss; uint32_t sdp_handle; int acceptsock, aaddrlen; acceptsock = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM); if (acceptsock < 0) err(1, "Could not create socket"); memcpy(&bt_addr_any, NG_HCI_BDADDR_ANY, sizeof(bt_addr_any)); memset(&ma, 0, sizeof(ma)); ma.rfcomm_len = sizeof(ma); ma.rfcomm_family = AF_BLUETOOTH; memcpy(&ma.rfcomm_bdaddr, &bt_addr_any, sizeof(bt_addr_any)); ma.rfcomm_channel = channel; if (bind(acceptsock, (struct sockaddr *)&ma, sizeof(ma)) < 0) err(1, "Could not bind socket on channel %d", channel); if (listen(acceptsock, 10) != 0) err(1, "Could not listen on socket"); aaddrlen = sizeof(ma); if (getsockname(acceptsock, (struct sockaddr *)&ma, &aaddrlen) < 0) err(1, "Could not get socket name"); channel = ma.rfcomm_channel; ss = sdp_open_local(NULL); if (ss == NULL) errx(1, "Unable to create local SDP session"); if (sdp_error(ss) != 0) errx(1, "Unable to open local SDP session. %s (%d)", strerror(sdp_error(ss)), sdp_error(ss)); memset(&sp, 0, sizeof(sp)); sp.server_channel = channel; if (sdp_register_service(ss, SDP_SERVICE_CLASS_SERIAL_PORT, &bt_addr_any, (void *)&sp, sizeof(sp), &sdp_handle) != 0) { errx(1, "Unable to register LAN service with " "local SDP daemon. %s (%d)", strerror(sdp_error(ss)), sdp_error(ss)); } s = -1; while (s < 0) { aaddrlen = sizeof(ra); s = accept(acceptsock, (struct sockaddr *)&ra, &aaddrlen); if (s < 0) err(1, "Unable to accept()"); if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) && memcmp(&addr, &ra.rfcomm_bdaddr, sizeof(addr))) { warnx("Connect from wrong client"); close(s); s = -1; } } sdp_unregister_service(ss, sdp_handle); sdp_close(ss); close(acceptsock); } else { /* Check channel, if was not set then obtain it via SDP */ if (channel == 0 && service != 0) if (rfcomm_channel_lookup(NULL, &addr, service, &channel, &n) != 0) errc(1, n, "Could not obtain RFCOMM channel"); if (channel <= 0 || channel > 30) errx(1, "Invalid RFCOMM channel number %d", channel); s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM); if (s < 0) err(1, "Could not create socket"); memset(&ra, 0, sizeof(ra)); ra.rfcomm_len = sizeof(ra); ra.rfcomm_family = AF_BLUETOOTH; if (bind(s, (struct sockaddr *) &ra, sizeof(ra)) < 0) err(1, "Could not bind socket"); memcpy(&ra.rfcomm_bdaddr, &addr, sizeof(ra.rfcomm_bdaddr)); ra.rfcomm_channel = channel; if (connect(s, (struct sockaddr *) &ra, sizeof(ra)) < 0) err(1, "Could not connect socket"); } /* Became daemon if required */ if (background && daemon(0, 0) < 0) err(1, "Could not daemon()"); openlog(SPPD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "Starting on %s...", (tty != NULL)? tty : "stdin/stdout"); /* Print used tty on stdout for wrappers to pick up */ if (!background) fprintf(stdout, "%s\n", tty); for (done = 0; !done; ) { FD_ZERO(&rfd); FD_SET(amaster, &rfd); FD_SET(s, &rfd); n = select(max(amaster, s) + 1, &rfd, NULL, NULL, NULL); if (n < 0) { if (errno == EINTR) continue; syslog(LOG_ERR, "Could not select(). %s", strerror(errno)); exit(1); } if (n == 0) continue; if (FD_ISSET(amaster, &rfd)) { n = sppd_read(amaster, buf, sizeof(buf)); if (n < 0) { syslog(LOG_ERR, "Could not read master pty, " \ "fd=%d. %s", amaster, strerror(errno)); exit(1); } if (n == 0) break; /* XXX */ if (sppd_write(s, buf, n) < 0) { syslog(LOG_ERR, "Could not write to socket, " \ "fd=%d, size=%d. %s", s, n, strerror(errno)); exit(1); } } if (FD_ISSET(s, &rfd)) { n = sppd_read(s, buf, sizeof(buf)); if (n < 0) { syslog(LOG_ERR, "Could not read socket, " \ "fd=%d. %s", s, strerror(errno)); exit(1); } if (n == 0) break; if (sppd_write(fd, buf, n) < 0) { syslog(LOG_ERR, "Could not write to master " \ "pty, fd=%d, size=%d. %s", fd, n, strerror(errno)); exit(1); } } } syslog(LOG_INFO, "Completed on %s", (tty != NULL)? tty : "stdin/stdout"); closelog(); close(s); if (tty != NULL) { close(aslave); close(amaster); } return (0); }