aboutgitcodebugslistschat
path: root/icmp.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-09-26 23:38:22 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-09-27 01:28:02 +0200
commitdd581730e54b934f80d5b6a820136707dc71c664 (patch)
treec58b140d407f4b308e1fc1d21703b444ea34cabd /icmp.c
parentdfc451319034f594037822b3193a30fa5715175f (diff)
downloadpasst-dd581730e54b934f80d5b6a820136707dc71c664.tar
passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.gz
passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.bz2
passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.lz
passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.xz
passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.zst
passt-dd581730e54b934f80d5b6a820136707dc71c664.zip
tap: Completely de-serialise input message batches
Until now, messages would be passed to protocol handlers in a single batch only if they happened to be dequeued in a row. Packets interleaved between different connections would result in multiple calls to the same protocol handler for a single connection. Instead, keep track of incoming packet descriptors, arrange them in sequences, and call protocol handlers only as we completely sorted input messages in batches. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'icmp.c')
-rw-r--r--icmp.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/icmp.c b/icmp.c
index 49fdf91..51848c2 100644
--- a/icmp.c
+++ b/icmp.c
@@ -141,23 +141,26 @@ void icmp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
* Return: count of consumed packets (always 1, even if malformed)
*/
int icmp_tap_handler(struct ctx *c, int af, void *addr,
- struct tap_msg *msg, int count, struct timespec *now)
+ struct tap_l4_msg *msg, int count, struct timespec *now)
{
(void)count;
if (af == AF_INET) {
- struct icmphdr *ih = (struct icmphdr *)msg[0].l4h;
union icmp_epoll_ref iref = { .v6 = 0 };
struct sockaddr_in sa = {
.sin_family = AF_INET,
.sin_addr = { .s_addr = INADDR_ANY },
- .sin_port = ih->un.echo.id,
};
+ struct icmphdr *ih;
int id, s;
+ ih = (struct icmphdr *)(pkt_buf + msg[0].pkt_buf_offset);
+
if (msg[0].l4_len < sizeof(*ih) || ih->type != ICMP_ECHO)
return 1;
+ sa.sin_port = ih->un.echo.id;
+
iref.id = id = ntohs(ih->un.echo.id);
if ((s = icmp_id_map[V4][id].sock) <= 0) {
@@ -171,22 +174,25 @@ int icmp_tap_handler(struct ctx *c, int af, void *addr,
bitmap_set(icmp_act[V4], id);
sa.sin_addr = *(struct in_addr *)addr;
- sendto(s, msg[0].l4h, msg[0].l4_len, MSG_NOSIGNAL,
+ sendto(s, ih, msg[0].l4_len, MSG_NOSIGNAL,
(struct sockaddr *)&sa, sizeof(sa));
} else if (af == AF_INET6) {
- struct icmp6hdr *ih = (struct icmp6hdr *)msg[0].l4h;
union icmp_epoll_ref iref = { .v6 = 1 };
struct sockaddr_in6 sa = {
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_ANY_INIT,
- .sin6_port = ih->icmp6_identifier,
};
+ struct icmp6hdr *ih;
int id, s;
+ ih = (struct icmp6hdr *)(pkt_buf + msg[0].pkt_buf_offset);
+
if (msg[0].l4_len < sizeof(*ih) ||
(ih->icmp6_type != 128 && ih->icmp6_type != 129))
return 1;
+ sa.sin6_port = ih->icmp6_identifier;
+
iref.id = id = ntohs(ih->icmp6_identifier);
if ((s = icmp_id_map[V6][id].sock) <= 0) {
s = sock_l4(c, AF_INET6, IPPROTO_ICMPV6, id, 0,
@@ -200,7 +206,7 @@ int icmp_tap_handler(struct ctx *c, int af, void *addr,
bitmap_set(icmp_act[V6], id);
sa.sin6_addr = *(struct in6_addr *)addr;
- sendto(s, msg[0].l4h, msg[0].l4_len, MSG_NOSIGNAL,
+ sendto(s, ih, msg[0].l4_len, MSG_NOSIGNAL,
(struct sockaddr *)&sa, sizeof(sa));
}