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 <errno.h> 29 30 #include <netlink/netlink.h> 31 #include <netlink/genl/genl.h> 32 #include <netlink/genl/ctrl.h> 33 #include <netlink/genl/family.h> 34 35 #include <bluetooth/bluetooth.h> 36 37 #include <glib.h> 38 39 #include "plugin.h" 40 #include "logging.h" 41 42 static struct nl_handle *handle; 43 static struct nl_cache *cache; 44 static struct genl_family *family; 45 46 static GIOChannel *channel; 47 48 static gboolean channel_callback(GIOChannel *chan, 49 GIOCondition cond, void *user_data) 50 { 51 int err; 52 53 if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) 54 return FALSE; 55 56 debug("Message available on netlink channel"); 57 58 err = nl_recvmsgs_default(handle); 59 60 return TRUE; 61 } 62 63 static int create_channel(int fd) 64 { 65 channel = g_io_channel_unix_new(fd); 66 if (channel == NULL) 67 return -ENOMEM; 68 69 g_io_add_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, 70 channel_callback, NULL); 71 72 return 0; 73 } 74 75 static int netlink_init(void) 76 { 77 info("Starting experimental netlink support"); 78 79 handle = nl_handle_alloc(); 80 if (!handle) { 81 error("Failed to allocate netlink handle"); 82 return -ENOMEM; 83 } 84 85 if (genl_connect(handle) < 0) { 86 error("Failed to connect to generic netlink"); 87 nl_handle_destroy(handle); 88 return -ENOLINK; 89 } 90 91 cache = genl_ctrl_alloc_cache(handle); 92 if (!cache) { 93 error("Failed to allocate generic netlink cache"); 94 return -ENOMEM; 95 nl_handle_destroy(handle); 96 } 97 98 family = genl_ctrl_search_by_name(cache, "bluetooth"); 99 if (!family) { 100 error("Failed to find Bluetooth netlink family"); 101 nl_cache_free(cache); 102 nl_handle_destroy(handle); 103 return -ENOENT; 104 } 105 106 if (create_channel(nl_socket_get_fd(handle)) < 0) { 107 error("Failed to create netlink IO channel"); 108 genl_family_put(family); 109 nl_cache_free(cache); 110 nl_handle_destroy(handle); 111 return -ENOMEM; 112 } 113 114 return 0; 115 } 116 117 static void netlink_exit(void) 118 { 119 g_io_channel_unref(channel); 120 121 genl_family_put(family); 122 nl_cache_free(cache); 123 nl_handle_destroy(handle); 124 } 125 126 BLUETOOTH_PLUGIN_DEFINE(netlink, VERSION, 127 BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, netlink_init, netlink_exit) 128