diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2024-02-29 15:15:34 +1100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2024-03-12 01:49:05 +0100 |
commit | 4779dfe12fd0aa6d94f9029e430d55f60f4c581f (patch) | |
tree | d22ce88dd4b322cbf6ce793d58e7e3edfcadc717 /icmp.c | |
parent | 02cbdb0b86fb8b03026bc542606333ebfc819f0f (diff) | |
download | passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.tar passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.tar.gz passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.tar.bz2 passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.tar.lz passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.tar.xz passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.tar.zst passt-4779dfe12fd0aa6d94f9029e430d55f60f4c581f.zip |
icmp: Use 'flowside' epoll references for ping sockets
Currently ping sockets use a custom epoll reference type which includes
the ICMP id. However, now that we have entries in the flow table for
ping flows, finding that is sufficient to get everything else we want,
including the id. Therefore remove the icmp_epoll_ref type and use the
general 'flowside' field for ping sockets.
Having done this we no longer need separate EPOLL_TYPE_ICMP and
EPOLL_TYPE_ICMPV6 reference types, because we can easily determine
which case we have from the flow type. Merge both types into
EPOLL_TYPE_PING.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'icmp.c')
-rw-r--r-- | icmp.c | 34 |
1 files changed, 17 insertions, 17 deletions
@@ -49,19 +49,19 @@ #define SOCKSIDE 0 #define TAPSIDE 1 +#define PINGF(idx) (&(FLOW(idx)->ping)) + /* Indexed by ICMP echo identifier */ static struct icmp_ping_flow *icmp_id_map[IP_VERSIONS][ICMP_NUM_IDS]; /** * icmp_sock_handler() - Handle new data from ICMP or ICMPv6 socket * @c: Execution context - * @af: Address family (AF_INET or AF_INET6) * @ref: epoll reference */ -void icmp_sock_handler(const struct ctx *c, sa_family_t af, union epoll_ref ref) +void icmp_sock_handler(const struct ctx *c, union epoll_ref ref) { - struct icmp_ping_flow *pingf = af == AF_INET - ? icmp_id_map[V4][ref.icmp.id] : icmp_id_map[V6][ref.icmp.id]; + struct icmp_ping_flow *pingf = PINGF(ref.flowside.flow); union sockaddr_inany sr; socklen_t sl = sizeof(sr); char buf[USHRT_MAX]; @@ -78,27 +78,26 @@ void icmp_sock_handler(const struct ctx *c, sa_family_t af, union epoll_ref ref) flow_err(pingf, "recvfrom() error: %s", strerror(errno)); return; } - if (sr.sa_family != af) - goto unexpected; - if (af == AF_INET) { + if (pingf->f.type == FLOW_PING4) { struct icmphdr *ih4 = (struct icmphdr *)buf; - if ((size_t)n < sizeof(*ih4) || ih4->type != ICMP_ECHOREPLY) + if (sr.sa_family != AF_INET || (size_t)n < sizeof(*ih4) || + ih4->type != ICMP_ECHOREPLY) goto unexpected; /* Adjust packet back to guest-side ID */ - ih4->un.echo.id = htons(ref.icmp.id); + ih4->un.echo.id = htons(pingf->id); seq = ntohs(ih4->un.echo.sequence); - } else if (af == AF_INET6) { + } else if (pingf->f.type == FLOW_PING6) { struct icmp6hdr *ih6 = (struct icmp6hdr *)buf; - if ((size_t)n < sizeof(*ih6) || + if (sr.sa_family != AF_INET6 || (size_t)n < sizeof(*ih6) || ih6->icmp6_type != ICMPV6_ECHO_REPLY) goto unexpected; /* Adjust packet back to guest-side ID */ - ih6->icmp6_identifier = htons(ref.icmp.id); + ih6->icmp6_identifier = htons(pingf->id); seq = ntohs(ih6->icmp6_sequence); } else { ASSERT(0); @@ -113,11 +112,11 @@ void icmp_sock_handler(const struct ctx *c, sa_family_t af, union epoll_ref ref) } flow_dbg(pingf, "echo reply to tap, ID: %"PRIu16", seq: %"PRIu16, - ref.icmp.id, seq); + pingf->id, seq); - if (af == AF_INET) + if (pingf->f.type == FLOW_PING4) tap_icmp4_send(c, sr.sa4.sin_addr, tap_ip4_daddr(c), buf, n); - else if (af == AF_INET6) + else if (pingf->f.type == FLOW_PING6) tap_icmp6_send(c, &sr.sa6.sin6_addr, tap_ip6_daddr(c, &sr.sa6.sin6_addr), buf, n); return; @@ -159,7 +158,7 @@ static struct icmp_ping_flow *icmp_ping_new(const struct ctx *c, sa_family_t af, uint16_t id) { uint8_t flowtype = af == AF_INET ? FLOW_PING4 : FLOW_PING6; - union icmp_epoll_ref iref = { .id = id }; + union epoll_ref ref = { .type = EPOLL_TYPE_PING }; union flow *flow = flow_alloc(); struct icmp_ping_flow *pingf; const void *bind_addr; @@ -181,8 +180,9 @@ static struct icmp_ping_flow *icmp_ping_new(const struct ctx *c, bind_if = c->ip6.ifname_out; } + ref.flowside = FLOW_SIDX(flow, SOCKSIDE); pingf->sock = sock_l4(c, af, flow_proto[flowtype], bind_addr, bind_if, - 0, iref.u32); + 0, ref.data); if (pingf->sock < 0) { warn("Cannot open \"ping\" socket. You might need to:"); |