passt/pif.h
David Gibson b8d4fac6a2 util, pif: Replace sock_l4() with pif_sock_l4()
The sock_l4() function is very convenient for creating sockets bound to
a given address, but its interface has some problems.

Most importantly, the address and port alone aren't enough in some cases.
For link-local addresses (at least) we also need the pif in order to
properly construct a socket adddress.  This case doesn't yet arise, but
it might cause us trouble in future.

Additionally, sock_l4() can take AF_UNSPEC with the special meaning that it
should attempt to create a "dual stack" socket which will respond to both
IPv4 and IPv6 traffic.  This only makes sense if there is no specific
address given.  We verify this at runtime, but it would be nicer if we
could enforce it structurally.

For sockets associated specifically with a single flow we already replaced
sock_l4() with flowside_sock_l4() which avoids those problems.  Now,
replace all the remaining users with a new pif_sock_l4() which also takes
an explicit pif.

The new function takes the address as an inany *, with NULL indicating the
dual stack case.  This does add some complexity in some of the callers,
however future planned cleanups should make this go away again.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2024-09-25 19:03:15 +02:00

66 lines
1.5 KiB
C

/* 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
*/
#ifndef PIF_H
#define PIF_H
union inany_addr;
union sockaddr_inany;
/**
* enum pif_type - Type of passt/pasta interface ("pif")
*
* pifs can be an L4 level channel (sockets) or an L2 level channel (tap device
* or qemu socket).
*/
enum pif_type {
/* Invalid or not present pif */
PIF_NONE = 0,
/* Host socket interface */
PIF_HOST,
/* Qemu socket or namespace tuntap interface */
PIF_TAP,
/* Namespace socket interface for splicing */
PIF_SPLICE,
PIF_NUM_TYPES,
};
#define PIF_NAMELEN 8
extern const char *pif_type_str[];
static inline const char *pif_type(enum pif_type pt)
{
if (pt < PIF_NUM_TYPES)
return pif_type_str[pt];
else
return "?";
}
static inline const char *pif_name(uint8_t pif)
{
return pif_type(pif);
}
/**
* pif_is_socket() - Is interface implemented via L4 sockets?
* @pif: pif to check
*
* Return: true of @pif is an L4 socket based interface, otherwise false
*/
static inline bool pif_is_socket(uint8_t pif)
{
return pif == PIF_HOST || pif == PIF_SPLICE;
}
void pif_sockaddr(const struct ctx *c, union sockaddr_inany *sa, socklen_t *sl,
uint8_t pif, const union inany_addr *addr, in_port_t port);
int pif_sock_l4(const struct ctx *c, enum epoll_type type, uint8_t pif,
const union inany_addr *addr, const char *ifname,
in_port_t port, uint32_t data);
#endif /* PIF_H */