1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2009 Marcel Holtmann <marcel@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 45static int bridge_socket = -1; 46static const char *gn_bridge = NULL; 47static const char *nap_bridge = NULL; 48 49int 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 70void bridge_cleanup(void) 71{ 72 close(bridge_socket); 73 74 bridge_socket = -1; 75} 76 77int 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 91int 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 109int 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 139const 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