13406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann/*
23406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
33406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
43406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
59184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
63406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
73406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
83406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  This program is free software; you can redistribute it and/or modify
93406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  it under the terms of the GNU General Public License as published by
103406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  the Free Software Foundation; either version 2 of the License, or
113406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  (at your option) any later version.
123406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
133406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  This program is distributed in the hope that it will be useful,
143406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
153406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  GNU General Public License for more details.
173406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
183406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  You should have received a copy of the GNU General Public License
193406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  along with this program; if not, write to the Free Software
203406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
213406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann *
223406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann */
233406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann
243406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann#ifdef HAVE_CONFIG_H
253406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann#include <config.h>
263406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann#endif
273406c27e758f3dfa182f6fdfcc878bc3a53e3c98Marcel Holtmann
28bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz#include <stdio.h>
29bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz#include <errno.h>
30bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz#include <unistd.h>
311556df2283e8480f3b96e9159940e606c4e2fe43Claudio Takahasi#include <netinet/in.h>
321556df2283e8480f3b96e9159940e606c4e2fe43Claudio Takahasi
3374b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi#include <bluetooth/bluetooth.h>
34c95ffdc65e97a75e65dbbd22e7fae7086346595eLuiz Augusto von Dentz#include <bluetooth/hci.h>
35bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz#include <bluetooth/bnep.h>
36f85b9560ece47c94ec82466cba9c44da715591d9Luiz Augusto von Dentz#include <bluetooth/sdp.h>
3774b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
3874b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi#include <glib.h>
3915ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#include <gdbus.h>
4074b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
41e891f7df6225c758da0d95f7554c6cc67f72f31eGustavo F. Padovan#include "log.h"
42f85b9560ece47c94ec82466cba9c44da715591d9Luiz Augusto von Dentz#include "glib-helper.h"
432ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz#include "btio.h"
44357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz#include "dbus-common.h"
453bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz#include "adapter.h"
463bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz#include "device.h"
47e5ba646776ba7c5c5c9c9d630bbfc8793f1c3b4eClaudio Takahasi
480ac929228aa1eb823f37776e2bbb84855417c66eLuiz Augusto von Dentz#include "error.h"
49bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz#include "common.h"
5086984e4b0e58517aa3e50e4678f5f7b0165d85d4Marcel Holtmann#include "connection.h"
5174b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
52b326ad96e35e4abcd0466a82e5c92c727c8cc2afMarcel Holtmann#define NETWORK_PEER_INTERFACE "org.bluez.Network"
53473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentz
541e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentztypedef enum {
551e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz	CONNECTED,
561e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz	CONNECTING,
571e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz	DISCONNECTED
581e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz} conn_state;
591e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz
6056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentzstruct network_peer {
611556df2283e8480f3b96e9159940e606c4e2fe43Claudio Takahasi	bdaddr_t	src;
621556df2283e8480f3b96e9159940e606c4e2fe43Claudio Takahasi	bdaddr_t	dst;
631556df2283e8480f3b96e9159940e606c4e2fe43Claudio Takahasi	char		*path;		/* D-Bus path */
643bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	struct btd_device *device;
6556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	GSList		*connections;
6656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz};
6756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
6856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentzstruct network_conn {
6956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	DBusMessage	*msg;
70b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz	char		dev[16];	/* Interface name */
71e5ba646776ba7c5c5c9c9d630bbfc8793f1c3b4eClaudio Takahasi	uint16_t	id;		/* Role: Service Class Identifier */
721556df2283e8480f3b96e9159940e606c4e2fe43Claudio Takahasi	conn_state	state;
7388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	GIOChannel	*io;
7482c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz	guint		watch;		/* Disconnect watch */
753bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	guint		dc_id;
7656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer;
7774b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi};
7874b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
79bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentzstruct __service_16 {
80bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	uint16_t dst;
81bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	uint16_t src;
82bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz} __attribute__ ((packed));
83bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
84b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentzstatic DBusConnection *connection = NULL;
8556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentzstatic GSList *peers = NULL;
8656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
8756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentzstatic struct network_peer *find_peer(GSList *list, const char *path)
8856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz{
8956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	GSList *l;
9056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
9156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	for (l = list; l; l = l->next) {
9256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		struct network_peer *peer = l->data;
9356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
9456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		if (!strcmp(peer->path, path))
9556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			return peer;
9656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	}
9756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
9856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	return NULL;
9956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz}
1004698b260ee4b278884ef3160e4990e5090373092Luiz Augusto von Dentz
10156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentzstatic struct network_conn *find_connection(GSList *list, uint16_t id)
1024698b260ee4b278884ef3160e4990e5090373092Luiz Augusto von Dentz{
10356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	GSList *l;
10456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
10556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	for (l = list; l; l = l->next) {
10656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		struct network_conn *nc = l->data;
1074698b260ee4b278884ef3160e4990e5090373092Luiz Augusto von Dentz
10856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		if (nc->id == id)
10956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			return nc;
11056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	}
11156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
11256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	return NULL;
1134698b260ee4b278884ef3160e4990e5090373092Luiz Augusto von Dentz}
114d0c225bdc87726ead2b2bcf5ba8e80921c338b57Luiz Augusto von Dentz
115617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic inline DBusMessage *not_supported(DBusMessage *msg)
116617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann{
117617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
1187b92589167f31915e6653c3d5eb2a45563581826Marcel Holtmann							"Not supported");
119617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann}
120617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
121617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic inline DBusMessage *already_connected(DBusMessage *msg)
122617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann{
123617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
124617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann						"Device already connected");
125617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann}
126617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
127617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic inline DBusMessage *not_connected(DBusMessage *msg)
128617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann{
129617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
130617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann						"Device not connected");
131617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann}
132617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
1331a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentzstatic inline DBusMessage *not_permited(DBusMessage *msg)
1341a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz{
1351a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
1361a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz						"Operation not permited");
1371a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz}
1381a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz
1392ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentzstatic inline DBusMessage *connection_attempt_failed(DBusMessage *msg,
1402ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz							const char *err)
141617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann{
1422ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	return g_dbus_create_error(msg,
1432ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				ERROR_INTERFACE ".ConnectionAttemptFailed",
1442ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				err ? err : "Connection attempt failed");
145617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann}
146617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
14785a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentzstatic gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
14885a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz				gpointer data)
14985a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz{
15085a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz	struct network_conn *nc = data;
15185a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz
152b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz	if (connection != NULL) {
153737e08aa766744772b07bf1f35f3aa50d9bf63f0Luiz Augusto von Dentz		gboolean connected = FALSE;
154737e08aa766744772b07bf1f35f3aa50d9bf63f0Luiz Augusto von Dentz		const char *property = "";
155c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg		emit_property_changed(connection, nc->peer->path,
156c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg					NETWORK_PEER_INTERFACE, "Connected",
157c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg					DBUS_TYPE_BOOLEAN, &connected);
158c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg		emit_property_changed(connection, nc->peer->path,
1595581e8d5b4d884214ecd4d18717002aa860bd63aMarcel Holtmann					NETWORK_PEER_INTERFACE, "Interface",
160c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg					DBUS_TYPE_STRING, &property);
161c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg		emit_property_changed(connection, nc->peer->path,
162c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg					NETWORK_PEER_INTERFACE, "UUID",
163c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg					DBUS_TYPE_STRING, &property);
1643bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz		device_remove_disconnect_watch(nc->peer->device, nc->dc_id);
165c4f3b52e2fbb2b81d915f3f6eb0707ed3740fbd2Luiz Augusto von Dentz		nc->dc_id = 0;
16682c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz		if (nc->watch) {
16782c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz			g_dbus_remove_watch(connection, nc->watch);
16882c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz			nc->watch = 0;
16982c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz		}
1701cbec5ebe8d67b1b4dcef1768efde2ac1ac51970Luiz Augusto von Dentz	}
171617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
17285a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz	info("%s disconnected", nc->dev);
173617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
174d6f0804e827a829edb7faef9ddbd53332c1ad8cbLuiz Augusto von Dentz	bnep_if_down(nc->dev);
175fe648edb4d67bb603509f392d3c82ebfe8334921Luiz Augusto von Dentz	nc->state = DISCONNECTED;
1768311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmann	memset(nc->dev, 0, sizeof(nc->dev));
1778311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmann	strcpy(nc->dev, "bnep%d");
178617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
179fe648edb4d67bb603509f392d3c82ebfe8334921Luiz Augusto von Dentz	return FALSE;
18085a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz}
18185a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz
18288b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentzstatic void cancel_connection(struct network_conn *nc, const char *err_msg)
18388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz{
18488b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	DBusMessage *reply;
18588b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
18688b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	if (nc->watch) {
18788b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		g_dbus_remove_watch(connection, nc->watch);
18888b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		nc->watch = 0;
18988b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	}
19088b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
19188b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	if (nc->msg && err_msg) {
19288b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		reply = connection_attempt_failed(nc->msg, err_msg);
19388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		g_dbus_send_message(connection, reply);
19488b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	}
19588b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
19688b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	g_io_channel_shutdown(nc->io, TRUE, NULL);
19788b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	g_io_channel_unref(nc->io);
19888b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	nc->io = NULL;
19988b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
20088b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	nc->state = DISCONNECTED;
20188b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz}
20288b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
20388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentzstatic void connection_destroy(DBusConnection *conn, void *user_data)
20488b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz{
20588b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	struct network_conn *nc = user_data;
20688b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
20788b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	if (nc->state == CONNECTED) {
20888b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		bnep_if_down(nc->dev);
20988b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		bnep_kill_connection(&nc->peer->dst);
21088b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	} else if (nc->io)
21188b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		cancel_connection(nc, NULL);
21288b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz}
21388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
214a381d5342d27b99612fd31dc9cc80b01f412ad39Luiz Augusto von Dentzstatic void disconnect_cb(struct btd_device *device, gboolean removal,
215a381d5342d27b99612fd31dc9cc80b01f412ad39Luiz Augusto von Dentz				void *user_data)
2163bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz{
2173bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	struct network_conn *nc = user_data;
2183bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz
2193bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	info("Network: disconnect %s", nc->peer->path);
2203bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz
2213bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	connection_destroy(NULL, user_data);
2223bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz}
2233bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz
22488b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentzstatic gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
225617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann							gpointer data)
226bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz{
227bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	struct network_conn *nc = data;
228bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	struct bnep_control_rsp *rsp;
229087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	struct timeval timeo;
230bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	char pkt[BNEP_MTU];
231bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	gsize r;
232bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	int sk;
23356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	const char *pdev, *uuid;
234737e08aa766744772b07bf1f35f3aa50d9bf63f0Luiz Augusto von Dentz	gboolean connected;
235bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
236bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (cond & G_IO_NVAL)
237bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		return FALSE;
238bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
239bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (cond & (G_IO_HUP | G_IO_ERR)) {
240bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		error("Hangup or error on l2cap server socket");
241bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
242bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
243bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
244bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	memset(pkt, 0, BNEP_MTU);
245bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (g_io_channel_read(chan, pkt, sizeof(pkt) - 1,
246bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz				&r) != G_IO_ERROR_NONE) {
247bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		error("IO Channel read error");
248bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
249bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
250bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
251bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (r <= 0) {
252bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		error("No packet received on l2cap socket");
253bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
254bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
255bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
256bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	errno = EPROTO;
257bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
258bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (r < sizeof(*rsp)) {
259bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		error("Packet received is not bnep type");
260bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
261bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
262bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
263bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	rsp = (void *) pkt;
264bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (rsp->type != BNEP_CONTROL) {
265bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		error("Packet received is not bnep type");
266bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
267bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
268bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
269bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
270bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		return TRUE;
271bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
272bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	r = ntohs(rsp->resp);
273bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
274bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (r != BNEP_SUCCESS) {
275479dbf10dca70f2d9917729e41d7b0055f5070f7Luiz Augusto von Dentz		error("bnep failed");
276bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
277bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
278bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
279bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	sk = g_io_channel_unix_get_fd(chan);
280bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
281087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	memset(&timeo, 0, sizeof(timeo));
282087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	timeo.tv_sec = 0;
283087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann
284087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
285087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann
286bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
28782cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz		error("%s could not be added", nc->dev);
288bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz		goto failed;
289bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	}
290bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
2918311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmann	bnep_if_up(nc->dev);
292999a1b2c1ff51119806d16430adbc5d7677ac4c4Luiz Augusto von Dentz	pdev = nc->dev;
29356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	uuid = bnep_uuid(nc->id);
294617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
29556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	g_dbus_send_reply(connection, nc->msg,
29656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			DBUS_TYPE_STRING, &pdev,
29756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			DBUS_TYPE_INVALID);
29856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
299737e08aa766744772b07bf1f35f3aa50d9bf63f0Luiz Augusto von Dentz	connected = TRUE;
300c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(connection, nc->peer->path,
301c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				NETWORK_PEER_INTERFACE, "Connected",
302c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				DBUS_TYPE_BOOLEAN, &connected);
303c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(connection, nc->peer->path,
3045581e8d5b4d884214ecd4d18717002aa860bd63aMarcel Holtmann				NETWORK_PEER_INTERFACE, "Interface",
3053862e5642d1dfcab7a3090cfb1daed2544a7b04dJohan Hedberg				DBUS_TYPE_STRING, &pdev);
306c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg	emit_property_changed(connection, nc->peer->path,
307c0736ea762bfea95e98c8b9f118b4e5464f2159cJohan Hedberg				NETWORK_PEER_INTERFACE, "UUID",
3083862e5642d1dfcab7a3090cfb1daed2544a7b04dJohan Hedberg				DBUS_TYPE_STRING, &uuid);
309479dbf10dca70f2d9917729e41d7b0055f5070f7Luiz Augusto von Dentz
3101e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz	nc->state = CONNECTED;
3113bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
3123bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz						nc, NULL);
313479dbf10dca70f2d9917729e41d7b0055f5070f7Luiz Augusto von Dentz
31482cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz	info("%s connected", nc->dev);
31585a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz	/* Start watchdog */
31685a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz	g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
31785a868434ea4de849a15673aa4f132f10d2ab94cLuiz Augusto von Dentz			(GIOFunc) bnep_watchdog_cb, nc);
31888b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	g_io_channel_unref(nc->io);
31988b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	nc->io = NULL;
32088b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz
321479dbf10dca70f2d9917729e41d7b0055f5070f7Luiz Augusto von Dentz	return FALSE;
322617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
323bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentzfailed:
32488b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	cancel_connection(nc, "bnep setup failed");
325617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann
326bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	return FALSE;
327bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz}
328bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
329479dbf10dca70f2d9917729e41d7b0055f5070f7Luiz Augusto von Dentzstatic int bnep_connect(struct network_conn *nc)
330bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz{
331bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	struct bnep_setup_conn_req *req;
332bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	struct __service_16 *s;
333087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	struct timeval timeo;
334bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	unsigned char pkt[BNEP_MTU];
33588b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	int fd;
336bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
337bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	/* Send request */
338bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	req = (void *) pkt;
339bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	req->type = BNEP_CONTROL;
340bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	req->ctrl = BNEP_SETUP_CONN_REQ;
341bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	req->uuid_size = 2;	/* 16bit UUID */
342bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	s = (void *) req->service;
3432e39ac58720cba4fc6e889ec5f18a8ce1d67276cClaudio Takahasi	s->dst = htons(nc->id);
344bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz	s->src = htons(BNEP_SVC_PANU);
345bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
346087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	memset(&timeo, 0, sizeof(timeo));
347087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann	timeo.tv_sec = 30;
348087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann
34988b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	fd = g_io_channel_unix_get_fd(nc->io);
35088b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
351087cd77cff3295f6bcb9d845a41fff7cae6e8ba6Marcel Holtmann
35288b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	if (send(fd, pkt, sizeof(*req) + sizeof(*s), 0) < 0)
35388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz		return -errno;
35454f74d381a5839455f734f08b285468987530a81Luiz Augusto von Dentz
35588b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
35688b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz			(GIOFunc) bnep_setup_cb, nc);
35754f74d381a5839455f734f08b285468987530a81Luiz Augusto von Dentz
35888b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	return 0;
359bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz}
360bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
3612ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentzstatic void connect_cb(GIOChannel *chan, GError *err, gpointer data)
36282cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz{
36382cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz	struct network_conn *nc = data;
3642ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	const char *err_msg;
3652ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	int perr;
36682cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz
3672ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	if (err) {
3682ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		error("%s", err->message);
3692ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		err_msg = err->message;
37082cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz		goto failed;
37182cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz	}
37282cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz
3732ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	perr = bnep_connect(nc);
3742ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	if (perr < 0) {
3752ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		err_msg = strerror(-perr);
3762ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		error("bnep connect(): %s (%d)", err_msg, -perr);
37782cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz		goto failed;
37882cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz	}
37982cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentz
380f85b9560ece47c94ec82466cba9c44da715591d9Luiz Augusto von Dentz	return;
381f85b9560ece47c94ec82466cba9c44da715591d9Luiz Augusto von Dentz
38282cef341d2adb711fc637c6b04d10862ef4120ceLuiz Augusto von Dentzfailed:
38388b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	cancel_connection(nc, err_msg);
38482c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz}
38582c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz
386bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz/* Connect and initiate BNEP session */
387617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic DBusMessage *connection_connect(DBusConnection *conn,
388bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz						DBusMessage *msg, void *data)
38974b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi{
39056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer = data;
39156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_conn *nc;
39256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	const char *svc;
39356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	uint16_t id;
3942ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	GError *err = NULL;
395bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
39656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,
39756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz						DBUS_TYPE_INVALID) == FALSE)
39856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return NULL;
39956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
40056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	id = bnep_service_id(svc);
40156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	nc = find_connection(peer->connections, id);
40256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (!nc)
40356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return not_supported(msg);
40456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
405617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	if (nc->state != DISCONNECTED)
406617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann		return already_connected(msg);
407bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
40888b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	nc->io = bt_io_connect(BT_IO_L2CAP, connect_cb, nc,
4092ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				NULL, &err,
4102ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				BT_IO_OPT_SOURCE_BDADDR, &peer->src,
4112ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				BT_IO_OPT_DEST_BDADDR, &peer->dst,
4122ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				BT_IO_OPT_PSM, BNEP_PSM,
4132ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				BT_IO_OPT_OMTU, BNEP_MTU,
4142ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				BT_IO_OPT_IMTU, BNEP_MTU,
4152ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz				BT_IO_OPT_INVALID);
41688b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	if (!nc->io) {
4172ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		DBusMessage *reply;
4182ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		error("%s", err->message);
4192ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		reply = connection_attempt_failed(msg, err->message);
4202ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		g_error_free(err);
4212ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz		return reply;
4222ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz	}
4232ecef94bcdd0324da979752352a286be85520059Luiz Augusto von Dentz
4241e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz	nc->state = CONNECTING;
425d0c225bdc87726ead2b2bcf5ba8e80921c338b57Luiz Augusto von Dentz	nc->msg = dbus_message_ref(msg);
42682c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz	nc->watch = g_dbus_add_disconnect_watch(conn,
42782c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz						dbus_message_get_sender(msg),
42882c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz						connection_destroy,
42982c82fe3270f9d33f5a2c7b2e7009fc9f4c7a131Luiz Augusto von Dentz						nc, NULL);
430f85b9560ece47c94ec82466cba9c44da715591d9Luiz Augusto von Dentz
431617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	return NULL;
43274b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi}
43374b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
434617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic DBusMessage *connection_cancel(DBusConnection *conn,
43539d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz						DBusMessage *msg, void *data)
43639d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz{
43739d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz	struct network_conn *nc = data;
4381a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz	const char *owner = dbus_message_get_sender(nc->msg);
4391a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz	const char *caller = dbus_message_get_sender(msg);
4401a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz
4411a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz	if (!g_str_equal(owner, caller))
4421a092fcbf4bf5ac7b59c8de58d2d3b890987596bLuiz Augusto von Dentz		return not_permited(msg);
44339d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz
44488b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	connection_destroy(conn, nc);
44539d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz
446617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
44739d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz}
44839d74106f6bbb9f998387dd27529fc077773a182Luiz Augusto von Dentz
449617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic DBusMessage *connection_disconnect(DBusConnection *conn,
45074b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi					DBusMessage *msg, void *data)
45174b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi{
45256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer = data;
45356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	GSList *l;
454bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
45556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	for (l = peer->connections; l; l = l->next) {
45656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		struct network_conn *nc = l->data;
457bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
45856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		if (nc->state == DISCONNECTED)
45956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			continue;
460bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
46156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return connection_cancel(conn, msg, nc);
46256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	}
46356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
46456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	return not_connected(msg);
46574b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi}
46674b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
467357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentzstatic DBusMessage *connection_get_properties(DBusConnection *conn,
468357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz					DBusMessage *msg, void *data)
469357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz{
470357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	struct network_peer *peer = data;
471b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg	struct network_conn *nc = NULL;
472357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	DBusMessage *reply;
473357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	DBusMessageIter iter;
474357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	DBusMessageIter dict;
475357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	dbus_bool_t connected;
476357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	const char *property;
477357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	GSList *l;
478357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
479d68a57d8bee6643b230b752b4588f66d89e51524Marcel Holtmann	reply = dbus_message_new_method_return(msg);
480d68a57d8bee6643b230b752b4588f66d89e51524Marcel Holtmann	if (!reply)
481d68a57d8bee6643b230b752b4588f66d89e51524Marcel Holtmann		return NULL;
482d68a57d8bee6643b230b752b4588f66d89e51524Marcel Holtmann
483357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	dbus_message_iter_init_append(reply, &iter);
484357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
485357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
486357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
487357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
488357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
489357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
490357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	/* Connected */
491357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	for (l = peer->connections; l; l = l->next) {
492b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg		struct network_conn *tmp = l->data;
493b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg
494b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg		if (tmp->state != CONNECTED)
495b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg			continue;
496357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
497b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg		nc = tmp;
498b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg		break;
499357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	}
500b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg
501b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg	connected = nc ? TRUE : FALSE;
502102df1da56cf6bdec1c67682da7858c35a3ae5abJohan Hedberg	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &connected);
503357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
5045581e8d5b4d884214ecd4d18717002aa860bd63aMarcel Holtmann	/* Interface */
505b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg	property = nc ? nc->dev : "";
5065581e8d5b4d884214ecd4d18717002aa860bd63aMarcel Holtmann	dict_append_entry(&dict, "Interface", DBUS_TYPE_STRING, &property);
507357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
508357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	/* UUID */
509b33d56deeac1577b2e87f604ab86139c19b05967Johan Hedberg	property = nc ? bnep_uuid(nc->id) : "";
510102df1da56cf6bdec1c67682da7858c35a3ae5abJohan Hedberg	dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &property);
511357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
512357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	dbus_message_iter_close_container(&iter, &dict);
513357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
514357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	return reply;
515357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz}
516357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz
51774b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasistatic void connection_free(struct network_conn *nc)
51874b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi{
519c4f3b52e2fbb2b81d915f3f6eb0707ed3740fbd2Luiz Augusto von Dentz	if (nc->dc_id)
520c4f3b52e2fbb2b81d915f3f6eb0707ed3740fbd2Luiz Augusto von Dentz		device_remove_disconnect_watch(nc->peer->device, nc->dc_id);
521c4f3b52e2fbb2b81d915f3f6eb0707ed3740fbd2Luiz Augusto von Dentz
52288b59d5500d626ce382b2edd8892d4b62ad40177Luiz Augusto von Dentz	connection_destroy(connection, nc);
523bdb402511c964ba8d65fd4657c638ab3c5fbf438Luiz Augusto von Dentz
52474b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi	g_free(nc);
5251cbec5ebe8d67b1b4dcef1768efde2ac1ac51970Luiz Augusto von Dentz	nc = NULL;
52674b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi}
52774b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
52856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentzstatic void peer_free(struct network_peer *peer)
52956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz{
53056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	g_slist_foreach(peer->connections, (GFunc) connection_free, NULL);
53156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	g_slist_free(peer->connections);
5323bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	btd_device_unref(peer->device);
53356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	g_free(peer->path);
53456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	g_free(peer);
53556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz}
53656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
537473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentzstatic void path_unregister(void *data)
53874b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi{
53956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer = data;
54074b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
5418e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan	DBG("Unregistered interface %s on path %s",
54256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		NETWORK_PEER_INTERFACE, peer->path);
54374b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
54456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peers = g_slist_remove(peers, peer);
54556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer_free(peer);
54674b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi}
54774b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
548617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic GDBusMethodTable connection_methods[] = {
54956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	{ "Connect",		"s",	"s",	connection_connect,
550617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann						G_DBUS_METHOD_FLAG_ASYNC },
551617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	{ "Disconnect",		"",	"",	connection_disconnect	},
552357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	{ "GetProperties",	"",	"a{sv}",connection_get_properties },
553617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	{ }
554a0d73b7c7ce83bdd633aca429897a89ac7667490Johan Hedberg};
555a0d73b7c7ce83bdd633aca429897a89ac7667490Johan Hedberg
556617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmannstatic GDBusSignalTable connection_signals[] = {
557357a15b5878b65edef89b00b2db5d128e85bd07eLuiz Augusto von Dentz	{ "PropertyChanged",	"sv"	},
558617faeead1ffd6674cc1ab174815ff1395aec311Marcel Holtmann	{ }
55974b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi};
56074b17da9af9fb4930677000ccbd74495adb3d4c6Claudio Takahasi
561473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentzvoid connection_unregister(const char *path, uint16_t id)
562473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentz{
56356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer;
56456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_conn *nc;
56556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
56656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer = find_peer(peers, path);
56756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (!peer)
56856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return;
56956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
57056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	nc = find_connection(peer->connections, id);
57156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (!nc)
57256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return;
57356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
57456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer->connections = g_slist_remove(peer->connections, nc);
57556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	connection_free(nc);
57656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (peer->connections)
57756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return;
57856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
57956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	g_dbus_unregister_interface(connection, path, NETWORK_PEER_INTERFACE);
58056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz}
58156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
5823bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentzstatic struct network_peer *create_peer(struct btd_device *device,
5833bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz					const char *path, bdaddr_t *src,
5843bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz					bdaddr_t *dst)
58556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz{
58656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer;
58756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
58856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer = g_new0(struct network_peer, 1);
5893bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz	peer->device = btd_device_ref(device);
59056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer->path = g_strdup(path);
59156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	bacpy(&peer->src, src);
59256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	bacpy(&peer->dst, dst);
59356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
59456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (g_dbus_register_interface(connection, path,
59556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz					NETWORK_PEER_INTERFACE,
59656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz					connection_methods,
59756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz					connection_signals, NULL,
59856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz					peer, path_unregister) == FALSE) {
59956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		error("D-Bus failed to register %s interface",
60056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			NETWORK_PEER_INTERFACE);
60139b8891dadd061429d6e768551680e7814f8a663Luiz Augusto von Dentz		peer_free(peer);
60256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return NULL;
60356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	}
60456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
6058e58667ef0a4cda88ac64137728da28d8fdf3f0fGustavo F. Padovan	DBG("Registered interface %s on path %s",
60656f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		NETWORK_PEER_INTERFACE, path);
607473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentz
60856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	return peer;
609473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentz}
610473e0415d60fd1c067d3a2741a13424b8b06bae1Luiz Augusto von Dentz
6113bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentzint connection_register(struct btd_device *device, const char *path,
6123bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz			bdaddr_t *src, bdaddr_t *dst, uint16_t id)
613851ad267e554850ae2cbfd486922cbcfb897f8b5Luiz Augusto von Dentz{
61456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	struct network_peer *peer;
615851ad267e554850ae2cbfd486922cbcfb897f8b5Luiz Augusto von Dentz	struct network_conn *nc;
616c95ffdc65e97a75e65dbbd22e7fae7086346595eLuiz Augusto von Dentz
617c95ffdc65e97a75e65dbbd22e7fae7086346595eLuiz Augusto von Dentz	if (!path)
618c95ffdc65e97a75e65dbbd22e7fae7086346595eLuiz Augusto von Dentz		return -EINVAL;
619c95ffdc65e97a75e65dbbd22e7fae7086346595eLuiz Augusto von Dentz
62056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer = find_peer(peers, path);
62156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (!peer) {
6223bcd43d2d3c56ae5c34a0d8df42a2a2ec795b152Luiz Augusto von Dentz		peer = create_peer(device, path, src, dst);
62356f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		if (!peer)
62456f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz			return -1;
62556f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		peers = g_slist_append(peers, peer);
626a0d73b7c7ce83bdd633aca429897a89ac7667490Johan Hedberg	}
627a0d73b7c7ce83bdd633aca429897a89ac7667490Johan Hedberg
62856f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	nc = find_connection(peer->connections, id);
62956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	if (nc)
63056f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz		return 0;
63156f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz
63256f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	nc = g_new0(struct network_conn, 1);
633d98a405d8fc5e9b3e5919b63c7498e6b11989663Claudio Takahasi	nc->id = id;
6348311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmann	memset(nc->dev, 0, sizeof(nc->dev));
6358311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmann	strcpy(nc->dev, "bnep%d");
6361e711201f649f10fee1a8365976d42b98e7373f9Luiz Augusto von Dentz	nc->state = DISCONNECTED;
63756f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	nc->peer = peer;
6384706fa6e70ea2e19c7892ade0323a35d4f0b5a47Claudio Takahasi
63956f867d9b7a018d582d87f31c87d1ecb7c7a12bcLuiz Augusto von Dentz	peer->connections = g_slist_append(peer->connections, nc);
6404706fa6e70ea2e19c7892ade0323a35d4f0b5a47Claudio Takahasi
641851ad267e554850ae2cbfd486922cbcfb897f8b5Luiz Augusto von Dentz	return 0;
642851ad267e554850ae2cbfd486922cbcfb897f8b5Luiz Augusto von Dentz}
6431cbec5ebe8d67b1b4dcef1768efde2ac1ac51970Luiz Augusto von Dentz
6448311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmannint connection_init(DBusConnection *conn)
645b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz{
646b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz	connection = dbus_connection_ref(conn);
647b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz
648b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz	return 0;
649b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz}
650b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz
6518311b1dfc829b25385f617c4fef4be054f34e5e2Marcel Holtmannvoid connection_exit(void)
652b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz{
653b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz	dbus_connection_unref(connection);
654b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz	connection = NULL;
655b94d1033b7c6919ca4705cf11139fb8224c3ecdeLuiz Augusto von Dentz}
656