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