udp: move udpX_l2_buf_t and udpX_l2_mh_sock out of udp_update_hdrX()

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
This commit is contained in:
Laurent Vivier 2024-01-11 16:29:54 +01:00
parent 4d7ca742ef
commit 72cadf34ad

105
udp.c
View file

@ -567,21 +567,22 @@ static void udp_splice_sendfrom(const struct ctx *c, unsigned start, unsigned n,
* *
* Return: size of tap frame with headers * Return: size of tap frame with headers
*/ */
static size_t udp_update_hdr4(const struct ctx *c, int n, in_port_t dstport, static size_t udp_update_hdr4(const struct ctx *c, struct iphdr *iph,
const struct timespec *now) size_t data_len, struct sockaddr_in *s_in,
in_port_t dstport, const struct timespec *now)
{ {
struct udp4_l2_buf_t *b = &udp4_l2_buf[n]; struct udphdr *uh = (struct udphdr *)(iph + 1);
const struct in_addr *src; const struct in_addr *src;
in_port_t src_port; in_port_t src_port;
size_t ip_len; size_t ip_len;
ip_len = udp4_l2_mh_sock[n].msg_len + sizeof(b->iph) + sizeof(b->uh); ip_len = data_len + sizeof(struct iphdr) + sizeof(struct udphdr);
b->iph.tot_len = htons(ip_len); iph->tot_len = htons(ip_len);
b->iph.daddr = c->ip4.addr_seen.s_addr; iph->daddr = c->ip4.addr_seen.s_addr;
src = &b->s_in.sin_addr; src = &s_in->sin_addr;
src_port = ntohs(b->s_in.sin_port); src_port = ntohs(s_in->sin_port);
if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) && if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) &&
IN4_ARE_ADDR_EQUAL(src, &c->ip4.dns_host) && src_port == 53) { IN4_ARE_ADDR_EQUAL(src, &c->ip4.dns_host) && src_port == 53) {
@ -600,15 +601,15 @@ static size_t udp_update_hdr4(const struct ctx *c, int n, in_port_t dstport,
src = &c->ip4.gw; src = &c->ip4.gw;
} }
b->iph.saddr = src->s_addr; iph->saddr = src->s_addr;
b->iph.check = csum_ip4_header(b->iph.tot_len, IPPROTO_UDP, iph->check = csum_ip4_header(iph->tot_len, IPPROTO_UDP,
*src, c->ip4.addr_seen); *src, c->ip4.addr_seen);
b->uh.source = b->s_in.sin_port; uh->source = s_in->sin_port;
b->uh.dest = htons(dstport); uh->dest = htons(dstport);
b->uh.len = htons(udp4_l2_mh_sock[n].msg_len + sizeof(b->uh)); uh->len = htons(data_len + sizeof(struct udphdr));
return tap_iov_len(c, &b->taph, ip_len); return ip_len;
} }
/** /**
@ -620,23 +621,24 @@ static size_t udp_update_hdr4(const struct ctx *c, int n, in_port_t dstport,
* *
* Return: size of tap frame with headers * Return: size of tap frame with headers
*/ */
static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport, static size_t udp_update_hdr6(const struct ctx *c, struct ipv6hdr *ip6h,
const struct timespec *now) size_t data_len, struct sockaddr_in6 *s_in6,
in_port_t dstport, const struct timespec *now)
{ {
struct udp6_l2_buf_t *b = &udp6_l2_buf[n]; struct udphdr *uh = (struct udphdr *)(ip6h + 1);
const struct in6_addr *src, *dst; const struct in6_addr *src, *dst;
uint16_t payload_len; uint16_t payload_len;
in_port_t src_port; in_port_t src_port;
size_t ip_len; size_t ip_len;
dst = &c->ip6.addr_seen; dst = &c->ip6.addr_seen;
src = &b->s_in6.sin6_addr; src = &s_in6->sin6_addr;
src_port = ntohs(b->s_in6.sin6_port); src_port = ntohs(s_in6->sin6_port);
ip_len = udp6_l2_mh_sock[n].msg_len + sizeof(b->ip6h) + sizeof(b->uh); ip_len = data_len + sizeof(struct ipv6hdr) + sizeof(struct udphdr);
payload_len = udp6_l2_mh_sock[n].msg_len + sizeof(b->uh); payload_len = data_len + sizeof(struct udphdr);
b->ip6h.payload_len = htons(payload_len); ip6h->payload_len = htons(payload_len);
if (IN6_IS_ADDR_LINKLOCAL(src)) { if (IN6_IS_ADDR_LINKLOCAL(src)) {
dst = &c->ip6.addr_ll_seen; dst = &c->ip6.addr_ll_seen;
@ -668,23 +670,22 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport,
src = &c->ip6.gw; src = &c->ip6.gw;
else else
src = &c->ip6.addr_ll; src = &c->ip6.addr_ll;
} }
b->ip6h.daddr = *dst; ip6h->daddr = *dst;
b->ip6h.saddr = *src; ip6h->saddr = *src;
b->ip6h.version = 6; ip6h->version = 6;
b->ip6h.nexthdr = IPPROTO_UDP; ip6h->nexthdr = IPPROTO_UDP;
b->ip6h.hop_limit = 255; ip6h->hop_limit = 255;
b->uh.source = b->s_in6.sin6_port; uh->source = s_in6->sin6_port;
b->uh.dest = htons(dstport); uh->dest = htons(dstport);
b->uh.len = b->ip6h.payload_len; uh->len = ip6h->payload_len;
b->uh.check = 0; uh->check = 0;
b->uh.check = csum(&b->uh, payload_len, uh->check = csum(uh, payload_len,
proto_ipv6_header_psum(payload_len, IPPROTO_UDP, proto_ipv6_header_psum(payload_len, IPPROTO_UDP,
src, dst)); src, dst));
return tap_iov_len(c, &b->taph, ip_len); return ip_len;
} }
/** /**
@ -698,6 +699,11 @@ static size_t udp_update_hdr6(const struct ctx *c, int n, in_port_t dstport,
* *
* Return: size of tap frame with headers * Return: size of tap frame with headers
*/ */
#pragma GCC diagnostic push
/* ignore unaligned pointer value warning for &udp6_l2_buf[i].ip6h and
* &udp4_l2_buf[i].iph
*/
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
static void udp_tap_send(const struct ctx *c, static void udp_tap_send(const struct ctx *c,
unsigned int start, unsigned int n, unsigned int start, unsigned int n,
in_port_t dstport, bool v6, const struct timespec *now) in_port_t dstport, bool v6, const struct timespec *now)
@ -711,18 +717,31 @@ static void udp_tap_send(const struct ctx *c,
tap_iov = udp4_l2_iov_tap; tap_iov = udp4_l2_iov_tap;
for (i = start; i < start + n; i++) { for (i = start; i < start + n; i++) {
size_t buf_len; size_t ip_len;
if (v6) if (v6) {
buf_len = udp_update_hdr6(c, i, dstport, now); ip_len = udp_update_hdr6(c, &udp6_l2_buf[i].ip6h,
else udp6_l2_mh_sock[i].msg_len,
buf_len = udp_update_hdr4(c, i, dstport, now); &udp6_l2_buf[i].s_in6, dstport,
now);
tap_iov[i].iov_len = tap_iov_len(c,
&udp6_l2_buf[i].taph,
ip_len);
} else {
ip_len = udp_update_hdr4(c, &udp4_l2_buf[i].iph,
udp4_l2_mh_sock[i].msg_len,
&udp4_l2_buf[i].s_in,
dstport, now);
tap_iov[i].iov_len = buf_len; tap_iov[i].iov_len = tap_iov_len(c,
&udp4_l2_buf[i].taph,
ip_len);
}
} }
tap_send_frames(c, tap_iov + start, n); tap_send_frames(c, tap_iov + start, n);
} }
#pragma GCC diagnostic pop
/** /**
* udp_sock_handler() - Handle new data from socket * udp_sock_handler() - Handle new data from socket