Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153449416
D7639.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D7639.diff
View Options
Index: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
@@ -96,6 +96,8 @@
static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
struct hn_softc *sc, struct vmbus_channel *chan,
const void *data, int dlen);
+static int hn_rndis_query(struct hn_softc *sc, uint32_t oid,
+ const void *idata, size_t idlen, void *odata, size_t *odlen0);
static __inline uint32_t
hn_rndis_rid(struct hn_softc *sc)
@@ -695,13 +697,23 @@
/*
* RNDIS filter query device MAC address
*/
-static inline int
+static int
hv_rf_query_device_mac(rndis_device *device)
{
- uint32_t size = ETHER_ADDR_LEN;
+ struct hn_softc *sc = device->sc;
+ size_t hwaddr_len;
+ int error;
- return (hv_rf_query_device(device,
- RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
+ hwaddr_len = ETHER_ADDR_LEN;
+ error = hn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
+ device->hw_mac_addr, &hwaddr_len);
+ if (error)
+ return error;
+ if (hwaddr_len != ETHER_ADDR_LEN) {
+ if_printf(sc->hn_ifp, "invalid hwaddr len %zu\n", hwaddr_len);
+ return EINVAL;
+ }
+ return 0;
}
/*
@@ -892,12 +904,12 @@
static const void *
hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
- size_t reqlen, size_t min_complen, uint32_t comp_type)
+ size_t reqlen, size_t *comp_len0, uint32_t comp_type)
{
struct vmbus_gpa gpa[HN_XACT_REQ_PGCNT];
const struct rndis_comp_hdr *comp;
bus_addr_t paddr;
- size_t comp_len;
+ size_t comp_len, min_complen = *comp_len0;
int gpa_cnt, error;
KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
@@ -946,7 +958,14 @@
* Check this RNDIS complete message.
*/
if (comp_len < min_complen) {
- if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu\n", comp_len);
+ if (comp_len >= sizeof(*comp)) {
+ /* rm_status field is valid */
+ if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu, "
+ "status 0x%08x\n", comp_len, comp->rm_status);
+ } else {
+ if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu\n",
+ comp_len);
+ }
return (NULL);
}
if (comp->rm_len < min_complen) {
@@ -965,9 +984,100 @@
return (NULL);
}
/* All pass! */
+ *comp_len0 = comp_len;
return (comp);
}
+static int
+hn_rndis_query(struct hn_softc *sc, uint32_t oid,
+ const void *idata, size_t idlen, void *odata, size_t *odlen0)
+{
+ struct rndis_query_req *req;
+ const struct rndis_query_comp *comp;
+ struct vmbus_xact *xact;
+ size_t reqlen, odlen = *odlen0, comp_len;
+ int error, ofs;
+ uint32_t rid;
+
+ reqlen = sizeof(*req) + idlen;
+ xact = vmbus_xact_get(sc->hn_xact, reqlen);
+ if (xact == NULL) {
+ if_printf(sc->hn_ifp, "no xact for RNDIS query\n");
+ return (ENXIO);
+ }
+ rid = hn_rndis_rid(sc);
+ req = vmbus_xact_req_data(xact);
+ req->rm_type = REMOTE_NDIS_QUERY_MSG;
+ req->rm_len = reqlen;
+ req->rm_rid = rid;
+ req->rm_oid = oid;
+ /*
+ * XXX
+ * This is _not_ RNDIS Spec conforming:
+ * "This MUST be set to 0 when there is no input data
+ * associated with the OID."
+ *
+ * If this field was set to 0 according to the RNDIS Spec,
+ * Hyper-V would set non-SUCCESS status in the query
+ * completion.
+ */
+ req->rm_infobufoffset = RNDIS_QUERY_REQ_INFOBUFOFFSET;
+
+ if (idlen > 0) {
+ req->rm_infobuflen = idlen;
+ /* Input data immediately follows RNDIS query. */
+ memcpy(req + 1, idata, idlen);
+ }
+
+ comp_len = sizeof(*comp) + odlen;
+ comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
+ REMOTE_NDIS_QUERY_CMPLT);
+ if (comp == NULL) {
+ if_printf(sc->hn_ifp, "exec RNDIS query 0x%08x failed\n", oid);
+ error = EIO;
+ goto done;
+ }
+
+ if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
+ if_printf(sc->hn_ifp, "RNDIS query 0x%08x failed: "
+ "status 0x%08x\n", oid, comp->rm_status);
+ error = EIO;
+ goto done;
+ }
+ if (comp->rm_infobuflen == 0 || comp->rm_infobufoffset == 0) {
+ /* No output data! */
+ if_printf(sc->hn_ifp, "RNDIS query 0x%08x, no data\n", oid);
+ *odlen0 = 0;
+ error = 0;
+ goto done;
+ }
+
+ /*
+ * Check output data length and offset.
+ */
+ /* ofs is the offset from the beginning of comp. */
+ ofs = RNDIS_QUERY_COMP_INFOBUFABS(comp->rm_infobufoffset);
+ if (ofs < sizeof(*comp) || ofs + comp->rm_infobuflen > comp_len) {
+ if_printf(sc->hn_ifp, "RNDIS query invalid comp ib off/len, "
+ "%u/%u\n", comp->rm_infobufoffset, comp->rm_infobuflen);
+ error = EINVAL;
+ goto done;
+ }
+
+ /*
+ * Save output data.
+ */
+ if (comp->rm_infobuflen < odlen)
+ odlen = comp->rm_infobuflen;
+ memcpy(odata, ((const uint8_t *)comp) + ofs, odlen);
+ *odlen0 = odlen;
+
+ error = 0;
+done:
+ vmbus_xact_put(xact);
+ return (error);
+}
+
/*
* RNDIS filter init device
*/
@@ -978,6 +1088,7 @@
struct rndis_init_req *req;
const struct rndis_init_comp *comp;
struct vmbus_xact *xact;
+ size_t comp_len;
uint32_t rid;
int error;
@@ -998,8 +1109,9 @@
req->rm_ver_minor = RNDIS_VERSION_MINOR;
req->rm_max_xfersz = HN_RNDIS_XFER_SIZE;
- comp = hn_rndis_xact_execute(sc, xact, rid, sizeof(*req),
- RNDIS_INIT_COMP_SIZE_MIN, REMOTE_NDIS_INITIALIZE_CMPLT);
+ comp_len = RNDIS_INIT_COMP_SIZE_MIN;
+ comp = hn_rndis_xact_execute(sc, xact, rid, sizeof(*req), &comp_len,
+ REMOTE_NDIS_INITIALIZE_CMPLT);
if (comp == NULL) {
if_printf(sc->hn_ifp, "exec RNDIS init failed\n");
error = EIO;
Index: head/sys/net/rndis.h
===================================================================
--- head/sys/net/rndis.h
+++ head/sys/net/rndis.h
@@ -172,6 +172,10 @@
uint32_t rm_devicevchdl;
};
+#define RNDIS_QUERY_REQ_INFOBUFOFFSET \
+ (sizeof(struct rndis_query_req) - \
+ __offsetof(struct rndis_query_req, rm_rid))
+
struct rndis_query_comp {
uint32_t rm_type;
uint32_t rm_len;
@@ -181,6 +185,9 @@
uint32_t rm_infobufoffset;
};
+#define RNDIS_QUERY_COMP_INFOBUFABS(ofs) \
+ ((ofs) + __offsetof(struct rndis_query_req, rm_rid))
+
/* Send a set object request. */
#define REMOTE_NDIS_SET_MSG 0x00000005
#define REMOTE_NDIS_SET_CMPLT 0x80000005
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 22, 6:00 AM (2 m, 46 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31957459
Default Alt Text
D7639.diff (6 KB)
Attached To
Mode
D7639: hyperv/hn: Use vmbus xact for RNDIS query.
Attached
Detach File
Event Timeline
Log In to Comment