|
Olaf Hering |
1f77a9 |
From: "Andrea Parri (Microsoft)" <parri.andrea@gmail.com>
|
|
Olaf Hering |
1f77a9 |
Date: Tue, 26 Jan 2021 17:29:07 +0100
|
|
Olaf Hering |
1f77a9 |
Patch-mainline: v5.12-rc1
|
|
Olaf Hering |
1f77a9 |
Subject: hv_netvsc: Copy packets sent by Hyper-V out of the receive buffer
|
|
Olaf Hering |
1f77a9 |
Git-commit: 0ba35fe91ce34f2d0feff626efd0062dac41781c
|
|
Olaf Hering |
1f77a9 |
References: bsc#1199364
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
Pointers to receive-buffer packets sent by Hyper-V are used within the
|
|
Olaf Hering |
1f77a9 |
guest VM. Hyper-V can send packets with erroneous values or modify
|
|
Olaf Hering |
1f77a9 |
packet fields after they are processed by the guest. To defend against
|
|
Olaf Hering |
1f77a9 |
these scenarios, copy (sections of) the incoming packet after validating
|
|
Olaf Hering |
1f77a9 |
their length and offset fields in netvsc_filter_receive(). In this way,
|
|
Olaf Hering |
1f77a9 |
the packet can no longer be modified by the host.
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
Reported-by: Juan Vazquez <juvazq@microsoft.com>
|
|
Olaf Hering |
1f77a9 |
Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
|
|
Olaf Hering |
1f77a9 |
Link: https://lore.kernel.org/r/20210126162907.21056-1-parri.andrea@gmail.com
|
|
Olaf Hering |
1f77a9 |
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
Olaf Hering |
1f77a9 |
Acked-by: Olaf Hering <ohering@suse.de>
|
|
Olaf Hering |
1f77a9 |
---
|
|
Olaf Hering |
1f77a9 |
drivers/net/hyperv/hyperv_net.h | 93 ++++++++++++++++++------------------
|
|
Olaf Hering |
1f77a9 |
drivers/net/hyperv/netvsc.c | 20 ++++++++
|
|
Olaf Hering |
1f77a9 |
drivers/net/hyperv/netvsc_drv.c | 24 ++++++----
|
|
Olaf Hering |
1f77a9 |
drivers/net/hyperv/rndis_filter.c | 99 +++++++++++++++++++++++++++------------
|
|
Olaf Hering |
1f77a9 |
4 files changed, 150 insertions(+), 86 deletions(-)
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
|
Olaf Hering |
1f77a9 |
--- a/drivers/net/hyperv/hyperv_net.h
|
|
Olaf Hering |
1f77a9 |
+++ b/drivers/net/hyperv/hyperv_net.h
|
|
Olaf Hering |
1f77a9 |
@@ -105,9 +105,43 @@ struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */
|
|
Olaf Hering |
1f77a9 |
u32 processor_masks_entry_size;
|
|
Olaf Hering |
1f77a9 |
};
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
-/* Fwd declaration */
|
|
Olaf Hering |
1f77a9 |
-struct ndis_tcp_ip_checksum_info;
|
|
Olaf Hering |
1f77a9 |
-struct ndis_pkt_8021q_info;
|
|
Olaf Hering |
1f77a9 |
+struct ndis_tcp_ip_checksum_info {
|
|
Olaf Hering |
1f77a9 |
+ union {
|
|
Olaf Hering |
1f77a9 |
+ struct {
|
|
Olaf Hering |
1f77a9 |
+ u32 is_ipv4:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 is_ipv6:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 tcp_checksum:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 udp_checksum:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 ip_header_checksum:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 reserved:11;
|
|
Olaf Hering |
1f77a9 |
+ u32 tcp_header_offset:10;
|
|
Olaf Hering |
1f77a9 |
+ } transmit;
|
|
Olaf Hering |
1f77a9 |
+ struct {
|
|
Olaf Hering |
1f77a9 |
+ u32 tcp_checksum_failed:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 udp_checksum_failed:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 ip_checksum_failed:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 tcp_checksum_succeeded:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 udp_checksum_succeeded:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 ip_checksum_succeeded:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 loopback:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 tcp_checksum_value_invalid:1;
|
|
Olaf Hering |
1f77a9 |
+ u32 ip_checksum_value_invalid:1;
|
|
Olaf Hering |
1f77a9 |
+ } receive;
|
|
Olaf Hering |
1f77a9 |
+ u32 value;
|
|
Olaf Hering |
1f77a9 |
+ };
|
|
Olaf Hering |
1f77a9 |
+};
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
+struct ndis_pkt_8021q_info {
|
|
Olaf Hering |
1f77a9 |
+ union {
|
|
Olaf Hering |
1f77a9 |
+ struct {
|
|
Olaf Hering |
1f77a9 |
+ u32 pri:3; /* User Priority */
|
|
Olaf Hering |
1f77a9 |
+ u32 cfi:1; /* Canonical Format ID */
|
|
Olaf Hering |
1f77a9 |
+ u32 vlanid:12; /* VLAN ID */
|
|
Olaf Hering |
1f77a9 |
+ u32 reserved:16;
|
|
Olaf Hering |
1f77a9 |
+ };
|
|
Olaf Hering |
1f77a9 |
+ u32 value;
|
|
Olaf Hering |
1f77a9 |
+ };
|
|
Olaf Hering |
1f77a9 |
+};
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
/*
|
|
Olaf Hering |
1f77a9 |
* Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
|
|
Olaf Hering |
1f77a9 |
@@ -194,7 +228,8 @@ int netvsc_send(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
struct sk_buff *skb,
|
|
Olaf Hering |
1f77a9 |
bool xdp_tx);
|
|
Olaf Hering |
1f77a9 |
void netvsc_linkstatus_callback(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
- struct rndis_message *resp);
|
|
Olaf Hering |
1f77a9 |
+ struct rndis_message *resp,
|
|
Olaf Hering |
1f77a9 |
+ void *data);
|
|
Olaf Hering |
1f77a9 |
int netvsc_recv_callback(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
struct netvsc_device *nvdev,
|
|
Olaf Hering |
1f77a9 |
struct netvsc_channel *nvchan);
|
|
Olaf Hering |
1f77a9 |
@@ -884,9 +919,10 @@ struct multi_recv_comp {
|
|
Olaf Hering |
1f77a9 |
#define NVSP_RSC_MAX 562 /* Max #RSC frags in a vmbus xfer page pkt */
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
struct nvsc_rsc {
|
|
Olaf Hering |
1f77a9 |
- const struct ndis_pkt_8021q_info *vlan;
|
|
Olaf Hering |
1f77a9 |
- const struct ndis_tcp_ip_checksum_info *csum_info;
|
|
Olaf Hering |
1f77a9 |
- const u32 *hash_info;
|
|
Olaf Hering |
1f77a9 |
+ struct ndis_pkt_8021q_info vlan;
|
|
Olaf Hering |
1f77a9 |
+ struct ndis_tcp_ip_checksum_info csum_info;
|
|
Olaf Hering |
1f77a9 |
+ u32 hash_info;
|
|
Olaf Hering |
1f77a9 |
+ u8 ppi_flags; /* valid/present bits for the above PPIs */
|
|
Olaf Hering |
1f77a9 |
u8 is_last; /* last RNDIS msg in a vmtransfer_page */
|
|
Olaf Hering |
1f77a9 |
u32 cnt; /* #fragments in an RSC packet */
|
|
Olaf Hering |
1f77a9 |
u32 pktlen; /* Full packet length */
|
|
Olaf Hering |
1f77a9 |
@@ -894,6 +930,10 @@ struct nvsc_rsc {
|
|
Olaf Hering |
1f77a9 |
u32 len[NVSP_RSC_MAX];
|
|
Olaf Hering |
1f77a9 |
};
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
+#define NVSC_RSC_VLAN BIT(0) /* valid/present bit for 'vlan' */
|
|
Olaf Hering |
1f77a9 |
+#define NVSC_RSC_CSUM_INFO BIT(1) /* valid/present bit for 'csum_info' */
|
|
Olaf Hering |
1f77a9 |
+#define NVSC_RSC_HASH_INFO BIT(2) /* valid/present bit for 'hash_info' */
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
struct netvsc_stats {
|
|
Olaf Hering |
1f77a9 |
u64 packets;
|
|
Olaf Hering |
1f77a9 |
u64 bytes;
|
|
Olaf Hering |
1f77a9 |
@@ -1002,6 +1042,7 @@ struct net_device_context {
|
|
Olaf Hering |
1f77a9 |
struct netvsc_channel {
|
|
Olaf Hering |
1f77a9 |
struct vmbus_channel *channel;
|
|
Olaf Hering |
1f77a9 |
struct netvsc_device *net_device;
|
|
Olaf Hering |
1f77a9 |
+ void *recv_buf; /* buffer to copy packets out from the receive buffer */
|
|
Olaf Hering |
1f77a9 |
const struct vmpacket_descriptor *desc;
|
|
Olaf Hering |
1f77a9 |
struct napi_struct napi;
|
|
Olaf Hering |
1f77a9 |
struct multi_send_data msd;
|
|
Olaf Hering |
1f77a9 |
@@ -1234,18 +1275,6 @@ struct rndis_pktinfo_id {
|
|
Olaf Hering |
1f77a9 |
u16 pkt_id;
|
|
Olaf Hering |
1f77a9 |
};
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
-struct ndis_pkt_8021q_info {
|
|
Olaf Hering |
1f77a9 |
- union {
|
|
Olaf Hering |
1f77a9 |
- struct {
|
|
Olaf Hering |
1f77a9 |
- u32 pri:3; /* User Priority */
|
|
Olaf Hering |
1f77a9 |
- u32 cfi:1; /* Canonical Format ID */
|
|
Olaf Hering |
1f77a9 |
- u32 vlanid:12; /* VLAN ID */
|
|
Olaf Hering |
1f77a9 |
- u32 reserved:16;
|
|
Olaf Hering |
1f77a9 |
- };
|
|
Olaf Hering |
1f77a9 |
- u32 value;
|
|
Olaf Hering |
1f77a9 |
- };
|
|
Olaf Hering |
1f77a9 |
-};
|
|
Olaf Hering |
1f77a9 |
-
|
|
Olaf Hering |
1f77a9 |
struct ndis_object_header {
|
|
Olaf Hering |
1f77a9 |
u8 type;
|
|
Olaf Hering |
1f77a9 |
u8 revision;
|
|
Olaf Hering |
1f77a9 |
@@ -1436,32 +1465,6 @@ struct ndis_offload_params {
|
|
Olaf Hering |
1f77a9 |
};
|
|
Olaf Hering |
1f77a9 |
};
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
-struct ndis_tcp_ip_checksum_info {
|
|
Olaf Hering |
1f77a9 |
- union {
|
|
Olaf Hering |
1f77a9 |
- struct {
|
|
Olaf Hering |
1f77a9 |
- u32 is_ipv4:1;
|
|
Olaf Hering |
1f77a9 |
- u32 is_ipv6:1;
|
|
Olaf Hering |
1f77a9 |
- u32 tcp_checksum:1;
|
|
Olaf Hering |
1f77a9 |
- u32 udp_checksum:1;
|
|
Olaf Hering |
1f77a9 |
- u32 ip_header_checksum:1;
|
|
Olaf Hering |
1f77a9 |
- u32 reserved:11;
|
|
Olaf Hering |
1f77a9 |
- u32 tcp_header_offset:10;
|
|
Olaf Hering |
1f77a9 |
- } transmit;
|
|
Olaf Hering |
1f77a9 |
- struct {
|
|
Olaf Hering |
1f77a9 |
- u32 tcp_checksum_failed:1;
|
|
Olaf Hering |
1f77a9 |
- u32 udp_checksum_failed:1;
|
|
Olaf Hering |
1f77a9 |
- u32 ip_checksum_failed:1;
|
|
Olaf Hering |
1f77a9 |
- u32 tcp_checksum_succeeded:1;
|
|
Olaf Hering |
1f77a9 |
- u32 udp_checksum_succeeded:1;
|
|
Olaf Hering |
1f77a9 |
- u32 ip_checksum_succeeded:1;
|
|
Olaf Hering |
1f77a9 |
- u32 loopback:1;
|
|
Olaf Hering |
1f77a9 |
- u32 tcp_checksum_value_invalid:1;
|
|
Olaf Hering |
1f77a9 |
- u32 ip_checksum_value_invalid:1;
|
|
Olaf Hering |
1f77a9 |
- } receive;
|
|
Olaf Hering |
1f77a9 |
- u32 value;
|
|
Olaf Hering |
1f77a9 |
- };
|
|
Olaf Hering |
1f77a9 |
-};
|
|
Olaf Hering |
1f77a9 |
-
|
|
Olaf Hering |
1f77a9 |
struct ndis_tcp_lso_info {
|
|
Olaf Hering |
1f77a9 |
union {
|
|
Olaf Hering |
1f77a9 |
struct {
|
|
Olaf Hering |
1f77a9 |
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
|
Olaf Hering |
1f77a9 |
--- a/drivers/net/hyperv/netvsc.c
|
|
Olaf Hering |
1f77a9 |
+++ b/drivers/net/hyperv/netvsc.c
|
|
Olaf Hering |
1f77a9 |
@@ -131,6 +131,7 @@ static void free_netvsc_device(struct rcu_head *head)
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
|
|
Olaf Hering |
1f77a9 |
xdp_rxq_info_unreg(&nvdev->chan_table[i].xdp_rxq);
|
|
Olaf Hering |
1f77a9 |
+ kfree(nvdev->chan_table[i].recv_buf);
|
|
Olaf Hering |
1f77a9 |
vfree(nvdev->chan_table[i].mrc.slots);
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
@@ -1284,6 +1285,19 @@ static int netvsc_receive(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
continue;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
+ /* We're going to copy (sections of) the packet into nvchan->recv_buf;
|
|
Olaf Hering |
1f77a9 |
+ * make sure that nvchan->recv_buf is large enough to hold the packet.
|
|
Olaf Hering |
1f77a9 |
+ */
|
|
Olaf Hering |
1f77a9 |
+ if (unlikely(buflen > net_device->recv_section_size)) {
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.cnt = 0;
|
|
Olaf Hering |
1f77a9 |
+ status = NVSP_STAT_FAIL;
|
|
Olaf Hering |
1f77a9 |
+ netif_err(net_device_ctx, rx_err, ndev,
|
|
Olaf Hering |
1f77a9 |
+ "Packet too big: buflen=%u recv_section_size=%u\n",
|
|
Olaf Hering |
1f77a9 |
+ buflen, net_device->recv_section_size);
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
+ continue;
|
|
Olaf Hering |
1f77a9 |
+ }
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
data = recv_buf + offset;
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
nvchan->rsc.is_last = (i == count - 1);
|
|
Olaf Hering |
1f77a9 |
@@ -1535,6 +1549,12 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
Olaf Hering |
1f77a9 |
for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
|
|
Olaf Hering |
1f77a9 |
struct netvsc_channel *nvchan = &net_device->chan_table[i];
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
+ nvchan->recv_buf = kzalloc(device_info->recv_section_size, GFP_KERNEL);
|
|
Olaf Hering |
1f77a9 |
+ if (nvchan->recv_buf == NULL) {
|
|
Olaf Hering |
1f77a9 |
+ ret = -ENOMEM;
|
|
Olaf Hering |
1f77a9 |
+ goto cleanup2;
|
|
Olaf Hering |
1f77a9 |
+ }
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
nvchan->channel = device->channel;
|
|
Olaf Hering |
1f77a9 |
nvchan->net_device = net_device;
|
|
Olaf Hering |
1f77a9 |
u64_stats_init(&nvchan->tx_stats.syncp);
|
|
Olaf Hering |
1f77a9 |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
|
Olaf Hering |
1f77a9 |
--- a/drivers/net/hyperv/netvsc_drv.c
|
|
Olaf Hering |
1f77a9 |
+++ b/drivers/net/hyperv/netvsc_drv.c
|
|
Olaf Hering |
1f77a9 |
@@ -743,7 +743,8 @@ static netdev_tx_t netvsc_start_xmit(struct sk_buff *skb,
|
|
Olaf Hering |
1f77a9 |
* netvsc_linkstatus_callback - Link up/down notification
|
|
Olaf Hering |
1f77a9 |
*/
|
|
Olaf Hering |
1f77a9 |
void netvsc_linkstatus_callback(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
- struct rndis_message *resp)
|
|
Olaf Hering |
1f77a9 |
+ struct rndis_message *resp,
|
|
Olaf Hering |
1f77a9 |
+ void *data)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
struct rndis_indicate_status *indicate = &resp->msg.indicate_status;
|
|
Olaf Hering |
1f77a9 |
struct net_device_context *ndev_ctx = netdev_priv(net);
|
|
Olaf Hering |
1f77a9 |
@@ -757,6 +758,9 @@ void netvsc_linkstatus_callback(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
return;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
+ /* Copy the RNDIS indicate status into nvchan->recv_buf */
|
|
Olaf Hering |
1f77a9 |
+ memcpy(indicate, data + RNDIS_HEADER_SIZE, sizeof(*indicate));
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
/* Update the physical link speed when changing to another vSwitch */
|
|
Olaf Hering |
1f77a9 |
if (indicate->status == RNDIS_STATUS_LINK_SPEED_CHANGE) {
|
|
Olaf Hering |
1f77a9 |
u32 speed;
|
|
Olaf Hering |
1f77a9 |
@@ -771,8 +775,7 @@ void netvsc_linkstatus_callback(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
return;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
- speed = *(u32 *)((void *)indicate
|
|
Olaf Hering |
1f77a9 |
- + indicate->status_buf_offset) / 10000;
|
|
Olaf Hering |
1f77a9 |
+ speed = *(u32 *)(data + RNDIS_HEADER_SIZE + indicate->status_buf_offset) / 10000;
|
|
Olaf Hering |
1f77a9 |
ndev_ctx->speed = speed;
|
|
Olaf Hering |
1f77a9 |
return;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
@@ -827,10 +830,11 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
struct xdp_buff *xdp)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
struct napi_struct *napi = &nvchan->napi;
|
|
Olaf Hering |
1f77a9 |
- const struct ndis_pkt_8021q_info *vlan = nvchan->rsc.vlan;
|
|
Olaf Hering |
1f77a9 |
+ const struct ndis_pkt_8021q_info *vlan = &nvchan->rsc.vlan;
|
|
Olaf Hering |
1f77a9 |
const struct ndis_tcp_ip_checksum_info *csum_info =
|
|
Olaf Hering |
1f77a9 |
- nvchan->rsc.csum_info;
|
|
Olaf Hering |
1f77a9 |
- const u32 *hash_info = nvchan->rsc.hash_info;
|
|
Olaf Hering |
1f77a9 |
+ &nvchan->rsc.csum_info;
|
|
Olaf Hering |
1f77a9 |
+ const u32 *hash_info = &nvchan->rsc.hash_info;
|
|
Olaf Hering |
1f77a9 |
+ u8 ppi_flags = nvchan->rsc.ppi_flags;
|
|
Olaf Hering |
1f77a9 |
struct sk_buff *skb;
|
|
Olaf Hering |
1f77a9 |
void *xbuf = xdp->data_hard_start;
|
|
Olaf Hering |
1f77a9 |
int i;
|
|
Olaf Hering |
1f77a9 |
@@ -874,7 +878,7 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
* We compute it here if the flags are set, because on Linux, the IP
|
|
Olaf Hering |
1f77a9 |
* checksum is always checked.
|
|
Olaf Hering |
1f77a9 |
*/
|
|
Olaf Hering |
1f77a9 |
- if (csum_info && csum_info->receive.ip_checksum_value_invalid &&
|
|
Olaf Hering |
1f77a9 |
+ if ((ppi_flags & NVSC_RSC_CSUM_INFO) && csum_info->receive.ip_checksum_value_invalid &&
|
|
Olaf Hering |
1f77a9 |
csum_info->receive.ip_checksum_succeeded &&
|
|
Olaf Hering |
1f77a9 |
skb->protocol == htons(ETH_P_IP)) {
|
|
Olaf Hering |
1f77a9 |
/* Check that there is enough space to hold the IP header. */
|
|
Olaf Hering |
1f77a9 |
@@ -886,16 +890,16 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
/* Do L4 checksum offload if enabled and present. */
|
|
Olaf Hering |
1f77a9 |
- if (csum_info && (net->features & NETIF_F_RXCSUM)) {
|
|
Olaf Hering |
1f77a9 |
+ if ((ppi_flags & NVSC_RSC_CSUM_INFO) && (net->features & NETIF_F_RXCSUM)) {
|
|
Olaf Hering |
1f77a9 |
if (csum_info->receive.tcp_checksum_succeeded ||
|
|
Olaf Hering |
1f77a9 |
csum_info->receive.udp_checksum_succeeded)
|
|
Olaf Hering |
1f77a9 |
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
- if (hash_info && (net->features & NETIF_F_RXHASH))
|
|
Olaf Hering |
1f77a9 |
+ if ((ppi_flags & NVSC_RSC_HASH_INFO) && (net->features & NETIF_F_RXHASH))
|
|
Olaf Hering |
1f77a9 |
skb_set_hash(skb, *hash_info, PKT_HASH_TYPE_L4);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
- if (vlan) {
|
|
Olaf Hering |
1f77a9 |
+ if (ppi_flags & NVSC_RSC_VLAN) {
|
|
Olaf Hering |
1f77a9 |
u16 vlan_tci = vlan->vlanid | (vlan->pri << VLAN_PRIO_SHIFT) |
|
|
Olaf Hering |
1f77a9 |
(vlan->cfi ? VLAN_CFI_MASK : 0);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
|
Olaf Hering |
1f77a9 |
--- a/drivers/net/hyperv/rndis_filter.c
|
|
Olaf Hering |
1f77a9 |
+++ b/drivers/net/hyperv/rndis_filter.c
|
|
Olaf Hering |
1f77a9 |
@@ -127,12 +127,13 @@ static void put_rndis_request(struct rndis_device *dev,
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
static void dump_rndis_message(struct net_device *netdev,
|
|
Olaf Hering |
1f77a9 |
- const struct rndis_message *rndis_msg)
|
|
Olaf Hering |
1f77a9 |
+ const struct rndis_message *rndis_msg,
|
|
Olaf Hering |
1f77a9 |
+ const void *data)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
switch (rndis_msg->ndis_msg_type) {
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_PACKET:
|
|
Olaf Hering |
1f77a9 |
if (rndis_msg->msg_len - RNDIS_HEADER_SIZE >= sizeof(struct rndis_packet)) {
|
|
Olaf Hering |
1f77a9 |
- const struct rndis_packet *pkt = &rndis_msg->msg.pkt;
|
|
Olaf Hering |
1f77a9 |
+ const struct rndis_packet *pkt = data + RNDIS_HEADER_SIZE;
|
|
Olaf Hering |
1f77a9 |
netdev_dbg(netdev, "RNDIS_MSG_PACKET (len %u, "
|
|
Olaf Hering |
1f77a9 |
"data offset %u data len %u, # oob %u, "
|
|
Olaf Hering |
1f77a9 |
"oob offset %u, oob len %u, pkt offset %u, "
|
|
Olaf Hering |
1f77a9 |
@@ -152,7 +153,7 @@ static void dump_rndis_message(struct net_device *netdev,
|
|
Olaf Hering |
1f77a9 |
if (rndis_msg->msg_len - RNDIS_HEADER_SIZE >=
|
|
Olaf Hering |
1f77a9 |
sizeof(struct rndis_initialize_complete)) {
|
|
Olaf Hering |
1f77a9 |
const struct rndis_initialize_complete *init_complete =
|
|
Olaf Hering |
1f77a9 |
- &rndis_msg->msg.init_complete;
|
|
Olaf Hering |
1f77a9 |
+ data + RNDIS_HEADER_SIZE;
|
|
Olaf Hering |
1f77a9 |
netdev_dbg(netdev, "RNDIS_MSG_INIT_C "
|
|
Olaf Hering |
1f77a9 |
"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
|
|
Olaf Hering |
1f77a9 |
"device flags %d, max xfer size 0x%x, max pkts %u, "
|
|
Olaf Hering |
1f77a9 |
@@ -173,7 +174,7 @@ static void dump_rndis_message(struct net_device *netdev,
|
|
Olaf Hering |
1f77a9 |
if (rndis_msg->msg_len - RNDIS_HEADER_SIZE >=
|
|
Olaf Hering |
1f77a9 |
sizeof(struct rndis_query_complete)) {
|
|
Olaf Hering |
1f77a9 |
const struct rndis_query_complete *query_complete =
|
|
Olaf Hering |
1f77a9 |
- &rndis_msg->msg.query_complete;
|
|
Olaf Hering |
1f77a9 |
+ data + RNDIS_HEADER_SIZE;
|
|
Olaf Hering |
1f77a9 |
netdev_dbg(netdev, "RNDIS_MSG_QUERY_C "
|
|
Olaf Hering |
1f77a9 |
"(len %u, id 0x%x, status 0x%x, buf len %u, "
|
|
Olaf Hering |
1f77a9 |
"buf offset %u)\n",
|
|
Olaf Hering |
1f77a9 |
@@ -188,7 +189,7 @@ static void dump_rndis_message(struct net_device *netdev,
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_SET_C:
|
|
Olaf Hering |
1f77a9 |
if (rndis_msg->msg_len - RNDIS_HEADER_SIZE + sizeof(struct rndis_set_complete)) {
|
|
Olaf Hering |
1f77a9 |
const struct rndis_set_complete *set_complete =
|
|
Olaf Hering |
1f77a9 |
- &rndis_msg->msg.set_complete;
|
|
Olaf Hering |
1f77a9 |
+ data + RNDIS_HEADER_SIZE;
|
|
Olaf Hering |
1f77a9 |
netdev_dbg(netdev,
|
|
Olaf Hering |
1f77a9 |
"RNDIS_MSG_SET_C (len %u, id 0x%x, status 0x%x)\n",
|
|
Olaf Hering |
1f77a9 |
rndis_msg->msg_len,
|
|
Olaf Hering |
1f77a9 |
@@ -201,7 +202,7 @@ static void dump_rndis_message(struct net_device *netdev,
|
|
Olaf Hering |
1f77a9 |
if (rndis_msg->msg_len - RNDIS_HEADER_SIZE >=
|
|
Olaf Hering |
1f77a9 |
sizeof(struct rndis_indicate_status)) {
|
|
Olaf Hering |
1f77a9 |
const struct rndis_indicate_status *indicate_status =
|
|
Olaf Hering |
1f77a9 |
- &rndis_msg->msg.indicate_status;
|
|
Olaf Hering |
1f77a9 |
+ data + RNDIS_HEADER_SIZE;
|
|
Olaf Hering |
1f77a9 |
netdev_dbg(netdev, "RNDIS_MSG_INDICATE "
|
|
Olaf Hering |
1f77a9 |
"(len %u, status 0x%x, buf len %u, buf offset %u)\n",
|
|
Olaf Hering |
1f77a9 |
rndis_msg->msg_len,
|
|
Olaf Hering |
1f77a9 |
@@ -286,8 +287,10 @@ static void rndis_set_link_state(struct rndis_device *rdev,
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
static void rndis_filter_receive_response(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
struct netvsc_device *nvdev,
|
|
Olaf Hering |
1f77a9 |
- const struct rndis_message *resp)
|
|
Olaf Hering |
1f77a9 |
+ struct rndis_message *resp,
|
|
Olaf Hering |
1f77a9 |
+ void *data)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
+ u32 *req_id = &resp->msg.init_complete.req_id;
|
|
Olaf Hering |
1f77a9 |
struct rndis_device *dev = nvdev->extension;
|
|
Olaf Hering |
1f77a9 |
struct rndis_request *request = NULL;
|
|
Olaf Hering |
1f77a9 |
bool found = false;
|
|
Olaf Hering |
1f77a9 |
@@ -312,14 +315,16 @@ static void rndis_filter_receive_response(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
return;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
+ /* Copy the request ID into nvchan->recv_buf */
|
|
Olaf Hering |
1f77a9 |
+ *req_id = *(u32 *)(data + RNDIS_HEADER_SIZE);
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
spin_lock_irqsave(&dev->request_lock, flags);
|
|
Olaf Hering |
1f77a9 |
list_for_each_entry(request, &dev->req_list, list_ent) {
|
|
Olaf Hering |
1f77a9 |
/*
|
|
Olaf Hering |
1f77a9 |
* All request/response message contains RequestId as the 1st
|
|
Olaf Hering |
1f77a9 |
* field
|
|
Olaf Hering |
1f77a9 |
*/
|
|
Olaf Hering |
1f77a9 |
- if (request->request_msg.msg.init_req.req_id
|
|
Olaf Hering |
1f77a9 |
- == resp->msg.init_complete.req_id) {
|
|
Olaf Hering |
1f77a9 |
+ if (request->request_msg.msg.init_req.req_id == *req_id) {
|
|
Olaf Hering |
1f77a9 |
found = true;
|
|
Olaf Hering |
1f77a9 |
break;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
@@ -329,8 +334,10 @@ static void rndis_filter_receive_response(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
if (found) {
|
|
Olaf Hering |
1f77a9 |
if (resp->msg_len <=
|
|
Olaf Hering |
1f77a9 |
sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
|
|
Olaf Hering |
1f77a9 |
- memcpy(&request->response_msg, resp,
|
|
Olaf Hering |
1f77a9 |
- resp->msg_len);
|
|
Olaf Hering |
1f77a9 |
+ memcpy(&request->response_msg, resp, RNDIS_HEADER_SIZE + sizeof(*req_id));
|
|
Olaf Hering |
1f77a9 |
+ memcpy((void *)&request->response_msg + RNDIS_HEADER_SIZE + sizeof(*req_id),
|
|
Olaf Hering |
1f77a9 |
+ data + RNDIS_HEADER_SIZE + sizeof(*req_id),
|
|
Olaf Hering |
1f77a9 |
+ resp->msg_len - RNDIS_HEADER_SIZE - sizeof(*req_id));
|
|
Olaf Hering |
1f77a9 |
if (request->request_msg.ndis_msg_type ==
|
|
Olaf Hering |
1f77a9 |
RNDIS_MSG_QUERY && request->request_msg.msg.
|
|
Olaf Hering |
1f77a9 |
query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS)
|
|
Olaf Hering |
1f77a9 |
@@ -359,7 +366,7 @@ static void rndis_filter_receive_response(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
netdev_err(ndev,
|
|
Olaf Hering |
1f77a9 |
"no rndis request found for this response "
|
|
Olaf Hering |
1f77a9 |
"(id 0x%x res type 0x%x)\n",
|
|
Olaf Hering |
1f77a9 |
- resp->msg.init_complete.req_id,
|
|
Olaf Hering |
1f77a9 |
+ *req_id,
|
|
Olaf Hering |
1f77a9 |
resp->ndis_msg_type);
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
@@ -371,7 +378,7 @@ static void rndis_filter_receive_response(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
static inline void *rndis_get_ppi(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
struct rndis_packet *rpkt,
|
|
Olaf Hering |
1f77a9 |
u32 rpkt_len, u32 type, u8 internal,
|
|
Olaf Hering |
1f77a9 |
- u32 ppi_size)
|
|
Olaf Hering |
1f77a9 |
+ u32 ppi_size, void *data)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
struct rndis_per_packet_info *ppi;
|
|
Olaf Hering |
1f77a9 |
int len;
|
|
Olaf Hering |
1f77a9 |
@@ -396,6 +403,8 @@ static inline void *rndis_get_ppi(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
ppi = (struct rndis_per_packet_info *)((ulong)rpkt +
|
|
Olaf Hering |
1f77a9 |
rpkt->per_pkt_info_offset);
|
|
Olaf Hering |
1f77a9 |
+ /* Copy the PPIs into nvchan->recv_buf */
|
|
Olaf Hering |
1f77a9 |
+ memcpy(ppi, data + RNDIS_HEADER_SIZE + rpkt->per_pkt_info_offset, rpkt->per_pkt_info_len);
|
|
Olaf Hering |
1f77a9 |
len = rpkt->per_pkt_info_len;
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
while (len > 0) {
|
|
Olaf Hering |
1f77a9 |
@@ -438,10 +447,29 @@ void rsc_add_data(struct netvsc_channel *nvchan,
|
|
Olaf Hering |
1f77a9 |
if (cnt) {
|
|
Olaf Hering |
1f77a9 |
nvchan->rsc.pktlen += len;
|
|
Olaf Hering |
1f77a9 |
} else {
|
|
Olaf Hering |
1f77a9 |
- nvchan->rsc.vlan = vlan;
|
|
Olaf Hering |
1f77a9 |
- nvchan->rsc.csum_info = csum_info;
|
|
Olaf Hering |
1f77a9 |
+ /* The data/values pointed by vlan, csum_info and hash_info are shared
|
|
Olaf Hering |
1f77a9 |
+ * across the different 'fragments' of the RSC packet; store them into
|
|
Olaf Hering |
1f77a9 |
+ * the packet itself.
|
|
Olaf Hering |
1f77a9 |
+ */
|
|
Olaf Hering |
1f77a9 |
+ if (vlan != NULL) {
|
|
Olaf Hering |
1f77a9 |
+ memcpy(&nvchan->rsc.vlan, vlan, sizeof(*vlan));
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.ppi_flags |= NVSC_RSC_VLAN;
|
|
Olaf Hering |
1f77a9 |
+ } else {
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.ppi_flags &= ~NVSC_RSC_VLAN;
|
|
Olaf Hering |
1f77a9 |
+ }
|
|
Olaf Hering |
1f77a9 |
+ if (csum_info != NULL) {
|
|
Olaf Hering |
1f77a9 |
+ memcpy(&nvchan->rsc.csum_info, csum_info, sizeof(*csum_info));
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.ppi_flags |= NVSC_RSC_CSUM_INFO;
|
|
Olaf Hering |
1f77a9 |
+ } else {
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.ppi_flags &= ~NVSC_RSC_CSUM_INFO;
|
|
Olaf Hering |
1f77a9 |
+ }
|
|
Olaf Hering |
1f77a9 |
nvchan->rsc.pktlen = len;
|
|
Olaf Hering |
1f77a9 |
- nvchan->rsc.hash_info = hash_info;
|
|
Olaf Hering |
1f77a9 |
+ if (hash_info != NULL) {
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.csum_info = *csum_info;
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.ppi_flags |= NVSC_RSC_HASH_INFO;
|
|
Olaf Hering |
1f77a9 |
+ } else {
|
|
Olaf Hering |
1f77a9 |
+ nvchan->rsc.ppi_flags &= ~NVSC_RSC_HASH_INFO;
|
|
Olaf Hering |
1f77a9 |
+ }
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
nvchan->rsc.data[cnt] = data;
|
|
Olaf Hering |
1f77a9 |
@@ -453,7 +481,7 @@ static int rndis_filter_receive_data(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
struct netvsc_device *nvdev,
|
|
Olaf Hering |
1f77a9 |
struct netvsc_channel *nvchan,
|
|
Olaf Hering |
1f77a9 |
struct rndis_message *msg,
|
|
Olaf Hering |
1f77a9 |
- u32 data_buflen)
|
|
Olaf Hering |
1f77a9 |
+ void *data, u32 data_buflen)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
struct rndis_packet *rndis_pkt = &msg->msg.pkt;
|
|
Olaf Hering |
1f77a9 |
const struct ndis_tcp_ip_checksum_info *csum_info;
|
|
Olaf Hering |
1f77a9 |
@@ -461,7 +489,6 @@ static int rndis_filter_receive_data(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
const struct rndis_pktinfo_id *pktinfo_id;
|
|
Olaf Hering |
1f77a9 |
const u32 *hash_info;
|
|
Olaf Hering |
1f77a9 |
u32 data_offset, rpkt_len;
|
|
Olaf Hering |
1f77a9 |
- void *data;
|
|
Olaf Hering |
1f77a9 |
bool rsc_more = false;
|
|
Olaf Hering |
1f77a9 |
int ret;
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
@@ -472,6 +499,9 @@ static int rndis_filter_receive_data(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
return NVSP_STAT_FAIL;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
+ /* Copy the RNDIS packet into nvchan->recv_buf */
|
|
Olaf Hering |
1f77a9 |
+ memcpy(rndis_pkt, data + RNDIS_HEADER_SIZE, sizeof(*rndis_pkt));
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
/* Validate rndis_pkt offset */
|
|
Olaf Hering |
1f77a9 |
if (rndis_pkt->data_offset >= data_buflen - RNDIS_HEADER_SIZE) {
|
|
Olaf Hering |
1f77a9 |
netdev_err(ndev, "invalid rndis packet offset: %u\n",
|
|
Olaf Hering |
1f77a9 |
@@ -497,18 +527,17 @@ static int rndis_filter_receive_data(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
return NVSP_STAT_FAIL;
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
- vlan = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, IEEE_8021Q_INFO, 0, sizeof(*vlan));
|
|
Olaf Hering |
1f77a9 |
+ vlan = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, IEEE_8021Q_INFO, 0, sizeof(*vlan),
|
|
Olaf Hering |
1f77a9 |
+ data);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
csum_info = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, TCPIP_CHKSUM_PKTINFO, 0,
|
|
Olaf Hering |
1f77a9 |
- sizeof(*csum_info));
|
|
Olaf Hering |
1f77a9 |
+ sizeof(*csum_info), data);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
hash_info = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, NBL_HASH_VALUE, 0,
|
|
Olaf Hering |
1f77a9 |
- sizeof(*hash_info));
|
|
Olaf Hering |
1f77a9 |
+ sizeof(*hash_info), data);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
pktinfo_id = rndis_get_ppi(ndev, rndis_pkt, rpkt_len, RNDIS_PKTINFO_ID, 1,
|
|
Olaf Hering |
1f77a9 |
- sizeof(*pktinfo_id));
|
|
Olaf Hering |
1f77a9 |
-
|
|
Olaf Hering |
1f77a9 |
- data = (void *)msg + data_offset;
|
|
Olaf Hering |
1f77a9 |
+ sizeof(*pktinfo_id), data);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
/* Identify RSC frags, drop erroneous packets */
|
|
Olaf Hering |
1f77a9 |
if (pktinfo_id && (pktinfo_id->flag & RNDIS_PKTINFO_SUBALLOC)) {
|
|
Olaf Hering |
1f77a9 |
@@ -537,7 +566,7 @@ static int rndis_filter_receive_data(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
* the data packet to the stack, without the rndis trailer padding
|
|
Olaf Hering |
1f77a9 |
*/
|
|
Olaf Hering |
1f77a9 |
rsc_add_data(nvchan, vlan, csum_info, hash_info,
|
|
Olaf Hering |
1f77a9 |
- data, rndis_pkt->data_len);
|
|
Olaf Hering |
1f77a9 |
+ data + data_offset, rndis_pkt->data_len);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
if (rsc_more)
|
|
Olaf Hering |
1f77a9 |
return NVSP_STAT_SUCCESS;
|
|
Olaf Hering |
1f77a9 |
@@ -559,10 +588,18 @@ int rndis_filter_receive(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
void *data, u32 buflen)
|
|
Olaf Hering |
1f77a9 |
{
|
|
Olaf Hering |
1f77a9 |
struct net_device_context *net_device_ctx = netdev_priv(ndev);
|
|
Olaf Hering |
1f77a9 |
- struct rndis_message *rndis_msg = data;
|
|
Olaf Hering |
1f77a9 |
+ struct rndis_message *rndis_msg = nvchan->recv_buf;
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
+ if (buflen < RNDIS_HEADER_SIZE) {
|
|
Olaf Hering |
1f77a9 |
+ netdev_err(ndev, "Invalid rndis_msg (buflen: %u)\n", buflen);
|
|
Olaf Hering |
1f77a9 |
+ return NVSP_STAT_FAIL;
|
|
Olaf Hering |
1f77a9 |
+ }
|
|
Olaf Hering |
1f77a9 |
+
|
|
Olaf Hering |
1f77a9 |
+ /* Copy the RNDIS msg header into nvchan->recv_buf */
|
|
Olaf Hering |
1f77a9 |
+ memcpy(rndis_msg, data, RNDIS_HEADER_SIZE);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
/* Validate incoming rndis_message packet */
|
|
Olaf Hering |
1f77a9 |
- if (buflen < RNDIS_HEADER_SIZE || rndis_msg->msg_len < RNDIS_HEADER_SIZE ||
|
|
Olaf Hering |
1f77a9 |
+ if (rndis_msg->msg_len < RNDIS_HEADER_SIZE ||
|
|
Olaf Hering |
1f77a9 |
buflen < rndis_msg->msg_len) {
|
|
Olaf Hering |
1f77a9 |
netdev_err(ndev, "Invalid rndis_msg (buflen: %u, msg_len: %u)\n",
|
|
Olaf Hering |
1f77a9 |
buflen, rndis_msg->msg_len);
|
|
Olaf Hering |
1f77a9 |
@@ -570,22 +607,22 @@ int rndis_filter_receive(struct net_device *ndev,
|
|
Olaf Hering |
1f77a9 |
}
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
if (netif_msg_rx_status(net_device_ctx))
|
|
Olaf Hering |
1f77a9 |
- dump_rndis_message(ndev, rndis_msg);
|
|
Olaf Hering |
1f77a9 |
+ dump_rndis_message(ndev, rndis_msg, data);
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
switch (rndis_msg->ndis_msg_type) {
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_PACKET:
|
|
Olaf Hering |
1f77a9 |
return rndis_filter_receive_data(ndev, net_dev, nvchan,
|
|
Olaf Hering |
1f77a9 |
- rndis_msg, buflen);
|
|
Olaf Hering |
1f77a9 |
+ rndis_msg, data, buflen);
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_INIT_C:
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_QUERY_C:
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_SET_C:
|
|
Olaf Hering |
1f77a9 |
/* completion msgs */
|
|
Olaf Hering |
1f77a9 |
- rndis_filter_receive_response(ndev, net_dev, rndis_msg);
|
|
Olaf Hering |
1f77a9 |
+ rndis_filter_receive_response(ndev, net_dev, rndis_msg, data);
|
|
Olaf Hering |
1f77a9 |
break;
|
|
Olaf Hering |
1f77a9 |
|
|
Olaf Hering |
1f77a9 |
case RNDIS_MSG_INDICATE:
|
|
Olaf Hering |
1f77a9 |
/* notification msgs */
|
|
Olaf Hering |
1f77a9 |
- netvsc_linkstatus_callback(ndev, rndis_msg);
|
|
Olaf Hering |
1f77a9 |
+ netvsc_linkstatus_callback(ndev, rndis_msg, data);
|
|
Olaf Hering |
1f77a9 |
break;
|
|
Olaf Hering |
1f77a9 |
default:
|
|
Olaf Hering |
1f77a9 |
netdev_err(ndev,
|