Fix the bug : TIVI-204 Fail to connect to bluetooth network
[profile/ivi/bluez.git] / network / common.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  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 <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <sys/param.h>
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35 #include <sys/wait.h>
36 #include <net/if.h>
37 #include <linux/sockios.h>
38
39 #include <bluetooth/bluetooth.h>
40 #include <bluetooth/l2cap.h>
41 #include <bluetooth/bnep.h>
42 #include <bluetooth/uuid.h>
43
44 #include <glib.h>
45
46 #include "log.h"
47 #include "common.h"
48
49 static int ctl;
50
51 static struct {
52         const char      *name;          /* Friendly name */
53         const char      *uuid128;       /* UUID 128 */
54         uint16_t        id;             /* Service class identifier */
55 } __svc[] = {
56         { "panu",       PANU_UUID,      BNEP_SVC_PANU   },
57         { "gn",         GN_UUID,        BNEP_SVC_GN     },
58         { "nap",        NAP_UUID,       BNEP_SVC_NAP    },
59         { NULL }
60 };
61
62 uint16_t bnep_service_id(const char *svc)
63 {
64         int i;
65         uint16_t id;
66
67         /* Friendly service name */
68         for (i = 0; __svc[i].name; i++)
69                 if (!strcasecmp(svc, __svc[i].name)) {
70                         return __svc[i].id;
71                 }
72
73         /* UUID 128 string */
74         for (i = 0; __svc[i].uuid128; i++)
75                 if (!strcasecmp(svc, __svc[i].uuid128)) {
76                         return __svc[i].id;
77                 }
78
79         /* Try convert to HEX */
80         id = strtol(svc, NULL, 16);
81         if ((id < BNEP_SVC_PANU) || (id > BNEP_SVC_GN))
82                 return 0;
83
84         return id;
85 }
86
87 const char *bnep_uuid(uint16_t id)
88 {
89         int i;
90
91         for (i = 0; __svc[i].uuid128; i++)
92                 if (__svc[i].id == id)
93                         return __svc[i].uuid128;
94         return NULL;
95 }
96
97 const char *bnep_name(uint16_t id)
98 {
99         int i;
100
101         for (i = 0; __svc[i].name; i++)
102                 if (__svc[i].id == id)
103                         return __svc[i].name;
104         return NULL;
105 }
106
107 int bnep_init(void)
108 {
109         ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
110
111         if (ctl < 0) {
112                 int err = -errno;
113                 error("Failed to open control socket: %s (%d)",
114                                                 strerror(-err), -err);
115                 return err;
116         }
117
118         return 0;
119 }
120
121 int bnep_cleanup(void)
122 {
123         close(ctl);
124         return 0;
125 }
126
127 int bnep_kill_connection(bdaddr_t *dst)
128 {
129         struct bnep_conndel_req req;
130
131         memset(&req, 0, sizeof(req));
132         baswap((bdaddr_t *)&req.dst, dst);
133         req.flags = 0;
134         if (ioctl(ctl, BNEPCONNDEL, &req)) {
135                 int err = -errno;
136                 error("Failed to kill connection: %s (%d)",
137                                                 strerror(-err), -err);
138                 return err;
139         }
140         return 0;
141 }
142
143 int bnep_kill_all_connections(void)
144 {
145         struct bnep_connlist_req req;
146         struct bnep_conninfo ci[7];
147         unsigned int i;
148         int err;
149
150         memset(&req, 0, sizeof(req));
151         req.cnum = 7;
152         req.ci   = ci;
153         if (ioctl(ctl, BNEPGETCONNLIST, &req)) {
154                 err = -errno;
155                 error("Failed to get connection list: %s (%d)",
156                                                 strerror(-err), -err);
157                 return err;
158         }
159
160         for (i = 0; i < req.cnum; i++) {
161                 struct bnep_conndel_req del;
162
163                 memset(&del, 0, sizeof(del));
164                 memcpy(del.dst, ci[i].dst, ETH_ALEN);
165                 del.flags = 0;
166                 ioctl(ctl, BNEPCONNDEL, &del);
167         }
168         return 0;
169 }
170
171 int bnep_connadd(int sk, uint16_t role, char *dev)
172 {
173         struct bnep_connadd_req req;
174
175         memset(&req, 0, sizeof(req));
176         strncpy(req.device, dev, 16);
177         req.device[15] = '\0';
178         req.sock = sk;
179         req.role = role;
180         if (ioctl(ctl, BNEPCONNADD, &req) < 0) {
181                 int err = -errno;
182                 error("Failed to add device %s: %s(%d)",
183                                 dev, strerror(-err), -err);
184                 return err;
185         }
186
187         strncpy(dev, req.device, 16);
188         return 0;
189 }
190
191 int bnep_if_up(const char *devname)
192 {
193         struct ifreq ifr;
194         int sk, err;
195
196         sk = socket(AF_INET, SOCK_DGRAM, 0);
197
198         memset(&ifr, 0, sizeof(ifr));
199         strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
200
201         ifr.ifr_flags |= IFF_UP;
202         ifr.ifr_flags |= IFF_MULTICAST;
203
204         err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
205
206         close(sk);
207
208         if (err < 0) {
209                 error("Could not bring up %s", devname);
210                 return err;
211         }
212
213         return 0;
214 }
215
216 int bnep_if_down(const char *devname)
217 {
218         struct ifreq ifr;
219         int sk, err;
220
221         sk = socket(AF_INET, SOCK_DGRAM, 0);
222
223         memset(&ifr, 0, sizeof(ifr));
224         strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1);
225
226         ifr.ifr_flags &= ~IFF_UP;
227
228         /* Bring down the interface */
229         err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr);
230
231         close(sk);
232
233         if (err < 0) {
234                 error("Could not bring down %s", devname);
235                 return err;
236         }
237
238         return 0;
239 }
240
241 int bnep_add_to_bridge(const char *devname, const char *bridge)
242 {
243         int ifindex = if_nametoindex(devname);
244         struct ifreq ifr;
245         int sk, err;
246
247         if (!devname || !bridge)
248                 return -EINVAL;
249
250         sk = socket(AF_INET, SOCK_STREAM, 0);
251         if (sk < 0)
252                 return -1;
253
254         memset(&ifr, 0, sizeof(ifr));
255         strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
256         ifr.ifr_ifindex = ifindex;
257
258         err = ioctl(sk, SIOCBRADDIF, &ifr);
259
260         close(sk);
261
262         if (err < 0)
263                 return err;
264
265         info("bridge %s: interface %s added", bridge, devname);
266
267         return 0;
268 }