mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-03 07:45:17 +00:00
tcp: Prepare sk-inet for dumping and restoring tcp connections
First of all -- to make crtools dump/restore established tcp sockets you have to specify the --tcp-established options. By doing so you inform crtools that a) you know, that after dump there will be a netfilter rules blocking the dumped connections b) you guarantee, that before restore this netfilter block is still there What else this patch does is simple -- collects establised sockets and calls the dump/restore tcp function (now empty) where appropriate. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
#include "syscall.h"
|
||||
#include "uts_ns.h"
|
||||
#include "ipc_ns.h"
|
||||
#include "files.h"
|
||||
#include "sk-inet.h"
|
||||
|
||||
struct cr_options opts;
|
||||
|
||||
@@ -347,6 +349,7 @@ int main(int argc, char *argv[])
|
||||
{ "namespaces", required_argument, 0, 'n' },
|
||||
{ "ext-unix-sk", no_argument, 0, 'x' },
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ SK_EST_PARAM, no_argument, 0, 42 },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -410,6 +413,10 @@ int main(int argc, char *argv[])
|
||||
log_level++;
|
||||
}
|
||||
break;
|
||||
case 42:
|
||||
pr_info("Will dump TCP connections\n");
|
||||
opts.tcp_established_ok = true;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
goto usage;
|
||||
|
@@ -66,6 +66,7 @@ struct cr_options {
|
||||
bool show_pages_content;
|
||||
bool restore_detach;
|
||||
bool ext_unix_sk;
|
||||
bool tcp_established_ok;
|
||||
unsigned int namespaces_flags;
|
||||
};
|
||||
|
||||
|
@@ -23,4 +23,16 @@ struct inet_sk_info {
|
||||
|
||||
int inet_bind(int sk, struct inet_sk_info *);
|
||||
int inet_connect(int sk, struct inet_sk_info *);
|
||||
|
||||
static inline int dump_one_tcp(int sk, struct inet_sk_desc *sd)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int restore_one_tcp(int sk, struct inet_sk_info *si)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SK_EST_PARAM "tcp-established"
|
||||
#endif
|
||||
|
@@ -39,7 +39,7 @@ struct socket_desc {
|
||||
struct socket_desc *lookup_socket(int ino);
|
||||
int sk_collect_one(int ino, int family, struct socket_desc *d);
|
||||
int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
|
||||
const struct cr_fdset *cr_fdset);
|
||||
int lfd, const struct cr_fdset *cr_fdset);
|
||||
int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
|
||||
int lfd, const struct cr_fdset *cr_fdset);
|
||||
struct nlmsghdr;
|
||||
|
30
sk-inet.c
30
sk-inet.c
@@ -72,6 +72,13 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case TCP_ESTABLISHED:
|
||||
if (!opts.tcp_established_ok) {
|
||||
pr_err("Connected TCP socket, consider using %s option.\n",
|
||||
SK_EST_PARAM);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("Unknown state %d\n", sk->state);
|
||||
return 0;
|
||||
@@ -80,8 +87,11 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define tcp_connection(sk) (((sk)->proto == IPPROTO_TCP) && \
|
||||
((sk)->state == TCP_ESTABLISHED))
|
||||
|
||||
int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
|
||||
const struct cr_fdset *cr_fdset)
|
||||
int lfd, const struct cr_fdset *cr_fdset)
|
||||
{
|
||||
struct inet_sk_desc *sk = (struct inet_sk_desc *)_sk;
|
||||
struct inet_sk_entry ie;
|
||||
@@ -123,6 +133,10 @@ int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
|
||||
show_one_inet("Dumping", sk);
|
||||
show_one_inet_img("Dumped", &ie);
|
||||
sk->sd.already_dumped = 1;
|
||||
|
||||
if (tcp_connection(sk))
|
||||
return dump_one_tcp(lfd, sk);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -221,6 +235,18 @@ static int open_inet_sk(struct file_desc *d)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcp_connection(&ii->ie)) {
|
||||
if (!opts.tcp_established_ok) {
|
||||
pr_err("Connected TCP socket in image\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (restore_one_tcp(sk, ii))
|
||||
goto err;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Listen sockets are easiest ones -- simply
|
||||
* bind() and listen(), and that's all.
|
||||
@@ -244,7 +270,7 @@ static int open_inet_sk(struct file_desc *d)
|
||||
if (ii->ie.state == TCP_ESTABLISHED &&
|
||||
inet_connect(sk, ii))
|
||||
goto err;
|
||||
|
||||
done:
|
||||
if (rst_file_params(sk, &ii->ie.fown, ii->ie.flags))
|
||||
goto err;
|
||||
|
||||
|
@@ -81,7 +81,7 @@ int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
|
||||
return dump_one_unix(sk, p, lfd, cr_fdset);
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return dump_one_inet(sk, p, cr_fdset);
|
||||
return dump_one_inet(sk, p, lfd, cr_fdset);
|
||||
default:
|
||||
pr_err("BUG! Unknown socket collected\n");
|
||||
break;
|
||||
@@ -220,8 +220,8 @@ int collect_sockets(void)
|
||||
req.r.i.sdiag_family = AF_INET;
|
||||
req.r.i.sdiag_protocol = IPPROTO_TCP;
|
||||
req.r.i.idiag_ext = 0;
|
||||
/* Only listening sockets supported yet */
|
||||
req.r.i.idiag_states = 1 << TCP_LISTEN;
|
||||
/* Only listening and established sockets supported yet */
|
||||
req.r.i.idiag_states = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
|
||||
tmp = collect_sockets_nl(nl, &req, sizeof(req), inet_tcp_receive_one);
|
||||
if (tmp)
|
||||
err = tmp;
|
||||
|
Reference in New Issue
Block a user