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