?? main.c
字號:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2002-2008 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#define _GNU_SOURCE#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <signal.h>#include <getopt.h>#include <sys/poll.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/l2cap.h>#include <bluetooth/bnep.h>#include "pand.h"#ifdef NEED_PPOLL#include "ppoll.h"#endifstatic uint16_t role = BNEP_SVC_PANU; /* Local role (ie service) */static uint16_t service = BNEP_SVC_NAP; /* Remote service */static int detach = 1;static int persist;static int use_sdp = 1;static int use_cache;static int link_mode = 0;static int cleanup;static int search_duration = 10;static struct { int valid; char dst[40]; bdaddr_t bdaddr;} cache;static char netdev[16] = "bnep%d";static char *pidfile = NULL;static char *devupcmd = NULL;static char *devdowncmd = NULL;static bdaddr_t src_addr = *BDADDR_ANY;static int src_dev = -1;static volatile int terminate;static void do_kill(char *dst);enum { NONE, SHOW, LISTEN, CONNECT, KILL} modes;struct script_arg { char dev[20]; char dst[20]; int sk; int nsk;};static void run_script(char *script, char *dev, char *dst, int sk, int nsk){ char *argv[4]; struct sigaction sa; if (!script) return; if (access(script, R_OK | X_OK)) return; if (fork()) return; if (sk >= 0) close(sk); if (nsk >= 0) close(nsk); memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); argv[0] = script; argv[1] = dev; argv[2] = dst; argv[3] = NULL; execv(script, argv); exit(1);}/* Wait for disconnect or error condition on the socket */static int w4_hup(int sk, struct script_arg *down_cmd){ struct pollfd pf; sigset_t sigs; int n; sigfillset(&sigs); sigdelset(&sigs, SIGCHLD); sigdelset(&sigs, SIGPIPE); sigdelset(&sigs, SIGTERM); sigdelset(&sigs, SIGINT); sigdelset(&sigs, SIGHUP); while (!terminate) { pf.fd = sk; pf.events = POLLERR | POLLHUP; n = ppoll(&pf, 1, NULL, &sigs); if (n < 0) { if (errno == EINTR || errno == EAGAIN) continue; syslog(LOG_ERR, "Poll failed. %s(%d)", strerror(errno), errno); return 1; } if (n) { int err = 0; socklen_t olen = sizeof(err); getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &olen); syslog(LOG_INFO, "%s disconnected%s%s", netdev, err ? " : " : "", err ? strerror(err) : ""); if (down_cmd) run_script(devdowncmd, down_cmd->dev, down_cmd->dst, down_cmd->sk, down_cmd->nsk); close(sk); return 0; } } return 0;}static int do_listen(void){ struct l2cap_options l2o; struct sockaddr_l2 l2a; socklen_t olen; int sk, lm; if (use_sdp) bnep_sdp_register(&src_addr, role); /* Create L2CAP socket and bind it to PSM BNEP */ sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (sk < 0) { syslog(LOG_ERR, "Cannot create L2CAP socket. %s(%d)", strerror(errno), errno); return -1; } memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, &src_addr); l2a.l2_psm = htobs(BNEP_PSM); if (bind(sk, (struct sockaddr *) &l2a, sizeof(l2a))) { syslog(LOG_ERR, "Bind failed. %s(%d)", strerror(errno), errno); return -1; } /* Setup L2CAP options according to BNEP spec */ memset(&l2o, 0, sizeof(l2o)); olen = sizeof(l2o); if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen) < 0) { syslog(LOG_ERR, "Failed to get L2CAP options. %s(%d)", strerror(errno), errno); return -1; } l2o.imtu = l2o.omtu = BNEP_MTU; if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)) < 0) { syslog(LOG_ERR, "Failed to set L2CAP options. %s(%d)", strerror(errno), errno); return -1; } /* Set link mode */ lm = link_mode; if (lm && setsockopt(sk, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm)) < 0) { syslog(LOG_ERR, "Failed to set link mode. %s(%d)", strerror(errno), errno); return -1; } listen(sk, 10); while (!terminate) { socklen_t alen = sizeof(l2a); char devname[16]; int nsk; nsk = accept(sk, (struct sockaddr *) &l2a, &alen); if (nsk < 0) { syslog(LOG_ERR, "Accept failed. %s(%d)", strerror(errno), errno); continue; } switch (fork()) { case 0: break; case -1: syslog(LOG_ERR, "Fork failed. %s(%d)", strerror(errno), errno); default: close(nsk); continue; } strncpy(devname, netdev, 16); devname[15] = '\0'; if (!bnep_accept_connection(nsk, role, devname)) { char str[40]; struct script_arg down_cmd; ba2str(&l2a.l2_bdaddr, str); syslog(LOG_INFO, "New connection from %s at %s", str, devname); run_script(devupcmd, devname, str, sk, nsk); memset(&down_cmd, 0, sizeof(struct script_arg)); strncpy(down_cmd.dev, devname, strlen(devname) + 1); strncpy(down_cmd.dst, str, strlen(str) + 1); down_cmd.sk = sk; down_cmd.nsk = nsk; w4_hup(nsk, &down_cmd); } else { syslog(LOG_ERR, "Connection failed. %s(%d)", strerror(errno), errno); } close(nsk); exit(0); } if (use_sdp) bnep_sdp_unregister(); return 0;}/* Connect and initiate BNEP session * Returns: * -1 - critical error (exit persist mode) * 1 - non critical error * 0 - success */static int create_connection(char *dst, bdaddr_t *bdaddr){ struct l2cap_options l2o; struct sockaddr_l2 l2a; socklen_t olen; int sk, r = 0; struct script_arg down_cmd; syslog(LOG_INFO, "Connecting to %s", dst); sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (sk < 0) { syslog(LOG_ERR, "Cannot create L2CAP socket. %s(%d)", strerror(errno), errno); return -1; } /* Setup L2CAP options according to BNEP spec */ memset(&l2o, 0, sizeof(l2o)); olen = sizeof(l2o); getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); l2o.imtu = l2o.omtu = BNEP_MTU; setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, &src_addr); if (bind(sk, (struct sockaddr *) &l2a, sizeof(l2a))) syslog(LOG_ERR, "Bind failed. %s(%d)", strerror(errno), errno); memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; bacpy(&l2a.l2_bdaddr, bdaddr); l2a.l2_psm = htobs(BNEP_PSM); if (!connect(sk, (struct sockaddr *) &l2a, sizeof(l2a)) && !bnep_create_connection(sk, role, service, netdev)) { syslog(LOG_INFO, "%s connected", netdev); run_script(devupcmd, netdev, dst, sk, -1); if (persist || devdowncmd) { memset(&down_cmd, 0, sizeof(struct script_arg)); strncpy(down_cmd.dev, netdev, strlen(netdev) + 1); strncpy(down_cmd.dst, dst, strlen(dst) + 1); down_cmd.sk = sk; down_cmd.nsk = -1; w4_hup(sk, &down_cmd); if (terminate && cleanup) { syslog(LOG_INFO, "Disconnecting from %s.", dst); do_kill(dst); } } r = 0; } else { syslog(LOG_ERR, "Connect to %s failed. %s(%d)", dst, strerror(errno), errno); r = 1; } close(sk); if (use_cache) { if (!r) { /* Succesesful connection, validate cache */ strcpy(cache.dst, dst); bacpy(&cache.bdaddr, bdaddr); cache.valid = use_cache; } else cache.valid--; } return r;}/* Search and connect * Returns: * -1 - critical error (exit persist mode) * 1 - non critical error * 0 - success */static int do_connect(void){ inquiry_info *ii; int reconnect = 0; int i, n, r = 0; do { if (reconnect)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -