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 @@ ...@@ -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[]) ...@@ -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[]) ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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;
......
...@@ -72,6 +72,13 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
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