Fix network out of range detection
[platform/upstream/connman.git] / plugins / 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/ioctl.h>
32 #include <sys/socket.h>
33 #include <net/if.h>
34 #include <net/ethernet.h>
35
36 #include "inet.h"
37
38 int inet_name2index(const char *name)
39 {
40         struct ifreq ifr;
41         int sk, err;
42
43         if (name == NULL)
44                 return -1;
45
46         sk = socket(PF_INET, SOCK_DGRAM, 0);
47         if (sk < 0)
48                 return -1;
49
50         memset(&ifr, 0, sizeof(ifr));
51         strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
52
53         err = ioctl(sk, SIOCGIFINDEX, &ifr);
54
55         close(sk);
56
57         if (err < 0)
58                 return -1;
59
60         return ifr.ifr_ifindex;
61 }
62
63 char *inet_index2name(int index)
64 {
65         struct ifreq ifr;
66         int sk, err;
67
68         if (index < 0)
69                 return NULL;
70
71         sk = socket(PF_INET, SOCK_DGRAM, 0);
72         if (sk < 0)
73                 return NULL;
74
75         memset(&ifr, 0, sizeof(ifr));
76         ifr.ifr_ifindex = index;
77
78         err = ioctl(sk, SIOCGIFNAME, &ifr);
79
80         close(sk);
81
82         if (err < 0)
83                 return NULL;
84
85         return strdup(ifr.ifr_name);
86 }
87
88 char *inet_index2ident(int index, const char *prefix)
89 {
90         struct ifreq ifr;
91         struct ether_addr *eth;
92         char *str;
93         int sk, err, len;
94
95         if (index < 0)
96                 return NULL;
97
98         sk = socket(PF_INET, SOCK_DGRAM, 0);
99         if (sk < 0)
100                 return NULL;
101
102         memset(&ifr, 0, sizeof(ifr));
103         ifr.ifr_ifindex = index;
104
105         err = ioctl(sk, SIOCGIFNAME, &ifr);
106
107         if (err == 0)
108                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
109
110         close(sk);
111
112         if (err < 0)
113                 return NULL;
114
115         len = prefix ? strlen(prefix) + 18 : 18;
116
117         str = malloc(len);
118         if (!str)
119                 return NULL;
120
121         eth = (void *) &ifr.ifr_hwaddr.sa_data;
122         snprintf(str, len, "%s%02X_%02X_%02X_%02X_%02X_%02X",
123                                                 prefix ? prefix : "",
124                                                 eth->ether_addr_octet[0],
125                                                 eth->ether_addr_octet[1],
126                                                 eth->ether_addr_octet[2],
127                                                 eth->ether_addr_octet[3],
128                                                 eth->ether_addr_octet[4],
129                                                 eth->ether_addr_octet[5]);
130
131         return str;
132 }
133
134 int inet_ifup(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                 goto done;
166         }
167
168         err = 0;
169
170 done:
171         close(sk);
172
173         return err;
174 }
175
176 int inet_ifdown(int index)
177 {
178         struct ifreq ifr;
179         int sk, err;
180
181         sk = socket(PF_INET, SOCK_DGRAM, 0);
182         if (sk < 0)
183                 return -errno;
184
185         memset(&ifr, 0, sizeof(ifr));
186         ifr.ifr_ifindex = index;
187
188         if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
189                 err = -errno;
190                 goto done;
191         }
192
193         if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
194                 err = -errno;
195                 goto done;
196         }
197
198         if (!(ifr.ifr_flags & IFF_UP)) {
199                 err = -EALREADY;
200                 goto done;
201         }
202
203         ifr.ifr_flags &= ~IFF_UP;
204
205         if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0)
206                 err = -errno;
207         else
208                 err = 0;
209
210 done:
211         close(sk);
212
213         return err;
214 }