treewide: Standardise variable names for various packet lengths

At various points we need to track the lengths of a packet including or
excluding various different sets of headers.  We don't always use the same
variable names for doing so.  Worse in some places we use the same name
for different things: e.g. tcp_fill_headers[46]() use ip_len for the
length including the IP headers, but then tcp_send_flag() which calls it
uses it to mean the IP payload length only.

To improve clarity, standardise on these names:
   dlen:		L4 protocol payload length ("data length")
   l4len:		plen + length of L4 protocol header
   l3len:		l4len + length of IPv4/IPv6 header
   l2len:		l3len + length of L2 (ethernet) header

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-05-01 16:53:49 +10:00 committed by Stefano Brivio
parent 9e22c53aa9
commit 5566386f5f
12 changed files with 194 additions and 193 deletions

6
arp.c
View file

@ -43,7 +43,7 @@ int arp(const struct ctx *c, const struct pool *p)
struct ethhdr *eh; struct ethhdr *eh;
struct arphdr *ah; struct arphdr *ah;
struct arpmsg *am; struct arpmsg *am;
size_t len; size_t l2len;
eh = packet_get(p, 0, 0, sizeof(*eh), NULL); eh = packet_get(p, 0, 0, sizeof(*eh), NULL);
ah = packet_get(p, 0, sizeof(*eh), sizeof(*ah), NULL); ah = packet_get(p, 0, sizeof(*eh), sizeof(*ah), NULL);
@ -78,11 +78,11 @@ int arp(const struct ctx *c, const struct pool *p)
memcpy(am->tip, am->sip, sizeof(am->tip)); memcpy(am->tip, am->sip, sizeof(am->tip));
memcpy(am->sip, swap, sizeof(am->sip)); memcpy(am->sip, swap, sizeof(am->sip));
len = sizeof(*eh) + sizeof(*ah) + sizeof(*am); l2len = sizeof(*eh) + sizeof(*ah) + sizeof(*am);
memcpy(eh->h_dest, eh->h_source, sizeof(eh->h_dest)); memcpy(eh->h_dest, eh->h_source, sizeof(eh->h_dest));
memcpy(eh->h_source, c->mac, sizeof(eh->h_source)); memcpy(eh->h_source, c->mac, sizeof(eh->h_source));
tap_send_single(c, eh, len); tap_send_single(c, eh, l2len);
return 1; return 1;
} }

View file

@ -116,19 +116,19 @@ uint16_t csum_fold(uint32_t sum)
/** /**
* csum_ip4_header() - Calculate IPv4 header checksum * csum_ip4_header() - Calculate IPv4 header checksum
* @tot_len: IPv4 packet length (data + IP header, host order) * @l3len: IPv4 packet length (host order)
* @protocol: Protocol number * @protocol: Protocol number
* @saddr: IPv4 source address * @saddr: IPv4 source address
* @daddr: IPv4 destination address * @daddr: IPv4 destination address
* *
* Return: 16-bit folded sum of the IPv4 header * Return: 16-bit folded sum of the IPv4 header
*/ */
uint16_t csum_ip4_header(uint16_t tot_len, uint8_t protocol, uint16_t csum_ip4_header(uint16_t l3len, uint8_t protocol,
struct in_addr saddr, struct in_addr daddr) struct in_addr saddr, struct in_addr daddr)
{ {
uint32_t sum = L2_BUF_IP4_PSUM(protocol); uint32_t sum = L2_BUF_IP4_PSUM(protocol);
sum += htons(tot_len); sum += htons(l3len);
sum += (saddr.s_addr >> 16) & 0xffff; sum += (saddr.s_addr >> 16) & 0xffff;
sum += saddr.s_addr & 0xffff; sum += saddr.s_addr & 0xffff;
sum += (daddr.s_addr >> 16) & 0xffff; sum += (daddr.s_addr >> 16) & 0xffff;
@ -140,13 +140,13 @@ uint16_t csum_ip4_header(uint16_t tot_len, uint8_t protocol,
/** /**
* proto_ipv4_header_psum() - Calculates the partial checksum of an * proto_ipv4_header_psum() - Calculates the partial checksum of an
* IPv4 header for UDP or TCP * IPv4 header for UDP or TCP
* @tot_len: IPv4 Payload length (host order) * @l4len: IPv4 Payload length (host order)
* @proto: Protocol number * @proto: Protocol number
* @saddr: Source address * @saddr: Source address
* @daddr: Destination address * @daddr: Destination address
* Returns: Partial checksum of the IPv4 header * Returns: Partial checksum of the IPv4 header
*/ */
uint32_t proto_ipv4_header_psum(uint16_t tot_len, uint8_t protocol, uint32_t proto_ipv4_header_psum(uint16_t l4len, uint8_t protocol,
struct in_addr saddr, struct in_addr daddr) struct in_addr saddr, struct in_addr daddr)
{ {
uint32_t psum = htons(protocol); uint32_t psum = htons(protocol);
@ -155,7 +155,7 @@ uint32_t proto_ipv4_header_psum(uint16_t tot_len, uint8_t protocol,
psum += saddr.s_addr & 0xffff; psum += saddr.s_addr & 0xffff;
psum += (daddr.s_addr >> 16) & 0xffff; psum += (daddr.s_addr >> 16) & 0xffff;
psum += daddr.s_addr & 0xffff; psum += daddr.s_addr & 0xffff;
psum += htons(tot_len); psum += htons(l4len);
return psum; return psum;
} }
@ -165,22 +165,22 @@ uint32_t proto_ipv4_header_psum(uint16_t tot_len, uint8_t protocol,
* @udp4hr: UDP header, initialised apart from checksum * @udp4hr: UDP header, initialised apart from checksum
* @saddr: IPv4 source address * @saddr: IPv4 source address
* @daddr: IPv4 destination address * @daddr: IPv4 destination address
* @payload: ICMPv4 packet payload * @payload: UDP packet payload
* @len: Length of @payload (not including UDP) * @dlen: Length of @payload (not including UDP header)
*/ */
void csum_udp4(struct udphdr *udp4hr, void csum_udp4(struct udphdr *udp4hr,
struct in_addr saddr, struct in_addr daddr, struct in_addr saddr, struct in_addr daddr,
const void *payload, size_t len) const void *payload, size_t dlen)
{ {
/* UDP checksums are optional, so don't bother */ /* UDP checksums are optional, so don't bother */
udp4hr->check = 0; udp4hr->check = 0;
if (UDP4_REAL_CHECKSUMS) { if (UDP4_REAL_CHECKSUMS) {
uint16_t tot_len = len + sizeof(struct udphdr); uint16_t l4len = dlen + sizeof(struct udphdr);
uint32_t psum = proto_ipv4_header_psum(tot_len, IPPROTO_UDP, uint32_t psum = proto_ipv4_header_psum(l4len, IPPROTO_UDP,
saddr, daddr); saddr, daddr);
psum = csum_unfolded(udp4hr, sizeof(struct udphdr), psum); psum = csum_unfolded(udp4hr, sizeof(struct udphdr), psum);
udp4hr->check = csum(payload, len, psum); udp4hr->check = csum(payload, dlen, psum);
} }
} }
@ -188,9 +188,9 @@ void csum_udp4(struct udphdr *udp4hr,
* csum_icmp4() - Calculate and set checksum for an ICMP packet * csum_icmp4() - Calculate and set checksum for an ICMP packet
* @icmp4hr: ICMP header, initialised apart from checksum * @icmp4hr: ICMP header, initialised apart from checksum
* @payload: ICMP packet payload * @payload: ICMP packet payload
* @len: Length of @payload (not including ICMP header) * @dlen: Length of @payload (not including ICMP header)
*/ */
void csum_icmp4(struct icmphdr *icmp4hr, const void *payload, size_t len) void csum_icmp4(struct icmphdr *icmp4hr, const void *payload, size_t dlen)
{ {
uint32_t psum; uint32_t psum;
@ -199,7 +199,7 @@ void csum_icmp4(struct icmphdr *icmp4hr, const void *payload, size_t len)
/* Partial checksum for ICMP header alone */ /* Partial checksum for ICMP header alone */
psum = sum_16b(icmp4hr, sizeof(*icmp4hr)); psum = sum_16b(icmp4hr, sizeof(*icmp4hr));
icmp4hr->checksum = csum(payload, len, psum); icmp4hr->checksum = csum(payload, dlen, psum);
} }
/** /**
@ -227,18 +227,18 @@ uint32_t proto_ipv6_header_psum(uint16_t payload_len, uint8_t protocol,
* csum_udp6() - Calculate and set checksum for a UDP over IPv6 packet * csum_udp6() - Calculate and set checksum for a UDP over IPv6 packet
* @udp6hr: UDP header, initialised apart from checksum * @udp6hr: UDP header, initialised apart from checksum
* @payload: UDP packet payload * @payload: UDP packet payload
* @len: Length of @payload (not including UDP header) * @dlen: Length of @payload (not including UDP header)
*/ */
void csum_udp6(struct udphdr *udp6hr, void csum_udp6(struct udphdr *udp6hr,
const struct in6_addr *saddr, const struct in6_addr *daddr, const struct in6_addr *saddr, const struct in6_addr *daddr,
const void *payload, size_t len) const void *payload, size_t dlen)
{ {
uint32_t psum = proto_ipv6_header_psum(len + sizeof(struct udphdr), uint32_t psum = proto_ipv6_header_psum(dlen + sizeof(struct udphdr),
IPPROTO_UDP, saddr, daddr); IPPROTO_UDP, saddr, daddr);
udp6hr->check = 0; udp6hr->check = 0;
psum = csum_unfolded(udp6hr, sizeof(struct udphdr), psum); psum = csum_unfolded(udp6hr, sizeof(struct udphdr), psum);
udp6hr->check = csum(payload, len, psum); udp6hr->check = csum(payload, dlen, psum);
} }
/** /**
@ -247,19 +247,19 @@ void csum_udp6(struct udphdr *udp6hr,
* @saddr: IPv6 source address * @saddr: IPv6 source address
* @daddr: IPv6 destination address * @daddr: IPv6 destination address
* @payload: ICMP packet payload * @payload: ICMP packet payload
* @len: Length of @payload (not including ICMPv6 header) * @dlen: Length of @payload (not including ICMPv6 header)
*/ */
void csum_icmp6(struct icmp6hdr *icmp6hr, void csum_icmp6(struct icmp6hdr *icmp6hr,
const struct in6_addr *saddr, const struct in6_addr *daddr, const struct in6_addr *saddr, const struct in6_addr *daddr,
const void *payload, size_t len) const void *payload, size_t dlen)
{ {
uint32_t psum = proto_ipv6_header_psum(len + sizeof(*icmp6hr), uint32_t psum = proto_ipv6_header_psum(dlen + sizeof(*icmp6hr),
IPPROTO_ICMPV6, saddr, daddr); IPPROTO_ICMPV6, saddr, daddr);
icmp6hr->icmp6_cksum = 0; icmp6hr->icmp6_cksum = 0;
/* Add in partial checksum for the ICMPv6 header alone */ /* Add in partial checksum for the ICMPv6 header alone */
psum += sum_16b(icmp6hr, sizeof(*icmp6hr)); psum += sum_16b(icmp6hr, sizeof(*icmp6hr));
icmp6hr->icmp6_cksum = csum(payload, len, psum); icmp6hr->icmp6_cksum = csum(payload, dlen, psum);
} }
#ifdef __AVX2__ #ifdef __AVX2__

View file

@ -13,23 +13,23 @@ struct icmp6hdr;
uint32_t sum_16b(const void *buf, size_t len); uint32_t sum_16b(const void *buf, size_t len);
uint16_t csum_fold(uint32_t sum); uint16_t csum_fold(uint32_t sum);
uint16_t csum_unaligned(const void *buf, size_t len, uint32_t init); uint16_t csum_unaligned(const void *buf, size_t len, uint32_t init);
uint16_t csum_ip4_header(uint16_t tot_len, uint8_t protocol, uint16_t csum_ip4_header(uint16_t l3len, uint8_t protocol,
struct in_addr saddr, struct in_addr daddr); struct in_addr saddr, struct in_addr daddr);
uint32_t proto_ipv4_header_psum(uint16_t tot_len, uint8_t protocol, uint32_t proto_ipv4_header_psum(uint16_t l4len, uint8_t protocol,
struct in_addr saddr, struct in_addr daddr); struct in_addr saddr, struct in_addr daddr);
void csum_udp4(struct udphdr *udp4hr, void csum_udp4(struct udphdr *udp4hr,
struct in_addr saddr, struct in_addr daddr, struct in_addr saddr, struct in_addr daddr,
const void *payload, size_t len); const void *payload, size_t dlen);
void csum_icmp4(struct icmphdr *icmp4hr, const void *payload, size_t len); void csum_icmp4(struct icmphdr *icmp4hr, const void *payload, size_t dlen);
uint32_t proto_ipv6_header_psum(uint16_t payload_len, uint8_t protocol, uint32_t proto_ipv6_header_psum(uint16_t payload_len, uint8_t protocol,
const struct in6_addr *saddr, const struct in6_addr *saddr,
const struct in6_addr *daddr); const struct in6_addr *daddr);
void csum_udp6(struct udphdr *udp6hr, void csum_udp6(struct udphdr *udp6hr,
const struct in6_addr *saddr, const struct in6_addr *daddr, const struct in6_addr *saddr, const struct in6_addr *daddr,
const void *payload, size_t len); const void *payload, size_t dlen);
void csum_icmp6(struct icmp6hdr *icmp6hr, void csum_icmp6(struct icmp6hdr *icmp6hr,
const struct in6_addr *saddr, const struct in6_addr *daddr, const struct in6_addr *saddr, const struct in6_addr *daddr,
const void *payload, size_t len); const void *payload, size_t dlen);
uint32_t csum_unfolded(const void *buf, size_t len, uint32_t init); uint32_t csum_unfolded(const void *buf, size_t len, uint32_t init);
uint16_t csum(const void *buf, size_t len, uint32_t init); uint16_t csum(const void *buf, size_t len, uint32_t init);
uint16_t csum_iov(const struct iovec *iov, size_t n, uint32_t init); uint16_t csum_iov(const struct iovec *iov, size_t n, uint32_t init);

6
dhcp.c
View file

@ -275,7 +275,7 @@ static void opt_set_dns_search(const struct ctx *c, size_t max_len)
*/ */
int dhcp(const struct ctx *c, const struct pool *p) int dhcp(const struct ctx *c, const struct pool *p)
{ {
size_t mlen, len, offset = 0, opt_len, opt_off = 0; size_t mlen, dlen, offset = 0, opt_len, opt_off = 0;
const struct ethhdr *eh; const struct ethhdr *eh;
const struct iphdr *iph; const struct iphdr *iph;
const struct udphdr *uh; const struct udphdr *uh;
@ -377,8 +377,8 @@ int dhcp(const struct ctx *c, const struct pool *p)
if (!c->no_dhcp_dns_search) if (!c->no_dhcp_dns_search)
opt_set_dns_search(c, sizeof(m->o)); opt_set_dns_search(c, sizeof(m->o));
len = offsetof(struct msg, o) + fill(m); dlen = offsetof(struct msg, o) + fill(m);
tap_udp4_send(c, c->ip4.gw, 67, c->ip4.addr, 68, m, len); tap_udp4_send(c, c->ip4.gw, 67, c->ip4.addr, 68, m, dlen);
return 1; return 1;
} }

12
icmp.c
View file

@ -224,8 +224,8 @@ int icmp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
union sockaddr_inany sa = { .sa_family = af }; union sockaddr_inany sa = { .sa_family = af };
const socklen_t sl = af == AF_INET ? sizeof(sa.sa4) : sizeof(sa.sa6); const socklen_t sl = af == AF_INET ? sizeof(sa.sa4) : sizeof(sa.sa6);
struct icmp_ping_flow *pingf, **id_sock; struct icmp_ping_flow *pingf, **id_sock;
size_t dlen, l4len;
uint16_t id, seq; uint16_t id, seq;
size_t plen;
void *pkt; void *pkt;
(void)saddr; (void)saddr;
@ -234,11 +234,11 @@ int icmp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
if (af == AF_INET) { if (af == AF_INET) {
const struct icmphdr *ih; const struct icmphdr *ih;
if (!(pkt = packet_get(p, 0, 0, sizeof(*ih), &plen))) if (!(pkt = packet_get(p, 0, 0, sizeof(*ih), &dlen)))
return 1; return 1;
ih = (struct icmphdr *)pkt; ih = (struct icmphdr *)pkt;
plen += sizeof(*ih); l4len = dlen + sizeof(*ih);
if (ih->type != ICMP_ECHO) if (ih->type != ICMP_ECHO)
return 1; return 1;
@ -250,11 +250,11 @@ int icmp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
} else if (af == AF_INET6) { } else if (af == AF_INET6) {
const struct icmp6hdr *ih; const struct icmp6hdr *ih;
if (!(pkt = packet_get(p, 0, 0, sizeof(*ih), &plen))) if (!(pkt = packet_get(p, 0, 0, sizeof(*ih), &dlen)))
return 1; return 1;
ih = (struct icmp6hdr *)pkt; ih = (struct icmp6hdr *)pkt;
plen += sizeof(*ih); l4len = dlen + sizeof(*ih);
if (ih->icmp6_type != ICMPV6_ECHO_REQUEST) if (ih->icmp6_type != ICMPV6_ECHO_REQUEST)
return 1; return 1;
@ -274,7 +274,7 @@ int icmp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
pingf->ts = now->tv_sec; pingf->ts = now->tv_sec;
if (sendto(pingf->sock, pkt, plen, MSG_NOSIGNAL, &sa.sa, sl) < 0) { if (sendto(pingf->sock, pkt, l4len, MSG_NOSIGNAL, &sa.sa, sl) < 0) {
flow_dbg(pingf, "failed to relay request to socket: %s", flow_dbg(pingf, "failed to relay request to socket: %s",
strerror(errno)); strerror(errno));
} else { } else {

6
ndp.c
View file

@ -54,7 +54,7 @@ int ndp(struct ctx *c, const struct icmp6hdr *ih, const struct in6_addr *saddr)
struct icmp6hdr *ihr; struct icmp6hdr *ihr;
struct ethhdr *ehr; struct ethhdr *ehr;
unsigned char *p; unsigned char *p;
size_t len; size_t dlen;
if (ih->icmp6_type < RS || ih->icmp6_type > NA) if (ih->icmp6_type < RS || ih->icmp6_type > NA)
return 0; return 0;
@ -175,7 +175,7 @@ dns_done:
return 1; return 1;
} }
len = (uintptr_t)p - (uintptr_t)ihr - sizeof(*ihr); dlen = (uintptr_t)p - (uintptr_t)ihr - sizeof(*ihr);
if (IN6_IS_ADDR_LINKLOCAL(saddr)) if (IN6_IS_ADDR_LINKLOCAL(saddr))
c->ip6.addr_ll_seen = *saddr; c->ip6.addr_ll_seen = *saddr;
@ -187,7 +187,7 @@ dns_done:
else else
rsaddr = &c->ip6.addr_ll; rsaddr = &c->ip6.addr_ll;
tap_icmp6_send(c, rsaddr, saddr, ihr, len + sizeof(*ihr)); tap_icmp6_send(c, rsaddr, saddr, ihr, dlen + sizeof(*ihr));
return 1; return 1;
} }

14
pcap.c
View file

@ -79,30 +79,30 @@ struct pcap_pkthdr {
static void pcap_frame(const struct iovec *iov, size_t iovcnt, static void pcap_frame(const struct iovec *iov, size_t iovcnt,
size_t offset, const struct timespec *now) size_t offset, const struct timespec *now)
{ {
size_t len = iov_size(iov, iovcnt) - offset; size_t l2len = iov_size(iov, iovcnt) - offset;
struct pcap_pkthdr h = { struct pcap_pkthdr h = {
.tv_sec = now->tv_sec, .tv_sec = now->tv_sec,
.tv_usec = DIV_ROUND_CLOSEST(now->tv_nsec, 1000), .tv_usec = DIV_ROUND_CLOSEST(now->tv_nsec, 1000),
.caplen = len, .caplen = l2len,
.len = len .len = l2len
}; };
struct iovec hiov = { &h, sizeof(h) }; struct iovec hiov = { &h, sizeof(h) };
if (write_remainder(pcap_fd, &hiov, 1, 0) < 0 || if (write_remainder(pcap_fd, &hiov, 1, 0) < 0 ||
write_remainder(pcap_fd, iov, iovcnt, offset) < 0) { write_remainder(pcap_fd, iov, iovcnt, offset) < 0) {
debug("Cannot log packet, length %zu: %s", debug("Cannot log packet, length %zu: %s",
len, strerror(errno)); l2len, strerror(errno));
} }
} }
/** /**
* pcap() - Capture a single frame to pcap file * pcap() - Capture a single frame to pcap file
* @pkt: Pointer to data buffer, including L2 headers * @pkt: Pointer to data buffer, including L2 headers
* @len: L2 packet length * @l2len: L2 frame length
*/ */
void pcap(const char *pkt, size_t len) void pcap(const char *pkt, size_t l2len)
{ {
struct iovec iov = { (char *)pkt, len }; struct iovec iov = { (char *)pkt, l2len };
struct timespec now; struct timespec now;
if (pcap_fd == -1) if (pcap_fd == -1)

2
pcap.h
View file

@ -6,7 +6,7 @@
#ifndef PCAP_H #ifndef PCAP_H
#define PCAP_H #define PCAP_H
void pcap(const char *pkt, size_t len); void pcap(const char *pkt, size_t l2len);
void pcap_multiple(const struct iovec *iov, size_t frame_parts, unsigned int n, void pcap_multiple(const struct iovec *iov, size_t frame_parts, unsigned int n,
size_t offset); size_t offset);
void pcap_iov(const struct iovec *iov, size_t iovcnt); void pcap_iov(const struct iovec *iov, size_t iovcnt);

137
tap.c
View file

@ -70,11 +70,11 @@ static PACKET_POOL_NOINIT(pool_tap6, TAP_MSGS, pkt_buf);
* tap_send_single() - Send a single frame * tap_send_single() - Send a single frame
* @c: Execution context * @c: Execution context
* @data: Packet buffer * @data: Packet buffer
* @len: Total L2 packet length * @l2len: Total L2 packet length
*/ */
void tap_send_single(const struct ctx *c, const void *data, size_t len) void tap_send_single(const struct ctx *c, const void *data, size_t l2len)
{ {
uint32_t vnet_len = htonl(len); uint32_t vnet_len = htonl(l2len);
struct iovec iov[2]; struct iovec iov[2];
size_t iovcnt = 0; size_t iovcnt = 0;
@ -85,7 +85,7 @@ void tap_send_single(const struct ctx *c, const void *data, size_t len)
} }
iov[iovcnt].iov_base = (void *)data; iov[iovcnt].iov_base = (void *)data;
iov[iovcnt].iov_len = len; iov[iovcnt].iov_len = l2len;
iovcnt++; iovcnt++;
tap_send_frames(c, iov, iovcnt, 1); tap_send_frames(c, iov, iovcnt, 1);
@ -141,27 +141,27 @@ static void *tap_push_l2h(const struct ctx *c, void *buf, uint16_t proto)
* @c: Execution context * @c: Execution context
* @src: IPv4 source address * @src: IPv4 source address
* @dst: IPv4 destination address * @dst: IPv4 destination address
* @len: L4 payload length * @l4len: IPv4 payload length
* @proto: L4 protocol number * @proto: L4 protocol number
* *
* Return: pointer at which to write the packet's payload * Return: pointer at which to write the packet's payload
*/ */
static void *tap_push_ip4h(struct iphdr *ip4h, struct in_addr src, static void *tap_push_ip4h(struct iphdr *ip4h, struct in_addr src,
struct in_addr dst, size_t len, uint8_t proto) struct in_addr dst, size_t l4len, uint8_t proto)
{ {
uint16_t tot_len = len + sizeof(*ip4h); uint16_t l3len = l4len + sizeof(*ip4h);
ip4h->version = 4; ip4h->version = 4;
ip4h->ihl = sizeof(struct iphdr) / 4; ip4h->ihl = sizeof(struct iphdr) / 4;
ip4h->tos = 0; ip4h->tos = 0;
ip4h->tot_len = htons(tot_len); ip4h->tot_len = htons(l3len);
ip4h->id = 0; ip4h->id = 0;
ip4h->frag_off = 0; ip4h->frag_off = 0;
ip4h->ttl = 255; ip4h->ttl = 255;
ip4h->protocol = proto; ip4h->protocol = proto;
ip4h->saddr = src.s_addr; ip4h->saddr = src.s_addr;
ip4h->daddr = dst.s_addr; ip4h->daddr = dst.s_addr;
ip4h->check = csum_ip4_header(tot_len, proto, src, dst); ip4h->check = csum_ip4_header(l3len, proto, src, dst);
return ip4h + 1; return ip4h + 1;
} }
@ -173,25 +173,25 @@ static void *tap_push_ip4h(struct iphdr *ip4h, struct in_addr src,
* @dst: IPv4 destination address * @dst: IPv4 destination address
* @dport: UDP destination port * @dport: UDP destination port
* @in: UDP payload contents (not including UDP header) * @in: UDP payload contents (not including UDP header)
* @len: UDP payload length (not including UDP header) * @dlen: UDP payload length (not including UDP header)
*/ */
void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport, void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport,
struct in_addr dst, in_port_t dport, struct in_addr dst, in_port_t dport,
const void *in, size_t len) const void *in, size_t dlen)
{ {
size_t udplen = len + sizeof(struct udphdr); size_t l4len = dlen + sizeof(struct udphdr);
char buf[USHRT_MAX]; char buf[USHRT_MAX];
struct iphdr *ip4h = tap_push_l2h(c, buf, ETH_P_IP); struct iphdr *ip4h = tap_push_l2h(c, buf, ETH_P_IP);
struct udphdr *uh = tap_push_ip4h(ip4h, src, dst, udplen, IPPROTO_UDP); struct udphdr *uh = tap_push_ip4h(ip4h, src, dst, l4len, IPPROTO_UDP);
char *data = (char *)(uh + 1); char *data = (char *)(uh + 1);
uh->source = htons(sport); uh->source = htons(sport);
uh->dest = htons(dport); uh->dest = htons(dport);
uh->len = htons(udplen); uh->len = htons(l4len);
csum_udp4(uh, src, dst, in, len); csum_udp4(uh, src, dst, in, dlen);
memcpy(data, in, len); memcpy(data, in, dlen);
tap_send_single(c, buf, len + (data - buf)); tap_send_single(c, buf, dlen + (data - buf));
} }
/** /**
@ -200,20 +200,20 @@ void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport,
* @src: IPv4 source address * @src: IPv4 source address
* @dst: IPv4 destination address * @dst: IPv4 destination address
* @in: ICMP packet, including ICMP header * @in: ICMP packet, including ICMP header
* @len: ICMP packet length, including ICMP header * @l4len: ICMP packet length, including ICMP header
*/ */
void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst, void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
const void *in, size_t len) const void *in, size_t l4len)
{ {
char buf[USHRT_MAX]; char buf[USHRT_MAX];
struct iphdr *ip4h = tap_push_l2h(c, buf, ETH_P_IP); struct iphdr *ip4h = tap_push_l2h(c, buf, ETH_P_IP);
struct icmphdr *icmp4h = tap_push_ip4h(ip4h, src, dst, struct icmphdr *icmp4h = tap_push_ip4h(ip4h, src, dst,
len, IPPROTO_ICMP); l4len, IPPROTO_ICMP);
memcpy(icmp4h, in, len); memcpy(icmp4h, in, l4len);
csum_icmp4(icmp4h, icmp4h + 1, len - sizeof(*icmp4h)); csum_icmp4(icmp4h, icmp4h + 1, l4len - sizeof(*icmp4h));
tap_send_single(c, buf, len + ((char *)icmp4h - buf)); tap_send_single(c, buf, l4len + ((char *)icmp4h - buf));
} }
/** /**
@ -221,7 +221,7 @@ void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
* @c: Execution context * @c: Execution context
* @src: IPv6 source address * @src: IPv6 source address
* @dst: IPv6 destination address * @dst: IPv6 destination address
* @len: L4 payload length * @l4len: L4 payload length
* @proto: L4 protocol number * @proto: L4 protocol number
* @flow: IPv6 flow identifier * @flow: IPv6 flow identifier
* *
@ -230,9 +230,9 @@ void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
static void *tap_push_ip6h(struct ipv6hdr *ip6h, static void *tap_push_ip6h(struct ipv6hdr *ip6h,
const struct in6_addr *src, const struct in6_addr *src,
const struct in6_addr *dst, const struct in6_addr *dst,
size_t len, uint8_t proto, uint32_t flow) size_t l4len, uint8_t proto, uint32_t flow)
{ {
ip6h->payload_len = htons(len); ip6h->payload_len = htons(l4len);
ip6h->priority = 0; ip6h->priority = 0;
ip6h->version = 6; ip6h->version = 6;
ip6h->nexthdr = proto; ip6h->nexthdr = proto;
@ -254,27 +254,27 @@ static void *tap_push_ip6h(struct ipv6hdr *ip6h,
* @dport: UDP destination port * @dport: UDP destination port
* @flow: Flow label * @flow: Flow label
* @in: UDP payload contents (not including UDP header) * @in: UDP payload contents (not including UDP header)
* @len: UDP payload length (not including UDP header) * @dlen: UDP payload length (not including UDP header)
*/ */
void tap_udp6_send(const struct ctx *c, void tap_udp6_send(const struct ctx *c,
const struct in6_addr *src, in_port_t sport, const struct in6_addr *src, in_port_t sport,
const struct in6_addr *dst, in_port_t dport, const struct in6_addr *dst, in_port_t dport,
uint32_t flow, const void *in, size_t len) uint32_t flow, const void *in, size_t dlen)
{ {
size_t udplen = len + sizeof(struct udphdr); size_t l4len = dlen + sizeof(struct udphdr);
char buf[USHRT_MAX]; char buf[USHRT_MAX];
struct ipv6hdr *ip6h = tap_push_l2h(c, buf, ETH_P_IPV6); struct ipv6hdr *ip6h = tap_push_l2h(c, buf, ETH_P_IPV6);
struct udphdr *uh = tap_push_ip6h(ip6h, src, dst, struct udphdr *uh = tap_push_ip6h(ip6h, src, dst,
udplen, IPPROTO_UDP, flow); l4len, IPPROTO_UDP, flow);
char *data = (char *)(uh + 1); char *data = (char *)(uh + 1);
uh->source = htons(sport); uh->source = htons(sport);
uh->dest = htons(dport); uh->dest = htons(dport);
uh->len = htons(udplen); uh->len = htons(l4len);
csum_udp6(uh, src, dst, in, len); csum_udp6(uh, src, dst, in, dlen);
memcpy(data, in, len); memcpy(data, in, dlen);
tap_send_single(c, buf, len + (data - buf)); tap_send_single(c, buf, dlen + (data - buf));
} }
/** /**
@ -283,21 +283,21 @@ void tap_udp6_send(const struct ctx *c,
* @src: IPv6 source address * @src: IPv6 source address
* @dst: IPv6 destination address * @dst: IPv6 destination address
* @in: ICMP packet, including ICMP header * @in: ICMP packet, including ICMP header
* @len: ICMP packet length, including ICMP header * @l4len: ICMP packet length, including ICMP header
*/ */
void tap_icmp6_send(const struct ctx *c, void tap_icmp6_send(const struct ctx *c,
const struct in6_addr *src, const struct in6_addr *dst, const struct in6_addr *src, const struct in6_addr *dst,
const void *in, size_t len) const void *in, size_t l4len)
{ {
char buf[USHRT_MAX]; char buf[USHRT_MAX];
struct ipv6hdr *ip6h = tap_push_l2h(c, buf, ETH_P_IPV6); struct ipv6hdr *ip6h = tap_push_l2h(c, buf, ETH_P_IPV6);
struct icmp6hdr *icmp6h = tap_push_ip6h(ip6h, src, dst, len, struct icmp6hdr *icmp6h = tap_push_ip6h(ip6h, src, dst, l4len,
IPPROTO_ICMPV6, 0); IPPROTO_ICMPV6, 0);
memcpy(icmp6h, in, len); memcpy(icmp6h, in, l4len);
csum_icmp6(icmp6h, src, dst, icmp6h + 1, len - sizeof(*icmp6h)); csum_icmp6(icmp6h, src, dst, icmp6h + 1, l4len - sizeof(*icmp6h));
tap_send_single(c, buf, len + ((char *)icmp6h - buf)); tap_send_single(c, buf, l4len + ((char *)icmp6h - buf));
} }
/** /**
@ -591,21 +591,21 @@ static int tap4_handler(struct ctx *c, const struct pool *in,
i = 0; i = 0;
resume: resume:
for (seq_count = 0, seq = NULL; i < in->count; i++) { for (seq_count = 0, seq = NULL; i < in->count; i++) {
size_t l2_len, l3_len, hlen, l4_len; size_t l2len, l3len, hlen, l4len;
const struct ethhdr *eh; const struct ethhdr *eh;
const struct udphdr *uh; const struct udphdr *uh;
struct iphdr *iph; struct iphdr *iph;
const char *l4h; const char *l4h;
packet_get(in, i, 0, 0, &l2_len); packet_get(in, i, 0, 0, &l2len);
eh = packet_get(in, i, 0, sizeof(*eh), &l3_len); eh = packet_get(in, i, 0, sizeof(*eh), &l3len);
if (!eh) if (!eh)
continue; continue;
if (ntohs(eh->h_proto) == ETH_P_ARP) { if (ntohs(eh->h_proto) == ETH_P_ARP) {
PACKET_POOL_P(pkt, 1, in->buf, sizeof(pkt_buf)); PACKET_POOL_P(pkt, 1, in->buf, sizeof(pkt_buf));
packet_add(pkt, l2_len, (char *)eh); packet_add(pkt, l2len, (char *)eh);
arp(c, pkt); arp(c, pkt);
continue; continue;
} }
@ -615,15 +615,15 @@ resume:
continue; continue;
hlen = iph->ihl * 4UL; hlen = iph->ihl * 4UL;
if (hlen < sizeof(*iph) || htons(iph->tot_len) > l3_len || if (hlen < sizeof(*iph) || htons(iph->tot_len) > l3len ||
hlen > l3_len) hlen > l3len)
continue; continue;
/* We don't handle IP fragments, drop them */ /* We don't handle IP fragments, drop them */
if (tap4_is_fragment(iph, now)) if (tap4_is_fragment(iph, now))
continue; continue;
l4_len = htons(iph->tot_len) - hlen; l4len = htons(iph->tot_len) - hlen;
if (IN4_IS_ADDR_LOOPBACK(&iph->saddr) || if (IN4_IS_ADDR_LOOPBACK(&iph->saddr) ||
IN4_IS_ADDR_LOOPBACK(&iph->daddr)) { IN4_IS_ADDR_LOOPBACK(&iph->daddr)) {
@ -638,7 +638,7 @@ resume:
if (iph->saddr && c->ip4.addr_seen.s_addr != iph->saddr) if (iph->saddr && c->ip4.addr_seen.s_addr != iph->saddr)
c->ip4.addr_seen.s_addr = iph->saddr; c->ip4.addr_seen.s_addr = iph->saddr;
l4h = packet_get(in, i, sizeof(*eh) + hlen, l4_len, NULL); l4h = packet_get(in, i, sizeof(*eh) + hlen, l4len, NULL);
if (!l4h) if (!l4h)
continue; continue;
@ -650,7 +650,7 @@ resume:
tap_packet_debug(iph, NULL, NULL, 0, NULL, 1); tap_packet_debug(iph, NULL, NULL, 0, NULL, 1);
packet_add(pkt, l4_len, l4h); packet_add(pkt, l4len, l4h);
icmp_tap_handler(c, PIF_TAP, AF_INET, icmp_tap_handler(c, PIF_TAP, AF_INET,
&iph->saddr, &iph->daddr, &iph->saddr, &iph->daddr,
pkt, now); pkt, now);
@ -664,7 +664,7 @@ resume:
if (iph->protocol == IPPROTO_UDP) { if (iph->protocol == IPPROTO_UDP) {
PACKET_POOL_P(pkt, 1, in->buf, sizeof(pkt_buf)); PACKET_POOL_P(pkt, 1, in->buf, sizeof(pkt_buf));
packet_add(pkt, l2_len, (char *)eh); packet_add(pkt, l2len, (char *)eh);
if (dhcp(c, pkt)) if (dhcp(c, pkt))
continue; continue;
} }
@ -713,7 +713,7 @@ resume:
#undef L4_SET #undef L4_SET
append: append:
packet_add((struct pool *)&seq->p, l4_len, l4h); packet_add((struct pool *)&seq->p, l4len, l4h);
} }
for (j = 0, seq = tap4_l4; j < seq_count; j++, seq++) { for (j = 0, seq = tap4_l4; j < seq_count; j++, seq++) {
@ -765,7 +765,7 @@ static int tap6_handler(struct ctx *c, const struct pool *in,
i = 0; i = 0;
resume: resume:
for (seq_count = 0, seq = NULL; i < in->count; i++) { for (seq_count = 0, seq = NULL; i < in->count; i++) {
size_t l4_len, plen, check; size_t l4len, plen, check;
struct in6_addr *saddr, *daddr; struct in6_addr *saddr, *daddr;
const struct ethhdr *eh; const struct ethhdr *eh;
const struct udphdr *uh; const struct udphdr *uh;
@ -788,7 +788,7 @@ resume:
if (plen != check) if (plen != check)
continue; continue;
if (!(l4h = ipv6_l4hdr(in, i, sizeof(*eh), &proto, &l4_len))) if (!(l4h = ipv6_l4hdr(in, i, sizeof(*eh), &proto, &l4len)))
continue; continue;
if (IN6_IS_ADDR_LOOPBACK(saddr) || IN6_IS_ADDR_LOOPBACK(daddr)) { if (IN6_IS_ADDR_LOOPBACK(saddr) || IN6_IS_ADDR_LOOPBACK(daddr)) {
@ -816,7 +816,7 @@ resume:
if (c->no_icmp) if (c->no_icmp)
continue; continue;
if (l4_len < sizeof(struct icmp6hdr)) if (l4len < sizeof(struct icmp6hdr))
continue; continue;
if (ndp(c, (struct icmp6hdr *)l4h, saddr)) if (ndp(c, (struct icmp6hdr *)l4h, saddr))
@ -824,20 +824,20 @@ resume:
tap_packet_debug(NULL, ip6h, NULL, proto, NULL, 1); tap_packet_debug(NULL, ip6h, NULL, proto, NULL, 1);
packet_add(pkt, l4_len, l4h); packet_add(pkt, l4len, l4h);
icmp_tap_handler(c, PIF_TAP, AF_INET6, icmp_tap_handler(c, PIF_TAP, AF_INET6,
saddr, daddr, pkt, now); saddr, daddr, pkt, now);
continue; continue;
} }
if (l4_len < sizeof(*uh)) if (l4len < sizeof(*uh))
continue; continue;
uh = (struct udphdr *)l4h; uh = (struct udphdr *)l4h;
if (proto == IPPROTO_UDP) { if (proto == IPPROTO_UDP) {
PACKET_POOL_P(pkt, 1, in->buf, sizeof(pkt_buf)); PACKET_POOL_P(pkt, 1, in->buf, sizeof(pkt_buf));
packet_add(pkt, l4_len, l4h); packet_add(pkt, l4len, l4h);
if (dhcpv6(c, pkt, saddr, daddr)) if (dhcpv6(c, pkt, saddr, daddr))
continue; continue;
@ -888,7 +888,7 @@ resume:
#undef L4_SET #undef L4_SET
append: append:
packet_add((struct pool *)&seq->p, l4_len, l4h); packet_add((struct pool *)&seq->p, l4len, l4h);
} }
for (j = 0, seq = tap6_l4; j < seq_count; j++, seq++) { for (j = 0, seq = tap6_l4; j < seq_count; j++, seq++) {
@ -971,7 +971,7 @@ redo:
} }
while (n > (ssize_t)sizeof(uint32_t)) { while (n > (ssize_t)sizeof(uint32_t)) {
ssize_t len = ntohl(*(uint32_t *)p); ssize_t l2len = ntohl(*(uint32_t *)p);
p += sizeof(uint32_t); p += sizeof(uint32_t);
n -= sizeof(uint32_t); n -= sizeof(uint32_t);
@ -979,19 +979,20 @@ redo:
/* At most one packet might not fit in a single read, and this /* At most one packet might not fit in a single read, and this
* needs to be blocking. * needs to be blocking.
*/ */
if (len > n) { if (l2len > n) {
rem = recv(c->fd_tap, p + n, len - n, 0); rem = recv(c->fd_tap, p + n, l2len - n, 0);
if ((n += rem) != len) if ((n += rem) != l2len)
return; return;
} }
/* Complete the partial read above before discarding a malformed /* Complete the partial read above before discarding a malformed
* frame, otherwise the stream will be inconsistent. * frame, otherwise the stream will be inconsistent.
*/ */
if (len < (ssize_t)sizeof(*eh) || len > (ssize_t)ETH_MAX_MTU) if (l2len < (ssize_t)sizeof(*eh) ||
l2len > (ssize_t)ETH_MAX_MTU)
goto next; goto next;
pcap(p, len); pcap(p, l2len);
eh = (struct ethhdr *)p; eh = (struct ethhdr *)p;
@ -1003,18 +1004,18 @@ redo:
switch (ntohs(eh->h_proto)) { switch (ntohs(eh->h_proto)) {
case ETH_P_ARP: case ETH_P_ARP:
case ETH_P_IP: case ETH_P_IP:
packet_add(pool_tap4, len, p); packet_add(pool_tap4, l2len, p);
break; break;
case ETH_P_IPV6: case ETH_P_IPV6:
packet_add(pool_tap6, len, p); packet_add(pool_tap6, l2len, p);
break; break;
default: default:
break; break;
} }
next: next:
p += len; p += l2len;
n -= len; n -= l2len;
} }
tap4_handler(c, pool_tap4, now); tap4_handler(c, pool_tap4, now);

18
tap.h
View file

@ -41,35 +41,35 @@ static inline void *tap_frame_base(const struct ctx *c, struct tap_hdr *taph)
* tap_frame_len() - Finalize tap frame and return total length * tap_frame_len() - Finalize tap frame and return total length
* @c: Execution context * @c: Execution context
* @taph: Tap header to finalize * @taph: Tap header to finalize
* @plen: L2 packet length (includes L2, excludes tap specific headers) * @l2len: L2 packet length (includes L2, excludes tap specific headers)
* *
* Returns: length of the tap frame including tap specific headers - suitable * Returns: length of the tap frame including tap specific headers - suitable
* for an iov_len to be passed to tap_send_frames() * for an iov_len to be passed to tap_send_frames()
*/ */
static inline size_t tap_frame_len(const struct ctx *c, struct tap_hdr *taph, static inline size_t tap_frame_len(const struct ctx *c, struct tap_hdr *taph,
size_t plen) size_t l2len)
{ {
if (c->mode == MODE_PASST) if (c->mode == MODE_PASST)
taph->vnet_len = htonl(plen); taph->vnet_len = htonl(l2len);
return plen + tap_hdr_len_(c); return l2len + tap_hdr_len_(c);
} }
struct in_addr tap_ip4_daddr(const struct ctx *c); struct in_addr tap_ip4_daddr(const struct ctx *c);
void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport, void tap_udp4_send(const struct ctx *c, struct in_addr src, in_port_t sport,
struct in_addr dst, in_port_t dport, struct in_addr dst, in_port_t dport,
const void *in, size_t len); const void *in, size_t dlen);
void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst, void tap_icmp4_send(const struct ctx *c, struct in_addr src, struct in_addr dst,
const void *in, size_t len); const void *in, size_t l4len);
const struct in6_addr *tap_ip6_daddr(const struct ctx *c, const struct in6_addr *tap_ip6_daddr(const struct ctx *c,
const struct in6_addr *src); const struct in6_addr *src);
void tap_udp6_send(const struct ctx *c, void tap_udp6_send(const struct ctx *c,
const struct in6_addr *src, in_port_t sport, const struct in6_addr *src, in_port_t sport,
const struct in6_addr *dst, in_port_t dport, const struct in6_addr *dst, in_port_t dport,
uint32_t flow, const void *in, size_t len); uint32_t flow, const void *in, size_t dlen);
void tap_icmp6_send(const struct ctx *c, void tap_icmp6_send(const struct ctx *c,
const struct in6_addr *src, const struct in6_addr *dst, const struct in6_addr *src, const struct in6_addr *dst,
const void *in, size_t len); const void *in, size_t l4len);
void tap_send_single(const struct ctx *c, const void *data, size_t len); void tap_send_single(const struct ctx *c, const void *data, size_t l2len);
size_t tap_send_frames(const struct ctx *c, const struct iovec *iov, size_t tap_send_frames(const struct ctx *c, const struct iovec *iov,
size_t bufs_per_frame, size_t nframes); size_t bufs_per_frame, size_t nframes);
void eth_update_mac(struct ethhdr *eh, void eth_update_mac(struct ethhdr *eh,

102
tcp.c
View file

@ -891,13 +891,13 @@ static void tcp_sock_set_bufsize(const struct ctx *c, int s)
*/ */
static void tcp_update_check_tcp4(const struct iphdr *iph, struct tcphdr *th) static void tcp_update_check_tcp4(const struct iphdr *iph, struct tcphdr *th)
{ {
uint16_t tlen = ntohs(iph->tot_len) - sizeof(struct iphdr); uint16_t l4len = ntohs(iph->tot_len) - sizeof(struct iphdr);
struct in_addr saddr = { .s_addr = iph->saddr }; struct in_addr saddr = { .s_addr = iph->saddr };
struct in_addr daddr = { .s_addr = iph->daddr }; struct in_addr daddr = { .s_addr = iph->daddr };
uint32_t sum = proto_ipv4_header_psum(tlen, IPPROTO_TCP, saddr, daddr); uint32_t sum = proto_ipv4_header_psum(l4len, IPPROTO_TCP, saddr, daddr);
th->check = 0; th->check = 0;
th->check = csum(th, tlen, sum); th->check = csum(th, l4len, sum);
} }
/** /**
@ -907,12 +907,12 @@ static void tcp_update_check_tcp4(const struct iphdr *iph, struct tcphdr *th)
*/ */
static void tcp_update_check_tcp6(struct ipv6hdr *ip6h, struct tcphdr *th) static void tcp_update_check_tcp6(struct ipv6hdr *ip6h, struct tcphdr *th)
{ {
uint16_t payload_len = ntohs(ip6h->payload_len); uint16_t l4len = ntohs(ip6h->payload_len);
uint32_t sum = proto_ipv6_header_psum(payload_len, IPPROTO_TCP, uint32_t sum = proto_ipv6_header_psum(l4len, IPPROTO_TCP,
&ip6h->saddr, &ip6h->daddr); &ip6h->saddr, &ip6h->daddr);
th->check = 0; th->check = 0;
th->check = csum(th, payload_len, sum); th->check = csum(th, l4len, sum);
} }
/** /**
@ -1337,7 +1337,7 @@ static void tcp_fill_header(struct tcphdr *th,
* @conn: Connection pointer * @conn: Connection pointer
* @iph: Pointer to IPv4 header * @iph: Pointer to IPv4 header
* @th: Pointer to TCP header * @th: Pointer to TCP header
* @plen: Payload length (including TCP header options) * @dlen: TCP payload length
* @check: Checksum, if already known * @check: Checksum, if already known
* @seq: Sequence number for this segment * @seq: Sequence number for this segment
* *
@ -1346,27 +1346,28 @@ static void tcp_fill_header(struct tcphdr *th,
static size_t tcp_fill_headers4(const struct ctx *c, static size_t tcp_fill_headers4(const struct ctx *c,
const struct tcp_tap_conn *conn, const struct tcp_tap_conn *conn,
struct iphdr *iph, struct tcphdr *th, struct iphdr *iph, struct tcphdr *th,
size_t plen, const uint16_t *check, size_t dlen, const uint16_t *check,
uint32_t seq) uint32_t seq)
{ {
size_t ip_len = plen + sizeof(struct iphdr) + sizeof(struct tcphdr);
const struct in_addr *a4 = inany_v4(&conn->faddr); const struct in_addr *a4 = inany_v4(&conn->faddr);
size_t l4len = dlen + sizeof(*th);
size_t l3len = l4len + sizeof(*iph);
ASSERT(a4); ASSERT(a4);
iph->tot_len = htons(ip_len); iph->tot_len = htons(l3len);
iph->saddr = a4->s_addr; iph->saddr = a4->s_addr;
iph->daddr = c->ip4.addr_seen.s_addr; iph->daddr = c->ip4.addr_seen.s_addr;
iph->check = check ? *check : iph->check = check ? *check :
csum_ip4_header(ip_len, IPPROTO_TCP, csum_ip4_header(l3len, IPPROTO_TCP,
*a4, c->ip4.addr_seen); *a4, c->ip4.addr_seen);
tcp_fill_header(th, conn, seq); tcp_fill_header(th, conn, seq);
tcp_update_check_tcp4(iph, th); tcp_update_check_tcp4(iph, th);
return ip_len; return l3len;
} }
/** /**
@ -1375,7 +1376,7 @@ static size_t tcp_fill_headers4(const struct ctx *c,
* @conn: Connection pointer * @conn: Connection pointer
* @ip6h: Pointer to IPv6 header * @ip6h: Pointer to IPv6 header
* @th: Pointer to TCP header * @th: Pointer to TCP header
* @plen: Payload length (including TCP header options) * @dlen: TCP payload length
* @check: Checksum, if already known * @check: Checksum, if already known
* @seq: Sequence number for this segment * @seq: Sequence number for this segment
* *
@ -1384,11 +1385,12 @@ static size_t tcp_fill_headers4(const struct ctx *c,
static size_t tcp_fill_headers6(const struct ctx *c, static size_t tcp_fill_headers6(const struct ctx *c,
const struct tcp_tap_conn *conn, const struct tcp_tap_conn *conn,
struct ipv6hdr *ip6h, struct tcphdr *th, struct ipv6hdr *ip6h, struct tcphdr *th,
size_t plen, uint32_t seq) size_t dlen, uint32_t seq)
{ {
size_t ip_len = plen + sizeof(struct ipv6hdr) + sizeof(struct tcphdr); size_t l4len = dlen + sizeof(*th);
size_t l3len = l4len + sizeof(*ip6h);
ip6h->payload_len = htons(plen + sizeof(struct tcphdr)); ip6h->payload_len = htons(l4len);
ip6h->saddr = conn->faddr.a6; ip6h->saddr = conn->faddr.a6;
if (IN6_IS_ADDR_LINKLOCAL(&ip6h->saddr)) if (IN6_IS_ADDR_LINKLOCAL(&ip6h->saddr))
ip6h->daddr = c->ip6.addr_ll_seen; ip6h->daddr = c->ip6.addr_ll_seen;
@ -1407,7 +1409,7 @@ static size_t tcp_fill_headers6(const struct ctx *c,
tcp_update_check_tcp6(ip6h, th); tcp_update_check_tcp6(ip6h, th);
return ip_len; return l3len;
} }
/** /**
@ -1415,7 +1417,7 @@ static size_t tcp_fill_headers6(const struct ctx *c,
* @c: Execution context * @c: Execution context
* @conn: Connection pointer * @conn: Connection pointer
* @iov: Pointer to an array of iovec of TCP pre-cooked buffers * @iov: Pointer to an array of iovec of TCP pre-cooked buffers
* @plen: Payload length (including TCP header options) * @dlen: TCP payload length
* @check: Checksum, if already known * @check: Checksum, if already known
* @seq: Sequence number for this segment * @seq: Sequence number for this segment
* *
@ -1423,25 +1425,25 @@ static size_t tcp_fill_headers6(const struct ctx *c,
*/ */
static size_t tcp_l2_buf_fill_headers(const struct ctx *c, static size_t tcp_l2_buf_fill_headers(const struct ctx *c,
const struct tcp_tap_conn *conn, const struct tcp_tap_conn *conn,
struct iovec *iov, size_t plen, struct iovec *iov, size_t dlen,
const uint16_t *check, uint32_t seq) const uint16_t *check, uint32_t seq)
{ {
const struct in_addr *a4 = inany_v4(&conn->faddr); const struct in_addr *a4 = inany_v4(&conn->faddr);
size_t ip_len, tlen; size_t l3len, l4len;
if (a4) { if (a4) {
ip_len = tcp_fill_headers4(c, conn, iov[TCP_IOV_IP].iov_base, l3len = tcp_fill_headers4(c, conn, iov[TCP_IOV_IP].iov_base,
iov[TCP_IOV_PAYLOAD].iov_base, plen, iov[TCP_IOV_PAYLOAD].iov_base, dlen,
check, seq); check, seq);
tlen = ip_len - sizeof(struct iphdr); l4len = l3len - sizeof(struct iphdr);
} else { } else {
ip_len = tcp_fill_headers6(c, conn, iov[TCP_IOV_IP].iov_base, l3len = tcp_fill_headers6(c, conn, iov[TCP_IOV_IP].iov_base,
iov[TCP_IOV_PAYLOAD].iov_base, plen, iov[TCP_IOV_PAYLOAD].iov_base, dlen,
seq); seq);
tlen = ip_len - sizeof(struct ipv6hdr); l4len = l3len - sizeof(struct ipv6hdr);
} }
return tlen; return l4len;
} }
/** /**
@ -1578,7 +1580,7 @@ static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
size_t optlen = 0; size_t optlen = 0;
struct tcphdr *th; struct tcphdr *th;
struct iovec *iov; struct iovec *iov;
size_t ip_len; size_t l4len;
char *data; char *data;
if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap) && if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap) &&
@ -1658,11 +1660,11 @@ static int tcp_send_flag(struct ctx *c, struct tcp_tap_conn *conn, int flags)
th->syn = !!(flags & SYN); th->syn = !!(flags & SYN);
th->fin = !!(flags & FIN); th->fin = !!(flags & FIN);
ip_len = tcp_l2_buf_fill_headers(c, conn, iov, optlen, NULL, l4len = tcp_l2_buf_fill_headers(c, conn, iov, optlen, NULL,
conn->seq_to_tap); conn->seq_to_tap);
iov[TCP_IOV_PAYLOAD].iov_len = ip_len; iov[TCP_IOV_PAYLOAD].iov_len = l4len;
*(uint32_t *)iov[TCP_IOV_VLEN].iov_base = htonl(vnet_len + ip_len); *(uint32_t *)iov[TCP_IOV_VLEN].iov_base = htonl(vnet_len + l4len);
if (th->ack) { if (th->ack) {
if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap)) if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap))
@ -2136,17 +2138,17 @@ static int tcp_sock_consume(const struct tcp_tap_conn *conn, uint32_t ack_seq)
* tcp_data_to_tap() - Finalise (queue) highest-numbered scatter-gather buffer * tcp_data_to_tap() - Finalise (queue) highest-numbered scatter-gather buffer
* @c: Execution context * @c: Execution context
* @conn: Connection pointer * @conn: Connection pointer
* @plen: Payload length at L4 * @dlen: TCP payload length
* @no_csum: Don't compute IPv4 checksum, use the one from previous buffer * @no_csum: Don't compute IPv4 checksum, use the one from previous buffer
* @seq: Sequence number to be sent * @seq: Sequence number to be sent
*/ */
static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn, static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn,
ssize_t plen, int no_csum, uint32_t seq) ssize_t dlen, int no_csum, uint32_t seq)
{ {
uint32_t *seq_update = &conn->seq_to_tap; uint32_t *seq_update = &conn->seq_to_tap;
struct iovec *iov; struct iovec *iov;
size_t ip_len;
uint32_t vnet_len; uint32_t vnet_len;
size_t l4len;
if (CONN_V4(conn)) { if (CONN_V4(conn)) {
struct iovec *iov_prev = tcp4_l2_iov[tcp4_payload_used - 1]; struct iovec *iov_prev = tcp4_l2_iov[tcp4_payload_used - 1];
@ -2158,26 +2160,24 @@ static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn,
} }
tcp4_seq_update[tcp4_payload_used].seq = seq_update; tcp4_seq_update[tcp4_payload_used].seq = seq_update;
tcp4_seq_update[tcp4_payload_used].len = plen; tcp4_seq_update[tcp4_payload_used].len = dlen;
iov = tcp4_l2_iov[tcp4_payload_used++]; iov = tcp4_l2_iov[tcp4_payload_used++];
ip_len = tcp_l2_buf_fill_headers(c, conn, iov, plen, check, l4len = tcp_l2_buf_fill_headers(c, conn, iov, dlen, check, seq);
seq); iov[TCP_IOV_PAYLOAD].iov_len = l4len;
iov[TCP_IOV_PAYLOAD].iov_len = ip_len; vnet_len = sizeof(struct ethhdr) + sizeof(struct iphdr) + l4len;
vnet_len = sizeof(struct ethhdr) + sizeof(struct iphdr) +
ip_len;
*(uint32_t *)iov[TCP_IOV_VLEN].iov_base = htonl(vnet_len); *(uint32_t *)iov[TCP_IOV_VLEN].iov_base = htonl(vnet_len);
if (tcp4_payload_used > TCP_FRAMES_MEM - 1) if (tcp4_payload_used > TCP_FRAMES_MEM - 1)
tcp_payload_flush(c); tcp_payload_flush(c);
} else if (CONN_V6(conn)) { } else if (CONN_V6(conn)) {
tcp6_seq_update[tcp6_payload_used].seq = seq_update; tcp6_seq_update[tcp6_payload_used].seq = seq_update;
tcp6_seq_update[tcp6_payload_used].len = plen; tcp6_seq_update[tcp6_payload_used].len = dlen;
iov = tcp6_l2_iov[tcp6_payload_used++]; iov = tcp6_l2_iov[tcp6_payload_used++];
ip_len = tcp_l2_buf_fill_headers(c, conn, iov, plen, NULL, seq); l4len = tcp_l2_buf_fill_headers(c, conn, iov, dlen, NULL, seq);
iov[TCP_IOV_PAYLOAD].iov_len = ip_len; iov[TCP_IOV_PAYLOAD].iov_len = l4len;
vnet_len = sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + vnet_len = sizeof(struct ethhdr) + sizeof(struct ipv6hdr)
ip_len; + l4len;
*(uint32_t *)iov[TCP_IOV_VLEN].iov_base = htonl(vnet_len); *(uint32_t *)iov[TCP_IOV_VLEN].iov_base = htonl(vnet_len);
if (tcp6_payload_used > TCP_FRAMES_MEM - 1) if (tcp6_payload_used > TCP_FRAMES_MEM - 1)
tcp_payload_flush(c); tcp_payload_flush(c);
@ -2197,7 +2197,7 @@ static int tcp_data_from_sock(struct ctx *c, struct tcp_tap_conn *conn)
{ {
uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap;
int fill_bufs, send_bufs = 0, last_len, iov_rem = 0; int fill_bufs, send_bufs = 0, last_len, iov_rem = 0;
int sendlen, len, plen, v4 = CONN_V4(conn); int sendlen, len, dlen, v4 = CONN_V4(conn);
int s = conn->sock, i, ret = 0; int s = conn->sock, i, ret = 0;
struct msghdr mh_sock = { 0 }; struct msghdr mh_sock = { 0 };
uint16_t mss = MSS_GET(conn); uint16_t mss = MSS_GET(conn);
@ -2289,16 +2289,16 @@ static int tcp_data_from_sock(struct ctx *c, struct tcp_tap_conn *conn)
tcp_update_seqack_wnd(c, conn, 0, NULL); tcp_update_seqack_wnd(c, conn, 0, NULL);
/* Finally, queue to tap */ /* Finally, queue to tap */
plen = mss; dlen = mss;
seq = conn->seq_to_tap; seq = conn->seq_to_tap;
for (i = 0; i < send_bufs; i++) { for (i = 0; i < send_bufs; i++) {
int no_csum = i && i != send_bufs - 1 && tcp4_payload_used; int no_csum = i && i != send_bufs - 1 && tcp4_payload_used;
if (i == send_bufs - 1) if (i == send_bufs - 1)
plen = last_len; dlen = last_len;
tcp_data_to_tap(c, conn, plen, no_csum, seq); tcp_data_to_tap(c, conn, dlen, no_csum, seq);
seq += plen; seq += dlen;
} }
conn_flag(c, conn, ACK_FROM_TAP_DUE); conn_flag(c, conn, ACK_FROM_TAP_DUE);

26
udp.c
View file

@ -570,16 +570,16 @@ static void udp_splice_sendfrom(const struct ctx *c, unsigned start, unsigned n,
* @c: Execution context * @c: Execution context
* @b: Pointer to udp4_l2_buf to update * @b: Pointer to udp4_l2_buf to update
* @dstport: Destination port number * @dstport: Destination port number
* @datalen: Length of UDP payload * @dlen: Length of UDP payload
* @now: Current timestamp * @now: Current timestamp
* *
* Return: size of tap frame with headers * Return: size of tap frame with headers
*/ */
static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *b, static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *b,
in_port_t dstport, size_t datalen, in_port_t dstport, size_t dlen,
const struct timespec *now) const struct timespec *now)
{ {
size_t ip_len = datalen + sizeof(b->iph) + sizeof(b->uh); size_t l3len = dlen + sizeof(b->iph) + sizeof(b->uh);
in_port_t srcport = ntohs(b->s_in.sin_port); in_port_t srcport = ntohs(b->s_in.sin_port);
struct in_addr src = b->s_in.sin_addr; struct in_addr src = b->s_in.sin_addr;
@ -602,17 +602,17 @@ static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *b,
src = c->ip4.gw; src = c->ip4.gw;
} }
b->iph.tot_len = htons(ip_len); b->iph.tot_len = htons(l3len);
b->iph.daddr = c->ip4.addr_seen.s_addr; b->iph.daddr = c->ip4.addr_seen.s_addr;
b->iph.saddr = src.s_addr; b->iph.saddr = src.s_addr;
b->iph.check = csum_ip4_header(ip_len, IPPROTO_UDP, b->iph.check = csum_ip4_header(l3len, IPPROTO_UDP,
src, c->ip4.addr_seen); src, c->ip4.addr_seen);
b->uh.source = b->s_in.sin_port; b->uh.source = b->s_in.sin_port;
b->uh.dest = htons(dstport); b->uh.dest = htons(dstport);
b->uh.len = htons(datalen + sizeof(b->uh)); b->uh.len = htons(dlen + sizeof(b->uh));
return tap_frame_len(c, &b->taph, ip_len + sizeof(b->eh)); return tap_frame_len(c, &b->taph, l3len + sizeof(b->eh));
} }
/** /**
@ -620,19 +620,19 @@ static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *b,
* @c: Execution context * @c: Execution context
* @b: Pointer to udp6_l2_buf to update * @b: Pointer to udp6_l2_buf to update
* @dstport: Destination port number * @dstport: Destination port number
* @datalen: Length of UDP payload * @dlen: Length of UDP payload
* @now: Current timestamp * @now: Current timestamp
* *
* Return: size of tap frame with headers * Return: size of tap frame with headers
*/ */
static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *b, static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *b,
in_port_t dstport, size_t datalen, in_port_t dstport, size_t dlen,
const struct timespec *now) const struct timespec *now)
{ {
const struct in6_addr *src = &b->s_in6.sin6_addr; const struct in6_addr *src = &b->s_in6.sin6_addr;
const struct in6_addr *dst = &c->ip6.addr_seen; const struct in6_addr *dst = &c->ip6.addr_seen;
uint16_t payload_len = datalen + sizeof(b->uh);
in_port_t srcport = ntohs(b->s_in6.sin6_port); in_port_t srcport = ntohs(b->s_in6.sin6_port);
uint16_t l4len = dlen + sizeof(b->uh);
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,7 +668,7 @@ static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *b,
} }
b->ip6h.payload_len = htons(payload_len); b->ip6h.payload_len = htons(l4len);
b->ip6h.daddr = *dst; b->ip6h.daddr = *dst;
b->ip6h.saddr = *src; b->ip6h.saddr = *src;
b->ip6h.version = 6; b->ip6h.version = 6;
@ -678,9 +678,9 @@ static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *b,
b->uh.source = b->s_in6.sin6_port; b->uh.source = b->s_in6.sin6_port;
b->uh.dest = htons(dstport); b->uh.dest = htons(dstport);
b->uh.len = b->ip6h.payload_len; b->uh.len = b->ip6h.payload_len;
csum_udp6(&b->uh, src, dst, b->data, datalen); csum_udp6(&b->uh, src, dst, b->data, dlen);
return tap_frame_len(c, &b->taph, payload_len + return tap_frame_len(c, &b->taph, l4len +
sizeof(b->ip6h) + sizeof(b->eh)); sizeof(b->ip6h) + sizeof(b->eh));
} }