Home | History | Annotate | Download | only in network
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel (at) holtmann.org>
      6  *
      7  *
      8  *  This program is free software; you can redistribute it and/or modify
      9  *  it under the terms of the GNU General Public License as published by
     10  *  the Free Software Foundation; either version 2 of the License, or
     11  *  (at your option) any later version.
     12  *
     13  *  This program is distributed in the hope that it will be useful,
     14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *  GNU General Public License for more details.
     17  *
     18  *  You should have received a copy of the GNU General Public License
     19  *  along with this program; if not, write to the Free Software
     20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include <config.h>
     26 #endif
     27 
     28 #include <bluetooth/bluetooth.h>
     29 #include <bluetooth/hci.h>
     30 #include <bluetooth/bnep.h>
     31 #include <bluetooth/sdp.h>
     32 
     33 #include <glib.h>
     34 #include <gdbus.h>
     35 
     36 #include "logging.h"
     37 
     38 #include "adapter.h"
     39 #include "device.h"
     40 #include "bridge.h"
     41 #include "manager.h"
     42 #include "common.h"
     43 #include "connection.h"
     44 #include "server.h"
     45 
     46 #define IFACE_PREFIX "bnep%d"
     47 #define GN_IFACE  "pan0"
     48 #define NAP_IFACE "pan1"
     49 
     50 static struct btd_adapter_driver network_panu_server_driver;
     51 static struct btd_adapter_driver network_gn_server_driver;
     52 static struct btd_adapter_driver network_nap_server_driver;
     53 
     54 static DBusConnection *connection = NULL;
     55 
     56 static struct network_conf {
     57 	gboolean connection_enabled;
     58 	gboolean server_enabled;
     59 	gboolean security;
     60 	char *iface_prefix;
     61 	char *panu_script;
     62 	char *gn_script;
     63 	char *nap_script;
     64 	char *gn_iface;
     65 	char *nap_iface;
     66 } conf = {
     67 	.connection_enabled = TRUE,
     68 	.server_enabled = TRUE,
     69 	.security = TRUE,
     70 	.iface_prefix = NULL,
     71 	.panu_script = NULL,
     72 	.gn_script = NULL,
     73 	.nap_script = NULL,
     74 	.gn_iface = NULL,
     75 	.nap_iface = NULL
     76 };
     77 
     78 static void conf_cleanup(void)
     79 {
     80 	g_free(conf.iface_prefix);
     81 	g_free(conf.panu_script);
     82 	g_free(conf.gn_script);
     83 	g_free(conf.nap_script);
     84 	g_free(conf.gn_iface);
     85 	g_free(conf.nap_iface);
     86 }
     87 
     88 static void read_config(const char *file)
     89 {
     90 	GKeyFile *keyfile;
     91 	GError *err = NULL;
     92 	char **disabled;
     93 
     94 	keyfile = g_key_file_new();
     95 
     96 	if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {
     97 		error("Parsing %s failed: %s", file, err->message);
     98 		g_clear_error(&err);
     99 		goto done;
    100 	}
    101 
    102 	disabled = g_key_file_get_string_list(keyfile, "General",
    103 						"Disable", NULL, &err);
    104 	if (err) {
    105 		debug("%s: %s", file, err->message);
    106 		g_clear_error(&err);
    107 	} else {
    108 		int i;
    109 		for (i = 0; disabled[i] != NULL; i++) {
    110 			if (g_str_equal(disabled[i], "Connection"))
    111 				conf.connection_enabled = FALSE;
    112 			else if (g_str_equal(disabled[i], "Server"))
    113 				conf.server_enabled = FALSE;
    114 		}
    115 		g_strfreev(disabled);
    116 	}
    117 
    118 	conf.security = !g_key_file_get_boolean(keyfile, "General",
    119 						"DisableSecurity", &err);
    120 	if (err) {
    121 		debug("%s: %s", file, err->message);
    122 		g_clear_error(&err);
    123 	}
    124 
    125 #if 0
    126 	conf.panu_script = g_key_file_get_string(keyfile, "PANU Role",
    127 						"Script", &err);
    128 	if (err) {
    129 		debug("%s: %s", file, err->message);
    130 		g_clear_error(&err);
    131 	}
    132 
    133 	conf.gn_script = g_key_file_get_string(keyfile, "GN Role",
    134 						"Script", &err);
    135 	if (err) {
    136 		debug("%s: %s", file, err->message);
    137 		g_clear_error(&err);
    138 	}
    139 
    140 	conf.nap_script = g_key_file_get_string(keyfile, "NAP Role",
    141 						"Script", &err);
    142 	if (err) {
    143 		debug("%s: %s", file, err->message);
    144 		g_clear_error(&err);
    145 	}
    146 #endif
    147 
    148 	conf.iface_prefix = g_key_file_get_string(keyfile, "PANU Role",
    149 						"Interface", &err);
    150 	if (err) {
    151 		debug("%s: %s", file, err->message);
    152 		g_clear_error(&err);
    153 	}
    154 
    155 	conf.gn_iface = g_key_file_get_string(keyfile, "GN Role",
    156 						"Interface", &err);
    157 	if (err) {
    158 		debug("%s: %s", file, err->message);
    159 		g_clear_error(&err);
    160 	}
    161 
    162 	conf.nap_iface = g_key_file_get_string(keyfile, "NAP Role",
    163 						"Interface", &err);
    164 	if (err) {
    165 		debug("%s: %s", file, err->message);
    166 		g_clear_error(&err);
    167 	}
    168 
    169 done:
    170 	g_key_file_free(keyfile);
    171 
    172 	if (!conf.iface_prefix)
    173 		conf.iface_prefix = g_strdup(IFACE_PREFIX);
    174 
    175 	if (!conf.gn_iface)
    176 		conf.gn_iface = g_strdup(GN_IFACE);
    177 	if (!conf.nap_iface)
    178 		conf.nap_iface = g_strdup(NAP_IFACE);
    179 
    180 	debug("Config options: InterfacePrefix=%s, PANU_Script=%s, "
    181 		"GN_Script=%s, NAP_Script=%s, GN_Interface=%s, "
    182 		"NAP_Interface=%s, Security=%s",
    183 		conf.iface_prefix, conf.panu_script, conf.gn_script,
    184 		conf.nap_script, conf.gn_iface, conf.nap_iface,
    185 		conf.security ? "true" : "false");
    186 }
    187 
    188 static int network_probe(struct btd_device *device, GSList *uuids, uint16_t id)
    189 {
    190 	struct btd_adapter *adapter = device_get_adapter(device);
    191 	const gchar *path = device_get_path(device);
    192 	bdaddr_t src, dst;
    193 
    194 	DBG("path %s", path);
    195 
    196 	adapter_get_address(adapter, &src);
    197 	device_get_address(device, &dst);
    198 
    199 	return connection_register(device, path, &src, &dst, id);
    200 }
    201 
    202 static void network_remove(struct btd_device *device, uint16_t id)
    203 {
    204 	const gchar *path = device_get_path(device);
    205 
    206 	DBG("path %s", path);
    207 
    208 	connection_unregister(path, id);
    209 }
    210 
    211 static int panu_probe(struct btd_device *device, GSList *uuids)
    212 {
    213 	return network_probe(device, uuids, BNEP_SVC_PANU);
    214 }
    215 
    216 static void panu_remove(struct btd_device *device)
    217 {
    218 	network_remove(device, BNEP_SVC_PANU);
    219 }
    220 
    221 static int gn_probe(struct btd_device *device, GSList *uuids)
    222 {
    223 	return network_probe(device, uuids, BNEP_SVC_GN);
    224 }
    225 
    226 static void gn_remove(struct btd_device *device)
    227 {
    228 	network_remove(device, BNEP_SVC_GN);
    229 }
    230 
    231 static int nap_probe(struct btd_device *device, GSList *uuids)
    232 {
    233 	return network_probe(device, uuids, BNEP_SVC_NAP);
    234 }
    235 
    236 static void nap_remove(struct btd_device *device)
    237 {
    238 	network_remove(device, BNEP_SVC_NAP);
    239 }
    240 
    241 static int network_server_probe(struct btd_adapter *adapter, uint16_t id)
    242 {
    243 	const gchar *path = adapter_get_path(adapter);
    244 
    245 	DBG("path %s", path);
    246 
    247 	if (!conf.server_enabled)
    248 		return 0;
    249 
    250 	return server_register(adapter, id);
    251 }
    252 
    253 static void network_server_remove(struct btd_adapter *adapter, uint16_t id)
    254 {
    255 	const gchar *path = adapter_get_path(adapter);
    256 
    257 	DBG("path %s", path);
    258 
    259 	server_unregister(adapter, id);
    260 }
    261 
    262 static int panu_server_probe(struct btd_adapter *adapter)
    263 {
    264 	return network_server_probe(adapter, BNEP_SVC_PANU);
    265 }
    266 
    267 static int gn_server_probe(struct btd_adapter *adapter)
    268 {
    269 	return network_server_probe(adapter, BNEP_SVC_GN);
    270 }
    271 
    272 static int nap_server_probe(struct btd_adapter *adapter)
    273 {
    274 	return network_server_probe(adapter, BNEP_SVC_NAP);
    275 }
    276 
    277 static void panu_server_remove(struct btd_adapter *adapter)
    278 {
    279 	network_server_remove(adapter, BNEP_SVC_PANU);
    280 }
    281 
    282 static void gn_server_remove(struct btd_adapter *adapter)
    283 {
    284 	network_server_remove(adapter, BNEP_SVC_GN);
    285 }
    286 
    287 static void nap_server_remove(struct btd_adapter *adapter)
    288 {
    289 	network_server_remove(adapter, BNEP_SVC_NAP);
    290 }
    291 
    292 static struct btd_device_driver network_panu_driver = {
    293 	.name	= "network-panu",
    294 	.uuids	= BTD_UUIDS(PANU_UUID),
    295 	.probe	= panu_probe,
    296 	.remove	= panu_remove,
    297 };
    298 
    299 static struct btd_device_driver network_gn_driver = {
    300 	.name	= "network-gn",
    301 	.uuids	= BTD_UUIDS(GN_UUID),
    302 	.probe	= gn_probe,
    303 	.remove	= gn_remove,
    304 };
    305 
    306 static struct btd_device_driver network_nap_driver = {
    307 	.name	= "network-nap",
    308 	.uuids	= BTD_UUIDS(NAP_UUID),
    309 	.probe	= nap_probe,
    310 	.remove	= nap_remove,
    311 };
    312 
    313 static struct btd_adapter_driver network_panu_server_driver = {
    314 	.name	= "network-panu-server",
    315 	.probe	= panu_server_probe,
    316 	.remove	= panu_server_remove,
    317 };
    318 
    319 static struct btd_adapter_driver network_gn_server_driver = {
    320 	.name	= "network-gn-server",
    321 	.probe	= gn_server_probe,
    322 	.remove	= gn_server_remove,
    323 };
    324 
    325 static struct btd_adapter_driver network_nap_server_driver = {
    326 	.name	= "network-nap-server",
    327 	.probe	= nap_server_probe,
    328 	.remove	= nap_server_remove,
    329 };
    330 
    331 int network_manager_init(DBusConnection *conn)
    332 {
    333 	read_config(CONFIGDIR "/network.conf");
    334 
    335 	if (bnep_init(conf.panu_script, conf.gn_script, conf.nap_script)) {
    336 		error("Can't init bnep module");
    337 		return -1;
    338 	}
    339 
    340 	/*
    341 	 * There is one socket to handle the incomming connections. NAP,
    342 	 * GN and PANU servers share the same PSM. The initial BNEP message
    343 	 * (setup connection request) contains the destination service
    344 	 * field that defines which service the source is connecting to.
    345 	 */
    346 	if (bridge_init(conf.gn_iface, conf.nap_iface) < 0) {
    347 		error("Can't init bridge module");
    348 		return -1;
    349 	}
    350 
    351 	if (server_init(conn, conf.iface_prefix, conf.security) < 0)
    352 		return -1;
    353 
    354 	/* Register PANU, GN and NAP servers if they don't exist */
    355 	btd_register_adapter_driver(&network_panu_server_driver);
    356 	btd_register_adapter_driver(&network_gn_server_driver);
    357 	btd_register_adapter_driver(&network_nap_server_driver);
    358 
    359 	if (connection_init(conn, conf.iface_prefix) < 0)
    360 		return -1;
    361 
    362 	btd_register_device_driver(&network_panu_driver);
    363 	btd_register_device_driver(&network_gn_driver);
    364 	btd_register_device_driver(&network_nap_driver);
    365 
    366 	connection = dbus_connection_ref(conn);
    367 
    368 	return 0;
    369 }
    370 
    371 void network_manager_exit(void)
    372 {
    373 	if (conf.server_enabled)
    374 		server_exit();
    375 
    376 	if (conf.connection_enabled) {
    377 		btd_unregister_device_driver(&network_panu_driver);
    378 		btd_unregister_device_driver(&network_gn_driver);
    379 		btd_unregister_device_driver(&network_nap_driver);
    380 		connection_exit();
    381 	}
    382 
    383 	btd_unregister_adapter_driver(&network_panu_server_driver);
    384 	btd_unregister_adapter_driver(&network_gn_server_driver);
    385 	btd_unregister_adapter_driver(&network_nap_server_driver);
    386 
    387 	dbus_connection_unref(connection);
    388 	connection = NULL;
    389 
    390 	bnep_cleanup();
    391 	bridge_cleanup();
    392 	conf_cleanup();
    393 }
    394