static int tcp_repair_establised(int fd, struct inet_sk_desc *sk) { int ret; pr_info("\tTurning repair on for socket %x\n", sk->sd.ino); /* * Keep the socket open in criu till the very end. In * case we close this fd after one task fd dumping and * fail we'll have to turn repair mode off */ sk->rfd = dup(fd); if (sk->rfd < 0) { pr_perror("Can't save socket fd for repair"); goto err1; } if (!(root_ns_mask & CLONE_NEWNET)) { ret = nf_lock_connection(sk); if (ret < 0) goto err2; } ret = tcp_repair_on(sk->rfd); if (ret < 0) goto err3; list_add_tail(&sk->rlist, &cpt_tcp_repair_sockets); ret = refresh_inet_sk(sk); if (ret < 0) goto err1; return 0; err3: if (!(root_ns_mask & CLONE_NEWNET)) nf_unlock_connection(sk); err2: close(sk->rfd); err1: return -1; }
static int dump_tcp_conn_state(struct inet_sk_desc *sk) { int ret, aux; struct tcp_info ti; struct cr_img *img; TcpStreamEntry tse = TCP_STREAM_ENTRY__INIT; char *in_buf, *out_buf; ret = refresh_inet_sk(sk, &ti); if (ret < 0) goto err_r; /* * Read queue */ pr_info("Reading inq for socket\n"); tse.inq_len = sk->rqlen; ret = tcp_stream_get_queue(sk->rfd, TCP_RECV_QUEUE, &tse.inq_seq, tse.inq_len, &in_buf); if (ret < 0) goto err_in; /* * Write queue */ pr_info("Reading outq for socket\n"); tse.outq_len = sk->wqlen; tse.unsq_len = sk->uwqlen; tse.has_unsq_len = true; ret = tcp_stream_get_queue(sk->rfd, TCP_SEND_QUEUE, &tse.outq_seq, tse.outq_len, &out_buf); if (ret < 0) goto err_out; /* * Initial options */ pr_info("Reading options for socket\n"); ret = tcp_stream_get_options(sk->rfd, &ti, &tse); if (ret < 0) goto err_opt; if (tcp_get_window(sk->rfd, &tse)) goto err_opt; /* * TCP socket options */ if (dump_opt(sk->rfd, SOL_TCP, TCP_NODELAY, &aux)) goto err_opt; if (aux) { tse.has_nodelay = true; tse.nodelay = true; } if (dump_opt(sk->rfd, SOL_TCP, TCP_CORK, &aux)) goto err_opt; if (aux) { tse.has_cork = true; tse.cork = true; } /* * Push the stuff to image */ img = open_image(CR_FD_TCP_STREAM, O_DUMP, sk->sd.ino); if (!img) goto err_img; ret = pb_write_one(img, &tse, PB_TCP_STREAM); if (ret < 0) goto err_iw; if (in_buf) { ret = write_img_buf(img, in_buf, tse.inq_len); if (ret < 0) goto err_iw; } if (out_buf) { ret = write_img_buf(img, out_buf, tse.outq_len); if (ret < 0) goto err_iw; } pr_info("Done\n"); err_iw: close_image(img); err_img: err_opt: xfree(out_buf); err_out: xfree(in_buf); err_in: err_r: return ret; }