aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/network.c
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2015-08-08 19:12:30 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2015-08-08 19:12:30 -0400
commit1379851360349d6617ad32944a25ee5e2bb74fc2 (patch)
treef69b48e90708bfa3c2723d5a27ed3e024c827b43 /src/firejail/network.c
parentdelete files (diff)
downloadfirejail-1379851360349d6617ad32944a25ee5e2bb74fc2.tar.gz
firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.tar.zst
firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.zip
Baseline firejail 0.9.28
Diffstat (limited to 'src/firejail/network.c')
-rw-r--r--src/firejail/network.c362
1 files changed, 362 insertions, 0 deletions
diff --git a/src/firejail/network.c b/src/firejail/network.c
new file mode 100644
index 000000000..6a1d52744
--- /dev/null
+++ b/src/firejail/network.c
@@ -0,0 +1,362 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20#include "firejail.h"
21#include <arpa/inet.h>
22#include <sys/socket.h>
23#include <sys/ioctl.h>
24#include <netdb.h>
25#include <ifaddrs.h>
26#include <net/if.h>
27#include <net/if_arp.h>
28#include <net/route.h>
29#include <linux/if_bridge.h>
30
31// scan interfaces in current namespace and print IP address/mask for each interface
32void net_ifprint(void) {
33 uint32_t ip;
34 uint32_t mask;
35 struct ifaddrs *ifaddr, *ifa;
36
37 if (getifaddrs(&ifaddr) == -1)
38 errExit("getifaddrs");
39
40 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
41 "Interface", "MAC", "IP", "Mask", "Status");
42 // walk through the linked list
43 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
44 if (ifa->ifa_addr == NULL)
45 continue;
46
47 if (ifa->ifa_addr->sa_family == AF_INET) {
48 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
49 mask = ntohl(si->sin_addr.s_addr);
50 si = (struct sockaddr_in *) ifa->ifa_addr;
51 ip = ntohl(si->sin_addr.s_addr);
52
53 // interface status
54 char *status;
55 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
56 status = "UP";
57 else
58 status = "DOWN";
59
60 // ip address and mask
61 char ipstr[30];
62 sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip));
63 char maskstr[30];
64 sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask));
65
66 // mac address
67 unsigned char mac[6];
68 net_get_mac(ifa->ifa_name, mac);
69 char macstr[30];
70 if (strcmp(ifa->ifa_name, "lo") == 0)
71 macstr[0] = '\0';
72 else
73 sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac));
74
75 // print
76 printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
77 ifa->ifa_name, macstr, ipstr, maskstr, status);
78
79 // network scanning
80 if (!arg_scan) // scanning disabled
81 continue;
82 if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning
83 continue;
84 if (mask2bits(mask) < 16) // not scanning large networks
85 continue;
86 if (!ip) // if not configured
87 continue;
88 // only if the interface is up and running
89 if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
90 arp_scan(ifa->ifa_name, ip, mask);
91 }
92 }
93 freeifaddrs(ifaddr);
94}
95
96
97// return -1 if the interface was not found; if the interface was found retrn 0 and fill in IP address and mask
98int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6]) {
99 assert(bridge);
100 assert(ip);
101 assert(mask);
102 int rv = -1;
103 struct ifaddrs *ifaddr, *ifa;
104
105 if (getifaddrs(&ifaddr) == -1)
106 errExit("getifaddrs");
107
108 // walk through the linked list; if the interface is found, extract IP address and mask
109 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
110 if (ifa->ifa_addr == NULL)
111 continue;
112 if (strcmp(ifa->ifa_name, bridge) != 0)
113 continue;
114
115 if (ifa->ifa_addr->sa_family == AF_INET) {
116 struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
117 *mask = ntohl(si->sin_addr.s_addr);
118 si = (struct sockaddr_in *) ifa->ifa_addr;
119 *ip = ntohl(si->sin_addr.s_addr);
120 if (strcmp(ifa->ifa_name, "lo") != 0)
121 net_get_mac(ifa->ifa_name, mac);
122
123 rv = 0;
124 break;
125 }
126 }
127
128 freeifaddrs(ifaddr);
129 return rv;
130}
131
132// bring interface up
133void net_if_up(const char *ifname) {
134 if (strlen(ifname) > IFNAMSIZ) {
135 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
136 exit(1);
137 }
138
139 int sock = socket(AF_INET,SOCK_DGRAM,0);
140 if (sock < 0)
141 errExit("socket");
142
143 // get the existing interface flags
144 struct ifreq ifr;
145 memset(&ifr, 0, sizeof(ifr));
146 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
147 ifr.ifr_addr.sa_family = AF_INET;
148
149 // read the existing flags
150 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
151 close(sock);
152 errExit("ioctl");
153 }
154
155 ifr.ifr_flags |= IFF_UP;
156
157 // set the new flags
158 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
159 close(sock);
160 errExit("ioctl");
161 }
162
163 // checking
164 // read the existing flags
165 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
166 close(sock);
167 errExit("ioctl");
168 }
169
170 // wait not more than 500ms for the interface to come up
171 int cnt = 0;
172 while (cnt < 50) {
173 usleep(10000); // sleep 10ms
174
175 // read the existing flags
176 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
177 close(sock);
178 errExit("ioctl");
179 }
180 if (ifr.ifr_flags & IFF_RUNNING)
181 break;
182 cnt++;
183 }
184
185 close(sock);
186}
187
188// configure interface
189void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask) {
190 if (strlen(ifname) > IFNAMSIZ) {
191 fprintf(stderr, "Error: invalid network device name %s\n", ifname);
192 exit(1);
193 }
194
195 int sock = socket(AF_INET,SOCK_DGRAM,0);
196 if (sock < 0)
197 errExit("socket");
198
199 struct ifreq ifr;
200 memset(&ifr, 0, sizeof(ifr));
201 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
202 ifr.ifr_addr.sa_family = AF_INET;
203
204 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip);
205 if (ioctl( sock, SIOCSIFADDR, &ifr ) < 0) {
206 close(sock);
207 errExit("ioctl");
208 }
209
210 if (ip != 0) {
211 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(mask);
212 if (ioctl( sock, SIOCSIFNETMASK, &ifr ) < 0) {
213 close(sock);
214 errExit("ioctl");
215 }
216 }
217
218 close(sock);
219 usleep(10000); // sleep 10ms
220}
221
222
223// add an IP route, return -1 if error, 0 if the route was added
224int net_add_route(uint32_t ip, uint32_t mask, uint32_t gw) {
225 int sock;
226 struct rtentry route;
227 struct sockaddr_in *addr;
228 int err = 0;
229
230 // create the socket
231 if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
232 errExit("socket");
233
234 memset(&route, 0, sizeof(route));
235
236 addr = (struct sockaddr_in*) &route.rt_gateway;
237 addr->sin_family = AF_INET;
238 addr->sin_addr.s_addr = htonl(gw);
239
240 addr = (struct sockaddr_in*) &route.rt_dst;
241 addr->sin_family = AF_INET;
242 addr->sin_addr.s_addr = htonl(ip);
243
244 addr = (struct sockaddr_in*) &route.rt_genmask;
245 addr->sin_family = AF_INET;
246 addr->sin_addr.s_addr = htonl(mask);
247
248 route.rt_flags = RTF_UP | RTF_GATEWAY;
249 route.rt_metric = 0;
250 if ((err = ioctl(sock, SIOCADDRT, &route)) != 0) {
251 close(sock);
252 return -1;
253 }
254
255 close(sock);
256 return 0;
257}
258
259
260// add a veth device to a bridge
261void net_bridge_add_interface(const char *bridge, const char *dev) {
262 if (strlen(bridge) > IFNAMSIZ) {
263 fprintf(stderr, "Error: invalid network device name %s\n", bridge);
264 exit(1);
265 }
266
267 struct ifreq ifr;
268 int err;
269 int ifindex = if_nametoindex(dev);
270
271 if (ifindex <= 0)
272 errExit("if_nametoindex");
273
274 int sock;
275 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
276 errExit("socket");
277
278 memset(&ifr, 0, sizeof(ifr));
279 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
280#ifdef SIOCBRADDIF
281 ifr.ifr_ifindex = ifindex;
282 err = ioctl(sock, SIOCBRADDIF, &ifr);
283 if (err < 0)
284#endif
285 {
286 unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
287
288 ifr.ifr_data = (char *) args;
289 err = ioctl(sock, SIOCDEVPRIVATE, &ifr);
290 }
291 (void) err;
292 close(sock);
293}
294
295#define BUFSIZE 1024
296uint32_t network_get_defaultgw(void) {
297 FILE *fp = fopen("/proc/self/net/route", "r");
298 if (!fp)
299 errExit("fopen");
300
301 char buf[BUFSIZE];
302 uint32_t retval = 0;
303 while (fgets(buf, BUFSIZE, fp)) {
304 if (strncmp(buf, "Iface", 5) == 0)
305 continue;
306
307 char *ptr = buf;
308 while (*ptr != ' ' && *ptr != '\t')
309 ptr++;
310 while (*ptr == ' ' || *ptr == '\t')
311 ptr++;
312
313 unsigned dest;
314 unsigned gw;
315 int rv = sscanf(ptr, "%x %x", &dest, &gw);
316 if (rv == 2 && dest == 0) {
317 retval = ntohl(gw);
318 break;
319 }
320 }
321
322 fclose(fp);
323 return retval;
324}
325
326int net_config_mac(const char *ifname, const unsigned char mac[6]) {
327 struct ifreq ifr;
328 int sock;
329
330 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
331 errExit("socket");
332
333 memset(&ifr, 0, sizeof(ifr));
334 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
335 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
336 memcpy(ifr.ifr_hwaddr.sa_data, mac, 6);
337
338 if (ioctl(sock, SIOCSIFHWADDR, &ifr) == -1)
339 errExit("ioctl");
340 close(sock);
341 return 0;
342}
343
344int net_get_mac(const char *ifname, unsigned char mac[6]) {
345
346 struct ifreq ifr;
347 int sock;
348
349 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
350 errExit("socket");
351
352 memset(&ifr, 0, sizeof(ifr));
353 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
354 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
355
356 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1)
357 errExit("ioctl");
358 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
359
360 close(sock);
361 return 0;
362}