VirtualBox

Changeset 11123 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Aug 4, 2008 8:28:13 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
34060
Message:

intnet: Implemented DHCP snooping.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r11119 r11123  
    4646/** @def INTNET_WITH_DHCP_SNOOPING
    4747 * Enabled DHCP snooping when in shared-mac-on-the-wire mode. */
    48 /*#define INTNET_WITH_DHCP_SNOOPING - the implementation isn't completed yet. */
     48#define INTNET_WITH_DHCP_SNOOPING
    4949
    5050
     
    809809static void intnetR0IfAddrCacheDeleteIt(PINTNETIF pIf, PINTNETADDRCACHE pCache, int iEntry, const char *pszMsg)
    810810{
    811     Log(("intnetR0IfAddrCacheDeleteIt: hIf=%RX32 type=%d #%d %.*Rhxs %s\n", pIf->hIf,
    812          (int)(intptr_t)(pCache - &pIf->aAddrCache[0]), iEntry, pCache->cbAddress,
    813          pCache->pbEntries + iEntry * pCache->cbEntry, pszMsg));
    814811    AssertReturnVoid(iEntry < pCache->cEntries);
     812    AssertReturnVoid(iEntry >= 0);
     813#ifdef LOG_ENABLED
     814    INTNETADDRTYPE enmAddrType = (INTNETADDRTYPE)(uintptr_t)(pCache - &pIf->aAddrCache[0]);
     815    PCRTNETADDRU pAddr = (PCRTNETADDRU)(pCache->pbEntries + iEntry * pCache->cbEntry);
     816    switch (enmAddrType)
     817    {
     818        case kIntNetAddrType_IPv4:
     819            Log(("intnetR0IfAddrCacheDeleteIt: hIf=%#x MAC=%.6Rhxs IPv4 added #%d %d.%d.%d.%d %s\n",
     820                 pIf->hIf, &pIf->Mac, iEntry, pAddr->au8[0], pAddr->au8[1], pAddr->au8[2], pAddr->au8[3], pszMsg));
     821            break;
     822        default:
     823            Log(("intnetR0IfAddrCacheDeleteIt: hIf=%RX32 MAC=%.6Rhxs type=%d #%d %.*Rhxs %s\n",
     824                 pIf->hIf, &pIf->Mac, enmAddrType, iEntry, pCache->cbAddress, pAddr, pszMsg));
     825            break;
     826    }
     827#endif
     828
    815829    pCache->cEntries--;
    816830    if (iEntry < pCache->cEntries)
     
    957971    memcpy(pbEntry, pAddr, pCache->cbAddress);
    958972    memset(pbEntry + pCache->cbAddress, '\0', pCache->cbEntry - pCache->cbAddress);
    959     Log(("intnetR0IfAddrCacheAddIt: type=%d added #%d %.*Rhxs %s\n",
    960          (int)(uintptr_t)(pCache - &pIf->aAddrCache[0]), pCache->cEntries,
    961          pCache->cbAddress, pAddr, pszMsg));
     973#ifdef LOG_ENABLED
     974    INTNETADDRTYPE enmAddrType = (INTNETADDRTYPE)(uintptr_t)(pCache - &pIf->aAddrCache[0]);
     975    switch (enmAddrType)
     976    {
     977        case kIntNetAddrType_IPv4:
     978            Log(("intnetR0IfAddrCacheAddIt: hIf=%#x MAC=%.6Rhxs IPv4 added #%d %d.%d.%d.%d %s\n",
     979                 pIf->hIf, &pIf->Mac, pCache->cEntries, pAddr->au8[0], pAddr->au8[1], pAddr->au8[2], pAddr->au8[3], pszMsg));
     980            break;
     981        default:
     982            Log(("intnetR0IfAddrCacheAddIt: hIf=%#x MAC=%.6Rhxs type=%d added #%d %.*Rhxs %s\n",
     983                 pIf->hIf, &pIf->Mac, enmAddrType, pCache->cEntries, pCache->cbAddress, pAddr, pszMsg));
     984            break;
     985    }
     986#endif
    962987    pCache->cEntries++;
    963988    Assert(pCache->cEntries <= pCache->cEntriesAlloc);
     
    10411066static void intnetR0NetworkSnoopDhcp(PINTNETNETWORK pNetwork, PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, uint32_t cbUdpPkt)
    10421067{
    1043     /** @todo later */
    1044 }
    1045 
    1046 
     1068    /*
     1069     * Check if the DHCP message is valid and get the type.
     1070     */
     1071    if (!RTNetIPv4IsUDPValid(pIpHdr, pUdpHdr, pUdpHdr + 1, cbUdpPkt))
     1072    {
     1073        Log6(("Bad UDP packet\n"));
     1074        return;
     1075    }
     1076    PCRTNETBOOTP pDhcp = (PCRTNETBOOTP)(pUdpHdr + 1);
     1077    uint8_t MsgType;
     1078    if (!RTNetIPv4IsDHCPValid(pUdpHdr, pDhcp, cbUdpPkt - sizeof(*pUdpHdr), &MsgType))
     1079    {
     1080        Log6(("Bad DHCP packet\n"));
     1081        return;
     1082    }
     1083
     1084#ifdef LOG_ENABLED
     1085    /*
     1086     * Log it.
     1087     */
     1088    const char *pszType = "unknown";
     1089    switch (MsgType)
     1090    {
     1091        case RTNET_DHCP_MT_DISCOVER: pszType = "discover";  break;
     1092        case RTNET_DHCP_MT_OFFER:    pszType = "offer"; break;
     1093        case RTNET_DHCP_MT_REQUEST:  pszType = "request"; break;
     1094        case RTNET_DHCP_MT_DECLINE:  pszType = "decline"; break;
     1095        case RTNET_DHCP_MT_ACK:      pszType = "ack";break;
     1096        case RTNET_DHCP_MT_NAC:      pszType = "nac"; break;
     1097        case RTNET_DHCP_MT_RELEASE:  pszType = "release"; break;
     1098        case RTNET_DHCP_MT_INFORM:   pszType = "inform"; break;
     1099    }
     1100    Log6(("DHCP msg: %d (%s) client %.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d\n", MsgType, pszType, &pDhcp->bp_chaddr,
     1101          pDhcp->bp_ciaddr.au8[0], pDhcp->bp_ciaddr.au8[1], pDhcp->bp_ciaddr.au8[2], pDhcp->bp_ciaddr.au8[3],
     1102          pDhcp->bp_yiaddr.au8[0], pDhcp->bp_yiaddr.au8[1], pDhcp->bp_yiaddr.au8[2], pDhcp->bp_yiaddr.au8[3]));
     1103#endif /* LOG_EANBLED */
     1104
     1105    /*
     1106     * Act upon the message.
     1107     */
     1108    switch (MsgType)
     1109    {
     1110        /*
     1111         * Lookup the interface by its MAC address and insert the IPv4 address into the cache.
     1112         * Delete the old client address first, just in case it changed in a renewal.
     1113         */
     1114        case RTNET_DHCP_MT_ACK:
     1115            if (intnetR0IPv4AddrIsGood(pDhcp->bp_yiaddr))
     1116                for (PINTNETIF pCur = pNetwork->pIFs; pCur; pCur = pCur->pNext)
     1117                    if (    pCur->fMacSet
     1118                        &&  !memcmp(&pCur->Mac, &pDhcp->bp_chaddr, sizeof(RTMAC)))
     1119                    {
     1120                        intnetR0IfAddrCacheDelete(pCur, &pCur->aAddrCache[kIntNetAddrType_IPv4],
     1121                                                  (PCRTNETADDRU)&pDhcp->bp_ciaddr, sizeof(RTNETADDRIPV4), "DHCP_MT_ACK");
     1122                        intnetR0IfAddrCacheAdd(pCur, &pCur->aAddrCache[kIntNetAddrType_IPv4],
     1123                                               (PCRTNETADDRU)&pDhcp->bp_yiaddr, sizeof(RTNETADDRIPV4), "DHCP_MT_ACK");
     1124                        break;
     1125                    }
     1126            break;
     1127
     1128
     1129        /*
     1130         * Lookup the interface by its MAC address and remove the IPv4 address(es) from the cache.
     1131         */
     1132        case RTNET_DHCP_MT_RELEASE:
     1133        {
     1134            for (PINTNETIF pCur = pNetwork->pIFs; pCur; pCur = pCur->pNext)
     1135                if (    pCur->fMacSet
     1136                    &&  !memcmp(&pCur->Mac, &pDhcp->bp_chaddr, sizeof(RTMAC)))
     1137                {
     1138                    intnetR0IfAddrCacheDelete(pCur, &pCur->aAddrCache[kIntNetAddrType_IPv4],
     1139                                              (PCRTNETADDRU)&pDhcp->bp_ciaddr, sizeof(RTNETADDRIPV4), "DHCP_MT_RELEASE");
     1140                    intnetR0IfAddrCacheDelete(pCur, &pCur->aAddrCache[kIntNetAddrType_IPv4],
     1141                                              (PCRTNETADDRU)&pDhcp->bp_yiaddr, sizeof(RTNETADDRIPV4), "DHCP_MT_RELEASE");
     1142                }
     1143            break;
     1144        }
     1145    }
     1146
     1147}
     1148
     1149
     1150/**
     1151 * Worker for intnetR0TrunkIfSnoopAddr that takes care of what
     1152 * is likely to be a DHCP message.
     1153 *
     1154 * The caller has already check that the UDP source and destination ports
     1155 * are BOOTPS or BOOTPC.
     1156 *
     1157 * @param   pNetwork        The network this frame was seen on.
     1158 * @param   pSG             The gather list for the frame.
     1159 */
    10471160static void intnetR0TrunkIfSnoopDhcp(PINTNETNETWORK pNetwork, PCINTNETSG pSG)
    10481161{
     1162    /*
     1163     * Get a pointer to a linear copy of the full packet, using the
     1164     * temporary buffer if necessary.
     1165     */
     1166    PCRTNETIPV4 pIpHdr = (PCRTNETIPV4)((PCRTNETETHERHDR)pSG->aSegs[0].pv + 1);
     1167    size_t cbPacket = pSG->cbTotal - sizeof(RTNETETHERHDR);
     1168    if (pSG->cSegsUsed > 1)
     1169    {
     1170        cbPacket = RT_MIN(cbPacket, INTNETNETWORK_TMP_SIZE);
     1171        Log6(("intnetR0TrunkIfSnoopDhcp: Copying IPv4/UDP/DHCP pkt %u\n", cbPacket));
     1172        if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR), cbPacket, pNetwork->pbTmp))
     1173            return;
     1174        //pSG->fFlags |= INTNETSG_FLAGS_PKT_CP_IN_TMP;
     1175        pIpHdr = (PCRTNETIPV4)pNetwork->pbTmp;
     1176    }
     1177
     1178    /*
     1179     * Validate the IP header and find the UDP packet.
     1180     */
     1181    if (!RTNetIPv4IsHdrValid(pIpHdr, cbPacket, pSG->cbTotal - sizeof(RTNETETHERHDR)))
     1182    {
     1183        Log(("intnetR0TrunkIfSnoopDhcp: bad ip header\n"));
     1184        return;
     1185    }
     1186    size_t cbIpHdr = pIpHdr->ip_hl * 4;
     1187
     1188    /*
     1189     * Hand it over to the common DHCP snooper.
     1190     */
     1191    intnetR0NetworkSnoopDhcp(pNetwork, pIpHdr, (PCRTNETUDP)((uintptr_t)pIpHdr + cbIpHdr), cbPacket - cbIpHdr);
    10491192}
    10501193
     
    10581201 * The purpose of this purging is to get rid of stale addresses.
    10591202 *
    1060  * @param   pNetwork        The network the this frame was seen on.
     1203 * @param   pNetwork        The network this frame was seen on.
    10611204 * @param   pSG             The gather list for the frame.
    10621205 */
     
    11581301            if (b)
    11591302                return;
     1303
     1304            /* get the lower byte of the UDP destination port number. */
     1305            b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + cbIpHdr + RT_OFFSETOF(RTNETUDP, uh_dport) + 1);
     1306            if (    b != RTNETIPV4_PORT_BOOTPS
     1307                &&  b != RTNETIPV4_PORT_BOOTPC)
     1308                return;
     1309            b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + cbIpHdr + RT_OFFSETOF(RTNETUDP, uh_dport));
     1310            if (b)
     1311                return;
    11601312            intnetR0TrunkIfSnoopDhcp(pNetwork, pSG);
    11611313            break;
     
    11971349        return;
    11981350    uint32_t cbHdr = (uint32_t)pIpHdr->ip_hl * 4;
    1199     if (    cbHdr < RT_UOFFSETOF(RTNETIPV4, ip_options)
     1351    if (    cbHdr < RTNETIPV4_MIN_LEN
    12001352        ||  cbPacket < cbHdr)
    12011353        return;
    12021354
    12031355    /*
    1204      * Ignore non good IP address (like broadcast and my network),
    1205      * also skip packets containing address that are already in the
    1206      * cache. Don't ignore potential DHCP traffic though.
     1356     * If the source address is good (not broadcast or my network) and
     1357     * not already in the address cache of the sender, add it. Validate
     1358     * the IP header before adding it.
    12071359     */
    12081360    bool fValidatedIpHdr = false;
     
    12121364        &&  intnetR0IfAddrCacheLookupLikely(&pIf->aAddrCache[kIntNetAddrType_IPv4], &Addr, sizeof(Addr.IPv4)) < 0)
    12131365    {
    1214         /*
    1215          * Got a candidate, check that the IP header is valid before adding it.
    1216          */
    12171366        if (!RTNetIPv4IsHdrValid(pIpHdr, cbPacket, cbPacket))
    12181367        {
     
    34553604                Assert(pTrunkIF->pIfPort);
    34563605                pNetwork->pTrunkIF = pTrunkIF;
    3457                 Log(("intnetR0NetworkCreateTrunkIf: VINF_SUCCESS - pszName=%s szTrunk=%s %s Network=%s%s\n",
     3606                Log(("intnetR0NetworkCreateTrunkIf: VINF_SUCCESS - pszName=%s szTrunk=%s%s Network=%s\n",
    34583607                     pszName, pNetwork->szTrunk, pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE ? " shared-mac" : "", pNetwork->szName));
    34593608                return VINF_SUCCESS;
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