diff options
Diffstat (limited to 'dund/dun.c')
-rw-r--r-- | dund/dun.c | 331 |
1 files changed, 0 insertions, 331 deletions
diff --git a/dund/dun.c b/dund/dun.c deleted file mode 100644 index de437cf4..00000000 --- a/dund/dun.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * - * 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 - -#include <stdio.h> -#include <errno.h> -#include <ctype.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <syslog.h> -#include <dirent.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/param.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <bluetooth/bluetooth.h> -#include <bluetooth/rfcomm.h> - -#include "dund.h" -#include "lib.h" - -#define PROC_BASE "/proc" - -static int for_each_port(int (*func)(struct rfcomm_dev_info *, unsigned long), unsigned long arg) -{ - struct rfcomm_dev_list_req *dl; - struct rfcomm_dev_info *di; - long r = 0; - int sk, i; - - sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM); - if (sk < 0 ) { - perror("Can't open RFCOMM control socket"); - exit(1); - } - - dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di)); - if (!dl) { - perror("Can't allocate request memory"); - close(sk); - exit(1); - } - - dl->dev_num = RFCOMM_MAX_DEV; - di = dl->dev_info; - - if (ioctl(sk, RFCOMMGETDEVLIST, (void *) dl) < 0) { - perror("Can't get device list"); - exit(1); - } - - for (i = 0; i < dl->dev_num; i++) { - r = func(di + i, arg); - if (r) break; - } - - close(sk); - return r; -} - -static int uses_rfcomm(char *path, char *dev) -{ - struct dirent *de; - DIR *dir; - - dir = opendir(path); - if (!dir) - return 0; - - if (chdir(path) < 0) - return 0; - - while ((de = readdir(dir)) != NULL) { - char link[PATH_MAX + 1]; - int len = readlink(de->d_name, link, sizeof(link)); - if (len > 0) { - link[len] = 0; - if (strstr(link, dev)) - return 1; - } - } - - closedir(dir); - - return 0; -} - -static int find_pppd(int id, pid_t *pid) -{ - struct dirent *de; - char path[PATH_MAX + 1]; - char dev[10]; - int empty = 1; - DIR *dir; - - dir = opendir(PROC_BASE); - if (!dir) { - perror(PROC_BASE); - return -1; - } - - sprintf(dev, "rfcomm%d", id); - - *pid = 0; - while ((de = readdir(dir)) != NULL) { - empty = 0; - if (isdigit(de->d_name[0])) { - sprintf(path, "%s/%s/fd", PROC_BASE, de->d_name); - if (uses_rfcomm(path, dev)) { - *pid = atoi(de->d_name); - break; - } - } - } - closedir(dir); - - if (empty) - fprintf(stderr, "%s is empty (not mounted ?)\n", PROC_BASE); - - return *pid != 0; -} - -static int dun_exec(char *tty, char *prog, char **args) -{ - int pid = fork(); - int fd; - - switch (pid) { - case -1: - return -1; - - case 0: - break; - - default: - return pid; - } - - setsid(); - - /* Close all FDs */ - for (fd = 3; fd < 20; fd++) - close(fd); - - execvp(prog, args); - - syslog(LOG_ERR, "Error while executing %s", prog); - - exit(1); -} - -static int dun_create_tty(int sk, char *tty, int size) -{ - struct sockaddr_rc sa; - struct stat st; - socklen_t alen; - int id, try = 30; - - struct rfcomm_dev_req req = { - flags: (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP), - dev_id: -1 - }; - - alen = sizeof(sa); - if (getpeername(sk, (struct sockaddr *) &sa, &alen) < 0) - return -1; - bacpy(&req.dst, &sa.rc_bdaddr); - - alen = sizeof(sa); - if (getsockname(sk, (struct sockaddr *) &sa, &alen) < 0) - return -1; - bacpy(&req.src, &sa.rc_bdaddr); - req.channel = sa.rc_channel; - - id = ioctl(sk, RFCOMMCREATEDEV, &req); - if (id < 0) - return id; - - snprintf(tty, size, "/dev/rfcomm%d", id); - while (stat(tty, &st) < 0) { - snprintf(tty, size, "/dev/bluetooth/rfcomm/%d", id); - if (stat(tty, &st) < 0) { - snprintf(tty, size, "/dev/rfcomm%d", id); - if (try--) { - usleep(100 * 1000); - continue; - } - - memset(&req, 0, sizeof(req)); - req.dev_id = id; - ioctl(sk, RFCOMMRELEASEDEV, &req); - - return -1; - } - } - - return id; -} - -int dun_init(void) -{ - return 0; -} - -int dun_cleanup(void) -{ - return 0; -} - -static int show_conn(struct rfcomm_dev_info *di, unsigned long arg) -{ - pid_t pid; - - if (di->state == BT_CONNECTED && - (di->flags & (1<<RFCOMM_REUSE_DLC)) && - (di->flags & (1<<RFCOMM_TTY_ATTACHED)) && - (di->flags & (1<<RFCOMM_RELEASE_ONHUP))) { - - if (find_pppd(di->id, &pid)) { - char dst[18]; - ba2str(&di->dst, dst); - - printf("rfcomm%d: %s channel %d pppd pid %d\n", - di->id, dst, di->channel, pid); - } - } - return 0; -} - -static int kill_conn(struct rfcomm_dev_info *di, unsigned long arg) -{ - bdaddr_t *dst = (bdaddr_t *) arg; - pid_t pid; - - if (di->state == BT_CONNECTED && - (di->flags & (1<<RFCOMM_REUSE_DLC)) && - (di->flags & (1<<RFCOMM_TTY_ATTACHED)) && - (di->flags & (1<<RFCOMM_RELEASE_ONHUP))) { - - if (dst && bacmp(&di->dst, dst)) - return 0; - - if (find_pppd(di->id, &pid)) { - if (kill(pid, SIGINT) < 0) - perror("Kill"); - - if (!dst) - return 0; - return 1; - } - } - return 0; -} - -int dun_show_connections(void) -{ - for_each_port(show_conn, 0); - return 0; -} - -int dun_kill_connection(uint8_t *dst) -{ - for_each_port(kill_conn, (unsigned long) dst); - return 0; -} - -int dun_kill_all_connections(void) -{ - for_each_port(kill_conn, 0); - return 0; -} - -int dun_open_connection(int sk, char *pppd, char **args, int wait) -{ - char tty[100]; - int pid; - - if (dun_create_tty(sk, tty, sizeof(tty) - 1) < 0) { - syslog(LOG_ERR, "RFCOMM TTY creation failed. %s(%d)", strerror(errno), errno); - return -1; - } - - args[0] = "pppd"; - args[1] = tty; - args[2] = "nodetach"; - - pid = dun_exec(tty, pppd, args); - if (pid < 0) { - syslog(LOG_ERR, "Exec failed. %s(%d)", strerror(errno), errno); - return -1; - } - - if (wait) { - int status; - waitpid(pid, &status, 0); - /* FIXME: Check for waitpid errors */ - } - - return 0; -} |