flow, icmp: Use general flow forwarding rules for ICMP

Current ICMP hard codes its forwarding rules, and never applies any
translations.  Change it to use the flow_target() function, so that
it's translated the same as TCP (excluding TCP specific port
redirection).

This means that gw mapping now applies to ICMP so "ping <gw address>" will
now ping the host's loopback instead of the actual gw machine.  This
removes the surprising behaviour that the target you ping might not be the
same as you connect to with TCP.

This removes the last user of flow_target_af(), so that's removed as well.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-07-18 15:26:44 +10:00 committed by Stefano Brivio
parent 060f24e310
commit c000f2aba6
2 changed files with 10 additions and 38 deletions

32
flow.c
View file

@ -369,38 +369,6 @@ const struct flowside *flow_initiate_sa(union flow *flow, uint8_t pif,
return ini; return ini;
} }
/**
* flow_target_af() - Move flow to TGT, setting TGTSIDE details
* @flow: Flow to change state
* @pif: pif of the target side
* @af: Address family for @eaddr and @faddr
* @saddr: Source address (pointer to in_addr or in6_addr)
* @sport: Endpoint port
* @daddr: Destination address (pointer to in_addr or in6_addr)
* @dport: Destination port
*
* Return: pointer to the target flowside information
*/
const struct flowside *flow_target_af(union flow *flow, uint8_t pif,
sa_family_t af,
const void *saddr, in_port_t sport,
const void *daddr, in_port_t dport)
{
struct flow_common *f = &flow->f;
struct flowside *tgt = &f->side[TGTSIDE];
ASSERT(pif != PIF_NONE);
ASSERT(flow_new_entry == flow && f->state == FLOW_STATE_INI);
ASSERT(f->type == FLOW_TYPE_NONE);
ASSERT(f->pif[INISIDE] != PIF_NONE && f->pif[TGTSIDE] == PIF_NONE);
flowside_from_af(tgt, af, daddr, dport, saddr, sport);
f->pif[TGTSIDE] = pif;
flow_set_state(f, FLOW_STATE_TGT);
return tgt;
}
/** /**
* flow_target() - Determine where flow should forward to, and move to TGT * flow_target() - Determine where flow should forward to, and move to TGT
* @c: Execution context * @c: Execution context

16
icmp.c
View file

@ -169,24 +169,28 @@ static struct icmp_ping_flow *icmp_ping_new(const struct ctx *c,
sa_family_t af, uint16_t id, sa_family_t af, uint16_t id,
const void *saddr, const void *daddr) const void *saddr, const void *daddr)
{ {
uint8_t proto = af == AF_INET ? IPPROTO_ICMP : IPPROTO_ICMPV6;
uint8_t flowtype = af == AF_INET ? FLOW_PING4 : FLOW_PING6; uint8_t flowtype = af == AF_INET ? FLOW_PING4 : FLOW_PING6;
union epoll_ref ref = { .type = EPOLL_TYPE_PING }; union epoll_ref ref = { .type = EPOLL_TYPE_PING };
union flow *flow = flow_alloc(); union flow *flow = flow_alloc();
struct icmp_ping_flow *pingf; struct icmp_ping_flow *pingf;
const struct flowside *tgt; const struct flowside *tgt;
const void *bind_addr;
if (!flow) if (!flow)
return NULL; return NULL;
flow_initiate_af(flow, PIF_TAP, af, saddr, id, daddr, id); flow_initiate_af(flow, PIF_TAP, af, saddr, id, daddr, id);
if (!(tgt = flow_target(c, flow, proto)))
goto cancel;
if (af == AF_INET) if (flow->f.pif[TGTSIDE] != PIF_HOST) {
bind_addr = &c->ip4.addr_out; flow_err(flow, "No support for forwarding %s from %s to %s",
else if (af == AF_INET6) proto == IPPROTO_ICMP ? "ICMP" : "ICMPv6",
bind_addr = &c->ip6.addr_out; pif_name(flow->f.pif[INISIDE]),
pif_name(flow->f.pif[TGTSIDE]));
goto cancel;
}
tgt = flow_target_af(flow, PIF_HOST, af, bind_addr, 0, daddr, 0);
pingf = FLOW_SET_TYPE(flow, flowtype, ping); pingf = FLOW_SET_TYPE(flow, flowtype, ping);
pingf->seq = -1; pingf->seq = -1;