1d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi/* 2d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * 3d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * BlueZ - Bluetooth protocol stack for Linux 4d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * 58307634aa6d9dd96c12cec8b8acf1059b54e0ae6Vinicius Costa Gomes * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 68307634aa6d9dd96c12cec8b8acf1059b54e0ae6Vinicius Costa Gomes * 7d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * 8d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * This program is free software; you can redistribute it and/or modify 9d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * it under the terms of the GNU General Public License as published by 10d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * the Free Software Foundation; either version 2 of the License, or 11d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * (at your option) any later version. 12d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * 13d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * This program is distributed in the hope that it will be useful, 14d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * but WITHOUT ANY WARRANTY; without even the implied warranty of 15d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * GNU General Public License for more details. 17d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * 18d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * You should have received a copy of the GNU General Public License 19d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * along with this program; if not, write to the Free Software 20d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi * 22d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi */ 23d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi 24612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi#ifdef HAVE_CONFIG_H 25d2657982a8a7f4caace5b6bd8d701c5c8f8ba644Claudio Takahasi#include <config.h> 26e04efbaddf3d6a178dbbab9e5355dfecaa4da3adBruna Moreira#endif 275399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi 28a278db781a26c639267b1d88d5fbe08f99af6c61Elvis Pfützenreuter#include <stdio.h> 295399423bd667efa5d15d8dec895250fe5a3bbec2Claudio Takahasi#include <errno.h> 302448a8ba038009ab5a89d6e141ee4e1b0c71aa53Claudio Takahasi#include <unistd.h> 312448a8ba038009ab5a89d6e141ee4e1b0c71aa53Claudio Takahasi#include <stdlib.h> 32922c5feb93adfb9773a854d8e89eb2c5604e632bSheldon Demario#include <sys/param.h> 33922c5feb93adfb9773a854d8e89eb2c5604e632bSheldon Demario#include <sys/ioctl.h> 34262323b597306be0758efcfbc068df73931ba2a4Anderson Lizardo#include <sys/socket.h> 35adc7ca1ece5e579998e5f3b0cca9af7bf8ac8ca1Sheldon Demario#include <sys/wait.h> 36adc7ca1ece5e579998e5f3b0cca9af7bf8ac8ca1Sheldon Demario#include <net/if.h> 37c4fe3b3a0b3da660d3ec59bfc392bd05c9a29e5aVinicius Costa Gomes#include <linux/sockios.h> 380a70694d3afd91470a83567c18d20a29ad1996e6Anderson Lizardo 390a70694d3afd91470a83567c18d20a29ad1996e6Anderson Lizardo#include <bluetooth/bluetooth.h> 400a70694d3afd91470a83567c18d20a29ad1996e6Anderson Lizardo#include <bluetooth/l2cap.h> 41c4fe3b3a0b3da660d3ec59bfc392bd05c9a29e5aVinicius Costa Gomes#include <bluetooth/bnep.h> 42c4fe3b3a0b3da660d3ec59bfc392bd05c9a29e5aVinicius Costa Gomes 43b1514662a0f04b11172ca97adfe4cac3c39536b2Bruna Moreira#include <glib.h> 44b1514662a0f04b11172ca97adfe4cac3c39536b2Bruna Moreira 45b1514662a0f04b11172ca97adfe4cac3c39536b2Bruna Moreira#include "log.h" 46ad0e7f2c5ab9270369301f81eb5da1954eaab82fSheldon Demario#include "common.h" 47ad0e7f2c5ab9270369301f81eb5da1954eaab82fSheldon Demario 48a278db781a26c639267b1d88d5fbe08f99af6c61Elvis Pfützenreuterstatic int ctl; 49ad0e7f2c5ab9270369301f81eb5da1954eaab82fSheldon Demario 501b07befa15ec80b00be4881c9ed8a253c54e15fcBruna Moreirastatic struct { 511b07befa15ec80b00be4881c9ed8a253c54e15fcBruna Moreira const char *name; /* Friendly name */ 521b07befa15ec80b00be4881c9ed8a253c54e15fcBruna Moreira const char *uuid128; /* UUID 128 */ 53612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi uint16_t id; /* Service class identifier */ 54612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi} __svc[] = { 55612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi { "panu", PANU_UUID, BNEP_SVC_PANU }, 56612d0207646064f309edd564a69d30b42de9e26fClaudio Takahasi { "gn", GN_UUID, BNEP_SVC_GN }, 57 { "nap", NAP_UUID, BNEP_SVC_NAP }, 58 { NULL } 59}; 60 61uint16_t bnep_service_id(const char *svc) 62{ 63 int i; 64 uint16_t id; 65 66 /* Friendly service name */ 67 for (i = 0; __svc[i].name; i++) 68 if (!strcasecmp(svc, __svc[i].name)) { 69 return __svc[i].id; 70 } 71 72 /* UUID 128 string */ 73 for (i = 0; __svc[i].uuid128; i++) 74 if (!strcasecmp(svc, __svc[i].uuid128)) { 75 return __svc[i].id; 76 } 77 78 /* Try convert to HEX */ 79 id = strtol(svc, NULL, 16); 80 if ((id < BNEP_SVC_PANU) || (id > BNEP_SVC_GN)) 81 return 0; 82 83 return id; 84} 85 86const char *bnep_uuid(uint16_t id) 87{ 88 int i; 89 90 for (i = 0; __svc[i].uuid128; i++) 91 if (__svc[i].id == id) 92 return __svc[i].uuid128; 93 return NULL; 94} 95 96const char *bnep_name(uint16_t id) 97{ 98 int i; 99 100 for (i = 0; __svc[i].name; i++) 101 if (__svc[i].id == id) 102 return __svc[i].name; 103 return NULL; 104} 105 106int bnep_init(void) 107{ 108 ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP); 109 110 if (ctl < 0) { 111 int err = errno; 112 error("Failed to open control socket: %s (%d)", 113 strerror(err), err); 114 return -err; 115 } 116 117 return 0; 118} 119 120int bnep_cleanup(void) 121{ 122 close(ctl); 123 return 0; 124} 125 126int bnep_kill_connection(bdaddr_t *dst) 127{ 128 struct bnep_conndel_req req; 129 130 memset(&req, 0, sizeof(req)); 131 baswap((bdaddr_t *)&req.dst, dst); 132 req.flags = 0; 133 if (ioctl(ctl, BNEPCONNDEL, &req)) { 134 int err = errno; 135 error("Failed to kill connection: %s (%d)", 136 strerror(err), err); 137 return -err; 138 } 139 return 0; 140} 141 142int bnep_kill_all_connections(void) 143{ 144 struct bnep_connlist_req req; 145 struct bnep_conninfo ci[7]; 146 unsigned int i; 147 int err; 148 149 memset(&req, 0, sizeof(req)); 150 req.cnum = 7; 151 req.ci = ci; 152 if (ioctl(ctl, BNEPGETCONNLIST, &req)) { 153 err = errno; 154 error("Failed to get connection list: %s (%d)", 155 strerror(err), err); 156 return -err; 157 } 158 159 for (i = 0; i < req.cnum; i++) { 160 struct bnep_conndel_req del; 161 162 memset(&del, 0, sizeof(del)); 163 memcpy(del.dst, ci[i].dst, ETH_ALEN); 164 del.flags = 0; 165 ioctl(ctl, BNEPCONNDEL, &del); 166 } 167 return 0; 168} 169 170int bnep_connadd(int sk, uint16_t role, char *dev) 171{ 172 struct bnep_connadd_req req; 173 174 memset(&req, 0, sizeof(req)); 175 strncpy(req.device, dev, 16); 176 req.device[15] = '\0'; 177 req.sock = sk; 178 req.role = role; 179 if (ioctl(ctl, BNEPCONNADD, &req) < 0) { 180 int err = errno; 181 error("Failed to add device %s: %s(%d)", 182 dev, strerror(err), err); 183 return -err; 184 } 185 186 strncpy(dev, req.device, 16); 187 return 0; 188} 189 190int bnep_if_up(const char *devname) 191{ 192 struct ifreq ifr; 193 int sk, err; 194 195 sk = socket(AF_INET, SOCK_DGRAM, 0); 196 197 memset(&ifr, 0, sizeof(ifr)); 198 strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1); 199 200 ifr.ifr_flags |= IFF_UP; 201 ifr.ifr_flags |= IFF_MULTICAST; 202 203 err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr); 204 205 close(sk); 206 207 if (err < 0) { 208 error("Could not bring up %s", devname); 209 return err; 210 } 211 212 return 0; 213} 214 215int bnep_if_down(const char *devname) 216{ 217 struct ifreq ifr; 218 int sk, err; 219 220 sk = socket(AF_INET, SOCK_DGRAM, 0); 221 222 memset(&ifr, 0, sizeof(ifr)); 223 strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1); 224 225 ifr.ifr_flags &= ~IFF_UP; 226 227 /* Bring down the interface */ 228 err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr); 229 230 close(sk); 231 232 if (err < 0) { 233 error("Could not bring down %s", devname); 234 return err; 235 } 236 237 return 0; 238} 239 240int bnep_add_to_bridge(const char *devname, const char *bridge) 241{ 242 int ifindex = if_nametoindex(devname); 243 struct ifreq ifr; 244 int sk, err; 245 246 if (!devname || !bridge) 247 return -EINVAL; 248 249 sk = socket(AF_INET, SOCK_STREAM, 0); 250 if (sk < 0) 251 return -1; 252 253 memset(&ifr, 0, sizeof(ifr)); 254 strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1); 255 ifr.ifr_ifindex = ifindex; 256 257 err = ioctl(sk, SIOCBRADDIF, &ifr); 258 259 close(sk); 260 261 if (err < 0) 262 return err; 263 264 info("bridge %s: interface %s added", bridge, devname); 265 266 return 0; 267} 268