Add helper to check if it is a mac80211 interface
[framework/connectivity/connman.git] / 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 <arpa/inet.h>
35 #include <net/route.h>
36 #include <net/ethernet.h>
37 #include <linux/if_arp.h>
38 #include <linux/wireless.h>
39
40 #include "connman.h"
41
42 int connman_inet_ifindex(const char *name)
43 {
44         struct ifreq ifr;
45         int sk, err;
46
47         if (name == NULL)
48                 return -1;
49
50         sk = socket(PF_INET, SOCK_DGRAM, 0);
51         if (sk < 0)
52                 return -1;
53
54         memset(&ifr, 0, sizeof(ifr));
55         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
56
57         err = ioctl(sk, SIOCGIFINDEX, &ifr);
58
59         close(sk);
60
61         if (err < 0)
62                 return -1;
63
64         return ifr.ifr_ifindex;
65 }
66
67 char *connman_inet_ifname(int index)
68 {
69         struct ifreq ifr;
70         int sk, err;
71
72         if (index < 0)
73                 return NULL;
74
75         sk = socket(PF_INET, SOCK_DGRAM, 0);
76         if (sk < 0)
77                 return NULL;
78
79         memset(&ifr, 0, sizeof(ifr));
80         ifr.ifr_ifindex = index;
81
82         err = ioctl(sk, SIOCGIFNAME, &ifr);
83
84         close(sk);
85
86         if (err < 0)
87                 return NULL;
88
89         return strdup(ifr.ifr_name);
90 }
91
92 int connman_inet_ifup(int index)
93 {
94         struct ifreq ifr;
95         int sk, err;
96
97         sk = socket(PF_INET, SOCK_DGRAM, 0);
98         if (sk < 0)
99                 return -errno;
100
101         memset(&ifr, 0, sizeof(ifr));
102         ifr.ifr_ifindex = index;
103
104         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
105                 err = -errno;
106                 goto done;
107         }
108
109         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
110                 err = -errno;
111                 goto done;
112         }
113
114         if (ifr.ifr_flags & IFF_UP) {
115                 err = -EALREADY;
116                 goto done;
117         }
118
119         ifr.ifr_flags |= IFF_UP;
120
121         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) {
122                 err = -errno;
123                 goto done;
124         }
125
126         err = 0;
127
128 done:
129         close(sk);
130
131         return err;
132 }
133
134 int connman_inet_ifdown(int index)
135 {
136         struct ifreq ifr;
137         int sk, err;
138
139         sk = socket(PF_INET, SOCK_DGRAM, 0);
140         if (sk < 0)
141                 return -errno;
142
143         memset(&ifr, 0, sizeof(ifr));
144         ifr.ifr_ifindex = index;
145
146         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
147                 err = -errno;
148                 goto done;
149         }
150
151         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
152                 err = -errno;
153                 goto done;
154         }
155
156         if (!(ifr.ifr_flags & IFF_UP)) {
157                 err = -EALREADY;
158                 goto done;
159         }
160
161         ifr.ifr_flags &= ~IFF_UP;
162
163         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
164                 err = -errno;
165         else
166                 err = 0;
167
168 done:
169         close(sk);
170
171         return err;
172 }
173
174 static unsigned short index2type(int index)
175 {
176         struct ifreq ifr;
177         int sk, err;
178
179         if (index < 0)
180                 return ARPHRD_VOID;
181
182         sk = socket(PF_INET, SOCK_DGRAM, 0);
183         if (sk < 0)
184                 return ARPHRD_VOID;
185
186         memset(&ifr, 0, sizeof(ifr));
187         ifr.ifr_ifindex = index;
188
189         err = ioctl(sk, SIOCGIFNAME, &ifr);
190
191         if (err == 0)
192                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
193
194         close(sk);
195
196         if (err < 0)
197                 return ARPHRD_VOID;
198
199         return ifr.ifr_hwaddr.sa_family;
200 }
201
202 static char *index2addr(int index)
203 {
204         struct ifreq ifr;
205         struct ether_addr eth;
206         char *str;
207         int sk, err;
208
209         if (index < 0)
210                 return NULL;
211
212         sk = socket(PF_INET, SOCK_DGRAM, 0);
213         if (sk < 0)
214                 return NULL;
215
216         memset(&ifr, 0, sizeof(ifr));
217         ifr.ifr_ifindex = index;
218
219         err = ioctl(sk, SIOCGIFNAME, &ifr);
220
221         if (err == 0)
222                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
223
224         close(sk);
225
226         if (err < 0)
227                 return NULL;
228
229         str = malloc(18);
230         if (!str)
231                 return NULL;
232
233         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
234         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
235                                                 eth.ether_addr_octet[0],
236                                                 eth.ether_addr_octet[1],
237                                                 eth.ether_addr_octet[2],
238                                                 eth.ether_addr_octet[3],
239                                                 eth.ether_addr_octet[4],
240                                                 eth.ether_addr_octet[5]);
241
242         return str;
243 }
244
245 static char *index2ident(int index, const char *prefix)
246 {
247         struct ifreq ifr;
248         struct ether_addr eth;
249         char *str;
250         int sk, err, len;
251
252         if (index < 0)
253                 return NULL;
254
255         sk = socket(PF_INET, SOCK_DGRAM, 0);
256         if (sk < 0)
257                 return NULL;
258
259         memset(&ifr, 0, sizeof(ifr));
260         ifr.ifr_ifindex = index;
261
262         err = ioctl(sk, SIOCGIFNAME, &ifr);
263
264         if (err == 0)
265                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
266
267         close(sk);
268
269         if (err < 0)
270                 return NULL;
271
272         len = prefix ? strlen(prefix) + 18 : 18;
273
274         str = malloc(len);
275         if (!str)
276                 return NULL;
277
278         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
279         snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
280                                                 prefix ? prefix : "",
281                                                 eth.ether_addr_octet[0],
282                                                 eth.ether_addr_octet[1],
283                                                 eth.ether_addr_octet[2],
284                                                 eth.ether_addr_octet[3],
285                                                 eth.ether_addr_octet[4],
286                                                 eth.ether_addr_octet[5]);
287
288         return str;
289 }
290
291 connman_bool_t connman_inet_is_mac80211(int index)
292 {
293         connman_bool_t result = FALSE;
294         char phy80211_path[PATH_MAX];
295         struct stat st;
296         struct ifreq ifr;
297         int sk;
298
299         sk = socket(PF_INET, SOCK_DGRAM, 0);
300         if (sk < 0)
301                 return FALSE;
302
303         memset(&ifr, 0, sizeof(ifr));
304         ifr.ifr_ifindex = index;
305
306         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0)
307                 goto done;
308
309         snprintf(phy80211_path, PATH_MAX,
310                                 "/sys/class/net/%s/phy80211", ifr.ifr_name);
311
312         if (stat(phy80211_path, &st) == 0 && (st.st_mode & S_IFDIR))
313                 result = TRUE;
314
315 done:
316         close(sk);
317
318         return result;
319 }
320
321 enum connman_device_type __connman_inet_get_device_type(int index)
322 {
323         enum connman_device_type devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
324         unsigned short type = index2type(index);
325         const char *devname;
326         struct ifreq ifr;
327         int sk;
328
329         sk = socket(PF_INET, SOCK_DGRAM, 0);
330         if (sk < 0)
331                 return devtype;
332
333         memset(&ifr, 0, sizeof(ifr));
334         ifr.ifr_ifindex = index;
335
336         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0)
337                 goto done;
338
339         devname = ifr.ifr_name;
340
341         if (type == ARPHRD_ETHER) {
342                 char phy80211_path[PATH_MAX];
343                 char bonding_path[PATH_MAX];
344                 char bridge_path[PATH_MAX];
345                 char wimax_path[PATH_MAX];
346                 struct stat st;
347                 struct iwreq iwr;
348                 char *devnode;
349
350                 snprintf(phy80211_path, PATH_MAX,
351                                         "/sys/class/net/%s/phy80211", devname);
352                 snprintf(bonding_path, PATH_MAX,
353                                         "/sys/class/net/%s/bonding", devname);
354                 snprintf(bridge_path, PATH_MAX,
355                                         "/sys/class/net/%s/bridge", devname);
356                 snprintf(wimax_path, PATH_MAX,
357                                         "/sys/class/net/%s/wimax", devname);
358
359                 memset(&iwr, 0, sizeof(iwr));
360                 strncpy(iwr.ifr_ifrn.ifrn_name, devname, IFNAMSIZ);
361
362                 devnode = __connman_udev_get_mbm_devnode(devname);
363                 if (devnode != NULL) {
364                         devtype = CONNMAN_DEVICE_TYPE_MBM;
365                         g_free(devnode);
366                         goto done;
367                 }
368
369                 if (g_str_has_prefix(devname, "vmnet") == TRUE)
370                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
371                 else if (g_str_has_prefix(ifr.ifr_name, "vboxnet") == TRUE)
372                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
373                 else if (g_str_has_prefix(devname, "bnep") == TRUE)
374                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
375                 else if (g_str_has_prefix(devname, "wmx") == TRUE)
376                         devtype = CONNMAN_DEVICE_TYPE_WIMAX;
377                 else if (stat(wimax_path, &st) == 0 && (st.st_mode & S_IFDIR))
378                         devtype = CONNMAN_DEVICE_TYPE_WIMAX;
379                 else if (stat(bridge_path, &st) == 0 && (st.st_mode & S_IFDIR))
380                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
381                 else if (stat(bonding_path, &st) == 0 && (st.st_mode & S_IFDIR))
382                         devtype = CONNMAN_DEVICE_TYPE_UNKNOWN;
383                 else if (stat(phy80211_path, &st) == 0 && (st.st_mode & S_IFDIR))
384                         devtype = CONNMAN_DEVICE_TYPE_WIFI;
385                 else if (ioctl(sk, SIOCGIWNAME, &iwr) == 0)
386                         devtype = CONNMAN_DEVICE_TYPE_WIFI;
387                 else
388                         devtype = CONNMAN_DEVICE_TYPE_ETHERNET;
389         } else if (type == ARPHRD_NONE) {
390                 if (g_str_has_prefix(devname, "hso") == TRUE)
391                         devtype = CONNMAN_DEVICE_TYPE_HSO;
392         }
393
394 done:
395         close(sk);
396
397         return devtype;
398 }
399
400 struct connman_device *connman_inet_create_device(int index)
401 {
402         enum connman_device_mode mode = CONNMAN_DEVICE_MODE_UNKNOWN;
403         enum connman_device_type type;
404         struct connman_device *device;
405         char *devname, *ident = NULL;
406         char *addr = NULL, *name = NULL, *node = NULL;
407
408         if (index < 0)
409                 return NULL;
410
411         devname = connman_inet_ifname(index);
412         if (devname == NULL)
413                 return NULL;
414
415         __connman_udev_get_devtype(devname);
416
417         type = __connman_inet_get_device_type(index);
418
419         switch (type) {
420         case CONNMAN_DEVICE_TYPE_UNKNOWN:
421                 connman_info("Ignoring network interface %s", devname);
422                 g_free(devname);
423                 return NULL;
424         case CONNMAN_DEVICE_TYPE_ETHERNET:
425         case CONNMAN_DEVICE_TYPE_WIFI:
426         case CONNMAN_DEVICE_TYPE_WIMAX:
427                 name = index2ident(index, "");
428                 addr = index2addr(index);
429                 break;
430         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
431         case CONNMAN_DEVICE_TYPE_GPS:
432         case CONNMAN_DEVICE_TYPE_HSO:
433         case CONNMAN_DEVICE_TYPE_NOZOMI:
434         case CONNMAN_DEVICE_TYPE_HUAWEI:
435         case CONNMAN_DEVICE_TYPE_NOVATEL:
436         case CONNMAN_DEVICE_TYPE_VENDOR:
437                 name = strdup(devname);
438                 break;
439         case CONNMAN_DEVICE_TYPE_MBM:
440                 name = strdup(devname);
441                 addr = index2addr(index);
442                 node = __connman_udev_get_mbm_devnode(devname);
443                 break;
444         }
445
446         device = connman_device_create(name, type);
447         if (device == NULL)
448                 goto done;
449
450         switch (type) {
451         case CONNMAN_DEVICE_TYPE_UNKNOWN:
452         case CONNMAN_DEVICE_TYPE_VENDOR:
453         case CONNMAN_DEVICE_TYPE_NOZOMI:
454         case CONNMAN_DEVICE_TYPE_HUAWEI:
455         case CONNMAN_DEVICE_TYPE_NOVATEL:
456         case CONNMAN_DEVICE_TYPE_GPS:
457                 mode = CONNMAN_DEVICE_MODE_UNKNOWN;
458                 break;
459         case CONNMAN_DEVICE_TYPE_ETHERNET:
460                 mode = CONNMAN_DEVICE_MODE_TRANSPORT_IP;
461                 ident = index2ident(index, NULL);
462                 break;
463         case CONNMAN_DEVICE_TYPE_WIFI:
464         case CONNMAN_DEVICE_TYPE_WIMAX:
465                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
466                 ident = index2ident(index, NULL);
467                 break;
468         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
469                 mode = CONNMAN_DEVICE_MODE_NETWORK_MULTIPLE;
470                 break;
471         case CONNMAN_DEVICE_TYPE_MBM:
472         case CONNMAN_DEVICE_TYPE_HSO:
473                 mode = CONNMAN_DEVICE_MODE_NETWORK_SINGLE;
474                 ident = index2ident(index, NULL);
475                 break;
476         }
477
478         connman_device_set_mode(device, mode);
479
480         connman_device_set_index(device, index);
481         connman_device_set_interface(device, devname, node);
482
483         if (ident != NULL) {
484                 connman_device_set_ident(device, ident);
485                 g_free(ident);
486         }
487
488         connman_device_set_string(device, "Address", addr);
489
490 done:
491         g_free(devname);
492         g_free(node);
493         g_free(name);
494         g_free(addr);
495
496         return device;
497 }
498
499 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
500 {
501         struct ifreq ifr;
502         struct sockaddr_in addr;
503         int sk, err;
504
505         sk = socket(PF_INET, SOCK_DGRAM, 0);
506         if (sk < 0)
507                 return -1;
508
509         memset(&ifr, 0, sizeof(ifr));
510         ifr.ifr_ifindex = index;
511
512         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
513                 close(sk);
514                 return -1;
515         }
516
517         DBG("ifname %s", ifr.ifr_name);
518
519         memset(&addr, 0, sizeof(addr));
520         addr.sin_family = AF_INET;
521         addr.sin_addr.s_addr = inet_addr(ipaddress->local);
522         memcpy(&ifr.ifr_addr, &addr, sizeof(ifr.ifr_addr));
523
524         err = ioctl(sk, SIOCSIFADDR, &ifr);
525
526         if (err < 0)
527                 DBG("address setting failed (%s)", strerror(errno));
528
529         memset(&addr, 0, sizeof(addr));
530         addr.sin_family = AF_INET;
531         addr.sin_addr.s_addr = htonl(~(0xfffffffflu >> ipaddress->prefixlen));
532         memcpy(&ifr.ifr_netmask, &addr, sizeof(ifr.ifr_netmask));
533
534         err = ioctl(sk, SIOCSIFNETMASK, &ifr);
535
536         if (err < 0)
537                 DBG("netmask setting failed (%s)", strerror(errno));
538
539         memset(&addr, 0, sizeof(addr));
540         addr.sin_family = AF_INET;
541         addr.sin_addr.s_addr = inet_addr(ipaddress->broadcast);
542         memcpy(&ifr.ifr_broadaddr, &addr, sizeof(ifr.ifr_broadaddr));
543
544         err = ioctl(sk, SIOCSIFBRDADDR, &ifr);
545
546         if (err < 0)
547                 DBG("broadcast setting failed (%s)", strerror(errno));
548
549         close(sk);
550
551         return 0;
552 }
553
554 int connman_inet_clear_address(int index)
555 {
556         struct ifreq ifr;
557         struct sockaddr_in addr;
558         int sk, err;
559
560         sk = socket(PF_INET, SOCK_DGRAM, 0);
561         if (sk < 0)
562                 return -1;
563
564         memset(&ifr, 0, sizeof(ifr));
565         ifr.ifr_ifindex = index;
566
567         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
568                 close(sk);
569                 return -1;
570         }
571
572         DBG("ifname %s", ifr.ifr_name);
573
574         memset(&addr, 0, sizeof(addr));
575         addr.sin_family = AF_INET;
576         addr.sin_addr.s_addr = INADDR_ANY;
577         memcpy(&ifr.ifr_addr, &addr, sizeof(ifr.ifr_addr));
578
579         //err = ioctl(sk, SIOCDIFADDR, &ifr);
580         err = ioctl(sk, SIOCSIFADDR, &ifr);
581
582         close(sk);
583
584         if (err < 0 && errno != EADDRNOTAVAIL) {
585                 DBG("address removal failed (%s)", strerror(errno));
586                 return -1;
587         }
588
589         return 0;
590 }
591
592 int connman_inet_set_gateway(int index, struct in_addr gateway)
593 {
594         struct ifreq ifr;
595         struct rtentry rt;
596         struct sockaddr_in addr;
597         int sk, err;
598
599         sk = socket(PF_INET, SOCK_DGRAM, 0);
600         if (sk < 0)
601                 return -1;
602
603         memset(&ifr, 0, sizeof(ifr));
604         ifr.ifr_ifindex = index;
605
606         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
607                 close(sk);
608                 return -1;
609         }
610
611         DBG("ifname %s", ifr.ifr_name);
612
613         memset(&rt, 0, sizeof(rt));
614         rt.rt_flags = RTF_UP | RTF_HOST;
615
616         memset(&addr, 0, sizeof(addr));
617         addr.sin_family = AF_INET;
618         addr.sin_addr = gateway;
619         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
620
621         memset(&addr, 0, sizeof(addr));
622         addr.sin_family = AF_INET;
623         addr.sin_addr.s_addr = INADDR_ANY;
624         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
625
626         memset(&addr, 0, sizeof(addr));
627         addr.sin_family = AF_INET;
628         addr.sin_addr.s_addr = INADDR_ANY;
629         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
630
631         rt.rt_dev = ifr.ifr_name;
632
633         err = ioctl(sk, SIOCADDRT, &rt);
634         if (err < 0)
635                 connman_error("Setting host gateway route failed (%s)",
636                                                         strerror(errno));
637
638         memset(&rt, 0, sizeof(rt));
639         rt.rt_flags = RTF_UP | RTF_GATEWAY;
640
641         memset(&addr, 0, sizeof(addr));
642         addr.sin_family = AF_INET;
643         addr.sin_addr.s_addr = INADDR_ANY;
644         memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
645
646         memset(&addr, 0, sizeof(addr));
647         addr.sin_family = AF_INET;
648         addr.sin_addr = gateway;
649         memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
650
651         memset(&addr, 0, sizeof(addr));
652         addr.sin_family = AF_INET;
653         addr.sin_addr.s_addr = INADDR_ANY;
654         memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
655
656         err = ioctl(sk, SIOCADDRT, &rt);
657         if (err < 0)
658                 connman_error("Setting default route failed (%s)",
659                                                         strerror(errno));
660
661         close(sk);
662
663         return err;
664 }