Home | History | Annotate | Download | only in plugins
      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