aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAkihiko Odaki <akihiko.odaki@daynix.com>2023-05-23 11:42:58 +0900
committerJason Wang <jasowang@redhat.com>2023-05-23 15:20:15 +0800
commit2f0fa232b8c330df029120a6824c8be3d4eb5cae (patch)
tree072462baff849b057cf4521ad724edee2f8de6ae /net
parentf0b1df5c4502b5ec89f83417924935ab201511d0 (diff)
downloadqemu-2f0fa232b8c330df029120a6824c8be3d4eb5cae.zip
qemu-2f0fa232b8c330df029120a6824c8be3d4eb5cae.tar.gz
qemu-2f0fa232b8c330df029120a6824c8be3d4eb5cae.tar.bz2
net/net_rx_pkt: Use iovec for net_rx_pkt_set_protocols()
igb does not properly ensure the buffer passed to net_rx_pkt_set_protocols() is contiguous for the entire L2/L3/L4 header. Allow it to pass scattered data to net_rx_pkt_set_protocols(). Fixes: 3a977deebe ("Intrdocue igb device emulation") Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Reviewed-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech> Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'net')
-rw-r--r--net/eth.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/net/eth.c b/net/eth.c
index 70bcd8e..d7b30df 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -136,7 +136,7 @@ _eth_tcp_has_data(bool is_ip4,
return l4len > TCP_HEADER_DATA_OFFSET(tcp);
}
-void eth_get_protocols(const struct iovec *iov, int iovcnt,
+void eth_get_protocols(const struct iovec *iov, size_t iovcnt, size_t iovoff,
bool *hasip4, bool *hasip6,
size_t *l3hdr_off,
size_t *l4hdr_off,
@@ -147,26 +147,24 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
{
int proto;
bool fragment = false;
- size_t l2hdr_len = eth_get_l2_hdr_length_iov(iov, iovcnt);
size_t input_size = iov_size(iov, iovcnt);
size_t copied;
uint8_t ip_p;
*hasip4 = *hasip6 = false;
+ *l3hdr_off = iovoff + eth_get_l2_hdr_length_iov(iov, iovcnt, iovoff);
l4hdr_info->proto = ETH_L4_HDR_PROTO_INVALID;
- proto = eth_get_l3_proto(iov, iovcnt, l2hdr_len);
-
- *l3hdr_off = l2hdr_len;
+ proto = eth_get_l3_proto(iov, iovcnt, *l3hdr_off);
if (proto == ETH_P_IP) {
struct ip_header *iphdr = &ip4hdr_info->ip4_hdr;
- if (input_size < l2hdr_len) {
+ if (input_size < *l3hdr_off) {
return;
}
- copied = iov_to_buf(iov, iovcnt, l2hdr_len, iphdr, sizeof(*iphdr));
+ copied = iov_to_buf(iov, iovcnt, *l3hdr_off, iphdr, sizeof(*iphdr));
if (copied < sizeof(*iphdr) ||
IP_HEADER_VERSION(iphdr) != IP_HEADER_VERSION_4) {
return;
@@ -175,17 +173,17 @@ void eth_get_protocols(const struct iovec *iov, int iovcnt,
*hasip4 = true;
ip_p = iphdr->ip_p;
ip4hdr_info->fragment = IP4_IS_FRAGMENT(iphdr);
- *l4hdr_off = l2hdr_len + IP_HDR_GET_LEN(iphdr);
+ *l4hdr_off = *l3hdr_off + IP_HDR_GET_LEN(iphdr);
fragment = ip4hdr_info->fragment;
} else if (proto == ETH_P_IPV6) {
- if (!eth_parse_ipv6_hdr(iov, iovcnt, l2hdr_len, ip6hdr_info)) {
+ if (!eth_parse_ipv6_hdr(iov, iovcnt, *l3hdr_off, ip6hdr_info)) {
return;
}
*hasip6 = true;
ip_p = ip6hdr_info->l4proto;
- *l4hdr_off = l2hdr_len + ip6hdr_info->full_hdr_len;
+ *l4hdr_off = *l3hdr_off + ip6hdr_info->full_hdr_len;
fragment = ip6hdr_info->fragment;
} else {
return;