Commit 051b0a1f authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a915a462
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment