VirtualBox

Changeset 58313 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Oct 19, 2015 4:31:59 PM (9 years ago)
Author:
vboxsync
Message:

VMM/GIM: Implemented simple DHCP for Hyper-V debug transport.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GIMHv.cpp

    r58283 r58313  
    7979};
    8080#undef GIMHV_MSRRANGE
     81
     82/**
     83 * DHCP OFFER packet response to the guest (client) over the Hyper-V debug
     84 * transport.
     85 *
     86 * - MAC: Destination: broadcast.
     87 * - MAC: Source: 00:00:00:00:01 (hypervisor). It's important that it's
     88 *   different from the client's MAC address which is all 0's.
     89 * - IP: Source: 10.0.5.1 (hypervisor)
     90 * - IP: Destination: broadcast.
     91 * - IP: Checksum included.
     92 * - BOOTP: Client IP address: 10.0.5.5.
     93 * - BOOTP: Server IP address: 10.0.5.1.
     94 * - DHCP options: Subnet mask, router, lease-time, DHCP server identifier.
     95 *   Options are kept to a minimum required for making Windows guests happy.
     96 */
     97#define GIMHV_DEBUGCLIENT_IPV4          RT_H2N_U32_C(0x0a000505)    /* 10.0.5.5 */
     98#define GIMHV_DEBUGSERVER_IPV4          RT_H2N_U32_C(0x0a000501)    /* 10.0.5.1 */
     99static const uint8_t g_abDhcpOffer[] =
     100{
     101    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x45, 0x10,
     102    0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x6a, 0xb5, 0x0a, 0x00, 0x05, 0x01, 0xff, 0xff,
     103    0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x14, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x00,
     104    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x05, 0x00, 0x00,
     105    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     106    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     107    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     108    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     109    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     110    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     111    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     112    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     113    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     114    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     115    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     116    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     117    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     118    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x01, 0x04, 0xff,
     119    0xff, 0xff, 0x00, 0x03, 0x04, 0x0a, 0x00, 0x05, 0x01, 0x33, 0x04, 0xff, 0xff, 0xff, 0xff, 0x36,
     120    0x04, 0x0a, 0x00, 0x05, 0x01, 0xff
     121};
     122
     123/**
     124 * DHCP ACK packet response to the guest (client) over the Hyper-V debug
     125 * transport.
     126 *
     127 * - MAC: Destination: 00:00:00:00:00 (client).
     128 * - IP: Destination: 10.0.5.5 (client).
     129 * - Rest are mostly similar to the DHCP offer.
     130 */
     131static const uint8_t g_abDhcpAck[] =
     132{
     133    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x45, 0x10,
     134    0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x5b, 0xb0, 0x0a, 0x00, 0x05, 0x01, 0x0a, 0x00,
     135    0x05, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x14, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x00,
     136    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x05, 0x0a, 0x00, 0x05, 0x05, 0x00, 0x00,
     137    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     138    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     139    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     140    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     141    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     142    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     143    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     144    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     145    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     146    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     147    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     148    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     149    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     150    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x01, 0x04, 0xff,
     151    0xff, 0xff, 0x00, 0x03, 0x04, 0x0a, 0x00, 0x05, 0x01, 0x33, 0x04, 0xff, 0xff, 0xff, 0xff, 0x36,
     152    0x04, 0x0a, 0x00, 0x05, 0x01, 0xff
     153};
     154
     155/**
     156 * ARP reply to the guest (client) over the Hyper-V debug transport.
     157 *
     158 * - MAC: Destination: 00:00:00:00:00 (client)
     159 * - MAC: Source: 00:00:00:00:01 (hypervisor)
     160 * - ARP: Reply: 10.0.5.1 is at Source MAC address.
     161 */
     162static const uint8_t g_abArpReply[] =
     163{
     164    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x01,
     165    0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x05, 0x01,
     166    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x05
     167};
    81168
    82169
     
    10261113    AssertReturn(cbBuf >= cbRead, VERR_INVALID_PARAMETER);
    10271114
    1028     /*
    1029      * Read the data.
    1030      */
    1031     size_t cbReallyRead = cbRead;
    1032     int rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead);
    1033 
    1034     /*
    1035      * Encapsulate it in a UDP packet if required.
    1036      */
    1037     if (   RT_SUCCESS(rc)
    1038         && fUdpPkt
    1039         && cbReallyRead > 0)
    1040     {
    1041         uint8_t abFrame[sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + sizeof(RTNETUDP)];
    1042         if (cbReallyRead + sizeof(abFrame) <= cbBuf)
     1115    int rc;
     1116    if (!fUdpPkt)
     1117    {
     1118        /*
     1119         * Read the raw debug data.
     1120         */
     1121        size_t cbReallyRead = cbRead;
     1122        rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead);
     1123        *pcbRead = (uint32_t)cbReallyRead;
     1124    }
     1125    else
     1126    {
     1127        /*
     1128         * Guest requires UDP encapsulated frames.
     1129         */
     1130        PGIMHV pHv = &pVM->gim.s.u.Hv;
     1131        rc = VERR_GIM_IPE_1;
     1132        switch (pHv->enmDebugReply)
    10431133        {
    1044             /*
    1045              * Windows guests pumps ethernet frames over the Hyper-V debug connection as
    1046              * explained in gimR3HvHypercallPostDebugData(). Here, we reconstruct the packet
    1047              * with the guest's self-chosen IP ARP address we saved in pHv->DbgGuestAddr.
    1048              *
    1049              * Note! We really need to pass the minimum IPv4 header length. The Windows 10 guest
    1050              * is -not- happy if we include the IPv4 options field, i.e. using sizeof(RTNETIPV4)
    1051              * instead of RTNETIPV4_MIN_LEN.
    1052              */
    1053             PGIMHV pHv = &pVM->gim.s.u.Hv;
    1054             RT_ZERO(abFrame);
    1055             PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)&abFrame[0];
    1056             PRTNETIPV4     pIpHdr  = (PRTNETIPV4)    (pEthHdr + 1);
    1057             PRTNETUDP      pUdpHdr = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
    1058 
    1059             /* Ethernet */
    1060             pEthHdr->EtherType = RT_H2N_U16_C(RTNET_ETHERTYPE_IPV4);
    1061             /* IPv4 */
    1062             pIpHdr->ip_v       = 4;
    1063             pIpHdr->ip_hl      = RTNETIPV4_MIN_LEN / sizeof(uint32_t);
    1064             pIpHdr->ip_tos     = 0;
    1065             pIpHdr->ip_len     = RT_H2N_U16((uint16_t)cbReallyRead + sizeof(RTNETUDP) + RTNETIPV4_MIN_LEN);
    1066             pIpHdr->ip_id      = 0;
    1067             pIpHdr->ip_off     = 0;
    1068             pIpHdr->ip_ttl     = 255;
    1069             pIpHdr->ip_p       = RTNETIPV4_PROT_UDP;
    1070             pIpHdr->ip_sum     = 0;
    1071             pIpHdr->ip_src.u   = 0;
    1072             pIpHdr->ip_dst.u   = pHv->DbgGuestAddr.u;
    1073             pIpHdr->ip_sum     = RTNetIPv4HdrChecksum(pIpHdr);
    1074             /* UDP */
    1075             pUdpHdr->uh_ulen   = RT_H2N_U16_C((uint16_t)cbReallyRead + sizeof(*pUdpHdr));
    1076 
    1077             /* Make room by moving the payload and prepending the headers. */
    1078             uint8_t *pbData = (uint8_t *)pvBuf;
    1079             memmove(pbData + sizeof(abFrame), pbData, cbReallyRead);
    1080             memcpy(pbData, &abFrame[0], sizeof(abFrame));
    1081 
    1082             /* Update the adjusted sizes. */
    1083             cbReallyRead += sizeof(abFrame);
     1134            case GIMHVDEBUGREPLY_UDP:
     1135            {
     1136                size_t cbReallyRead = cbRead;
     1137                rc = GIMR3DebugRead(pVM, pvBuf, &cbReallyRead);
     1138                if (   RT_SUCCESS(rc)
     1139                    && cbReallyRead > 0)
     1140                {
     1141                    uint8_t abFrame[sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + sizeof(RTNETUDP)];
     1142                    if (cbReallyRead + sizeof(abFrame) <= cbBuf)
     1143                    {
     1144                        /*
     1145                         * Windows guests pumps ethernet frames over the Hyper-V debug connection as
     1146                         * explained in gimR3HvHypercallPostDebugData(). Here, we reconstruct the packet
     1147                         * with the guest's self-chosen IP ARP address we saved in pHv->DbgGuestAddr.
     1148                         *
     1149                         * Note! We really need to pass the minimum IPv4 header length. The Windows 10 guest
     1150                         * is -not- happy if we include the IPv4 options field, i.e. using sizeof(RTNETIPV4)
     1151                         * instead of RTNETIPV4_MIN_LEN.
     1152                         */
     1153                        RT_ZERO(abFrame);
     1154                        PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)&abFrame[0];
     1155                        PRTNETIPV4     pIpHdr  = (PRTNETIPV4)    (pEthHdr + 1);
     1156                        PRTNETUDP      pUdpHdr = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
     1157
     1158                        /* Ethernet */
     1159                        pEthHdr->EtherType = RT_H2N_U16_C(RTNET_ETHERTYPE_IPV4);
     1160                        /* IPv4 */
     1161                        pIpHdr->ip_v       = 4;
     1162                        pIpHdr->ip_hl      = RTNETIPV4_MIN_LEN / sizeof(uint32_t);
     1163                        pIpHdr->ip_tos     = 0;
     1164                        pIpHdr->ip_len     = RT_H2N_U16((uint16_t)cbReallyRead + sizeof(RTNETUDP) + RTNETIPV4_MIN_LEN);
     1165                        pIpHdr->ip_id      = 0;
     1166                        pIpHdr->ip_off     = 0;
     1167                        pIpHdr->ip_ttl     = 255;
     1168                        pIpHdr->ip_p       = RTNETIPV4_PROT_UDP;
     1169                        pIpHdr->ip_sum     = 0;
     1170                        pIpHdr->ip_src.u   = 0;
     1171                        pIpHdr->ip_dst.u   = pHv->DbgGuestAddr.u;
     1172                        pIpHdr->ip_sum     = RTNetIPv4HdrChecksum(pIpHdr);
     1173                        /* UDP */
     1174                        pUdpHdr->uh_ulen   = RT_H2N_U16_C((uint16_t)cbReallyRead + sizeof(*pUdpHdr));
     1175
     1176                        /* Make room by moving the payload and prepending the headers. */
     1177                        uint8_t *pbData = (uint8_t *)pvBuf;
     1178                        memmove(pbData + sizeof(abFrame), pbData, cbReallyRead);
     1179                        memcpy(pbData, &abFrame[0], sizeof(abFrame));
     1180
     1181                        /* Update the adjusted sizes. */
     1182                        cbReallyRead += sizeof(abFrame);
     1183                    }
     1184                    else
     1185                        rc = VERR_BUFFER_UNDERFLOW;
     1186                }
     1187                *pcbRead = (uint32_t)cbReallyRead;
     1188                break;
     1189            }
     1190
     1191            case GIMHVDEBUGREPLY_ARP_REPLY:
     1192            {
     1193                uint32_t const cbArpReplyPkt =  sizeof(g_abArpReply);
     1194                if (cbBuf >= cbArpReplyPkt)
     1195                {
     1196                    memcpy(pvBuf, g_abArpReply, cbArpReplyPkt);
     1197                    rc = VINF_SUCCESS;
     1198                    *pcbRead = cbArpReplyPkt;
     1199                    pHv->enmDebugReply = GIMHVDEBUGREPLY_ARP_REPLY_SENT;
     1200                }
     1201                else
     1202                {
     1203                    rc = VERR_BUFFER_UNDERFLOW;
     1204                    *pcbRead = 0;
     1205                }
     1206                break;
     1207            }
     1208
     1209            case GIMHVDEBUGREPLY_DHCP_OFFER:
     1210            {
     1211                uint32_t const cbDhcpOfferPkt = sizeof(g_abDhcpOffer);
     1212                if (cbBuf >= cbDhcpOfferPkt)
     1213                {
     1214                    memcpy(pvBuf, g_abDhcpOffer, cbDhcpOfferPkt);
     1215                    PRTNETETHERHDR pEthHdr   = (PRTNETETHERHDR)pvBuf;
     1216                    PRTNETIPV4     pIpHdr    = (PRTNETIPV4)    (pEthHdr + 1);
     1217                    PRTNETUDP      pUdpHdr   = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
     1218                    PRTNETBOOTP    pBootpHdr = (PRTNETBOOTP)   (pUdpHdr + 1);
     1219                    pBootpHdr->bp_xid = pHv->uBootpXId;
     1220
     1221                    rc = VINF_SUCCESS;
     1222                    *pcbRead = cbDhcpOfferPkt;
     1223                    pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_OFFER_SENT;
     1224                    LogRel(("GIM: HyperV: Debug DHCP offered IP address %RTnaipv4, transaction Id %#x\n", pBootpHdr->bp_yiaddr,
     1225                            RT_N2H_U32(pHv->uBootpXId)));
     1226                }
     1227                else
     1228                {
     1229                    rc = VERR_BUFFER_UNDERFLOW;
     1230                    *pcbRead = 0;
     1231                }
     1232                break;
     1233            }
     1234
     1235            case GIMHVDEBUGREPLY_DHCP_ACK:
     1236            {
     1237                uint32_t const cbDhcpAckPkt = sizeof(g_abDhcpAck);
     1238                if (cbBuf >= cbDhcpAckPkt)
     1239                {
     1240                    memcpy(pvBuf, g_abDhcpAck, cbDhcpAckPkt);
     1241                    PRTNETETHERHDR pEthHdr = (PRTNETETHERHDR)pvBuf;
     1242                    PRTNETIPV4     pIpHdr  = (PRTNETIPV4)    (pEthHdr + 1);
     1243                    PRTNETUDP      pUdpHdr = (PRTNETUDP)     ((uint8_t *)pIpHdr + RTNETIPV4_MIN_LEN);
     1244                    PRTNETBOOTP    pBootpHdr = (PRTNETBOOTP) (pUdpHdr + 1);
     1245                    pBootpHdr->bp_xid = pHv->uBootpXId;
     1246
     1247                    rc = VINF_SUCCESS;
     1248                    *pcbRead = cbDhcpAckPkt;
     1249                    pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_ACK_SENT;
     1250                    LogRel(("GIM: HyperV: Debug DHCP acknowledged IP address %RTnaipv4, transaction Id %#x\n",
     1251                            pBootpHdr->bp_yiaddr, RT_N2H_U32(pHv->uBootpXId)));
     1252                }
     1253                else
     1254                {
     1255                    rc = VERR_BUFFER_UNDERFLOW;
     1256                    *pcbRead = 0;
     1257                }
     1258                break;
     1259            }
     1260
     1261            case GIMHVDEBUGREPLY_ARP_REPLY_SENT:
     1262            case GIMHVDEBUGREPLY_DHCP_OFFER_SENT:
     1263            case GIMHVDEBUGREPLY_DHCP_ACK_SENT:
     1264            {
     1265                rc = VINF_SUCCESS;
     1266                *pcbRead = 0;
     1267                break;
     1268            }
     1269
     1270            default:
     1271            {
     1272                AssertMsgFailed(("GIM: HyperV: Invalid/unimplemented debug reply type %u\n", pHv->enmDebugReply));
     1273                rc = VERR_INTERNAL_ERROR_2;
     1274            }
    10841275        }
    1085         else
    1086             rc = VERR_BUFFER_UNDERFLOW;
    1087     }
    1088 
    1089     *pcbRead = (uint32_t)cbReallyRead;
     1276        Assert(rc != VERR_GIM_IPE_1);
     1277    }
    10901278    return rc;
    10911279}
     
    11221310         * protocol payload.
    11231311         *
    1124          * At present, we only handle guests configured with the "nodhcp" option. This makes
    1125          * the guest send ARP queries with a self-chosen IP and after a couple of attempts of
    1126          * receiving no replies, the guest picks its own IP address. After this, the guest
    1127          * starts sending the UDP packets we require. We thus ignore the initial ARP packets
    1128          * (and to be safe all non-UDP packets) until the guest eventually starts talking
    1129          * UDP. Then we can finally feed the UDP payload over the debug connection.
     1312         * If the guest is configured with the "nodhcp" option it sends ARP queries with
     1313         * a self-chosen IP and after a couple of attempts of receiving no replies, the guest
     1314         * picks its own IP address. After this, the guest starts sending the UDP packets
     1315         * we require. We thus ignore the initial ARP packets until the guest eventually
     1316         * starts talking UDP. Then we can finally feed the UDP payload over the debug
     1317         * connection.
    11301318         */
    11311319        if (cbWrite > sizeof(RTNETETHERHDR))
     
    11501338                        {
    11511339                            /*
    1152                              * Extract the UDP payload and pass it to the debugger and record the guest IP address.
    1153                              * Hyper-V sends UDP debugger packets with source and destination port as 0. If we don't
    1154                              * filter out the ports here, we would receive BOOTP, NETBIOS and other UDP sub-protocol
    1155                              * packets which the debugger yells as "Bad packet received from...".
     1340                             * Check for DHCP.
    11561341                             */
    1157                             if (   !pUdpHdr->uh_dport
    1158                                 && !pUdpHdr->uh_sport)
     1342                            size_t const cbUdpPkt = cbMaxIpPkt - cbIpHdr;
     1343                            if (   pUdpHdr->uh_dport == RT_N2H_U16_C(RTNETIPV4_PORT_BOOTPS)
     1344                                && pUdpHdr->uh_sport == RT_N2H_U16_C(RTNETIPV4_PORT_BOOTPC)
     1345                                && cbMaxIpPkt >= cbIpHdr + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN)
    11591346                            {
     1347                                PCRTNETBOOTP pDhcpPkt = (PCRTNETBOOTP)(pUdpHdr + 1);
     1348                                uint8_t bMsgType;
     1349                                if (RTNetIPv4IsDHCPValid(pUdpHdr, pDhcpPkt, cbUdpPkt - sizeof(*pUdpHdr), &bMsgType))
     1350                                {
     1351                                    switch (bMsgType)
     1352                                    {
     1353                                        case RTNET_DHCP_MT_DISCOVER:
     1354                                            pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_OFFER;
     1355                                            pHv->uBootpXId = pDhcpPkt->bp_xid;
     1356                                            break;
     1357                                        case RTNET_DHCP_MT_REQUEST:
     1358                                            pHv->enmDebugReply = GIMHVDEBUGREPLY_DHCP_ACK;
     1359                                            pHv->uBootpXId = pDhcpPkt->bp_xid;
     1360                                            break;
     1361                                        default:
     1362                                            LogRelMax(5, ("GIM: HyperV: Debug DHCP MsgType %#x not implemented! Packet dropped\n",
     1363                                                          bMsgType));
     1364                                            break;
     1365                                    }
     1366                                }
     1367                                fIgnorePkt = true;
     1368                            }
     1369                            else if (   !pUdpHdr->uh_dport
     1370                                     && !pUdpHdr->uh_sport)
     1371                            {
     1372                                /*
     1373                                 * Extract the UDP payload and pass it to the debugger and record the guest IP address.
     1374                                 * Hyper-V sends UDP debugger packets with source and destination port as 0. If we don't
     1375                                 * filter out the ports here, we would receive BOOTP, NETBIOS and other UDP sub-protocol
     1376                                 * packets which the debugger yells as "Bad packet received from...".
     1377                                 */
    11601378                                uint32_t const cbFrameHdr = sizeof(RTNETETHERHDR) + cbIpHdr + sizeof(RTNETUDP);
    11611379                                pbData  += cbFrameHdr;
    11621380                                cbWrite -= cbFrameHdr;
    11631381                                pHv->DbgGuestAddr = pIp4Hdr->ip_src;
     1382                                pHv->enmDebugReply = GIMHVDEBUGREPLY_UDP;
    11641383                            }
    11651384                            else
     
    11891408                }
    11901409            }
     1410            else if (pEtherHdr->EtherType == RT_H2N_U16_C(RTNET_ETHERTYPE_ARP))
     1411            {
     1412                /*
     1413                 * Check for targetted ARP query.
     1414                 */
     1415                PCRTNETARPHDR pArpHdr = (PCRTNETARPHDR)(pbData + sizeof(RTNETETHERHDR));
     1416                if (   pArpHdr->ar_hlen  == sizeof(RTMAC)
     1417                    && pArpHdr->ar_plen  == sizeof(RTNETADDRIPV4)
     1418                    && pArpHdr->ar_htype == RT_H2N_U16(RTNET_ARP_ETHER)
     1419                    && pArpHdr->ar_ptype == RT_H2N_U16(RTNET_ETHERTYPE_IPV4))
     1420                {
     1421                    uint16_t uArpOp = pArpHdr->ar_oper;
     1422                    if (uArpOp == RT_H2N_U16_C(RTNET_ARPOP_REQUEST))
     1423                    {
     1424                        PCRTNETARPIPV4 pArpPkt = (PCRTNETARPIPV4)pArpHdr;
     1425                        bool fGratuitous = pArpPkt->ar_spa.u == pArpPkt->ar_tpa.u;
     1426                        if (   !fGratuitous
     1427                            &&  pArpPkt->ar_spa.u == GIMHV_DEBUGCLIENT_IPV4
     1428                            &&  pArpPkt->ar_tpa.u == GIMHV_DEBUGSERVER_IPV4)
     1429                        {
     1430                            pHv->enmDebugReply = GIMHVDEBUGREPLY_ARP_REPLY;
     1431                        }
     1432                    }
     1433                }
     1434                fIgnorePkt = true;
     1435            }
    11911436            else
    11921437            {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette