pnat.c revision 903804a0f1d74b324182b33fbc5a4d57da959e83
11202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg/* 21202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 31202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * BlueZ - Bluetooth protocol stack for Linux 41202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 51202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * Copyright (C) 2010 Nokia Corporation 61202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org> 71202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 81202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 91202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * This program is free software; you can redistribute it and/or modify 101202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * it under the terms of the GNU General Public License as published by 111202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * the Free Software Foundation; either version 2 of the License, or 121202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * (at your option) any later version. 131202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 141202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * This program is distributed in the hope that it will be useful, 151202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * but WITHOUT ANY WARRANTY; without even the implied warranty of 161202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 171202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * GNU General Public License for more details. 181202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 191202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * You should have received a copy of the GNU General Public License 201202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * along with this program; if not, write to the Free Software 211202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 221202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg * 231202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg */ 241202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 251202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#ifdef HAVE_CONFIG_H 261202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <config.h> 271202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#endif 281202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 291202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <errno.h> 301202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <unistd.h> 311202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <sys/socket.h> 32895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#include <sys/ioctl.h> 33895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#include <sys/types.h> 34895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#include <sys/stat.h> 35895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#include <sys/wait.h> 36895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#include <fcntl.h> 371202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 381202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <bluetooth/bluetooth.h> 391202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <bluetooth/rfcomm.h> 401202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <bluetooth/sdp.h> 411202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <bluetooth/sdp_lib.h> 421202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 431202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <glib.h> 441202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 451202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include <gdbus.h> 461202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 471202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include "plugin.h" 481202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include "sdpd.h" 491202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include "btio.h" 501202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include "adapter.h" 511202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#include "logging.h" 521202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 53895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg/* FIXME: This location should be build-time configurable */ 54895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#define PNATD "/usr/sbin/phonet-at" 55895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 561202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#define DUN_CHANNEL 1 571202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg#define DUN_UUID "00001103-0000-1000-8000-00805F9B34FB" 581202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 59895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#define TTY_TIMEOUT 100 60895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg#define TTY_TRIES 10 61895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 62895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergstruct dun_client { 63895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg bdaddr_t bda; 64895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 65895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg GIOChannel *io; /* Client socket */ 66895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg guint io_watch; /* Client IO watch id */ 67895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 68895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg guint tty_timer; 69895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg int tty_tries; 70895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg gboolean tty_open; 71895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg int tty_id; 72895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg char tty_name[PATH_MAX]; 73895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 74895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg GPid pnatd_pid; 75895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg guint pnatd_watch; 76895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg}; 77895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 781202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstruct dun_server { 79895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg bdaddr_t bda; /* Local adapter address */ 80895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 811202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg uint32_t record_handle; /* Local SDP record handle */ 821202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GIOChannel *server; /* Server socket */ 83895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 84895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg int rfcomm_ctl; 85895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 86895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client client; 871202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg}; 881202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 891202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic GSList *servers = NULL; 901202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 911202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic void disconnect(struct dun_server *server) 921202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 93895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 94895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 95895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (!client->io) 96895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return; 97895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 98895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_io_channel_unref(client->io); 99895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io = NULL; 100895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 101895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->io_watch > 0) { 102895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_source_remove(client->io_watch); 103895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io_watch = 0; 104895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 105895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 106895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->pnatd_watch > 0) { 107895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_source_remove(client->pnatd_watch); 108895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->pnatd_watch = 0; 109895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->pnatd_pid > 0) 110895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg kill(client->pnatd_pid, SIGTERM); 111895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 112895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 113895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->pnatd_pid > 0) { 114895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_spawn_close_pid(client->pnatd_pid); 115895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->pnatd_pid = 0; 116895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 117895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 118895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->tty_timer > 0) { 119895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_source_remove(client->tty_timer); 120895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_timer = 0; 121895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 122895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 123895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->tty_id >= 0) { 124895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct rfcomm_dev_req req; 125895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 126895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg memset(&req, 0, sizeof(req)); 127895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg req.dev_id = client->tty_id; 128895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg req.flags = (1 << RFCOMM_HANGUP_NOW); 129895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg ioctl(server->rfcomm_ctl, RFCOMMRELEASEDEV, &req); 130895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 131895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_name[0] = '\0'; 132895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_open = FALSE; 133895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_id = -1; 134895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 1351202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 1361202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 137895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergstatic gboolean client_event(GIOChannel *chan, 1381202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GIOCondition cond, gpointer data) 1391202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 1401202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server = data; 141895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 142895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg char addr[18]; 1431202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 144895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg ba2str(&client->bda, addr); 1451202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 146895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg debug("Disconnected DUN from %s (%s)", addr, client->tty_name); 147895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 148895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io_watch = 0; 149895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg disconnect(server); 1501202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 151895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return FALSE; 152895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg} 153895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 154895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergstatic void pnatd_exit(GPid pid, gint status, gpointer user_data) 155895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg{ 156895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_server *server = user_data; 157895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 158895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 159895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (WIFEXITED(status)) 160895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg debug("pnatd (%d) exited with status %d", pid, 161895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg WEXITSTATUS(status)); 162895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg else 163895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg debug("pnatd (%d) was killed by signal %d", pid, 164895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg WTERMSIG(status)); 165895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 166895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->pnatd_watch = 0; 167895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 168895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg disconnect(server); 169895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg} 170895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 171895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergstatic gboolean start_pnatd(struct dun_server *server) 172895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg{ 173895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 174895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH; 175895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg char *argv[] = { PNATD, client->tty_name, NULL }; 176895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg GError *err = NULL; 177895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg GPid pid; 178895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 179895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_spawn_async(NULL, argv, NULL, flags, NULL, NULL, &pid, &err); 180895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (err != NULL) { 181895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg error("Unable to spawn pnatd: %s", err->message); 18276208a5d2612081517846692bb6b8f99c4059fcaJohan Hedberg g_error_free(err); 183895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return FALSE; 184895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 185895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 186895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg debug("pnatd started for %s with pid %d", client->tty_name, pid); 187895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 188895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->pnatd_pid = pid; 189895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->pnatd_watch = g_child_watch_add(pid, pnatd_exit, server); 1901202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 1911202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return TRUE; 192895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg} 1931202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 194895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergstatic gboolean tty_try_open(gpointer user_data) 195895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg{ 196895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_server *server = user_data; 197895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 198895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg int tty_fd; 199895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 200895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg tty_fd = open(client->tty_name, O_RDONLY | O_NOCTTY); 201895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (tty_fd < 0) { 202895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (errno == EACCES) 203895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg goto disconnect; 204895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 205895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_tries--; 206895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 207895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->tty_tries <= 0) 208895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg goto disconnect; 209895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 210895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return TRUE; 211895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 212895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 213895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg debug("%s created for DUN", client->tty_name); 214895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 215895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_open = TRUE; 216895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_timer = 0; 217895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 218895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_io_channel_unref(client->io); 219895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg g_source_remove(client->io_watch); 220895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 221895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io = g_io_channel_unix_new(tty_fd); 222895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io_watch = g_io_add_watch(client->io, 223895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg G_IO_HUP | G_IO_ERR | G_IO_NVAL, 224895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client_event, server); 225895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 226895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (!start_pnatd(server)) 227895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg goto disconnect; 228895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 229895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return FALSE; 230895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 231895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergdisconnect: 232895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_timer = 0; 2331202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg disconnect(server); 2341202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return FALSE; 2351202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 2361202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 237895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedbergstatic gboolean create_tty(struct dun_server *server) 238895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg{ 239895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 240895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct rfcomm_dev_req req; 241895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg int dev, sk = g_io_channel_unix_get_fd(client->io); 242895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 243895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg memset(&req, 0, sizeof(req)); 244895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg req.dev_id = -1; 245895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP); 246895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 247895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg bacpy(&req.src, &server->bda); 248895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg bacpy(&req.dst, &client->bda); 249895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 250895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg bt_io_get(client->io, BT_IO_RFCOMM, NULL, 251895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg BT_IO_OPT_DEST_CHANNEL, &req.channel, 252895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg BT_IO_OPT_INVALID); 253895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 254895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg dev = ioctl(sk, RFCOMMCREATEDEV, &req); 255895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (dev < 0) { 256895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg error("Can't create RFCOMM TTY: %s", strerror(errno)); 257895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return FALSE; 258895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 259895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 260895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg snprintf(client->tty_name, PATH_MAX - 1, "/dev/rfcomm%d", dev); 261895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 262895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_tries = TTY_TRIES; 263895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 264895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg tty_try_open(server); 265895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (!client->tty_open && client->tty_tries > 0) 266895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->tty_timer = g_timeout_add(TTY_TIMEOUT, 267895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg tty_try_open, server); 268895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 269895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return TRUE; 270895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg} 271895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 2721202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic void connect_cb(GIOChannel *io, GError *err, gpointer user_data) 2731202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 2741202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server = user_data; 2751202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 2761202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (err) { 2771202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Accepting DUN connection failed: %s", err->message); 2781202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg disconnect(server); 2791202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return; 2801202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 2811202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 282895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (!create_tty(server)) { 283895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg error("Device creation failed"); 284895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg disconnect(server); 285895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 2861202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 2871202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 2881202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic void auth_cb(DBusError *derr, void *user_data) 2891202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 2901202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server = user_data; 291895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 2921202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GError *err = NULL; 2931202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 2941202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (derr && dbus_error_is_set(derr)) { 2951202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("DUN access denied: %s", derr->message); 2961202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg goto drop; 2971202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 2981202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 299895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (!bt_io_accept(client->io, connect_cb, server, NULL, &err)) { 3001202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("bt_io_accept: %s", err->message); 3011202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_error_free(err); 3021202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg goto drop; 3031202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 3041202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3051202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return; 3061202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3071202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergdrop: 3081202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg disconnect(server); 3091202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 3101202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3111202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic gboolean auth_watch(GIOChannel *chan, GIOCondition cond, gpointer data) 3121202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 3131202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server = data; 314895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 3151202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3161202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("DUN client disconnected while waiting for authorization"); 3171202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 318895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg btd_cancel_authorization(&server->bda, &client->bda); 3191202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3201202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg disconnect(server); 3211202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3221202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return FALSE; 3231202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 3241202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3251202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic void confirm_cb(GIOChannel *io, gpointer user_data) 3261202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 3271202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server = user_data; 328895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg struct dun_client *client = &server->client; 3291202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GError *err = NULL; 3301202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 331895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (client->io) { 3321202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Rejecting DUN connection since one already exists"); 3331202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return; 3341202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 3351202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3361202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg bt_io_get(io, BT_IO_RFCOMM, &err, 337895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg BT_IO_OPT_DEST_BDADDR, &client->bda, 3381202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg BT_IO_OPT_INVALID); 3391202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (err != NULL) { 3401202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Unable to get DUN source and dest address: %s", 3411202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg err->message); 3421202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_error_free(err); 3431202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return; 3441202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 3451202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 346895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (btd_request_authorization(&server->bda, &client->bda, DUN_UUID, 3471202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg auth_cb, user_data) < 0) { 3481202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Requesting DUN authorization failed"); 3491202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return; 3501202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 3511202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 352895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io_watch = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL, 3531202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg (GIOFunc) auth_watch, server); 354895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg client->io = g_io_channel_ref(io); 3551202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 3561202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3571202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic sdp_record_t *dun_record(uint8_t ch) 3581202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 3591202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto; 3601202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg uuid_t root_uuid, dun, gn, l2cap, rfcomm; 3611202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_profile_desc_t profile; 3621202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_t *proto[2]; 3631202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_record_t *record; 3641202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_data_t *channel; 3651202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3661202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg record = sdp_record_alloc(); 3671202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (!record) 3681202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return NULL; 3691202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3701202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 3711202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg root = sdp_list_append(NULL, &root_uuid); 3721202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_set_browse_groups(record, root); 3731202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3741202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID); 3751202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg svclass_id = sdp_list_append(NULL, &dun); 3761202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID); 3771202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg svclass_id = sdp_list_append(svclass_id, &gn); 3781202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_set_service_classes(record, svclass_id); 3791202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3801202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID); 3811202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg profile.version = 0x0100; 3821202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg pfseq = sdp_list_append(NULL, &profile); 3831202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_set_profile_descs(record, pfseq); 3841202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3851202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_uuid16_create(&l2cap, L2CAP_UUID); 3861202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg proto[0] = sdp_list_append(NULL, &l2cap); 3871202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg apseq = sdp_list_append(NULL, proto[0]); 3881202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3891202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_uuid16_create(&rfcomm, RFCOMM_UUID); 3901202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg proto[1] = sdp_list_append(NULL, &rfcomm); 3911202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg channel = sdp_data_alloc(SDP_UINT8, &ch); 3921202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg proto[1] = sdp_list_append(proto[1], channel); 3931202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg apseq = sdp_list_append(apseq, proto[1]); 3941202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3951202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg aproto = sdp_list_append(0, apseq); 3961202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_set_access_protos(record, aproto); 3971202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 3981202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_set_info_attr(record, "Dial-Up Networking", 0, 0); 3991202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4001202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_data_free(channel); 4011202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(root, NULL); 4021202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(svclass_id, NULL); 4031202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(proto[0], NULL); 4041202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(proto[1], NULL); 4051202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(pfseq, NULL); 4061202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(apseq, NULL); 4071202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_list_free(aproto, NULL); 4081202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4091202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return record; 4101202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 4111202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4121202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic gint server_cmp(gconstpointer a, gconstpointer b) 4131202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 4141202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg const struct dun_server *server = a; 4151202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg const bdaddr_t *src = b; 4161202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 417895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg return bacmp(src, &server->bda); 4181202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 4191202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4201202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic int pnat_probe(struct btd_adapter *adapter) 4211202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 4221202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server; 4231202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GIOChannel *io; 4241202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GError *err = NULL; 4251202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg sdp_record_t *record; 4261202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg bdaddr_t src; 4271202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4281202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg adapter_get_address(adapter, &src); 4291202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4301202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg server = g_new0(struct dun_server, 1); 4311202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4321202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_cb, server, NULL, &err, 4331202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg BT_IO_OPT_SOURCE_BDADDR, &src, 4341202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg BT_IO_OPT_CHANNEL, DUN_CHANNEL, 4351202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg BT_IO_OPT_INVALID); 4361202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (err != NULL) { 4371202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Failed to start DUN server: %s", err->message); 4381202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_error_free(err); 439903804a0f1d74b324182b33fbc5a4d57da959e83Johan Hedberg goto fail; 4401202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 4411202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4421202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg record = dun_record(DUN_CHANNEL); 4431202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (!record) { 4441202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Unable to allocate new service record"); 4451202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg goto fail; 4461202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 4471202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4481202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (add_record_to_server(&src, record) < 0) { 4491202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg error("Unable to register DUN service record"); 4501202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg goto fail; 4511202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg } 4521202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 453895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg server->rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM); 454895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg if (server->rfcomm_ctl < 0) { 455895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg error("Unable to create RFCOMM control socket: %s (%d)", 456895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg strerror(errno), errno); 457895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg goto fail; 458895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg } 459895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg 4601202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg server->server = io; 4611202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg server->record_handle = record->handle; 462895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg bacpy(&server->bda, &src); 4631202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4641202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg servers = g_slist_append(servers, server); 4651202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4661202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return 0; 4671202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4681202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergfail: 4691202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (io != NULL) 4701202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_io_channel_unref(io); 4711202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_free(server); 4721202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return -EIO; 4731202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 4741202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4751202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic void pnat_remove(struct btd_adapter *adapter) 4761202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 4771202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg struct dun_server *server; 4781202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg GSList *match; 4791202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg bdaddr_t src; 4801202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4811202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg adapter_get_address(adapter, &src); 4821202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4831202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg match = g_slist_find_custom(servers, &src, server_cmp); 4841202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg if (match == NULL) 4851202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return; 4861202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4871202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg server = match->data; 4881202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4891202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg servers = g_slist_delete_link(servers, match); 4901202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 491895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg disconnect(server); 4921202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 4931202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg remove_record_from_server(server->record_handle); 494895eea1347243bae4aa65eea8531452fe5dd81eaJohan Hedberg close(server->rfcomm_ctl); 4951202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_io_channel_shutdown(server->server, TRUE, NULL); 4961202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_io_channel_unref(server->server); 4971202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg g_free(server); 4981202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 4991202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 5001202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic struct btd_adapter_driver pnat_server = { 5011202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg .name = "pnat-server", 5021202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg .probe = pnat_probe, 5031202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg .remove = pnat_remove, 5041202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg}; 5051202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 5061202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic int pnat_init(void) 5071202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 5081202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg debug("Setup Phonet AT (DUN) plugin"); 5091202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 5101202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg return btd_register_adapter_driver(&pnat_server); 5111202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 5121202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 5131202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedbergstatic void pnat_exit(void) 5141202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg{ 5151202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg debug("Cleanup Phonet AT (DUN) plugin"); 5161202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 5171202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg btd_unregister_adapter_driver(&pnat_server); 5181202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg} 5191202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg 5201202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan HedbergBLUETOOTH_PLUGIN_DEFINE(pnat, VERSION, 5211202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, 5221202ec1f3e2e23ed3f343bedbc7ca86377030c2cJohan Hedberg pnat_init, pnat_exit) 523