2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-29 05:18:00 +00:00
criu/netfilter.c
Andrew Vagin 0a1b70bb23 tcp: block connections in both directions
The packet can be retransmited after dumping the tcp connect.  The first
one is that the connection is blocked for only one direction. The second
one is that TCP timers continue work during dumping and they can send
packets. tcp_timestamp is saved for each tcp connections and then it’s
restored. So if a packet is sent after dumping, its timestamps is
saved by another side and this timestamp is sent back in the next packet
as the tsecr parameter. If this packet is received after restoring, it
looks like a packets from the future.

https://bugzilla.openvz.org/show_bug.cgi?id=2676

Signed-off-by: Andrew Vagin <avagin@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2013-08-06 14:21:12 +04:00

115 lines
2.7 KiB
C

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <stdlib.h>
#include "asm/types.h"
#include "util.h"
#include "list.h"
#include "files.h"
#include "netfilter.h"
#include "sockets.h"
#include "sk-inet.h"
static char buf[512];
/*
* Need to configure simple netfilter rules for blocking connections
* ANy brave soul to write it using xtables-devel?
*/
static const char *nf_conn_cmd = "%s -t filter %s INPUT --protocol tcp "
"--source %s --sport %d --destination %s --dport %d -j DROP";
static char iptable_cmd_ipv4[] = "iptables";
static char iptable_cmd_ipv6[] = "ip6tables";
static int nf_connection_switch_raw(int family, u32 *src_addr, u16 src_port, u32 *dst_addr, u16 dst_port, int lock)
{
char sip[INET_ADDR_LEN], dip[INET_ADDR_LEN];
char *cmd;
int ret;
switch (family) {
case AF_INET:
cmd = iptable_cmd_ipv4;
break;
case AF_INET6:
cmd = iptable_cmd_ipv6;
break;
default:
pr_err("Unknown socket family %d\n", family);
return -1;
};
if (!inet_ntop(family, (void *)src_addr, sip, INET_ADDR_LEN) ||
!inet_ntop(family, (void *)dst_addr, dip, INET_ADDR_LEN)) {
pr_perror("nf: Can't translate ip addr");
return -1;
}
snprintf(buf, sizeof(buf), nf_conn_cmd, cmd, lock ? "-A" : "-D",
dip, (int)dst_port, sip, (int)src_port);
pr_debug("\tRunning iptables [%s]\n", buf);
ret = system(buf);
if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret)) {
pr_perror("Iptables configuration failed");
return -1;
}
pr_info("%s %s:%d - %s:%d connection\n", lock ? "Locked" : "Unlocked",
sip, (int)src_port, dip, (int)dst_port);
return 0;
}
static int nf_connection_switch(struct inet_sk_desc *sk, int lock)
{
int ret = 0;
ret = nf_connection_switch_raw(sk->sd.family,
sk->src_addr, sk->src_port,
sk->dst_addr, sk->dst_port, lock);
if (ret)
return -1;
ret = nf_connection_switch_raw(sk->sd.family,
sk->dst_addr, sk->dst_port,
sk->src_addr, sk->src_port, lock);
if (ret) /* rollback */
nf_connection_switch_raw(sk->sd.family,
sk->src_addr, sk->src_port,
sk->dst_addr, sk->dst_port, !lock);
return ret;
}
int nf_lock_connection(struct inet_sk_desc *sk)
{
return nf_connection_switch(sk, 1);
}
int nf_unlock_connection(struct inet_sk_desc *sk)
{
return nf_connection_switch(sk, 0);
}
int nf_unlock_connection_info(struct inet_sk_info *si)
{
int ret = 0;
ret |= nf_connection_switch_raw(si->ie->family,
si->ie->src_addr, si->ie->src_port,
si->ie->dst_addr, si->ie->dst_port, 0);
ret |= nf_connection_switch_raw(si->ie->family,
si->ie->dst_addr, si->ie->dst_port,
si->ie->src_addr, si->ie->src_port, 0);
/*
* rollback nothing in case of any error,
* because nobody checks errors of this function
*/
return ret;
}