mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-03 15:55:53 +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 "syscall.h"
|
||||||
#include "uts_ns.h"
|
#include "uts_ns.h"
|
||||||
#include "ipc_ns.h"
|
#include "ipc_ns.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "sk-inet.h"
|
||||||
|
|
||||||
struct cr_options opts;
|
struct cr_options opts;
|
||||||
|
|
||||||
@@ -347,6 +349,7 @@ int main(int argc, char *argv[])
|
|||||||
{ "namespaces", required_argument, 0, 'n' },
|
{ "namespaces", required_argument, 0, 'n' },
|
||||||
{ "ext-unix-sk", no_argument, 0, 'x' },
|
{ "ext-unix-sk", no_argument, 0, 'x' },
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ SK_EST_PARAM, no_argument, 0, 42 },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -410,6 +413,10 @@ int main(int argc, char *argv[])
|
|||||||
log_level++;
|
log_level++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 42:
|
||||||
|
pr_info("Will dump TCP connections\n");
|
||||||
|
opts.tcp_established_ok = true;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
goto usage;
|
goto usage;
|
||||||
|
@@ -66,6 +66,7 @@ struct cr_options {
|
|||||||
bool show_pages_content;
|
bool show_pages_content;
|
||||||
bool restore_detach;
|
bool restore_detach;
|
||||||
bool ext_unix_sk;
|
bool ext_unix_sk;
|
||||||
|
bool tcp_established_ok;
|
||||||
unsigned int namespaces_flags;
|
unsigned int namespaces_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -23,4 +23,16 @@ struct inet_sk_info {
|
|||||||
|
|
||||||
int inet_bind(int sk, struct inet_sk_info *);
|
int inet_bind(int sk, struct inet_sk_info *);
|
||||||
int inet_connect(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
|
#endif
|
||||||
|
@@ -39,7 +39,7 @@ struct socket_desc {
|
|||||||
struct socket_desc *lookup_socket(int ino);
|
struct socket_desc *lookup_socket(int ino);
|
||||||
int sk_collect_one(int ino, int family, struct socket_desc *d);
|
int sk_collect_one(int ino, int family, struct socket_desc *d);
|
||||||
int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
|
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 dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
|
||||||
int lfd, const struct cr_fdset *cr_fdset);
|
int lfd, const struct cr_fdset *cr_fdset);
|
||||||
struct nlmsghdr;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
pr_err("Unknown state %d\n", sk->state);
|
pr_err("Unknown state %d\n", sk->state);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -80,8 +87,11 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
|
|||||||
return 1;
|
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,
|
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_desc *sk = (struct inet_sk_desc *)_sk;
|
||||||
struct inet_sk_entry ie;
|
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("Dumping", sk);
|
||||||
show_one_inet_img("Dumped", &ie);
|
show_one_inet_img("Dumped", &ie);
|
||||||
sk->sd.already_dumped = 1;
|
sk->sd.already_dumped = 1;
|
||||||
|
|
||||||
|
if (tcp_connection(sk))
|
||||||
|
return dump_one_tcp(lfd, sk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -221,6 +235,18 @@ static int open_inet_sk(struct file_desc *d)
|
|||||||
return -1;
|
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
|
* Listen sockets are easiest ones -- simply
|
||||||
* bind() and listen(), and that's all.
|
* 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 &&
|
if (ii->ie.state == TCP_ESTABLISHED &&
|
||||||
inet_connect(sk, ii))
|
inet_connect(sk, ii))
|
||||||
goto err;
|
goto err;
|
||||||
|
done:
|
||||||
if (rst_file_params(sk, &ii->ie.fown, ii->ie.flags))
|
if (rst_file_params(sk, &ii->ie.fown, ii->ie.flags))
|
||||||
goto err;
|
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);
|
return dump_one_unix(sk, p, lfd, cr_fdset);
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
return dump_one_inet(sk, p, cr_fdset);
|
return dump_one_inet(sk, p, lfd, cr_fdset);
|
||||||
default:
|
default:
|
||||||
pr_err("BUG! Unknown socket collected\n");
|
pr_err("BUG! Unknown socket collected\n");
|
||||||
break;
|
break;
|
||||||
@@ -220,8 +220,8 @@ int collect_sockets(void)
|
|||||||
req.r.i.sdiag_family = AF_INET;
|
req.r.i.sdiag_family = AF_INET;
|
||||||
req.r.i.sdiag_protocol = IPPROTO_TCP;
|
req.r.i.sdiag_protocol = IPPROTO_TCP;
|
||||||
req.r.i.idiag_ext = 0;
|
req.r.i.idiag_ext = 0;
|
||||||
/* Only listening sockets supported yet */
|
/* Only listening and established sockets supported yet */
|
||||||
req.r.i.idiag_states = 1 << TCP_LISTEN;
|
req.r.i.idiag_states = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
|
||||||
tmp = collect_sockets_nl(nl, &req, sizeof(req), inet_tcp_receive_one);
|
tmp = collect_sockets_nl(nl, &req, sizeof(req), inet_tcp_receive_one);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
err = tmp;
|
err = tmp;
|
||||||
|
Reference in New Issue
Block a user