diff options
Diffstat (limited to 'src/fnet')
-rw-r--r-- | src/fnet/arp.c | 208 | ||||
-rw-r--r-- | src/fnet/fnet.h | 9 | ||||
-rw-r--r-- | src/fnet/interface.c | 212 | ||||
-rw-r--r-- | src/fnet/main.c | 39 |
4 files changed, 465 insertions, 3 deletions
diff --git a/src/fnet/arp.c b/src/fnet/arp.c new file mode 100644 index 000000000..96684fdf9 --- /dev/null +++ b/src/fnet/arp.c | |||
@@ -0,0 +1,208 @@ | |||
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 | #include "fnet.h" | ||
21 | #include <sys/socket.h> | ||
22 | #include <sys/ioctl.h> | ||
23 | #include <linux/if_ether.h> //TCP/IP Protocol Suite for Linux | ||
24 | #include <net/if.h> | ||
25 | #include <netinet/in.h> | ||
26 | #include <linux/ip.h> | ||
27 | #include <linux/udp.h> | ||
28 | #include <linux/tcp.h> | ||
29 | #include <linux/if_packet.h> | ||
30 | |||
31 | typedef struct arp_hdr_t { | ||
32 | uint16_t htype; | ||
33 | uint16_t ptype; | ||
34 | uint8_t hlen; | ||
35 | uint8_t plen; | ||
36 | uint16_t opcode; | ||
37 | uint8_t sender_mac[6]; | ||
38 | uint8_t sender_ip[4]; | ||
39 | uint8_t target_mac[6]; | ||
40 | uint8_t target_ip[4]; | ||
41 | } ArpHdr; | ||
42 | |||
43 | |||
44 | // scan interface (--scan option) | ||
45 | void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) { | ||
46 | assert(dev); | ||
47 | assert(ifip); | ||
48 | |||
49 | // printf("Scanning interface %s (%d.%d.%d.%d/%d)\n", | ||
50 | // dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask)); | ||
51 | |||
52 | if (strlen(dev) > IFNAMSIZ) { | ||
53 | fprintf(stderr, "Error: invalid network device name %s\n", dev); | ||
54 | exit(1); | ||
55 | } | ||
56 | |||
57 | // find interface mac address | ||
58 | int sock; | ||
59 | if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) | ||
60 | errExit("socket"); | ||
61 | struct ifreq ifr; | ||
62 | memset(&ifr, 0, sizeof (ifr)); | ||
63 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); | ||
64 | if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) | ||
65 | errExit("ioctl"); | ||
66 | close(sock); | ||
67 | uint8_t mac[6]; | ||
68 | memcpy (mac, ifr.ifr_hwaddr.sa_data, 6); | ||
69 | |||
70 | // open layer2 socket | ||
71 | if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) | ||
72 | errExit("socket"); | ||
73 | |||
74 | // try all possible ip addresses in ascending order | ||
75 | uint32_t range = ~ifmask + 1; // the number of potential addresses | ||
76 | // this software is not supported for /31 networks | ||
77 | if (range < 4) { | ||
78 | fprintf(stderr, "Warning: this option is not supported for /31 networks\n"); | ||
79 | close(sock); | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | uint32_t dest = (ifip & ifmask) + 1; | ||
84 | uint32_t last = dest + range - 1; | ||
85 | uint32_t src = htonl(ifip); | ||
86 | |||
87 | // wait not more than one second for an answer | ||
88 | int header_printed = 0; | ||
89 | uint32_t last_ip = 0; | ||
90 | struct timeval ts; | ||
91 | ts.tv_sec = 2; // 2 seconds receive timeout | ||
92 | ts.tv_usec = 0; | ||
93 | |||
94 | while (1) { | ||
95 | fd_set rfds; | ||
96 | FD_ZERO(&rfds); | ||
97 | FD_SET(sock, &rfds); | ||
98 | fd_set wfds; | ||
99 | FD_ZERO(&wfds); | ||
100 | FD_SET(sock, &wfds); | ||
101 | int maxfd = sock; | ||
102 | |||
103 | uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc | ||
104 | memset(frame, 0, ETH_FRAME_LEN); | ||
105 | |||
106 | int nready; | ||
107 | if (dest < last) | ||
108 | nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL); | ||
109 | else | ||
110 | nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts); | ||
111 | |||
112 | if (nready < 0) | ||
113 | errExit("select"); | ||
114 | |||
115 | if (nready == 0) { // timeout | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | if (FD_ISSET(sock, &wfds) && dest < last) { | ||
120 | // configure layer2 socket address information | ||
121 | struct sockaddr_ll addr; | ||
122 | memset(&addr, 0, sizeof(addr)); | ||
123 | if ((addr.sll_ifindex = if_nametoindex(dev)) == 0) | ||
124 | errExit("if_nametoindex"); | ||
125 | addr.sll_family = AF_PACKET; | ||
126 | memcpy (addr.sll_addr, mac, 6); | ||
127 | addr.sll_halen = htons(6); | ||
128 | |||
129 | // build the arp packet header | ||
130 | ArpHdr hdr; | ||
131 | memset(&hdr, 0, sizeof(hdr)); | ||
132 | hdr.htype = htons(1); | ||
133 | hdr.ptype = htons(ETH_P_IP); | ||
134 | hdr.hlen = 6; | ||
135 | hdr.plen = 4; | ||
136 | hdr.opcode = htons(1); //ARPOP_REQUEST | ||
137 | memcpy(hdr.sender_mac, mac, 6); | ||
138 | memcpy(hdr.sender_ip, (uint8_t *)&src, 4); | ||
139 | uint32_t dst = htonl(dest); | ||
140 | memcpy(hdr.target_ip, (uint8_t *)&dst, 4); | ||
141 | |||
142 | // build ethernet frame | ||
143 | uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc | ||
144 | memset(frame, 0, sizeof(frame)); | ||
145 | frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff; | ||
146 | memcpy(frame + 6, mac, 6); | ||
147 | frame[12] = ETH_P_ARP / 256; | ||
148 | frame[13] = ETH_P_ARP % 256; | ||
149 | memcpy (frame + 14, &hdr, sizeof(hdr)); | ||
150 | |||
151 | // send packet | ||
152 | int len; | ||
153 | if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0) | ||
154 | errExit("send"); | ||
155 | //printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest)); | ||
156 | fflush(0); | ||
157 | dest++; | ||
158 | } | ||
159 | |||
160 | if (FD_ISSET(sock, &rfds)) { | ||
161 | // read the incoming packet | ||
162 | int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL); | ||
163 | if (len < 0) { | ||
164 | perror("recvfrom"); | ||
165 | } | ||
166 | |||
167 | // parse the incoming packet | ||
168 | if ((unsigned int) len < 14 + sizeof(ArpHdr)) | ||
169 | continue; | ||
170 | |||
171 | // look only at ARP packets | ||
172 | if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256)) | ||
173 | continue; | ||
174 | |||
175 | ArpHdr hdr; | ||
176 | memcpy(&hdr, frame + 14, sizeof(ArpHdr)); | ||
177 | |||
178 | if (hdr.opcode == htons(2)) { | ||
179 | // check my mac and my address | ||
180 | if (memcmp(mac, hdr.target_mac, 6) != 0) | ||
181 | continue; | ||
182 | uint32_t ip; | ||
183 | memcpy(&ip, hdr.target_ip, 4); | ||
184 | if (ip != src) | ||
185 | continue; | ||
186 | memcpy(&ip, hdr.sender_ip, 4); | ||
187 | ip = ntohl(ip); | ||
188 | |||
189 | if (ip == last_ip) // filter duplicates | ||
190 | continue; | ||
191 | last_ip = ip; | ||
192 | |||
193 | // printing | ||
194 | if (header_printed == 0) { | ||
195 | printf(" Network scan:\n"); | ||
196 | header_printed = 1; | ||
197 | } | ||
198 | printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n", | ||
199 | PRINT_MAC(hdr.sender_mac), PRINT_IP(ip)); | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | |||
204 | close(sock); | ||
205 | } | ||
206 | |||
207 | |||
208 | |||
diff --git a/src/fnet/fnet.h b/src/fnet/fnet.h index 58efbbed5..0c5e5baef 100644 --- a/src/fnet/fnet.h +++ b/src/fnet/fnet.h | |||
@@ -36,5 +36,14 @@ void net_bridge_add_interface(const char *bridge, const char *dev); | |||
36 | void net_if_up(const char *ifname); | 36 | void net_if_up(const char *ifname); |
37 | int net_get_mtu(const char *ifname); | 37 | int net_get_mtu(const char *ifname); |
38 | void net_set_mtu(const char *ifname, int mtu); | 38 | void net_set_mtu(const char *ifname, int mtu); |
39 | void net_ifprint(int scan); | ||
40 | int net_get_mac(const char *ifname, unsigned char mac[6]); | ||
41 | void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu); | ||
42 | int net_if_mac(const char *ifname, const unsigned char mac[6]); | ||
43 | void net_if_ip6(const char *ifname, const char *addr6); | ||
44 | |||
45 | |||
46 | // arp.c | ||
47 | void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask); | ||
39 | 48 | ||
40 | #endif | 49 | #endif |
diff --git a/src/fnet/interface.c b/src/fnet/interface.c index b1903dd46..67af062bf 100644 --- a/src/fnet/interface.c +++ b/src/fnet/interface.c | |||
@@ -180,4 +180,216 @@ void net_set_mtu(const char *ifname, int mtu) { | |||
180 | close(s); | 180 | close(s); |
181 | } | 181 | } |
182 | 182 | ||
183 | // scan interfaces in current namespace and print IP address/mask for each interface | ||
184 | void net_ifprint(int scan) { | ||
185 | uint32_t ip; | ||
186 | uint32_t mask; | ||
187 | struct ifaddrs *ifaddr, *ifa; | ||
183 | 188 | ||
189 | if (getifaddrs(&ifaddr) == -1) | ||
190 | errExit("getifaddrs"); | ||
191 | |||
192 | printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n", | ||
193 | "Interface", "MAC", "IP", "Mask", "Status"); | ||
194 | // walk through the linked list | ||
195 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | ||
196 | if (ifa->ifa_addr == NULL) | ||
197 | continue; | ||
198 | |||
199 | if (ifa->ifa_addr->sa_family == AF_INET) { | ||
200 | struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask; | ||
201 | mask = ntohl(si->sin_addr.s_addr); | ||
202 | si = (struct sockaddr_in *) ifa->ifa_addr; | ||
203 | ip = ntohl(si->sin_addr.s_addr); | ||
204 | |||
205 | // interface status | ||
206 | char *status; | ||
207 | if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) | ||
208 | status = "UP"; | ||
209 | else | ||
210 | status = "DOWN"; | ||
211 | |||
212 | // ip address and mask | ||
213 | char ipstr[30]; | ||
214 | sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip)); | ||
215 | char maskstr[30]; | ||
216 | sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask)); | ||
217 | |||
218 | // mac address | ||
219 | unsigned char mac[6]; | ||
220 | net_get_mac(ifa->ifa_name, mac); | ||
221 | char macstr[30]; | ||
222 | if (strcmp(ifa->ifa_name, "lo") == 0) | ||
223 | macstr[0] = '\0'; | ||
224 | else | ||
225 | sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac)); | ||
226 | |||
227 | |||
228 | printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n", | ||
229 | ifa->ifa_name, macstr, ipstr, maskstr, status); | ||
230 | |||
231 | // network scanning | ||
232 | if (!scan) // scanning disabled | ||
233 | continue; | ||
234 | if (strcmp(ifa->ifa_name, "lo") == 0) // no loopbabck scanning | ||
235 | continue; | ||
236 | if (mask2bits(mask) < 16) // not scanning large networks | ||
237 | continue; | ||
238 | if (!ip) // if not configured | ||
239 | continue; | ||
240 | // only if the interface is up and running | ||
241 | if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) | ||
242 | arp_scan(ifa->ifa_name, ip, mask); | ||
243 | } | ||
244 | } | ||
245 | freeifaddrs(ifaddr); | ||
246 | } | ||
247 | |||
248 | int net_get_mac(const char *ifname, unsigned char mac[6]) { | ||
249 | |||
250 | struct ifreq ifr; | ||
251 | int sock; | ||
252 | |||
253 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) | ||
254 | errExit("socket"); | ||
255 | |||
256 | memset(&ifr, 0, sizeof(ifr)); | ||
257 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
258 | ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; | ||
259 | |||
260 | if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) | ||
261 | errExit("ioctl"); | ||
262 | memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); | ||
263 | |||
264 | close(sock); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | // configure interface ipv4 address | ||
269 | void net_if_ip(const char *ifname, uint32_t ip, uint32_t mask, int mtu) { | ||
270 | if (strlen(ifname) > IFNAMSIZ) { | ||
271 | fprintf(stderr, "Error: invalid network device name %s\n", ifname); | ||
272 | exit(1); | ||
273 | } | ||
274 | |||
275 | int sock = socket(AF_INET,SOCK_DGRAM,0); | ||
276 | if (sock < 0) | ||
277 | errExit("socket"); | ||
278 | |||
279 | struct ifreq ifr; | ||
280 | memset(&ifr, 0, sizeof(ifr)); | ||
281 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
282 | ifr.ifr_addr.sa_family = AF_INET; | ||
283 | |||
284 | ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip); | ||
285 | if (ioctl( sock, SIOCSIFADDR, &ifr ) < 0) { | ||
286 | close(sock); | ||
287 | errExit("ioctl"); | ||
288 | } | ||
289 | |||
290 | if (ip != 0) { | ||
291 | ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(mask); | ||
292 | if (ioctl( sock, SIOCSIFNETMASK, &ifr ) < 0) { | ||
293 | close(sock); | ||
294 | errExit("ioctl"); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | // configure mtu | ||
299 | if (mtu > 0) { | ||
300 | ifr.ifr_mtu = mtu; | ||
301 | if (ioctl( sock, SIOCSIFMTU, &ifr ) < 0) { | ||
302 | close(sock); | ||
303 | errExit("ioctl"); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | close(sock); | ||
308 | usleep(10000); // sleep 10ms | ||
309 | } | ||
310 | |||
311 | int net_if_mac(const char *ifname, const unsigned char mac[6]) { | ||
312 | struct ifreq ifr; | ||
313 | int sock; | ||
314 | |||
315 | if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) | ||
316 | errExit("socket"); | ||
317 | |||
318 | memset(&ifr, 0, sizeof(ifr)); | ||
319 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
320 | ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; | ||
321 | memcpy(ifr.ifr_hwaddr.sa_data, mac, 6); | ||
322 | |||
323 | if (ioctl(sock, SIOCSIFHWADDR, &ifr) == -1) | ||
324 | errExit("ioctl"); | ||
325 | close(sock); | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | // configure interface ipv6 address | ||
330 | // ex: firejail --net=eth0 --ip6=2001:0db8:0:f101::1/64 | ||
331 | struct ifreq6 { | ||
332 | struct in6_addr ifr6_addr; | ||
333 | uint32_t ifr6_prefixlen; | ||
334 | unsigned int ifr6_ifindex; | ||
335 | }; | ||
336 | void net_if_ip6(const char *ifname, const char *addr6) { | ||
337 | if (strchr(addr6, ':') == NULL) { | ||
338 | fprintf(stderr, "Error fnet: invalid IPv6 address %s\n", addr6); | ||
339 | exit(1); | ||
340 | } | ||
341 | |||
342 | // extract prefix | ||
343 | unsigned long prefix; | ||
344 | char *ptr; | ||
345 | if ((ptr = strchr(addr6, '/'))) { | ||
346 | prefix = atol(ptr + 1); | ||
347 | if (prefix > 128) { | ||
348 | fprintf(stderr, "Error fnet: invalid prefix for IPv6 address %s\n", addr6); | ||
349 | exit(1); | ||
350 | } | ||
351 | *ptr = '\0'; // mark the end of the address | ||
352 | } | ||
353 | else | ||
354 | prefix = 128; | ||
355 | |||
356 | // extract address | ||
357 | struct sockaddr_in6 sin6; | ||
358 | memset(&sin6, 0, sizeof(sin6)); | ||
359 | sin6.sin6_family = AF_INET6; | ||
360 | int rv = inet_pton(AF_INET6, addr6, sin6.sin6_addr.s6_addr); | ||
361 | if (rv <= 0) { | ||
362 | fprintf(stderr, "Error fnet: invalid IPv6 address %s\n", addr6); | ||
363 | exit(1); | ||
364 | } | ||
365 | |||
366 | // open socket | ||
367 | int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP); | ||
368 | if (sock < 0) { | ||
369 | fprintf(stderr, "Error fnet: IPv6 is not supported on this system\n"); | ||
370 | exit(1); | ||
371 | } | ||
372 | |||
373 | // find interface index | ||
374 | struct ifreq ifr; | ||
375 | memset(&ifr, 0, sizeof(ifr)); | ||
376 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ); | ||
377 | ifr.ifr_addr.sa_family = AF_INET; | ||
378 | if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) { | ||
379 | perror("ioctl SIOGIFINDEX"); | ||
380 | exit(1); | ||
381 | } | ||
382 | |||
383 | // configure address | ||
384 | struct ifreq6 ifr6; | ||
385 | memset(&ifr6, 0, sizeof(ifr6)); | ||
386 | ifr6.ifr6_prefixlen = prefix; | ||
387 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; | ||
388 | memcpy((char *) &ifr6.ifr6_addr, (char *) &sin6.sin6_addr, sizeof(struct in6_addr)); | ||
389 | if (ioctl(sock, SIOCSIFADDR, &ifr6) < 0) { | ||
390 | perror("ioctl SIOCSIFADDR"); | ||
391 | exit(1); | ||
392 | } | ||
393 | |||
394 | close(sock); | ||
395 | } | ||
diff --git a/src/fnet/main.c b/src/fnet/main.c index f17287cb9..4ae9eb6e3 100644 --- a/src/fnet/main.c +++ b/src/fnet/main.c | |||
@@ -24,12 +24,18 @@ static void usage(void) { | |||
24 | printf("\tfnet create veth dev1 dev2 bridge child\n"); | 24 | printf("\tfnet create veth dev1 dev2 bridge child\n"); |
25 | printf("\tfnet create macvlan dev parent child\n"); | 25 | printf("\tfnet create macvlan dev parent child\n"); |
26 | printf("\tfnet moveif dev proc\n"); | 26 | printf("\tfnet moveif dev proc\n"); |
27 | printf("\tfnet printif\n"); | ||
28 | printf("\tfnet printif scan\n"); | ||
29 | printf("\tfnet config interface dev ip mask mtu\n"); | ||
30 | printf("\tfnet config mac addr\n"); | ||
31 | printf("\tfnet config ipv6 dev ipn"); | ||
32 | printf("\tfmet ifup dev\n"); | ||
27 | } | 33 | } |
28 | 34 | ||
29 | int main(int argc, char **argv) { | 35 | int main(int argc, char **argv) { |
30 | #if 0 | 36 | #if 0 |
31 | { | 37 | { |
32 | system("cat /proc/self/status"); | 38 | //system("cat /proc/self/status"); |
33 | int i; | 39 | int i; |
34 | for (i = 0; i < argc; i++) | 40 | for (i = 0; i < argc; i++) |
35 | printf("*%s* ", argv[i]); | 41 | printf("*%s* ", argv[i]); |
@@ -45,22 +51,49 @@ printf("\n"); | |||
45 | usage(); | 51 | usage(); |
46 | return 0; | 52 | return 0; |
47 | } | 53 | } |
54 | else if (argc == 3 && strcmp(argv[1], "ifup") == 0) { | ||
55 | net_if_up(argv[2]); | ||
56 | } | ||
57 | else if (argc == 2 && strcmp(argv[1], "printif") == 0) { | ||
58 | net_ifprint(0); | ||
59 | } | ||
60 | else if (argc == 3 && strcmp(argv[1], "printif") == 0 && strcmp(argv[2], "scan") == 0) { | ||
61 | net_ifprint(1); | ||
62 | } | ||
48 | else if (argc == 7 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "veth") == 0) { | 63 | else if (argc == 7 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "veth") == 0) { |
49 | // create veth pair and move one end in the the namespace | 64 | // create veth pair and move one end in the the namespace |
50 | net_create_veth(argv[3], argv[4], atoi(argv[6])); | 65 | net_create_veth(argv[3], argv[4], atoi(argv[6])); |
51 | |||
52 | // connect the ohter veth end to the bridge ... | 66 | // connect the ohter veth end to the bridge ... |
53 | net_bridge_add_interface(argv[5], argv[3]); | 67 | net_bridge_add_interface(argv[5], argv[3]); |
54 | |||
55 | // ... and bring it up | 68 | // ... and bring it up |
56 | net_if_up(argv[3]); | 69 | net_if_up(argv[3]); |
57 | } | 70 | } |
58 | else if (argc == 6 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "macvlan") == 0) { | 71 | else if (argc == 6 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "macvlan") == 0) { |
59 | net_create_macvlan(argv[3], argv[4], atoi(argv[5])); | 72 | net_create_macvlan(argv[3], argv[4], atoi(argv[5])); |
60 | } | 73 | } |
74 | else if (argc == 7 && strcmp(argv[1], "config") == 0 && strcmp(argv[2], "interface") == 0) { | ||
75 | char *dev = argv[3]; | ||
76 | uint32_t ip = (uint32_t) atoll(argv[4]); | ||
77 | uint32_t mask = (uint32_t) atoll(argv[5]); | ||
78 | int mtu = atoi(argv[6]); | ||
79 | // configure interface | ||
80 | net_if_ip(dev, ip, mask, mtu); | ||
81 | // ... and bring it up | ||
82 | net_if_up(dev); | ||
83 | } | ||
84 | else if (argc == 5 && strcmp(argv[1], "config") == 0 && strcmp(argv[2], "mac") == 0) { | ||
85 | unsigned char mac[6]; | ||
86 | if (atomac(argv[4], mac)) { | ||
87 | fprintf(stderr, "Error fnet: invalid mac address %s\n", argv[4]); | ||
88 | } | ||
89 | net_if_mac(argv[3], mac); | ||
90 | } | ||
61 | else if (argc == 4 && strcmp(argv[1], "moveif") == 0) { | 91 | else if (argc == 4 && strcmp(argv[1], "moveif") == 0) { |
62 | net_move_interface(argv[2], atoi(argv[3])); | 92 | net_move_interface(argv[2], atoi(argv[3])); |
63 | } | 93 | } |
94 | else if (argc == 5 && strcmp(argv[1], "config") == 0 && strcmp(argv[2], "ipv6") == 0) { | ||
95 | net_if_ip6(argv[3], argv[4]); | ||
96 | } | ||
64 | else { | 97 | else { |
65 | fprintf(stderr, "Error fnet: invalid arguments\n"); | 98 | fprintf(stderr, "Error fnet: invalid arguments\n"); |
66 | return 1; | 99 | return 1; |