Remove obsolete file.
[connman] / src / inet.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <net/ethernet.h>
35 #include <linux/if_arp.h>
36 #include <linux/wireless.h>
37
38 #include "connman.h"
39
40 int connman_inet_ifindex(const char *name)
41 {
42         struct ifreq ifr;
43         int sk, err;
44
45         if (name == NULL)
46                 return -1;
47
48         sk = socket(PF_INET, SOCK_DGRAM, 0);
49         if (sk < 0)
50                 return -1;
51
52         memset(&ifr, 0, sizeof(ifr));
53         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
54
55         err = ioctl(sk, SIOCGIFINDEX, &ifr);
56
57         close(sk);
58
59         if (err < 0)
60                 return -1;
61
62         return ifr.ifr_ifindex;
63 }
64
65 char *connman_inet_ifname(int index)
66 {
67         struct ifreq ifr;
68         int sk, err;
69
70         if (index < 0)
71                 return NULL;
72
73         sk = socket(PF_INET, SOCK_DGRAM, 0);
74         if (sk < 0)
75                 return NULL;
76
77         memset(&ifr, 0, sizeof(ifr));
78         ifr.ifr_ifindex = index;
79
80         err = ioctl(sk, SIOCGIFNAME, &ifr);
81
82         close(sk);
83
84         if (err < 0)
85                 return NULL;
86
87         return strdup(ifr.ifr_name);
88 }
89
90 int connman_inet_ifup(int index)
91 {
92         struct ifreq ifr;
93         int sk, err;
94
95         sk = socket(PF_INET, SOCK_DGRAM, 0);
96         if (sk < 0)
97                 return -errno;
98
99         memset(&ifr, 0, sizeof(ifr));
100         ifr.ifr_ifindex = index;
101
102         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
103                 err = -errno;
104                 goto done;
105         }
106
107         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
108                 err = -errno;
109                 goto done;
110         }
111
112         if (ifr.ifr_flags & IFF_UP) {
113                 err = -EALREADY;
114                 goto done;
115         }
116
117         ifr.ifr_flags |= IFF_UP;
118
119         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
120                 err = -errno;
121                 goto done;
122         }
123
124         err = 0;
125
126 done:
127         close(sk);
128
129         return err;
130 }
131
132 int connman_inet_ifdown(int index)
133 {
134         struct ifreq ifr;
135         int sk, err;
136
137         sk = socket(PF_INET, SOCK_DGRAM, 0);
138         if (sk < 0)
139                 return -errno;
140
141         memset(&ifr, 0, sizeof(ifr));
142         ifr.ifr_ifindex = index;
143
144         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
145                 err = -errno;
146                 goto done;
147         }
148
149         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
150                 err = -errno;
151                 goto done;
152         }
153
154         if (!(ifr.ifr_flags & IFF_UP)) {
155                 err = -EALREADY;
156                 goto done;
157         }
158
159         ifr.ifr_flags &= ~IFF_UP;
160
161         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
162                 err = -errno;
163         else
164                 err = 0;
165
166 done:
167         close(sk);
168
169         return err;
170 }
171
172 static unsigned short index2type(int index)
173 {
174         struct ifreq ifr;
175         int sk, err;
176
177         if (index < 0)
178                 return ARPHRD_VOID;
179
180         sk = socket(PF_INET, SOCK_DGRAM, 0);
181         if (sk < 0)
182                 return ARPHRD_VOID;
183
184         memset(&ifr, 0, sizeof(ifr));
185         ifr.ifr_ifindex = index;
186
187         err = ioctl(sk, SIOCGIFNAME, &ifr);
188
189         if (err == 0)
190                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
191
192         close(sk);
193
194         if (err < 0)
195                 return ARPHRD_VOID;
196
197         return ifr.ifr_hwaddr.sa_family;
198 }
199
200 static char *index2addr(int index)
201 {
202         struct ifreq ifr;
203         struct ether_addr *eth;
204         char *str;
205         int sk, err;
206
207         if (index < 0)
208                 return NULL;
209
210         sk = socket(PF_INET, SOCK_DGRAM, 0);
211         if (sk < 0)
212                 return NULL;
213
214         memset(&ifr, 0, sizeof(ifr));
215         ifr.ifr_ifindex = index;
216
217         err = ioctl(sk, SIOCGIFNAME, &ifr);
218
219         if (err == 0)
220                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
221
222         close(sk);
223
224         if (err < 0)
225                 return NULL;
226
227         str = malloc(18);
228         if (!str)
229                 return NULL;
230
231         eth = (void *) &ifr.ifr_hwaddr.sa_data;
232         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
233                                                 eth->ether_addr_octet[0],
234                                                 eth->ether_addr_octet[1],
235                                                 eth->ether_addr_octet[2],
236                                                 eth->ether_addr_octet[3],
237                                                 eth->ether_addr_octet[4],
238                                                 eth->ether_addr_octet[5]);
239
240         return str;
241 }
242
243 static char *index2ident(int index, const char *prefix)
244 {
245         struct ifreq ifr;
246         struct ether_addr *eth;
247         char *str;
248         int sk, err, len;
249
250         if (index < 0)
251                 return NULL;
252
253         sk = socket(PF_INET, SOCK_DGRAM, 0);
254         if (sk < 0)
255                 return NULL;
256
257         memset(&ifr, 0, sizeof(ifr));
258         ifr.ifr_ifindex = index;
259
260         err = ioctl(sk, SIOCGIFNAME, &ifr);
261
262         if (err == 0)
263                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
264
265         close(sk);
266
267         if (err < 0)
268                 return NULL;
269
270         len = prefix ? strlen(prefix) + 18 : 18;
271
272         str = malloc(len);
273         if (!str)
274                 return NULL;
275
276         eth = (void *) &ifr.ifr_hwaddr.sa_data;
277         snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
278                                                 prefix ? prefix : "",
279                                                 eth->ether_addr_octet[0],
280                                                 eth->ether_addr_octet[1],
281                                                 eth->ether_addr_octet[2],
282                                                 eth->ether_addr_octet[3],
283                                                 eth->ether_addr_octet[4],
284                                                 eth->ether_addr_octet[5]);
285
286         return str;
287 }
288
289 struct connman_device *connman_inet_create_device(int index)
290 {
291         enum connman_device_type devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
292         enum connman_device_mode mode = CONNMAN_DEVICE_MODE_UNKNOWN;
293         struct connman_device *device;
294         unsigned short type = index2type(index);
295         char *addr, *name, *devname, *ident = NULL;
296
297         if (index < 0)
298                 return NULL;
299
300         devname = connman_inet_ifname(index);
301         if (devname == NULL)
302                 return NULL;
303
304         if (type == ARPHRD_ETHER) {
305                 char bridge_path[PATH_MAX], wimax_path[PATH_MAX];
306                 struct stat st;
307                 struct iwreq iwr;
308                 int sk;
309
310                 snprintf(bridge_path, PATH_MAX,
311                                         "/sys/class/net/%s/bridge", devname);
312                 snprintf(wimax_path, PATH_MAX,
313                                         "/sys/class/net/%s/wimax", devname);
314
315                 memset(&iwr, 0, sizeof(iwr));
316                 strncpy(iwr.ifr_ifrn.ifrn_name, devname, IFNAMSIZ);
317
318                 sk = socket(PF_INET, SOCK_DGRAM, 0);
319
320                 if (g_str_has_prefix(devname, "vmnet") == TRUE ||
321                                 g_str_has_prefix(devname, "vboxnet") == TRUE) {
322                         connman_info("Ignoring network interface %s", devname);
323                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
324                 } else if (g_str_has_prefix(devname, "bnep") == TRUE)
325                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
326                 else if (g_str_has_prefix(devname, "wmx") == TRUE)
327                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
328                 else if (stat(wimax_path, &st) == 0 && (st.st_mode & S_IFDIR))
329                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
330                 else if (stat(bridge_path, &st) == 0 && (st.st_mode & S_IFDIR))
331                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
332                 else if (ioctl(sk, SIOCGIWNAME, &iwr) == 0)
333                         devtype = CONNMAN_DEVICE_TYPE_WIFI;
334                 else
335                         devtype = CONNMAN_DEVICE_TYPE_ETHERNET;
336
337                 close(sk);
338         } else if (type == ARPHRD_NONE) {
339                 if (g_str_has_prefix(devname, "hso") == TRUE)
340                         devtype = CONNMAN_DEVICE_TYPE_HSO;
341         }
342
343         switch (devtype) {
344         case CONNMAN_DEVICE_TYPE_UNKNOWN:
345                 g_free(devname);
346                 return NULL;
347         case CONNMAN_DEVICE_TYPE_ETHERNET:
348         case CONNMAN_DEVICE_TYPE_WIFI:
349         case CONNMAN_DEVICE_TYPE_WIMAX:
350                 name = index2ident(index, "");
351                 addr = index2addr(index);
352                 break;
353         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
354         case CONNMAN_DEVICE_TYPE_GPS:
355         case CONNMAN_DEVICE_TYPE_HSO:
356         case CONNMAN_DEVICE_TYPE_NOZOMI:
357         case CONNMAN_DEVICE_TYPE_HUAWEI:
358         case CONNMAN_DEVICE_TYPE_NOVATEL:
359         case CONNMAN_DEVICE_TYPE_VENDOR:
360                 name = strdup(devname);
361                 addr = NULL;
362                 break;
363         }
364
365         device = connman_device_create(name, devtype);
366         if (device == NULL) {
367                 g_free(devname);
368                 g_free(name);
369                 g_free(addr);
370                 return NULL;
371         }
372
373         switch (devtype) {
374         case CONNMAN_DEVICE_TYPE_UNKNOWN:
375         case CONNMAN_DEVICE_TYPE_VENDOR:
376         case CONNMAN_DEVICE_TYPE_NOZOMI:
377         case CONNMAN_DEVICE_TYPE_HUAWEI:
378         case CONNMAN_DEVICE_TYPE_NOVATEL:
379         case CONNMAN_DEVICE_TYPE_GPS:
380                 mode = CONNMAN_DEVICE_MODE_UNKNOWN;
381                 break;
382         case CONNMAN_DEVICE_TYPE_ETHERNET:
383                 mode = CONNMAN_DEVICE_MODE_TRANSPORT_IP;
384                 ident = index2ident(index, NULL);
385                 break;
386         case CONNMAN_DEVICE_TYPE_WIFI:
387         case CONNMAN_DEVICE_TYPE_WIMAX:
388                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
389                 ident = index2ident(index, NULL);
390                 break;
391         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
392                 mode = CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE;
393                 break;
394         case CONNMAN_DEVICE_TYPE_HSO:
395                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
396                 connman_device_set_policy(device, CONNMAN_DEVICE_POLICY_MANUAL);
397                 break;
398         }
399
400         connman_device_set_mode(device, mode);
401
402         connman_device_set_index(device, index);
403         connman_device_set_interface(device, devname);
404
405         if (ident != NULL) {
406                 connman_device_set_ident(device, ident);
407                 g_free(ident);
408         }
409
410         connman_device_set_string(device, "Address", addr);
411
412         g_free(devname);
413         g_free(name);
414         g_free(addr);
415
416         return device;
417 }