public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob d31fe3f79d84798f98e26b2c5c05649ecb85562d 3483 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
 
// SPDX-License-Identifier: GPL-2.0-or-later

/* liste-vs-repair.c
 *
 * Do listening sockets have address conflicts with sockets under repair
 * ====================================================================
 *
 * When we accept() an incoming connection the accept()ed socket will have the
 * same local address as the listening socket.  This can be a complication on
 * migration.  On the migration target we've already set up listening sockets
 * according to the command line.  However to restore connections that we're
 * migrating in we need to bind the new sockets to the same address, which would
 * be an address conflict on the face of it.  This test program verifies that
 * enabling repair mode before bind() correctly suppresses that conflict.
 *
 * Copyright Red Hat
 * Author: David Gibson <david@gibson.dropbear.id.au>
 */

/* NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
#define _GNU_SOURCE

#include <arpa/inet.h>
#include <errno.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "common.h"

#define PORT	13256U
#define CPORT	13257U

/* 127.0.0.1:PORT */
static const struct sockaddr_in addr = SOCKADDR_INIT(INADDR_LOOPBACK, PORT);

/* 127.0.0.1:CPORT */
static const struct sockaddr_in caddr = SOCKADDR_INIT(INADDR_LOOPBACK, CPORT);

/* Put ourselves into a network sandbox */
static void net_sandbox(void)
{
	/* NOLINTNEXTLINE(altera-struct-pack-align) */
	const struct req_t {
		struct nlmsghdr nlh;
		struct ifinfomsg ifm;
	} __attribute__((packed)) req = {
		.nlh.nlmsg_type		= RTM_NEWLINK,
		.nlh.nlmsg_flags	= NLM_F_REQUEST,
		.nlh.nlmsg_len		= sizeof(req),
		.nlh.nlmsg_seq		= 1,
		.ifm.ifi_family		= AF_UNSPEC,
                .ifm.ifi_index		= 1,
                .ifm.ifi_flags		= IFF_UP,
                .ifm.ifi_change		= IFF_UP,
	};
	int nl;

	if (unshare(CLONE_NEWUSER | CLONE_NEWNET))
		die("unshare(): %s\n", strerror(errno));

	/* Bring up lo in the new netns */
	nl = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
	if (nl < 0)
		die("Can't create netlink socket: %s\n", strerror(errno));

	if (send(nl, &req, sizeof(req), 0) < 0)
		die("Netlink send(): %s\n", strerror(errno));
	close(nl);
}

static void check(void)
{
	int s1, s2, op;

	s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s1 < 0)
		die("socket() 1: %s\n", strerror(errno));

	if (bind(s1, (struct sockaddr *)&addr, sizeof(addr)))
		die("bind() 1: %s\n", strerror(errno));

	if (listen(s1, 0))
		die("listen(): %s\n", strerror(errno));

	s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s2 < 0)
		die("socket() 2: %s\n", strerror(errno));

	op = TCP_REPAIR_ON;
	if (setsockopt(s2, SOL_TCP, TCP_REPAIR, &op, sizeof(op)))
		die("TCP_REPAIR: %s\n", strerror(errno));

	if (bind(s2, (struct sockaddr *)&addr, sizeof(addr)))
		die("bind() 2: %s\n", strerror(errno));

	if (connect(s2, (struct sockaddr *)&caddr, sizeof(caddr)))
		die("connect(): %s\n", strerror(errno));

	op = TCP_REPAIR_OFF_NO_WP;
	if (setsockopt(s2, SOL_TCP, TCP_REPAIR, &op, sizeof(op)))
		die("TCP_REPAIR: %s\n", strerror(errno));

	close(s1);
	close(s2);
}

int main(int argc, char *argv[])
{
	(void)argc;
	(void)argv;

	net_sandbox();

	check();

	printf("Repair mode appears to properly suppress conflicts with listening sockets\n");

	exit(0);
}

debug log:

solving d31fe3f7 ...
found d31fe3f7 in https://passt.top/passt

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).