public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
8ade587c623ac0a76e5c9218a073df5c2df58ad5 blob 3378 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
129
130
131
132
133
134
135
136
137
138
139
140
141
 
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright Red Hat
 * Author: David Gibson <david@gibson.dropbear.id.au>
 *
 * Passt/pasta interface types and IDs
 */

#include <errno.h>
#include <stdint.h>
#include <assert.h>
#include <netinet/in.h>

#include "util.h"
#include "pif.h"
#include "siphash.h"
#include "ip.h"
#include "inany.h"
#include "epoll_ctl.h"

const char pif_type_str[][PIF_NAME_SIZE] = {
	[PIF_NONE]		= "<none>",
	[PIF_HOST]		= "HOST",
	[PIF_TAP]		= "TAP",
	[PIF_SPLICE]		= "SPLICE",
};
static_assert(ARRAY_SIZE(pif_type_str) == PIF_NUM_TYPES,
	      "pif_type_str[] doesn't match enum pif_type");


/** pif_sockaddr() - Construct a socket address suitable for an interface
 * @c:		Execution context
 * @sa:		Pointer to sockaddr to fill in
 * @pif:	Interface to create the socket address
 * @addr:	IPv[46] address
 * @port:	Port (host byte order)
 */
void pif_sockaddr(const struct ctx *c, union sockaddr_inany *sa,
		  uint8_t pif, const union inany_addr *addr, in_port_t port)
{
	const struct in_addr *v4 = inany_v4(addr);

	assert(pif_is_socket(pif));

	if (v4) {
		sa->sa_family = AF_INET;
		sa->sa4.sin_addr = *v4;
		sa->sa4.sin_port = htons(port);
		memset(&sa->sa4.sin_zero, 0, sizeof(sa->sa4.sin_zero));
	} else {
		sa->sa_family = AF_INET6;
		sa->sa6.sin6_addr = addr->a6;
		sa->sa6.sin6_port = htons(port);
		if (IN6_IS_ADDR_LINKLOCAL(&addr->a6)) {
			if (pif == PIF_HOST)
				sa->sa6.sin6_scope_id = c->ifi6;
			else if (pif == PIF_SPLICE)
				sa->sa6.sin6_scope_id = c->pasta_ifi;
		} else {
			sa->sa6.sin6_scope_id = 0;
		}
		sa->sa6.sin6_flowinfo = 0;
	}
}

/** pif_listen() - Open a listening socket on a specified pif
 * @c:		Execution context
 * @proto:	Socket protocol (IPPROTO_TCP or IPPROTO_UDP)
 * @pif:	Interface for this socket
 * @addr:	Address to bind to, or NULL for dual-stack any
 * @ifname:	Interface for binding, NULL for any
 * @port:	Port number to bind to (host byte order)
 * @rule:	Forwarding rule index this socket belongs to
 *
 * NOTE: For namespace pifs, this must be called having already entered the
 * relevant namespace.
 *
 * Return: newly created socket, negative error code on failure
 */
int pif_listen(const struct ctx *c, uint8_t proto, uint8_t pif,
	       const union inany_addr *addr, const char *ifname,
	       in_port_t port, unsigned rule)
{
	enum epoll_type type;
	union epoll_ref ref;
	int ret;

	assert(pif_is_socket(pif));

	if (proto == IPPROTO_TCP)
		type = EPOLL_TYPE_TCP_LISTEN;
	else if (proto == IPPROTO_UDP)
		type = EPOLL_TYPE_UDP_LISTEN;
	else
		return -EPROTONOSUPPORT;

	if (!c->ifi4) {
		if (!addr)
			/* Restrict to v6 only */
			addr = &inany_any6;
		else if (inany_v4(addr))
			return -EAFNOSUPPORT;
	}
	if (!c->ifi6) {
		if (!addr)
			/* Restrict to v4 only */
			addr = &inany_any4;
		else if (!inany_v4(addr))
			return -EAFNOSUPPORT;
	}

	if (!addr) {
		ref.fd = sock_l4_dualstack_any(c, type, port, ifname);
	} else {
		union sockaddr_inany sa;

		pif_sockaddr(c, &sa, pif, addr, port);
		ref.fd = sock_l4(c, type, &sa, ifname);
	}

	if (ref.fd < 0)
		return ref.fd;

	ref.type = type;
	ref.listen.port = port;
	ref.listen.pif = pif;
	ref.listen.rule = rule;

	if (proto == IPPROTO_TCP && listen(ref.fd, 128) < 0) {
		ret = -errno;
		goto fail;
	}

	ret = epoll_add(c->epollfd, EPOLLIN, ref);
	if (ret < 0)
		goto fail;

	return ref.fd;
fail:
	close(ref.fd);
	return ret;
}
debug log:

solving 8ade587c ...
found 8ade587c in https://archives.passt.top/passt-dev/20260616010936.1672156-5-david@gibson.dropbear.id.au/
found 4cf0f6ed in https://archives.passt.top/passt-dev/20260616010936.1672156-4-david@gibson.dropbear.id.au/
found d5e31613 in https://passt.top/passt
preparing index
index prepared:
100644 d5e316132ff07f200811b75d2a0d12663fe0bdd5	pif.c

applying [1/2] https://archives.passt.top/passt-dev/20260616010936.1672156-4-david@gibson.dropbear.id.au/
diff --git a/pif.c b/pif.c
index d5e31613..4cf0f6ed 100644


applying [2/2] https://archives.passt.top/passt-dev/20260616010936.1672156-5-david@gibson.dropbear.id.au/
diff --git a/pif.c b/pif.c
index 4cf0f6ed..8ade587c 100644

Checking patch pif.c...
Applied patch pif.c cleanly.
Checking patch pif.c...
Applied patch pif.c cleanly.

index at:
100644 8ade587c623ac0a76e5c9218a073df5c2df58ad5	pif.c

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).