Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <sys/socket.h>
3 : : #include <linux/netlink.h>
4 : : #include <linux/rtnetlink.h>
5 : : #include <string.h>
6 : : #include <net/if_arp.h>
7 : : #include <sys/wait.h>
8 : : #include <sched.h>
9 : : #include <sys/mount.h>
10 : :
11 : : #include "fdset.h"
12 : : #include "syscall-types.h"
13 : : #include "namespaces.h"
14 : : #include "net.h"
15 : : #include "libnetlink.h"
16 : : #include "cr_options.h"
17 : : #include "sk-inet.h"
18 : : #include "tun.h"
19 : : #include "util-pie.h"
20 : : #include "plugin.h"
21 : :
22 : : #include "protobuf.h"
23 : : #include "protobuf/netdev.pb-c.h"
24 : :
25 : : static int ns_fd = -1;
26 : : static int ns_sysfs_fd = -1;
27 : :
28 : 0 : int read_ns_sys_file(char *path, char *buf, int len)
29 : : {
30 : : int fd, rlen;
31 : :
32 [ # # ]: 0 : BUG_ON(ns_sysfs_fd == -1);
33 : :
34 : 0 : fd = openat(ns_sysfs_fd, path, O_RDONLY, 0);
35 [ # # ]: 0 : if (fd < 0) {
36 : 0 : pr_perror("Can't open ns' %s", path);
37 : 0 : return -1;
38 : : }
39 : :
40 : 0 : rlen = read(fd, buf, len);
41 : 0 : close(fd);
42 : :
43 [ # # ]: 0 : if (rlen >= 0)
44 : 0 : buf[rlen] = '\0';
45 : :
46 : 0 : return rlen;
47 : : }
48 : :
49 : 214 : int write_netdev_img(NetDeviceEntry *nde, struct cr_fdset *fds)
50 : : {
51 : 214 : return pb_write_one(fdset_fd(fds, CR_FD_NETDEV), nde, PB_NETDEV);
52 : : }
53 : :
54 : 428 : static int dump_one_netdev(int type, struct ifinfomsg *ifi,
55 : : struct rtattr **tb, struct cr_fdset *fds,
56 : : int (*dump)(NetDeviceEntry *, struct cr_fdset *))
57 : : {
58 : 214 : NetDeviceEntry netdev = NET_DEVICE_ENTRY__INIT;
59 : :
60 [ - + ]: 214 : if (!tb[IFLA_IFNAME]) {
61 : 0 : pr_err("No name for link %d\n", ifi->ifi_index);
62 : : return -1;
63 : : }
64 : :
65 : 214 : netdev.type = type;
66 : 214 : netdev.ifindex = ifi->ifi_index;
67 : 214 : netdev.mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
68 : 214 : netdev.flags = ifi->ifi_flags;
69 : 214 : netdev.name = RTA_DATA(tb[IFLA_IFNAME]);
70 : :
71 [ + - ][ - + ]: 214 : if (tb[IFLA_ADDRESS] && (type != ND_TYPE__LOOPBACK)) {
72 : 0 : netdev.has_address = true;
73 : 0 : netdev.address.data = RTA_DATA(tb[IFLA_ADDRESS]);
74 : 0 : netdev.address.len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
75 : 0 : pr_info("Found ll addr (%02x:../%d) for %s\n",
76 : : (int)netdev.address.data[0],
77 : : (int)netdev.address.len, netdev.name);
78 : : }
79 : :
80 [ + - ]: 214 : if (!dump)
81 : : dump = write_netdev_img;
82 : :
83 : 214 : return dump(&netdev, fds);
84 : : }
85 : :
86 : 0 : static char *link_kind(struct ifinfomsg *ifi, struct rtattr **tb)
87 : : {
88 : : struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
89 : :
90 [ # # ]: 0 : if (!tb[IFLA_LINKINFO]) {
91 : 0 : pr_err("No linkinfo for eth link %d\n", ifi->ifi_index);
92 : : return NULL;
93 : : }
94 : :
95 : 0 : parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
96 [ # # ]: 0 : if (!linkinfo[IFLA_INFO_KIND]) {
97 : 0 : pr_err("No kind for eth link %d\n", ifi->ifi_index);
98 : : return NULL;
99 : : }
100 : :
101 : 0 : return RTA_DATA(linkinfo[IFLA_INFO_KIND]);
102 : : }
103 : :
104 : 0 : static int dump_unknown_device(struct ifinfomsg *ifi, char *kind,
105 : : struct rtattr **tb, struct cr_fdset *fds)
106 : : {
107 : : int ret;
108 : :
109 : 0 : ret = cr_plugin_dump_ext_link(ifi->ifi_index, ifi->ifi_type, kind);
110 [ # # ]: 0 : if (ret == 0)
111 : 0 : return dump_one_netdev(ND_TYPE__EXTLINK, ifi, tb, fds, NULL);
112 : :
113 [ # # ]: 0 : if (ret == -ENOTSUP)
114 : 0 : pr_err("Unsupported link %d (type %d kind %s)\n",
115 : : ifi->ifi_index, ifi->ifi_type, kind);
116 : : return -1;
117 : : }
118 : :
119 : 0 : static int dump_one_ethernet(struct ifinfomsg *ifi, char *kind,
120 : : struct rtattr **tb, struct cr_fdset *fds)
121 : : {
122 [ # # ]: 0 : if (!strcmp(kind, "veth"))
123 : : /*
124 : : * This is not correct. The peer of the veth device may
125 : : * be either outside or inside the netns we're working
126 : : * on, but there's currently no way of finding this out.
127 : : *
128 : : * Sigh... we have to assume, that the veth device is a
129 : : * connection to the outer world and just dump this end :(
130 : : */
131 : 0 : return dump_one_netdev(ND_TYPE__VETH, ifi, tb, fds, NULL);
132 [ # # ][ # # ]: 0 : if (!strcmp(kind, "tun"))
[ # # ][ # # ]
133 : 0 : return dump_one_netdev(ND_TYPE__TUN, ifi, tb, fds, dump_tun_link);
134 : :
135 : 0 : return dump_unknown_device(ifi, kind, tb, fds);
136 : : }
137 : :
138 : 0 : static int dump_one_gendev(struct ifinfomsg *ifi, char *kind,
139 : : struct rtattr **tb, struct cr_fdset *fds)
140 : : {
141 [ # # ][ # # ]: 0 : if (!strcmp(kind, "tun"))
[ # # ][ # # ]
142 : 0 : return dump_one_netdev(ND_TYPE__TUN, ifi, tb, fds, dump_tun_link);
143 : :
144 : 0 : return dump_unknown_device(ifi, kind, tb, fds);
145 : : }
146 : :
147 : 0 : static int dump_one_voiddev(struct ifinfomsg *ifi, char *kind,
148 : : struct rtattr **tb, struct cr_fdset *fds)
149 : : {
150 [ # # ]: 0 : if (!strcmp(kind, "venet"))
151 : : /*
152 : : * If we meet a link we know about, such as
153 : : * OpenVZ's venet, save general parameters of
154 : : * it as external link.
155 : : */
156 : 0 : return dump_one_netdev(ND_TYPE__EXTLINK, ifi, tb, fds, NULL);
157 : :
158 : 0 : return dump_unknown_device(ifi, kind, tb, fds);
159 : : }
160 : :
161 : 214 : static int dump_one_link(struct nlmsghdr *hdr, void *arg)
162 : : {
163 : : struct cr_fdset *fds = arg;
164 : 214 : struct ifinfomsg *ifi;
165 : 214 : int ret = 0, len = hdr->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
166 : : struct rtattr *tb[IFLA_MAX + 1];
167 : : char *kind;
168 : :
169 : 214 : ifi = NLMSG_DATA(hdr);
170 : :
171 [ - + ]: 214 : if (len < 0) {
172 : 0 : pr_err("No iflas for link %d\n", ifi->ifi_index);
173 : 0 : return -1;
174 : : }
175 : :
176 : 214 : parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
177 : 214 : pr_info("\tLD: Got link %d, type %d\n", ifi->ifi_index, ifi->ifi_type);
178 : :
179 [ + - ]: 214 : if (ifi->ifi_type == ARPHRD_LOOPBACK)
180 : 214 : return dump_one_netdev(ND_TYPE__LOOPBACK, ifi, tb, fds, NULL);
181 : :
182 : 0 : kind = link_kind(ifi, tb);
183 [ # # ]: 0 : if (!kind)
184 : : goto unk;
185 : :
186 [ # # # # ]: 0 : switch (ifi->ifi_type) {
187 : : case ARPHRD_ETHER:
188 : 0 : ret = dump_one_ethernet(ifi, kind, tb, fds);
189 : 0 : break;
190 : : case ARPHRD_NONE:
191 : 0 : ret = dump_one_gendev(ifi, kind, tb, fds);
192 : 0 : break;
193 : : case ARPHRD_VOID:
194 : 0 : ret = dump_one_voiddev(ifi, kind, tb, fds);
195 : 0 : break;
196 : : default:
197 : : unk:
198 : 0 : ret = dump_unknown_device(ifi, kind, tb, fds);
199 : 0 : break;
200 : : }
201 : :
202 : 0 : return ret;
203 : : }
204 : :
205 : 214 : static int dump_links(struct cr_fdset *fds)
206 : : {
207 : : int sk, ret;
208 : : struct {
209 : : struct nlmsghdr nlh;
210 : : struct rtgenmsg g;
211 : : } req;
212 : :
213 : 214 : pr_info("Dumping netns links\n");
214 : :
215 : 214 : ret = sk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
216 [ - + ]: 214 : if (sk < 0) {
217 : 0 : pr_perror("Can't open rtnl sock for net dump");
218 : 0 : goto out;
219 : : }
220 : :
221 : : memset(&req, 0, sizeof(req));
222 : 214 : req.nlh.nlmsg_len = sizeof(req);
223 : 214 : req.nlh.nlmsg_type = RTM_GETLINK;
224 : 214 : req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
225 : : req.nlh.nlmsg_pid = 0;
226 : 214 : req.nlh.nlmsg_seq = CR_NLMSG_SEQ;
227 : 214 : req.g.rtgen_family = AF_PACKET;
228 : :
229 : 214 : ret = do_rtnl_req(sk, &req, sizeof(req), dump_one_link, fds);
230 : 214 : close(sk);
231 : : out:
232 : 214 : return ret;
233 : : }
234 : :
235 : 0 : static int restore_link_cb(struct nlmsghdr *hdr, void *arg)
236 : : {
237 : 0 : pr_info("Got response on SETLINK =)\n");
238 : 0 : return 0;
239 : : }
240 : :
241 : : struct newlink_req {
242 : : struct nlmsghdr h;
243 : : struct ifinfomsg i;
244 : : char buf[1024];
245 : : };
246 : :
247 : 214 : static int do_rtm_link_req(int msg_type, NetDeviceEntry *nde, int nlsk,
248 : : int (*link_info)(NetDeviceEntry *, struct newlink_req *))
249 : : {
250 : : struct newlink_req req;
251 : :
252 : : memset(&req, 0, sizeof(req));
253 : :
254 : 214 : req.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
255 : 214 : req.h.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE;
256 : 214 : req.h.nlmsg_type = msg_type;
257 : 214 : req.h.nlmsg_seq = CR_NLMSG_SEQ;
258 : 214 : req.i.ifi_family = AF_PACKET;
259 : : /*
260 : : * SETLINK is called for external devices which may
261 : : * have ifindex changed. Thus configure them by their
262 : : * name only.
263 : : */
264 [ - + ]: 214 : if (msg_type == RTM_NEWLINK)
265 : 0 : req.i.ifi_index = nde->ifindex;
266 : 214 : req.i.ifi_flags = nde->flags;
267 : :
268 : 214 : addattr_l(&req.h, sizeof(req), IFLA_IFNAME, nde->name, strlen(nde->name));
269 : 214 : addattr_l(&req.h, sizeof(req), IFLA_MTU, &nde->mtu, sizeof(nde->mtu));
270 : :
271 [ - + ]: 214 : if (nde->has_address) {
272 : 0 : pr_debug("Restore ll addr (%02x:../%d) for device\n",
273 : : (int)nde->address.data[0], (int)nde->address.len);
274 : 0 : addattr_l(&req.h, sizeof(req), IFLA_ADDRESS,
275 : 0 : nde->address.data, nde->address.len);
276 : : }
277 : :
278 [ - + ]: 214 : if (link_info) {
279 : : struct rtattr *linkinfo;
280 : : int ret;
281 : :
282 : 0 : linkinfo = NLMSG_TAIL(&req.h);
283 : 0 : addattr_l(&req.h, sizeof(req), IFLA_LINKINFO, NULL, 0);
284 : :
285 : 0 : ret = link_info(nde, &req);
286 [ # # ]: 0 : if (ret < 0)
287 : : return ret;
288 : :
289 : 0 : linkinfo->rta_len = (void *)NLMSG_TAIL(&req.h) - (void *)linkinfo;
290 : : }
291 : :
292 : 214 : return do_rtnl_req(nlsk, &req, req.h.nlmsg_len, restore_link_cb, NULL);
293 : : }
294 : :
295 : 0 : int restore_link_parms(NetDeviceEntry *nde, int nlsk)
296 : : {
297 : 214 : return do_rtm_link_req(RTM_SETLINK, nde, nlsk, NULL);
298 : : }
299 : :
300 : 0 : static int restore_one_link(NetDeviceEntry *nde, int nlsk,
301 : : int (*link_info)(NetDeviceEntry *, struct newlink_req *))
302 : : {
303 : 0 : pr_info("Restoring netdev %s idx %d\n", nde->name, nde->ifindex);
304 : 0 : return do_rtm_link_req(RTM_NEWLINK, nde, nlsk, link_info);
305 : : }
306 : :
307 : : #ifndef VETH_INFO_MAX
308 : : enum {
309 : : VETH_INFO_UNSPEC,
310 : : VETH_INFO_PEER,
311 : :
312 : : __VETH_INFO_MAX
313 : : #define VETH_INFO_MAX (__VETH_INFO_MAX - 1)
314 : : };
315 : : #endif
316 : :
317 : : #if IFLA_MAX <= 28
318 : : #define IFLA_NET_NS_FD 28
319 : : #endif
320 : :
321 : 0 : static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req)
322 : : {
323 : : struct rtattr *veth_data, *peer_data;
324 : : struct ifinfomsg ifm;
325 : : struct veth_pair *n;
326 : :
327 [ # # ]: 0 : BUG_ON(ns_fd < 0);
328 : :
329 : 0 : addattr_l(&req->h, sizeof(*req), IFLA_INFO_KIND, "veth", 4);
330 : :
331 : 0 : veth_data = NLMSG_TAIL(&req->h);
332 : 0 : addattr_l(&req->h, sizeof(*req), IFLA_INFO_DATA, NULL, 0);
333 : 0 : peer_data = NLMSG_TAIL(&req->h);
334 : : memset(&ifm, 0, sizeof(ifm));
335 : 0 : addattr_l(&req->h, sizeof(*req), VETH_INFO_PEER, &ifm, sizeof(ifm));
336 [ # # ]: 0 : list_for_each_entry(n, &opts.veth_pairs, node) {
337 [ # # ]: 0 : if (!strcmp(nde->name, n->inside))
338 : : break;
339 : : }
340 [ # # ]: 0 : if (&n->node != &opts.veth_pairs)
341 : 0 : addattr_l(&req->h, sizeof(*req), IFLA_IFNAME, n->outside, strlen(n->outside));
342 : 0 : addattr_l(&req->h, sizeof(*req), IFLA_NET_NS_FD, &ns_fd, sizeof(ns_fd));
343 : 0 : peer_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)peer_data;
344 : 0 : veth_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)veth_data;
345 : :
346 : 0 : return 0;
347 : : }
348 : :
349 : 214 : static int restore_link(NetDeviceEntry *nde, int nlsk)
350 : : {
351 : 214 : pr_info("Restoring link %s type %d\n", nde->name, nde->type);
352 : :
353 [ + - - - ]: 214 : switch (nde->type) {
354 : : case ND_TYPE__LOOPBACK: /* fallthrough */
355 : : case ND_TYPE__EXTLINK: /* see comment in protobuf/netdev.proto */
356 : 214 : return restore_link_parms(nde, nlsk);
357 : : case ND_TYPE__VETH:
358 : 0 : return restore_one_link(nde, nlsk, veth_link_info);
359 : : case ND_TYPE__TUN:
360 : 0 : return restore_one_tun(nde, nlsk);
361 : : default:
362 : 0 : pr_err("Unsupported link type %d\n", nde->type);
363 : : break;
364 : : }
365 : :
366 : 0 : return -1;
367 : : }
368 : :
369 : 214 : static int restore_links(int pid)
370 : : {
371 : : int fd, nlsk, ret;
372 : : NetDeviceEntry *nde;
373 : :
374 : 214 : fd = open_image(CR_FD_NETDEV, O_RSTR, pid);
375 [ + - ]: 214 : if (fd < 0)
376 : : return -1;
377 : :
378 : 214 : nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
379 [ - + ]: 214 : if (nlsk < 0) {
380 : 0 : pr_perror("Can't create nlk socket");
381 : 0 : close_safe(&fd);
382 : 214 : return -1;
383 : : }
384 : :
385 : : while (1) {
386 : 428 : ret = pb_read_one_eof(fd, &nde, PB_NETDEV);
387 [ + + ]: 428 : if (ret <= 0)
388 : : break;
389 : :
390 : 214 : ret = restore_link(nde, nlsk);
391 : 214 : net_device_entry__free_unpacked(nde, NULL);
392 [ + - ]: 214 : if (ret)
393 : : break;
394 : : }
395 : :
396 : 214 : close(nlsk);
397 : 214 : close(fd);
398 : 214 : return ret;
399 : : }
400 : :
401 : 856 : static int run_ip_tool(char *arg1, char *arg2, int fdin, int fdout)
402 : : {
403 : : char *ip_tool_cmd;
404 : : int ret;
405 : :
406 : 856 : pr_debug("\tRunning ip %s %s\n", arg1, arg2);
407 : :
408 : 856 : ip_tool_cmd = getenv("CR_IP_TOOL");
409 [ + - ]: 856 : if (!ip_tool_cmd)
410 : : ip_tool_cmd = "ip";
411 : :
412 : 856 : ret = cr_system(fdin, fdout, -1, ip_tool_cmd,
413 : 856 : (char *[]) { "ip", arg1, arg2, NULL });
414 [ - + ]: 856 : if (ret) {
415 : 0 : pr_err("IP tool failed on %s %s\n", arg1, arg2);
416 : 0 : return -1;
417 : : }
418 : :
419 : : return 0;
420 : : }
421 : :
422 : 428 : static int run_iptables_tool(char *def_cmd, int fdin, int fdout)
423 : : {
424 : : int ret;
425 : : char *cmd;
426 : :
427 : 428 : cmd = getenv("CR_IPTABLES");
428 [ + - ]: 428 : if (!cmd)
429 : : cmd = def_cmd;
430 : 428 : pr_debug("\tRunning %s for %s\n", cmd, def_cmd);
431 : 428 : ret = cr_system(fdin, fdout, -1, "sh", (char *[]) { "sh", "-c", cmd, NULL });
432 [ - + ]: 220 : if (ret)
433 : 0 : pr_err("%s failed\n", def_cmd);
434 : :
435 : 220 : return ret;
436 : : }
437 : :
438 : 214 : static inline int dump_ifaddr(struct cr_fdset *fds)
439 : : {
440 : 214 : return run_ip_tool("addr", "save", -1, fdset_fd(fds, CR_FD_IFADDR));
441 : : }
442 : :
443 : 214 : static inline int dump_route(struct cr_fdset *fds)
444 : : {
445 : 214 : return run_ip_tool("route", "save", -1, fdset_fd(fds, CR_FD_ROUTE));
446 : : }
447 : :
448 : 214 : static inline int dump_iptables(struct cr_fdset *fds)
449 : : {
450 : 214 : return run_iptables_tool("iptables-save", -1, fdset_fd(fds, CR_FD_IPTABLES));
451 : : }
452 : :
453 : 428 : static int restore_ip_dump(int type, int pid, char *cmd)
454 : : {
455 : : int fd, ret;
456 : :
457 : 428 : ret = fd = open_image(type, O_RSTR, pid);
458 [ + - ]: 428 : if (fd >= 0) {
459 : 428 : ret = run_ip_tool(cmd, "restore", fd, -1);
460 : 428 : close(fd);
461 : : }
462 : :
463 : 428 : return ret;
464 : : }
465 : :
466 : : static inline int restore_ifaddr(int pid)
467 : : {
468 : 214 : return restore_ip_dump(CR_FD_IFADDR, pid, "addr");
469 : : }
470 : :
471 : : static inline int restore_route(int pid)
472 : : {
473 : 214 : return restore_ip_dump(CR_FD_ROUTE, pid, "route");
474 : : }
475 : :
476 : 214 : static inline int restore_iptables(int pid)
477 : : {
478 : : int ret, fd;
479 : :
480 : 214 : ret = fd = open_image(CR_FD_IPTABLES, O_RSTR, pid);
481 [ + - ]: 214 : if (fd >= 0) {
482 : 214 : ret = run_iptables_tool("iptables-restore", fd, -1);
483 : 6 : close(fd);
484 : : }
485 : :
486 : 6 : return ret;
487 : : }
488 : :
489 : 214 : static int mount_ns_sysfs(void)
490 : : {
491 : 214 : char sys_mount[] = "crtools-sys.XXXXXX";
492 : :
493 [ - + ]: 214 : BUG_ON(ns_sysfs_fd != -1);
494 : :
495 : : /*
496 : : * A new mntns is required to avoid the race between
497 : : * open_detach_mount and creating mntns.
498 : : */
499 [ - + ]: 214 : if (unshare(CLONE_NEWNS)) {
500 : 0 : pr_perror("Can't create new mount namespace");
501 : 0 : return -1;
502 : : }
503 : :
504 [ - + ]: 214 : if (mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL)) {
505 : 0 : pr_perror("Can't mark the root mount as private");
506 : 0 : return -1;
507 : : }
508 : :
509 [ - + ]: 214 : if (mkdtemp(sys_mount) == NULL) {
510 : 0 : pr_perror("mkdtemp failed %s", sys_mount);
511 : 0 : return -1;
512 : : }
513 : :
514 : : /*
515 : : * The setns() is called, so we're in proper context,
516 : : * no need in pulling the mountpoint from parasite.
517 : : */
518 : 214 : pr_info("Mount ns' sysfs in %s\n", sys_mount);
519 [ - + ]: 214 : if (mount("sysfs", sys_mount, "sysfs", MS_MGC_VAL, NULL)) {
520 : 0 : pr_perror("mount failed");
521 : 0 : rmdir(sys_mount);
522 : 0 : return -1;
523 : : }
524 : :
525 : 214 : ns_sysfs_fd = open_detach_mount(sys_mount);
526 [ - + ]: 214 : return ns_sysfs_fd >= 0 ? 0 : -1;
527 : : }
528 : :
529 : 214 : int dump_net_ns(int pid, int ns_id)
530 : : {
531 : : struct cr_fdset *fds;
532 : : int ret;
533 : :
534 : 214 : fds = cr_fdset_open(ns_id, NETNS, O_DUMP);
535 [ + - ]: 214 : if (fds == NULL)
536 : : return -1;
537 : :
538 : 214 : ret = switch_ns(pid, &net_ns_desc, NULL);
539 [ + - ]: 214 : if (!ret)
540 : 214 : ret = mount_ns_sysfs();
541 [ + - ]: 214 : if (!ret)
542 : 214 : ret = dump_links(fds);
543 [ + - ]: 214 : if (!ret)
544 : 214 : ret = dump_ifaddr(fds);
545 [ + - ]: 214 : if (!ret)
546 : 214 : ret = dump_route(fds);
547 [ + - ]: 214 : if (!ret)
548 : 214 : ret = dump_iptables(fds);
549 : :
550 : 214 : close(ns_sysfs_fd);
551 : 214 : ns_sysfs_fd = -1;
552 : :
553 : 214 : close_cr_fdset(&fds);
554 : 214 : return ret;
555 : : }
556 : :
557 : 214 : int prepare_net_ns(int pid)
558 : : {
559 : : int ret;
560 : :
561 : 214 : ret = restore_links(pid);
562 [ + - ]: 214 : if (!ret)
563 : : ret = restore_ifaddr(pid);
564 [ + - ]: 214 : if (!ret)
565 : : ret = restore_route(pid);
566 [ + - ]: 214 : if (!ret)
567 : 214 : ret = restore_iptables(pid);
568 : :
569 : 6 : close(ns_fd);
570 : :
571 : 6 : return ret;
572 : : }
573 : :
574 : 428 : int netns_pre_create(void)
575 : : {
576 : 428 : ns_fd = open("/proc/self/ns/net", O_RDONLY | O_CLOEXEC);
577 [ - + ]: 428 : if (ns_fd < 0) {
578 : 0 : pr_perror("Can't cache net fd");
579 : 0 : return -1;
580 : : }
581 : :
582 : 428 : pr_info("Saved netns fd for links restore\n");
583 : 428 : return 0;
584 : : }
585 : :
586 : 448 : int network_lock(void)
587 : : {
588 : 448 : pr_info("Lock network\n");
589 : :
590 : : /* Each connection will be locked on dump */
591 [ + + ]: 448 : if (!(root_ns_mask & CLONE_NEWNET))
592 : : return 0;
593 : :
594 : 214 : return run_scripts("network-lock");
595 : : }
596 : :
597 : 448 : void network_unlock(void)
598 : : {
599 : 448 : pr_info("Unlock network\n");
600 : :
601 : 448 : cpt_unlock_tcp_connections();
602 : 448 : rst_unlock_tcp_connections();
603 : :
604 [ + + ]: 448 : if (root_ns_mask & CLONE_NEWNET)
605 : 214 : run_scripts("network-unlock");
606 : 448 : }
607 : :
608 : 0 : int veth_pair_add(char *in, char *out)
609 : : {
610 : : struct veth_pair *n;
611 : :
612 [ # # ]: 0 : n = xmalloc(sizeof(*n));
613 [ # # ]: 0 : if (n == NULL)
614 : : return -1;
615 : :
616 : 0 : n->inside = in;
617 : 0 : n->outside = out;
618 : 0 : list_add(&n->node, &opts.veth_pairs);
619 : 0 : pr_debug("Added %s:%s veth map\n", in, out);
620 : 0 : return 0;
621 : : }
622 : :
623 : : struct ns_desc net_ns_desc = NS_DESC_ENTRY(CLONE_NEWNET, "net");
|