📄 main.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2002-2004 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 version 2 as * published by the Free Software Foundation; * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS * SOFTWARE IS DISCLAIMED. * * * $Id: main.c,v 1.14 2005/06/09 01:47:57 holtmann Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <syslog.h>#include <signal.h>#include <errno.h>#include <getopt.h>#include <sys/socket.h>#include <sys/poll.h>#include <sys/types.h>#include <sys/stat.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"static 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 auth;static int encrypt;static int secure;static int master;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 bdaddr_t src_addr = *BDADDR_ANY;static int src_dev = -1;volatile int terminate;static void do_kill(char *dst);enum { NONE, SHOW, LISTEN, CONNECT, KILL} modes;static void run_devup(char *dev, char *dst, int sk, int nsk){ char *argv[4], prog[40]; struct sigaction sa; sprintf(prog, "%s/%s", PAND_CONFIG_DIR, PAND_DEVUP_CMD); if (access(prog, 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] = prog; argv[1] = dev; argv[2] = dst; argv[3] = NULL; execv(prog, argv); exit(1);}static int do_listen(void){ struct l2cap_options l2o; struct sockaddr_l2 l2a; int sk, olen, lm; if (use_sdp) bnep_sdp_register(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 = 0; if (master) lm |= L2CAP_LM_MASTER; if (auth) lm |= L2CAP_LM_AUTH; if (encrypt) lm |= L2CAP_LM_ENCRYPT; if (secure) lm |= L2CAP_LM_SECURE; 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) { int alen = sizeof(l2a); 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; } if (!bnep_accept_connection(nsk, role, netdev)) { char str[40]; ba2str(&l2a.l2_bdaddr, str); syslog(LOG_INFO, "New connection from %s %s", str, netdev); run_devup(netdev, str, sk, nsk); } else { syslog(LOG_ERR, "Connection failed. %s(%d)", strerror(errno), errno); } close(nsk); exit(0); } if (use_sdp) bnep_sdp_unregister(); return 0;}/* Wait for disconnect or error condition on the socket */static int w4_hup(int sk){ struct pollfd pf; int n; while (!terminate) { pf.fd = sk; pf.events = POLLERR | POLLHUP; n = poll(&pf, 1, -1); 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, olen = sizeof(err); getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &olen); syslog(LOG_INFO, "%s disconnected%s%s", netdev, err ? " : " : "", err ? strerror(err) : ""); close(sk); return 0; } } 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; int sk, olen, r = 0; 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_devup(netdev, dst, sk, -1); if (persist) { w4_hup(sk); 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) sleep(persist); reconnect = 1; if (cache.valid > 0) { /* Use cached bdaddr */ r = create_connection(cache.dst, &cache.bdaddr); if (r < 0) { terminate = 1; break; } continue; } syslog(LOG_INFO, "Inquiring"); /* FIXME: Should we use non general LAP here ? */ ii = NULL; n = hci_inquiry(src_dev, search_duration, 0, NULL, &ii, 0); if (n < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -