aboutsummaryrefslogtreecommitdiffstats
path: root/src/fnet/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fnet/interface.c')
-rw-r--r--src/fnet/interface.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/fnet/interface.c b/src/fnet/interface.c
new file mode 100644
index 000000000..b1903dd46
--- /dev/null
+++ b/src/fnet/interface.c
@@ -0,0 +1,183 @@
1 /*
2 * Copyright (C) 2014-2016 Firejail Authors
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
21#include "fnet.h"
22#include <arpa/inet.h>
23#include <sys/socket.h>
24#include <sys/ioctl.h>
25#include <netdb.h>
26#include <ifaddrs.h>
27#include <net/if.h>
28#include <net/if_arp.h>
29#include <net/route.h>
30#include <linux/if_bridge.h>
31
32// add a veth device to a bridge
33void net_bridge_add_interface(const char *bridge, const char *dev) {
34 if (strlen(bridge) > IFNAMSIZ) {
35 fprintf(stderr, "Error fnet: invalid network device name %s\n", bridge);
36 exit(1);
37 }
38
39 // somehow adding the interface to the bridge resets MTU on bridge device!!!
40 // workaround: restore MTU on the bridge device
41 // todo: put a real fix in
42 int mtu1 = net_get_mtu(bridge);
43
44 struct ifreq ifr;
45 int err;
46 int ifindex = if_nametoindex(dev);
47
48 if (ifindex <= 0)
49 errExit("if_nametoindex");
50
51 int sock;
52 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
53 errExit("socket");
54
55 memset(&ifr, 0, sizeof(ifr));
56 strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
57#ifdef SIOCBRADDIF
58 ifr.ifr_ifindex = ifindex;
59 err = ioctl(sock, SIOCBRADDIF, &ifr);
60 if (err < 0)
61#endif
62 {
63 unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
64
65 ifr.ifr_data = (char *) args;
66 err = ioctl(sock, SIOCDEVPRIVATE, &ifr);
67 }
68 (void) err;
69 close(sock);
70
71 int mtu2 = net_get_mtu(bridge);
72 if (mtu1 != mtu2) {
73 net_set_mtu(bridge, mtu1);
74 }
75}
76
77
78// bring interface up
79void net_if_up(const char *ifname) {
80 if (strlen(ifname) > IFNAMSIZ) {
81 fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname);
82 exit(1);
83 }
84
85 int sock = socket(AF_INET,SOCK_DGRAM,0);
86 if (sock < 0)
87 errExit("socket");
88
89 // get the existing interface flags
90 struct ifreq ifr;
91 memset(&ifr, 0, sizeof(ifr));
92 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
93 ifr.ifr_addr.sa_family = AF_INET;
94
95 // read the existing flags
96 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
97 close(sock);
98 printf("Error fnet: cannot bring up interface %s\n", ifname);
99 errExit("ioctl");
100 }
101
102 ifr.ifr_flags |= IFF_UP;
103
104 // set the new flags
105 if (ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0) {
106 close(sock);
107 printf("Error fnet: cannot bring up interface %s\n", ifname);
108 errExit("ioctl");
109 }
110
111 // checking
112 // read the existing flags
113 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
114 close(sock);
115 printf("Error fnet: cannot bring up interface %s\n", ifname);
116 errExit("ioctl");
117 }
118
119 // wait not more than 500ms for the interface to come up
120 int cnt = 0;
121 while (cnt < 50) {
122 usleep(10000); // sleep 10ms
123
124 // read the existing flags
125 if (ioctl(sock, SIOCGIFFLAGS, &ifr ) < 0) {
126 close(sock);
127 printf("Error fnet: cannot bring up interface %s\n", ifname);
128 errExit("ioctl");
129 }
130 if (ifr.ifr_flags & IFF_RUNNING)
131 break;
132 cnt++;
133 }
134
135 close(sock);
136}
137
138int net_get_mtu(const char *ifname) {
139 int mtu = 0;
140 if (strlen(ifname) > IFNAMSIZ) {
141 fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname);
142 exit(1);
143 }
144
145 int s;
146 struct ifreq ifr;
147
148 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
149 errExit("socket");
150
151 memset(&ifr, 0, sizeof(ifr));
152 ifr.ifr_addr.sa_family = AF_INET;
153 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
154 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == 0)
155 mtu = ifr.ifr_mtu;
156 close(s);
157
158
159 return mtu;
160}
161
162void net_set_mtu(const char *ifname, int mtu) {
163 if (strlen(ifname) > IFNAMSIZ) {
164 fprintf(stderr, "Error fnet: invalid network device name %s\n", ifname);
165 exit(1);
166 }
167
168 int s;
169 struct ifreq ifr;
170
171 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
172 errExit("socket");
173
174 memset(&ifr, 0, sizeof(ifr));
175 ifr.ifr_addr.sa_family = AF_INET;
176 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
177 ifr.ifr_mtu = mtu;
178 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) != 0)
179 fprintf(stderr, "Warning fnet: cannot set mtu for interface %s\n", ifname);
180 close(s);
181}
182
183