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 <errno.h>
     29 #include <unistd.h>
     30 #include <string.h>
     31 #include <sys/ioctl.h>
     32 #include <sys/stat.h>
     33 #include <sys/types.h>
     34 #include <net/if.h>
     35 #include <linux/sockios.h>
     36 
     37 #include <bluetooth/bluetooth.h>
     38 #include <bluetooth/l2cap.h>
     39 #include <bluetooth/bnep.h>
     40 
     41 #include "logging.h"
     42 #include "bridge.h"
     43 #include "common.h"
     44 
     45 static int bridge_socket = -1;
     46 static const char *gn_bridge = NULL;
     47 static const char *nap_bridge = NULL;
     48 
     49 int bridge_init(const char *gn_iface, const char *nap_iface)
     50 {
     51 #if 0
     52 	struct stat st;
     53 
     54 	if (stat("/sys/module/bridge", &st) < 0)
     55 		return -EOPNOTSUPP;
     56 #endif
     57 	bridge_socket = socket(AF_INET, SOCK_STREAM, 0);
     58 	if (bridge_socket < 0) {
     59 		error("Failed to open bridge socket: %s (%d)",
     60 				strerror(errno), errno);
     61 		return -errno;
     62 	}
     63 
     64 	gn_bridge = gn_iface;
     65 	nap_bridge = nap_iface;
     66 
     67 	return 0;
     68 }
     69 
     70 void bridge_cleanup(void)
     71 {
     72 	close(bridge_socket);
     73 
     74 	bridge_socket = -1;
     75 }
     76 
     77 int bridge_create(int id)
     78 {
     79 	int err;
     80 	const char *name = bridge_get_name(id);
     81 
     82 	err = ioctl(bridge_socket, SIOCBRADDBR, name);
     83 	if (err < 0)
     84 		return -errno;
     85 
     86 	info("bridge %s created", name);
     87 
     88 	return 0;
     89 }
     90 
     91 int bridge_remove(int id)
     92 {
     93 	int err;
     94 	const char *name = bridge_get_name(id);
     95 
     96 	err = bnep_if_down(name);
     97 	if (err < 0)
     98 		return err;
     99 
    100 	err = ioctl(bridge_socket, SIOCBRDELBR, name);
    101 	if (err < 0)
    102 		return -errno;
    103 
    104 	info("bridge %s removed", name);
    105 
    106 	return 0;
    107 }
    108 
    109 int bridge_add_interface(int id, const char *dev)
    110 {
    111 	struct ifreq ifr;
    112 	int err;
    113 	int ifindex = if_nametoindex(dev);
    114 	const char *name = bridge_get_name(id);
    115 
    116 	if (!name)
    117 		return -EINVAL;
    118 
    119 	if (ifindex == 0)
    120 		return -ENODEV;
    121 
    122 	memset(&ifr, 0, sizeof(ifr));
    123 	strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
    124 	ifr.ifr_ifindex = ifindex;
    125 
    126 	err = ioctl(bridge_socket, SIOCBRADDIF, &ifr);
    127 	if (err < 0)
    128 		return err;
    129 
    130 	info("bridge %s: interface %s added", name, dev);
    131 
    132 	err = bnep_if_up(name, id);
    133 	if (err < 0)
    134 		return err;
    135 
    136 	return 0;
    137 }
    138 
    139 const char *bridge_get_name(int id)
    140 {
    141 	if (id == BNEP_SVC_GN)
    142 		return gn_bridge;
    143 
    144 	if (id == BNEP_SVC_NAP)
    145 		return nap_bridge;
    146 
    147 	return NULL;
    148 }
    149