mirror of
https://passt.top/passt
synced 2025-06-15 03:45:34 +02:00

We've recently added support for propagating ICMP errors related to a UDP flow from the host to the guest, by handling the extended UDP error on the socket and synthesizing a suitable ICMP on the tap interface. Currently we create that ICMP with a source address of the "offender" from the extended error information - the source of the ICMP error received on the host. However, we don't translate this address for cases where we NAT between host and guest. This means (amongst other things) that we won't get a "Connection refused" error as expected if send data from the guest to the --map-host-loopback address. The error comes from 127.0.0.1 on the host, which doesn't make sense on the tap interface and will be discarded by the guest. Because ICMP errors can be sent by an intermediate host, not just by the endpoints of the flow, we can't handle this translation purely with the information in the flow table entry. We need to explicitly translate this address by our NAT rules, which we can do with the nat_inbound() helper. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
60 lines
1.8 KiB
C
60 lines
1.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright Red Hat
|
|
* Author: Stefano Brivio <sbrivio@redhat.com>
|
|
* Author: David Gibson <david@gibson.dropbear.id.au>
|
|
*/
|
|
|
|
#ifndef FWD_H
|
|
#define FWD_H
|
|
|
|
union inany_addr;
|
|
struct flowside;
|
|
|
|
/* Number of ports for both TCP and UDP */
|
|
#define NUM_PORTS (1U << 16)
|
|
|
|
void fwd_probe_ephemeral(void);
|
|
bool fwd_port_is_ephemeral(in_port_t port);
|
|
|
|
enum fwd_ports_mode {
|
|
FWD_UNSET = 0,
|
|
FWD_SPEC = 1,
|
|
FWD_NONE,
|
|
FWD_AUTO,
|
|
FWD_ALL,
|
|
};
|
|
|
|
#define PORT_BITMAP_SIZE DIV_ROUND_UP(NUM_PORTS, 8)
|
|
|
|
/**
|
|
* fwd_ports - Describes port forwarding for one protocol and direction
|
|
* @mode: Overall forwarding mode (all, none, auto, specific ports)
|
|
* @scan4: /proc/net fd to scan for IPv4 ports when in AUTO mode
|
|
* @scan6: /proc/net fd to scan for IPv6 ports when in AUTO mode
|
|
* @map: Bitmap describing which ports are forwarded
|
|
* @delta: Offset between the original destination and mapped port number
|
|
*/
|
|
struct fwd_ports {
|
|
enum fwd_ports_mode mode;
|
|
int scan4;
|
|
int scan6;
|
|
uint8_t map[PORT_BITMAP_SIZE];
|
|
in_port_t delta[NUM_PORTS];
|
|
};
|
|
|
|
void fwd_scan_ports_tcp(struct fwd_ports *fwd, const struct fwd_ports *rev);
|
|
void fwd_scan_ports_udp(struct fwd_ports *fwd, const struct fwd_ports *rev,
|
|
const struct fwd_ports *tcp_fwd,
|
|
const struct fwd_ports *tcp_rev);
|
|
void fwd_scan_ports_init(struct ctx *c);
|
|
|
|
bool nat_inbound(const struct ctx *c, const union inany_addr *addr,
|
|
union inany_addr *translated);
|
|
uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t proto,
|
|
const struct flowside *ini, struct flowside *tgt);
|
|
uint8_t fwd_nat_from_splice(const struct ctx *c, uint8_t proto,
|
|
const struct flowside *ini, struct flowside *tgt);
|
|
uint8_t fwd_nat_from_host(const struct ctx *c, uint8_t proto,
|
|
const struct flowside *ini, struct flowside *tgt);
|
|
|
|
#endif /* FWD_H */
|