From df29623c07eca7831df9d6c1f7271af07e356654 Mon Sep 17 00:00:00 2001 From: sephe Date: Thu, 13 Oct 2016 07:42:44 +0000 Subject: [PATCH] MFC 305405,305407,305408,305410,305411,305453 305405 hyperv/vmbus: Stringent header length and total length check. While I'm here, minor style changes. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7752 305407 hyperv/hn: Stringent NVS notification length check. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7753 305408 hyperv/hn: Stringent NVS RNDIS packets length checks. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7755 305410 net/rndis: Define RNDIS status message, which could be sent by device. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7757 305411 hyperv/hn: Stringent RNDIS control message length check. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7758 305453 hyperv/hn: Stringent RNDIS packet message length/offset check. While I'm here, use definition in net/rndis.h Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7782 git-svn-id: svn://svn.freebsd.org/base/stable/10@307198 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/hyperv/netvsc/hv_net_vsc.c | 46 +++- sys/dev/hyperv/netvsc/hv_rndis_filter.c | 269 ++++++++++++++++++------ sys/dev/hyperv/netvsc/hv_rndis_filter.h | 2 +- sys/dev/hyperv/vmbus/vmbus_chan.c | 38 +++- sys/dev/hyperv/vmbus/vmbus_reg.h | 3 + sys/net/rndis.h | 35 ++- 6 files changed, 307 insertions(+), 86 deletions(-) diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index e6f4e6843..51f32f3c1 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -741,32 +741,53 @@ hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, { const struct vmbus_chanpkt_rxbuf *pkt; const struct hn_nvs_hdr *nvs_hdr; - int count = 0; - int i = 0; + int count, i, hlen; - /* Make sure that this is a RNDIS message. */ + if (__predict_false(VMBUS_CHANPKT_DATALEN(pkthdr) < sizeof(*nvs_hdr))) { + if_printf(rxr->hn_ifp, "invalid nvs RNDIS\n"); + return; + } nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr); + + /* Make sure that this is a RNDIS message. */ if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) { if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n", nvs_hdr->nvs_type); return; } - + + hlen = VMBUS_CHANPKT_GETLEN(pkthdr->cph_hlen); + if (__predict_false(hlen < sizeof(*pkt))) { + if_printf(rxr->hn_ifp, "invalid rxbuf chanpkt\n"); + return; + } pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; - if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) { - if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n", + if (__predict_false(pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID)) { + if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n", pkt->cp_rxbuf_id); return; } count = pkt->cp_rxbuf_cnt; + if (__predict_false(hlen < + __offsetof(struct vmbus_chanpkt_rxbuf, cp_rxbuf[count]))) { + if_printf(rxr->hn_ifp, "invalid rxbuf_cnt %d\n", count); + return; + } /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ - for (i = 0; i < count; i++) { - hv_rf_on_receive(sc, rxr, - rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs, - pkt->cp_rxbuf[i].rb_len); + for (i = 0; i < count; ++i) { + int ofs, len; + + ofs = pkt->cp_rxbuf[i].rb_ofs; + len = pkt->cp_rxbuf[i].rb_len; + if (__predict_false(ofs + len > NETVSC_RECEIVE_BUFFER_SIZE)) { + if_printf(rxr->hn_ifp, "%dth RNDIS msg overflow rxbuf, " + "ofs %d, len %d\n", i, ofs, len); + continue; + } + hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len); } /* @@ -815,7 +836,12 @@ hn_proc_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) { const struct hn_nvs_hdr *hdr; + if (VMBUS_CHANPKT_DATALEN(pkt) < sizeof(*hdr)) { + if_printf(sc->hn_ifp, "invalid nvs notify\n"); + return; + } hdr = VMBUS_CHANPKT_CONST_DATA(pkt); + if (hdr->nvs_type == HN_NVS_TYPE_TXTBL_NOTE) { /* Useless; ignore */ return; diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.c b/sys/dev/hyperv/netvsc/hv_rndis_filter.c index 2772f92ee..91ecc2c5d 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$"); * Forward declarations */ static void hv_rf_receive_indicate_status(struct hn_softc *sc, - const rndis_msg *response); + const void *data, int dlen); static void hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen); static int hv_rf_query_device_mac(struct hn_softc *sc, uint8_t *eaddr); @@ -132,59 +132,50 @@ hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size, * RNDIS filter receive indicate status */ static void -hv_rf_receive_indicate_status(struct hn_softc *sc, const rndis_msg *response) +hv_rf_receive_indicate_status(struct hn_softc *sc, const void *data, int dlen) { - const rndis_indicate_status *indicate = &response->msg.indicate_status; - - switch(indicate->status) { + const struct rndis_status_msg *msg; + + if (dlen < sizeof(*msg)) { + if_printf(sc->hn_ifp, "invalid RNDIS status\n"); + return; + } + msg = data; + + switch (msg->rm_status) { case RNDIS_STATUS_MEDIA_CONNECT: netvsc_linkstatus_callback(sc, 1); break; + case RNDIS_STATUS_MEDIA_DISCONNECT: netvsc_linkstatus_callback(sc, 0); break; + default: /* TODO: */ - if_printf(sc->hn_ifp, - "unknown status %d received\n", indicate->status); + if_printf(sc->hn_ifp, "unknown RNDIS status 0x%08x\n", + msg->rm_status); break; } } static int -hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info) +hn_rndis_rxinfo(const void *info_data, int info_dlen, struct hn_recvinfo *info) { - const struct rndis_pktinfo *pi; - uint32_t mask = 0, len; + const struct rndis_pktinfo *pi = info_data; + uint32_t mask = 0; - info->vlan_info = HN_NDIS_VLAN_INFO_INVALID; - info->csum_info = HN_NDIS_RXCSUM_INFO_INVALID; - info->hash_info = HN_NDIS_HASH_INFO_INVALID; - - if (rpkt->per_pkt_info_offset == 0) - return (0); - if (__predict_false(rpkt->per_pkt_info_offset & - (RNDIS_PKTINFO_ALIGN - 1))) - return (EINVAL); - if (__predict_false(rpkt->per_pkt_info_offset < - RNDIS_PACKET_MSG_OFFSET_MIN)) - return (EINVAL); - - pi = (const struct rndis_pktinfo *) - ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset); - len = rpkt->per_pkt_info_length; - - while (len != 0) { + while (info_dlen != 0) { const void *data; uint32_t dlen; - if (__predict_false(len < sizeof(*pi))) + if (__predict_false(info_dlen < sizeof(*pi))) return (EINVAL); - if (__predict_false(len < pi->rm_size)) + if (__predict_false(info_dlen < pi->rm_size)) return (EINVAL); - len -= pi->rm_size; + info_dlen -= pi->rm_size; - if (__predict_false(pi->rm_size & (RNDIS_PKTINFO_ALIGN - 1))) + if (__predict_false(pi->rm_size & RNDIS_PKTINFO_SIZE_ALIGNMASK)) return (EINVAL); if (__predict_false(pi->rm_size < pi->rm_pktinfooffset)) return (EINVAL); @@ -242,76 +233,223 @@ hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info) return (0); } +static __inline bool +hn_rndis_check_overlap(int off, int len, int check_off, int check_len) +{ + + if (off < check_off) { + if (__predict_true(off + len <= check_off)) + return (false); + } else if (off > check_off) { + if (__predict_true(check_off + check_len <= off)) + return (false); + } + return (true); +} + /* * RNDIS filter receive data */ static void hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen) { - const rndis_msg *message = data; - const rndis_packet *rndis_pkt; - uint32_t data_offset; + const struct rndis_packet_msg *pkt; struct hn_recvinfo info; - - rndis_pkt = &message->msg.packet; + int data_off, pktinfo_off, data_len, pktinfo_len; /* - * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this - * netvsc packet (ie tot_data_buf_len != message_length) + * Check length. */ + if (__predict_false(dlen < sizeof(*pkt))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg\n"); + return; + } + pkt = data; - /* Remove rndis header, then pass data packet up the stack */ - data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; + if (__predict_false(dlen < pkt->rm_len)) { + if_printf(rxr->hn_ifp, "truncated RNDIS packet msg, " + "dlen %d, msglen %u\n", dlen, pkt->rm_len); + return; + } + if (__predict_false(pkt->rm_len < + pkt->rm_datalen + pkt->rm_oobdatalen + pkt->rm_pktinfolen)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msglen, " + "msglen %u, data %u, oob %u, pktinfo %u\n", + pkt->rm_len, pkt->rm_datalen, pkt->rm_oobdatalen, + pkt->rm_pktinfolen); + return; + } + if (__predict_false(pkt->rm_datalen == 0)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, no data\n"); + return; + } - dlen -= data_offset; - if (dlen < rndis_pkt->data_length) { - if_printf(rxr->hn_ifp, - "total length %u is less than data length %u\n", - dlen, rndis_pkt->data_length); + /* + * Check offests. + */ +#define IS_OFFSET_INVALID(ofs) \ + ((ofs) < RNDIS_PACKET_MSG_OFFSET_MIN || \ + ((ofs) & RNDIS_PACKET_MSG_OFFSET_ALIGNMASK)) + + /* XXX Hyper-V does not meet data offset alignment requirement */ + if (__predict_false(pkt->rm_dataoffset < RNDIS_PACKET_MSG_OFFSET_MIN)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "data offset %u\n", pkt->rm_dataoffset); + return; + } + if (__predict_false(pkt->rm_oobdataoffset > 0 && + IS_OFFSET_INVALID(pkt->rm_oobdataoffset))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob offset %u\n", pkt->rm_oobdataoffset); + return; + } + if (__predict_true(pkt->rm_pktinfooffset > 0) && + __predict_false(IS_OFFSET_INVALID(pkt->rm_pktinfooffset))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo offset %u\n", pkt->rm_pktinfooffset); return; } - dlen = rndis_pkt->data_length; - data = (const uint8_t *)data + data_offset; +#undef IS_OFFSET_INVALID + + data_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_dataoffset); + data_len = pkt->rm_datalen; + pktinfo_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_pktinfooffset); + pktinfo_len = pkt->rm_pktinfolen; + + /* + * Check OOB coverage. + */ + if (__predict_false(pkt->rm_oobdatalen != 0)) { + int oob_off, oob_len; + + if_printf(rxr->hn_ifp, "got oobdata\n"); + oob_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_oobdataoffset); + oob_len = pkt->rm_oobdatalen; + + if (__predict_false(oob_off + oob_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overflow, msglen %u, oob abs %d len %d\n", + pkt->rm_len, oob_off, oob_len); + return; + } + + /* + * Check against data. + */ + if (hn_rndis_check_overlap(oob_off, oob_len, + data_off, data_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overlaps data, oob abs %d len %d, " + "data abs %d len %d\n", + oob_off, oob_len, data_off, data_len); + return; + } + + /* + * Check against pktinfo. + */ + if (pktinfo_len != 0 && + hn_rndis_check_overlap(oob_off, oob_len, + pktinfo_off, pktinfo_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overlaps pktinfo, oob abs %d len %d, " + "pktinfo abs %d len %d\n", + oob_off, oob_len, pktinfo_off, pktinfo_len); + return; + } + } + + /* + * Check per-packet-info coverage and find useful per-packet-info. + */ + info.vlan_info = HN_NDIS_VLAN_INFO_INVALID; + info.csum_info = HN_NDIS_RXCSUM_INFO_INVALID; + info.hash_info = HN_NDIS_HASH_INFO_INVALID; + if (__predict_true(pktinfo_len != 0)) { + bool overlap; + int error; + + if (__predict_false(pktinfo_off + pktinfo_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo overflow, msglen %u, " + "pktinfo abs %d len %d\n", + pkt->rm_len, pktinfo_off, pktinfo_len); + return; + } + + /* + * Check packet info coverage. + */ + overlap = hn_rndis_check_overlap(pktinfo_off, pktinfo_len, + data_off, data_len); + if (__predict_false(overlap)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo overlap data, pktinfo abs %d len %d, " + "data abs %d len %d\n", + pktinfo_off, pktinfo_len, data_off, data_len); + return; + } + + /* + * Find useful per-packet-info. + */ + error = hn_rndis_rxinfo(((const uint8_t *)pkt) + pktinfo_off, + pktinfo_len, &info); + if (__predict_false(error)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg " + "pktinfo\n"); + return; + } + } - if (hv_rf_find_recvinfo(rndis_pkt, &info)) { - if_printf(rxr->hn_ifp, "recvinfo parsing failed\n"); + if (__predict_false(data_off + data_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "data overflow, msglen %u, data abs %d len %d\n", + pkt->rm_len, data_off, data_len); return; } - netvsc_recv(rxr, data, dlen, &info); + netvsc_recv(rxr, ((const uint8_t *)pkt) + data_off, data_len, &info); } /* * RNDIS filter on receive */ -int +void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, const void *data, int dlen) { - const rndis_msg *rndis_hdr; const struct rndis_comp_hdr *comp; + const struct rndis_msghdr *hdr; + + if (__predict_false(dlen < sizeof(*hdr))) { + if_printf(rxr->hn_ifp, "invalid RNDIS msg\n"); + return; + } + hdr = data; - rndis_hdr = data; - switch (rndis_hdr->ndis_msg_type) { - /* data message */ + switch (hdr->rm_type) { case REMOTE_NDIS_PACKET_MSG: hv_rf_receive_data(rxr, data, dlen); break; - /* completion messages */ case REMOTE_NDIS_INITIALIZE_CMPLT: case REMOTE_NDIS_QUERY_CMPLT: case REMOTE_NDIS_SET_CMPLT: - case REMOTE_NDIS_KEEPALIVE_CMPLT: + case REMOTE_NDIS_KEEPALIVE_CMPLT: /* unused */ + if (dlen < sizeof(*comp)) { + if_printf(rxr->hn_ifp, "invalid RNDIS cmplt\n"); + return; + } comp = data; + KASSERT(comp->rm_rid > HN_RNDIS_RID_COMPAT_MAX, - ("invalid rid 0x%08x\n", comp->rm_rid)); + ("invalid RNDIS rid 0x%08x\n", comp->rm_rid)); vmbus_xact_ctx_wakeup(sc->hn_xact, comp, dlen); break; - /* notification message */ case REMOTE_NDIS_INDICATE_STATUS_MSG: - hv_rf_receive_indicate_status(sc, rndis_hdr); + hv_rf_receive_indicate_status(sc, data, dlen); break; case REMOTE_NDIS_RESET_CMPLT: @@ -322,15 +460,14 @@ hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, * RESET is not issued by hn(4), so this message should * _not_ be observed. */ - if_printf(sc->hn_ifp, "RESET CMPLT received\n"); + if_printf(rxr->hn_ifp, "RESET cmplt received\n"); break; default: - if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n", - rndis_hdr->ndis_msg_type); + if_printf(rxr->hn_ifp, "unknown RNDIS msg 0x%x\n", + hdr->rm_type); break; } - return (0); } /* @@ -552,7 +689,7 @@ hn_rndis_query(struct hn_softc *sc, uint32_t oid, * Check output data length and offset. */ /* ofs is the offset from the beginning of comp. */ - ofs = RNDIS_QUERY_COMP_INFOBUFABS(comp->rm_infobufoffset); + ofs = RNDIS_QUERY_COMP_INFOBUFOFFSET_ABS(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); diff --git a/sys/dev/hyperv/netvsc/hv_rndis_filter.h b/sys/dev/hyperv/netvsc/hv_rndis_filter.h index 82c4d7587..ad29e8b0f 100644 --- a/sys/dev/hyperv/netvsc/hv_rndis_filter.h +++ b/sys/dev/hyperv/netvsc/hv_rndis_filter.h @@ -40,7 +40,7 @@ */ struct hn_rx_ring; -int hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, +void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, const void *data, int dlen); void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan, diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c index 73e34f9bd..6accc0e1b 100644 --- a/sys/dev/hyperv/vmbus/vmbus_chan.c +++ b/sys/dev/hyperv/vmbus/vmbus_chan.c @@ -721,7 +721,20 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); if (error) - return error; + return (error); + + if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { + device_printf(chan->ch_dev, "invalid hlen %u\n", + pkt.cph_hlen); + /* XXX this channel is dead actually. */ + return (EIO); + } + if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) { + device_printf(chan->ch_dev, "invalid hlen %u and tlen %u\n", + pkt.cph_hlen, pkt.cph_tlen); + /* XXX this channel is dead actually. */ + return (EIO); + } hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen); dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen; @@ -729,7 +742,7 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, if (*dlen0 < dlen) { /* Return the size of this packet's data. */ *dlen0 = dlen; - return ENOBUFS; + return (ENOBUFS); } *xactid = pkt.cph_xactid; @@ -739,7 +752,7 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0, error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen); KASSERT(!error, ("vmbus_rxbr_read failed")); - return 0; + return (0); } int @@ -751,13 +764,26 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan, error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); if (error) - return error; + return (error); + + if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { + device_printf(chan->ch_dev, "invalid hlen %u\n", + pkt.cph_hlen); + /* XXX this channel is dead actually. */ + return (EIO); + } + if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) { + device_printf(chan->ch_dev, "invalid hlen %u and tlen %u\n", + pkt.cph_hlen, pkt.cph_tlen); + /* XXX this channel is dead actually. */ + return (EIO); + } pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen); if (*pktlen0 < pktlen) { /* Return the size of this packet. */ *pktlen0 = pktlen; - return ENOBUFS; + return (ENOBUFS); } *pktlen0 = pktlen; @@ -765,7 +791,7 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan, error = vmbus_rxbr_read(&chan->ch_rxbr, pkt0, pktlen, 0); KASSERT(!error, ("vmbus_rxbr_read failed")); - return 0; + return (0); } static void diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h index b1a2de029..522e68c02 100644 --- a/sys/dev/hyperv/vmbus/vmbus_reg.h +++ b/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -153,6 +153,9 @@ do { \ #define VMBUS_CHANPKT_TOTLEN(tlen) \ roundup2((tlen), VMBUS_CHANPKT_SIZE_ALIGN) +#define VMBUS_CHANPKT_HLEN_MIN \ + (sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT) + struct vmbus_chanpkt { struct vmbus_chanpkt_hdr cp_hdr; } __packed; diff --git a/sys/net/rndis.h b/sys/net/rndis.h index 0477a6570..2cd1a0d71 100644 --- a/sys/net/rndis.h +++ b/sys/net/rndis.h @@ -127,6 +127,14 @@ struct rndis_packet_msg { (sizeof(struct rndis_packet_msg) - \ __offsetof(struct rndis_packet_msg, rm_dataoffset)) +/* Offset from the beginning of rndis_packet_msg. */ +#define RNDIS_PACKET_MSG_OFFSET_ABS(ofs) \ + ((ofs) + __offsetof(struct rndis_packet_msg, rm_dataoffset)) + +#define RNDIS_PACKET_MSG_OFFSET_ALIGN 4 +#define RNDIS_PACKET_MSG_OFFSET_ALIGNMASK \ + (RNDIS_PACKET_MSG_OFFSET_ALIGN - 1) + /* Per-packet-info for RNDIS data message */ struct rndis_pktinfo { uint32_t rm_size; @@ -137,7 +145,8 @@ struct rndis_pktinfo { #define RNDIS_PKTINFO_OFFSET \ __offsetof(struct rndis_pktinfo, rm_data[0]) -#define RNDIS_PKTINFO_ALIGN 4 +#define RNDIS_PKTINFO_SIZE_ALIGN 4 +#define RNDIS_PKTINFO_SIZE_ALIGNMASK (RNDIS_PKTINFO_SIZE_ALIGN - 1) #define NDIS_PKTINFO_TYPE_CSUM 0 #define NDIS_PKTINFO_TYPE_IPSEC 1 @@ -236,7 +245,8 @@ struct rndis_query_comp { uint32_t rm_infobufoffset; }; -#define RNDIS_QUERY_COMP_INFOBUFABS(ofs) \ +/* infobuf offset from the beginning of rndis_query_comp. */ +#define RNDIS_QUERY_COMP_INFOBUFOFFSET_ABS(ofs) \ ((ofs) + __offsetof(struct rndis_query_req, rm_rid)) /* Send a set object request. */ @@ -295,9 +305,28 @@ struct rndis_reset_comp { uint32_t rm_adrreset; }; -/* 802.3 link-state or undefined message error. */ +/* 802.3 link-state or undefined message error. Sent by device. */ #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007 +struct rndis_status_msg { + uint32_t rm_type; + uint32_t rm_len; + uint32_t rm_status; + uint32_t rm_stbuflen; + uint32_t rm_stbufoffset; + /* rndis_diag_info */ +}; + +/* + * Immediately after rndis_status_msg.rm_stbufoffset, if a control + * message is malformatted, or a packet message contains inappropriate + * content. + */ +struct rndis_diag_info { + uint32_t rm_diagstatus; + uint32_t rm_erroffset; +}; + /* Keepalive messsage. May be sent by device. */ #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008 #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008 -- 2.45.0