diff options
author | 2016-01-11 19:52:15 -0500 | |
---|---|---|
committer | 2016-01-11 19:52:15 -0500 | |
commit | e669dbee639c4956430bc90345e1f05687c9d50a (patch) | |
tree | 233d0ffca44049d9940f60f35bac74eb3e5db723 /src/firejail/network.c | |
parent | fixed minimum mtu (diff) | |
download | firejail-e669dbee639c4956430bc90345e1f05687c9d50a.tar.gz firejail-e669dbee639c4956430bc90345e1f05687c9d50a.tar.zst firejail-e669dbee639c4956430bc90345e1f05687c9d50a.zip |
IPv6 support
Diffstat (limited to 'src/firejail/network.c')
-rw-r--r-- | src/firejail/network.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/src/firejail/network.c b/src/firejail/network.c index ece406fc8..72bc5e7c6 100644 --- a/src/firejail/network.c +++ b/src/firejail/network.c | |||
@@ -274,7 +274,75 @@ void net_if_down(const char *ifname) { | |||
274 | close(sock); | 274 | close(sock); |
275 | } | 275 | } |
276 | 276 | ||
277 | // configure interface | 277 | struct ifreq6 { |
278 | struct in6_addr ifr6_addr; | ||
279 | uint32_t ifr6_prefixlen; | ||
280 | unsigned int ifr6_ifindex; | ||
281 | }; | ||
282 | // configure interface ipv6 address | ||
283 | // ex: firejail --net=eth0 --ip6=2001:0db8:0:f101::1/64 | ||
284 | void net_if_ip6(const char *ifname, const char *addr6) { | ||
285 | if (strchr(addr6, ':') == NULL) { | ||
286 | fprintf(stderr, "Error: invalid IPv6 address %s\n", addr6); | ||
287 | exit(1); | ||
288 | } | ||
289 | |||
290 | // extract prefix | ||
291 | unsigned long prefix; | ||
292 | char *ptr; | ||
293 | if ((ptr = strchr(addr6, '/'))) { | ||
294 | prefix = atol(ptr + 1); | ||
295 | if ((prefix < 0) || (prefix > 128)) { | ||
296 | fprintf(stderr, "Error: invalid prefix for IPv6 address %s\n", addr6); | ||
297 | exit(1); | ||
298 | } | ||
299 | *ptr = '\0'; // mark the end of the address | ||
300 | } | ||
301 | else | ||
302 | prefix = 128; | ||
303 | |||
304 | // extract address | ||
305 | struct sockaddr_in6 sin6; | ||
306 | memset(&sin6, 0, sizeof(sin6)); | ||
307 | sin6.sin6_family = AF_INET6; | ||
308 | int rv = inet_pton(AF_INET6, addr6, sin6.sin6_addr.s6_addr); | ||
309 | if (rv <= 0) { | ||
310 | fprintf(stderr, "Error: invalid IPv6 address %s\n", addr6); | ||
311 | exit(1); | ||
312 | } | ||
313 | |||
314 | // open socket | ||
315 | int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP); | ||
316 | if (sock < 0) { | ||
317 | fprintf(stderr, "Error: IPv6 is not supported on this system\n"); | ||
318 | exit(1); | ||
319 | } | ||
320 | |||
321 | // find interface index | ||
322 | struct ifreq ifr; | ||
323 | memset(&ifr, 0, sizeof(ifr)); | ||
324 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
325 | ifr.ifr_addr.sa_family = AF_INET; | ||
326 | if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) { | ||
327 | perror("ioctl SIOGIFINDEX"); | ||
328 | exit(1); | ||
329 | } | ||
330 | |||
331 | // configure address | ||
332 | struct ifreq6 ifr6; | ||
333 | memset(&ifr6, 0, sizeof(ifr6)); | ||
334 | ifr6.ifr6_prefixlen = prefix; | ||
335 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; | ||
336 | memcpy((char *) &ifr6.ifr6_addr, (char *) &sin6.sin6_addr, sizeof(struct in6_addr)); | ||
337 | if (ioctl(sock, SIOCSIFADDR, &ifr6) < 0) { | ||
338 | perror("ioctl SIOCSIFADDR"); | ||
339 | exit(1); | ||
340 | } | ||
341 | |||
342 | close(sock); | ||
343 | } | ||
344 | |||
345 | // configure interface ipv4 address | ||
278 | void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu) { | 346 | void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu) { |
279 | if (strlen(ifname) > IFNAMSIZ) { | 347 | if (strlen(ifname) > IFNAMSIZ) { |
280 | fprintf(stderr, "Error: invalid network device name %s\n", ifname); | 348 | fprintf(stderr, "Error: invalid network device name %s\n", ifname); |