mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
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>
This commit is contained in:
parent
f0b1df5c45
commit
2f0fa232b8
7 changed files with 34 additions and 30 deletions
18
net/eth.c
18
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue