Changeset 11055 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Aug 1, 2008 1:29:38 AM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 33950
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
r11053 r11055 271 271 272 272 273 /** 274 * Initializes a scatter / gather buffer from a simple linear buffer. 275 * 276 * @returns Pointer to the start of the frame. 277 * @param pSG Pointer to the scatter / gather structure. 278 * (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.) 279 * @param pvFrame Pointer to the frame 280 * @param cbFrame The size of the frame. 281 */ 282 DECLINLINE(void) intnetR0SgInitTemp(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame) 283 { 284 pSG->pvOwnerData = NULL; 285 pSG->pvUserData = NULL; 286 pSG->pvUserData2 = NULL; 287 pSG->cbTotal = cbFrame; 288 pSG->cUsers = 1; 289 pSG->fFlags = INTNETSG_FLAGS_TEMP; 290 pSG->cSegsAlloc = 1; 291 pSG->cSegsUsed = 1; 292 pSG->aSegs[0].Phys = NIL_RTHCPHYS; 293 pSG->aSegs[0].pv = pvFrame; 294 pSG->aSegs[0].cb = cbFrame; 295 } 296 297 298 /** 299 * Initializes a scatter / gather buffer from a internal networking packet. 300 * 301 * @returns Pointer to the start of the frame. 302 * @param pSG Pointer to the scatter / gather structure. 303 * (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.) 304 * @param pHdr Pointer to the packet header. 305 * @param pBuf The buffer the header is within. Only used in strict builds. 306 */ 307 DECLINLINE(void) intnetR0SgInitFromPkt(PINTNETSG pSG, PCINTNETHDR pPktHdr, PCINTNETBUF pBuf) 308 { 309 pSG->cSegsUsed = 1; 310 pSG->cbTotal = pSG->aSegs[0].cb = pPktHdr->cbFrame; 311 pSG->aSegs[0].pv = INTNETHdrGetFramePtr(pPktHdr, pBuf); 312 pSG->aSegs[0].Phys = NIL_RTHCPHYS; 313 } 314 315 316 /** 317 * Reads a byte from a SG list. 318 * 319 * @returns The byte on success. 0xff on failure. 320 * @param pSG The SG list to read. 321 * @param off The offset (into the SG) off the byte. 322 */ 323 DECLINLINE(uint8_t) intnetR0SgReadByte(PCINTNETSG pSG, uint32_t off) 324 { 325 if (RT_LIKELY(pSG->aSegs[0].cb > off)) 326 return ((uint8_t const *)pSG->aSegs[0].pv)[off]; 327 328 unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed); 329 for (unsigned iSeg = 1; iSeg < cSegs; iSeg++) 330 { 331 if (pSG->aSegs[iSeg].cb > 0) 332 return ((uint8_t const *)pSG->aSegs[iSeg].pv)[off]; 333 off -= pSG->aSegs[iSeg].cb; 334 } 335 return false; 336 } 337 338 339 /** 340 * Worker for intnetR0SgReadPart that deals with the case where the 341 * requested data isn't in the first segment. 342 * 343 * @returns true, unless the SG is invalid. 344 * @param pSG The SG list to read. 345 * @param off Where to start reading (offset into the SG). 346 * @param cb How much to read. 347 * @param pvBuf The buffer to read into. 348 */ 349 static bool intnetR0SgReadPartSlow(PCINTNETSG pSG, uint32_t off, uint32_t cb, void *pvBuf) 350 { 351 if (RT_UNLIKELY(off + cb > pSG->cbTotal)) 352 return false; 353 354 /* 355 * Skip ahead to the segment where off starts. 356 */ 357 unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed); 358 unsigned iSeg = 0; 359 while (off > pSG->aSegs[iSeg].cb) 360 { 361 off -= pSG->aSegs[iSeg++].cb; 362 AssertReturn(iSeg < cSegs, false); 363 } 364 365 /* 366 * Copy the data, hoping that it's all from one segment... 367 */ 368 uint32_t cbCanCopy = pSG->aSegs[iSeg].cb - off; 369 if (cbCanCopy >= cb) 370 memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cb); 371 else 372 { 373 /* copy the portion in the current segment. */ 374 memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cbCanCopy); 375 cb -= cbCanCopy; 376 377 /* copy the portions in the other segments. */ 378 do 379 { 380 pvBuf = (uint8_t *)pvBuf + cbCanCopy; 381 iSeg++; 382 AssertReturn(iSeg < cSegs, false); 383 384 cbCanCopy = RT_MIN(cb, pSG->aSegs[iSeg].cb); 385 memcpy(pvBuf, (uint8_t const *)pSG->aSegs[iSeg].pv + off, cbCanCopy); 386 387 cb -= cbCanCopy; 388 } while (cb > 0); 389 } 390 391 return true; 392 } 393 394 395 /** 396 * Reads a part of an SG into a buffer. 397 * 398 * @returns true on success, false on failure (out of bounds). 399 * @param pSG The SG list to read. 400 * @param off Where to start reading (offset into the SG). 401 * @param cb How much to read. 402 * @param pvBuf The buffer to read into. 403 */ 404 DECLINLINE(bool) intnetR0SgReadPart(PCINTNETSG pSG, uint32_t off, uint32_t cb, void *pvBuf) 405 { 406 Assert(off + cb > off); 407 408 /* The optimized case. */ 409 if (RT_LIKELY( pSG->cSegsUsed == 1 410 || pSG->aSegs[0].cb >= off + cb)) 411 { 412 Assert(pSG->cbTotal == pSG->aSegs[0].cb); 413 memcpy(pvBuf, (uint8_t const *)pSG->aSegs[0].pv + off, cb); 414 return true; 415 } 416 return intnetR0SgReadPartSlow(pSG, off, cb, pvBuf); 417 } 418 419 420 /** 421 * Reads an entire SG into a fittingly size buffer. 422 * 423 * @param pSG The SG list to read. 424 * @param pvBuf The buffer to read into (at least pSG->cbTotal in size). 425 */ 426 DECLINLINE(void) intnetR0SgRead(PCINTNETSG pSG, void *pvBuf) 427 { 428 if (pSG->cSegsUsed == 1) 429 { 430 Assert(pSG->cbTotal == pSG->aSegs[0].cb); 431 memcpy(pvBuf, pSG->aSegs[0].pv, pSG->cbTotal); 432 } 433 else 434 { 435 uint8_t *pbDst = (uint8_t *)pvBuf; 436 unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed); 437 for (unsigned iSeg = 0; iSeg < cSegs; iSeg++) 438 { 439 uint32_t cbSeg = pSG->aSegs[iSeg].cb; 440 Assert(cbSeg <= pSG->cbTotal && (uintptr_t)(pbDst - (uint8_t *)pvBuf) + cbSeg <= pSG->cbTotal); 441 memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg); 442 pbDst += cbSeg; 443 } 444 } 445 } 446 447 448 449 450 451 273 452 274 453 /** … … 323 502 return VINF_SUCCESS; 324 503 } 504 505 506 507 325 508 326 509 … … 753 936 754 937 /** 755 * Snoops IP assignments and releases from the DHCPv4 traf ik.756 * 757 * The caller is responsible for making sure this traf ikbetween the938 * Snoops IP assignments and releases from the DHCPv4 traffic. 939 * 940 * The caller is responsible for making sure this traffic between the 758 941 * BOOTPS and BOOTPC ports and validate the IP header. The UDP packet 759 942 * need not be validated beyond the ports. … … 766 949 * @param cbUdpPkt What's left of the frame when starting at the UDP header. 767 950 */ 768 static void intnetR0NetworkSnoopD HCP(PINTNETNETWORK pNetwork, PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, uint32_t cbUdpPkt)951 static void intnetR0NetworkSnoopDhcp(PINTNETNETWORK pNetwork, PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, uint32_t cbUdpPkt) 769 952 { 770 953 /** @todo later */ 954 } 955 956 957 static void intnetR0TrunkIfSnoopDhcp(PINTNETNETWORK pNetwork, PCINTNETSG pSG) 958 { 959 960 } 961 962 static void intnetR0TrunkIfSnoopArp(PINTNETNETWORK pNetwork, PCINTNETSG pSG) 963 { 964 965 } 966 967 968 /** 969 * Snoop up addresses from ARP and DHCP traffic from frames comming 970 * over the trunk connection. 971 * 972 * The caller is responsible for do some basic filtering before calling 973 * this function. 974 * For IPv4 this means checking against the minimum DHCPv4 frame size. 975 * 976 * @param pNetwork The network. 977 * @param pSG The SG list for the frame. 978 * @param EtherType The Ethertype of the frame. 979 */ 980 static void intnetR0TrunkIfSnoopAddr(PINTNETNETWORK pNetwork, PCINTNETSG pSG, uint16_t EtherType) 981 { 982 switch (EtherType) 983 { 984 case RTNET_ETHERTYPE_IPV4: 985 { 986 Assert(pSG->cbTotal >= sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN); 987 /** @todo optimize for the case where we can expect both the IP and UDP header to be in the first segment. */ 988 989 /* check if the protocol is UDP */ 990 if ( intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + RT_OFFSETOF(RTNETIPV4, ip_p)) 991 != RTNETIPV4_PROT_UDP) 992 return; 993 994 /* get the TCP header length */ 995 uint8_t b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + 0); /* (IPv4 first byte, a bitfield) */ 996 uint32_t cbIpHdr = (b & 0x0f) * 4; 997 if (cbIpHdr < RTNETIPV4_MIN_LEN) 998 return; 999 1000 /* get the lower byte of the UDP source port number. */ 1001 b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + cbIpHdr + RT_OFFSETOF(RTNETUDP, uh_sport) + 1); 1002 if ( b != RTNETIPV4_PORT_BOOTPS 1003 && b != RTNETIPV4_PORT_BOOTPC) 1004 return; 1005 b = intnetR0SgReadByte(pSG, sizeof(RTNETETHERHDR) + cbIpHdr + RT_OFFSETOF(RTNETUDP, uh_sport)); 1006 if (b) 1007 return; 1008 intnetR0TrunkIfSnoopDhcp(pNetwork, pSG); 1009 break; 1010 } 1011 1012 case RTNET_ETHERTYPE_ARP: 1013 intnetR0TrunkIfSnoopArp(pNetwork, pSG); 1014 break; 1015 } 1016 /** @todo soon */ 771 1017 } 772 1018 … … 799 1045 * Ignore non good IP address (like broadcast and my network), 800 1046 * also skip packets containing address that are already in the 801 * cache. Don't ignore potential DHCP traf ikthough.1047 * cache. Don't ignore potential DHCP traffic though. 802 1048 */ 803 1049 bool fValidatedIpHdr = false; … … 833 1079 if ( fValidatedIpHdr 834 1080 || RTNetIPv4IsHdrValid(pIpHdr, cbPacket, cbPacket)) 835 intnetR0NetworkSnoopD HCP(pIf->pNetwork, pIpHdr, pUdpHdr, cbPacket - cbHdr);1081 intnetR0NetworkSnoopDhcp(pIf->pNetwork, pIpHdr, pUdpHdr, cbPacket - cbHdr); 836 1082 else 837 1083 Log(("intnetR0IfSnoopIPv4SourceAddr: bad ip header (dhcp)\n")); … … 849 1095 * request 'cause of min ethernet frame size). 850 1096 */ 851 static void intnetR0IfSnoopArp SourceAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket)1097 static void intnetR0IfSnoopArpAddr(PINTNETIF pIf, PCRTNETARPHDR pHdr, uint32_t cbPacket) 852 1098 { 853 1099 /* … … 928 1174 * @param cbFrame The size of the frame. 929 1175 */ 930 static void intnetR0I SnoopSourceAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame)1176 static void intnetR0IfSnoopAddr(PINTNETIF pIf, uint8_t const *pbFrame, uint32_t cbFrame) 931 1177 { 932 1178 /* … … 938 1184 939 1185 uint16_t EtherType = RT_H2BE_U16(((PCRTNETETHERHDR)pbFrame)->EtherType); 940 if (EtherType == RTNET_ETHERTYPE_IPV4) 941 intnetR0IfSnoopIPv4SourceAddr(pIf, (PCRTNETIPV4)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 1186 switch (EtherType) 1187 { 1188 case RTNET_ETHERTYPE_IPV4: 1189 intnetR0IfSnoopIPv4SourceAddr(pIf, (PCRTNETIPV4)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 1190 break; 942 1191 #if 0 /** @todo IntNet: implement IPv6 for wireless MAC sharing. */ 943 else if (EtherType == RTNET_ETHERTYPE_IPV6) 944 intnetR0IfSnoopIPv6SourceAddr(pIf, (PCINTNETIPV6)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 1192 case RTNET_ETHERTYPE_IPV6: 1193 intnetR0IfSnoopIPv6SourceAddr(pIf, (PCINTNETIPV6)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 1194 break; 945 1195 #endif 946 1196 #if 0 /** @todo IntNet: implement IPX for wireless MAC sharing? */ 947 else if ( EtherType == RT_H2BE_U16(0x8137) //??948 || EtherType == RT_H2BE_U16(0x8138) //??949 || EtherType == RT_H2BE_U16(0x8037) //??950 )951 intnetR0IfSnoopIpxSourceAddr(pIf, (PCINTNETIPX)((PCRTNETETHERHDR)pbFrame + 1), cbFrame);1197 case RTNET_ETHERTYPE_IPX_1: 1198 case RTNET_ETHERTYPE_IPX_2: 1199 case RTNET_ETHERTYPE_IPX_3: 1200 intnetR0IfSnoopIpxSourceAddr(pIf, (PCINTNETIPX)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 1201 break; 952 1202 #endif 953 else if (EtherType == RT_H2BE_U16(RTNET_ETHERTYPE_ARP)) 954 intnetR0IfSnoopArpSourceAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 955 } 956 957 958 /** 959 * Initializes a scatter / gather buffer from a simple linear buffer. 960 * 961 * @returns Pointer to the start of the frame. 962 * @param pSG Pointer to the scatter / gather structure. 963 * (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.) 964 * @param pvFrame Pointer to the frame 965 * @param cbFrame The size of the frame. 966 */ 967 DECLINLINE(void) intnetR0SgInitTemp(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame) 968 { 969 pSG->pvOwnerData = NULL; 970 pSG->pvUserData = NULL; 971 pSG->pvUserData2 = NULL; 972 pSG->cbTotal = cbFrame; 973 pSG->cUsers = 1; 974 pSG->fFlags = INTNETSG_FLAGS_TEMP; 975 pSG->cSegsAlloc = 1; 976 pSG->cSegsUsed = 1; 977 pSG->aSegs[0].Phys = NIL_RTHCPHYS; 978 pSG->aSegs[0].pv = pvFrame; 979 pSG->aSegs[0].cb = cbFrame; 980 } 981 982 983 /** 984 * Initializes a scatter / gather buffer from a internal networking packet. 985 * 986 * @returns Pointer to the start of the frame. 987 * @param pSG Pointer to the scatter / gather structure. 988 * (The pvOwnerData, fFlags, cUsers, and cSegsAlloc members are left untouched.) 989 * @param pHdr Pointer to the packet header. 990 * @param pBuf The buffer the header is within. Only used in strict builds. 991 */ 992 DECLINLINE(void) intnetR0SgInitFromPkt(PINTNETSG pSG, PCINTNETHDR pPktHdr, PCINTNETBUF pBuf) 993 { 994 pSG->cSegsUsed = 1; 995 pSG->cbTotal = pSG->aSegs[0].cb = pPktHdr->cbFrame; 996 pSG->aSegs[0].pv = INTNETHdrGetFramePtr(pPktHdr, pBuf); 997 pSG->aSegs[0].Phys = NIL_RTHCPHYS; 1203 case RTNET_ETHERTYPE_ARP: 1204 intnetR0IfSnoopArpAddr(pIf, (PCRTNETARPHDR)((PCRTNETETHERHDR)pbFrame + 1), cbFrame); 1205 break; 1206 } 998 1207 } 999 1208 … … 1031 1240 } 1032 1241 #endif /* IN_INTNET_TESTCASE */ 1033 1034 1035 /**1036 * Reads an entire SG into a fittingly size buffer.1037 *1038 * @param pSG The SG list to read.1039 * @param pvBuf The buffer to read into (at least pSG->cbTotal in size).1040 */1041 DECLINLINE(void) intnetR0SgRead(PCINTNETSG pSG, void *pvBuf)1042 {1043 if (pSG->cSegsUsed == 1)1044 {1045 Assert(pSG->cbTotal == pSG->aSegs[0].cb);1046 memcpy(pvBuf, pSG->aSegs[0].pv, pSG->cbTotal);1047 }1048 else1049 {1050 uint8_t *pbDst = (uint8_t *)pvBuf;1051 unsigned const cSegs = pSG->cSegsUsed; Assert(cSegs == pSG->cSegsUsed);1052 for (unsigned iSeg = 0; iSeg < cSegs; iSeg++)1053 {1054 uint32_t cbSeg = pSG->aSegs[iSeg].cb;1055 Assert(cbSeg <= pSG->cbTotal && (uintptr_t)(pbDst - (uint8_t *)pvBuf) + cbSeg <= pSG->cbTotal);1056 memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg);1057 pbDst += cbSeg;1058 }1059 }1060 }1061 1242 1062 1243 … … 1308 1489 * @param pSG Pointer to the gather list. 1309 1490 * @param fTrunkLocked Whether the caller owns the out-bound trunk lock. 1310 */ 1311 static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, PINTNETSG pSG, bool fTrunkLocked) 1491 * @param pEthHdr Pointer to the ethernet header. 1492 */ 1493 static bool intnetR0NetworkSendBroadcast(PINTNETNETWORK pNetwork, PINTNETIF pIfSender, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr) 1312 1494 { 1313 1495 /* … … 1329 1511 && pTrunkIf) 1330 1512 intnetR0TrunkIfSend(pTrunkIf, pNetwork, INTNETTRUNKDIR_HOST | INTNETTRUNKDIR_WIRE, pSG, fTrunkLocked); 1513 1514 /* 1515 * Snoop address info from packet orginating from the trunk connection. 1516 */ 1517 else if ( (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE) 1518 && !pIfSender) 1519 { 1520 uint16_t EtherType = RT_BE2H_U16(pEthHdr->EtherType); 1521 if ( ( EtherType == RTNET_ETHERTYPE_IPV4 /* for DHCP */ 1522 && pSG->cbTotal >= RTNETBOOTP_DHCP_MIN_LEN) 1523 || EtherType == RTNET_ETHERTYPE_ARP) 1524 intnetR0TrunkIfSnoopAddr(pNetwork, pSG, EtherType); 1525 } 1526 1331 1527 return false; /* broadcast frames are never dropped */ 1332 1528 } … … 1349 1545 { 1350 1546 /** @todo implement multicast */ 1351 return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked); 1547 return intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked, pEthHdr); 1548 } 1549 1550 1551 /** 1552 * Sends a unicast frame using the network layer address instead 1553 * of the link layer one. 1554 * 1555 * The caller must own the network mutex, might be abandond temporarily. 1556 * 1557 * @returns true if it's addressed to someone on the network, otherwise false. 1558 * @param pNetwork The network the frame is being sent to. 1559 * @param pSG Pointer to the gather list. 1560 * @param fTrunkLocked Whether the caller owns the out-bound trunk lock. 1561 * @param pEthHdr Pointer to the ethernet header. 1562 */ 1563 static bool intnetR0NetworkSendUnicastWithSharedMac(PINTNETNETWORK pNetwork, PINTNETSG pSG, bool fTrunkLocked, PCRTNETETHERHDR pEthHdr) 1564 { 1565 /* 1566 * Extract the network address from the packet. 1567 */ 1568 RTNETADDRU Addr; 1569 INTNETADDRTYPE enmAddrType; 1570 uint8_t cbAddr; 1571 switch (RT_BE2H_U16(pEthHdr->EtherType)) 1572 { 1573 case RTNET_ETHERTYPE_IPV4: 1574 if (!intnetR0SgReadPart(pSG, RT_OFFSETOF(RTNETIPV4, ip_dst), sizeof(Addr.IPv4), &Addr)) 1575 return false; 1576 enmAddrType = kIntNetAddrType_IPv4; 1577 cbAddr = sizeof(Addr.IPv4); 1578 break; 1579 1580 #if 0 /** @todo IntNet: implement IPv6 for wireless MAC sharing. */ 1581 case RTNET_ETHERTYPE_IPV6 1582 if (!intnetR0SgReadPart(pSG, RT_OFFSETOF(RTNETIPV6, ip6_dst), sizeof(Addr.IPv6), &Addr)) 1583 return false; 1584 enmAddrType = kIntNetAddrType_IPv6; 1585 cbAddr = sizeof(Addr.IPv6); 1586 break; 1587 #endif 1588 #if 0 /** @todo IntNet: implement IPX for wireless MAC sharing? */ 1589 case RTNET_ETHERTYPE_IPX_1: 1590 case RTNET_ETHERTYPE_IPX_2: 1591 case RTNET_ETHERTYPE_IPX_3: 1592 if (!intnetR0SgReadPart(pSG, RT_OFFSETOF(RTNETIPX, ipx_dstnet), sizeof(Addr.IPX), &Addr)) 1593 return false; 1594 enmAddrType = kIntNetAddrType_IPX; 1595 cbAddr = sizeof(Addr.IPX); 1596 break; 1597 #endif 1598 1599 /* 1600 * Treat ARP is broadcast (it shouldn't end up here normally, 1601 * so it goes last in the switch). 1602 */ 1603 case RTNET_ETHERTYPE_ARP: 1604 return intnetR0NetworkSendBroadcast(pNetwork, NULL, pSG, fTrunkLocked, pEthHdr); 1605 1606 /* 1607 * Unknown packets are sent do all interfaces that are in promiscuous mode. 1608 */ 1609 default: 1610 { 1611 if (!(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))) 1612 { 1613 for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext) 1614 if (pIf->fPromiscuous) 1615 { 1616 Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac)); 1617 intnetR0IfSend(pIf, NULL, pSG); 1618 } 1619 } 1620 return false; 1621 } 1622 } 1623 1624 /* 1625 * Send it to interfaces with matching network addresses. 1626 */ 1627 bool fExactIntNetRecipient = false; 1628 for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext) 1629 { 1630 bool fIt = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmAddrType], &Addr, cbAddr) >= 0; 1631 if ( fIt 1632 || ( pIf->fPromiscuous 1633 && !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC)))) 1634 { 1635 Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac)); 1636 fExactIntNetRecipient |= fIt; 1637 intnetR0IfSend(pIf, NULL, pSG); 1638 } 1639 } 1640 1641 /* 1642 * Perform DHCP snooping. 1643 */ 1644 if ( enmAddrType == kIntNetAddrType_IPv4 1645 && pSG->cbTotal >= RTNETBOOTP_DHCP_MIN_LEN) 1646 intnetR0TrunkIfSnoopAddr(pNetwork, pSG, RT_BE2H_U16(pEthHdr->EtherType)); 1647 1648 return fExactIntNetRecipient; 1352 1649 } 1353 1650 … … 1519 1816 && EthHdr.DstMac.au16[1] == 0xffff 1520 1817 && EthHdr.DstMac.au16[2] == 0xffff) 1521 fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked); 1818 fRc = intnetR0NetworkSendBroadcast(pNetwork, pIfSender, pSG, fTrunkLocked, &EthHdr); 1819 else if ( !(pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE) 1820 || !(fSrc & INTNETTRUNKDIR_WIRE)) 1821 fRc = intnetR0NetworkSendUnicast(pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr); 1522 1822 else 1523 fRc = intnetR0NetworkSendUnicast (pNetwork, pIfSender, fSrc, pSG, fTrunkLocked, &EthHdr);1823 fRc = intnetR0NetworkSendUnicastWithSharedMac(pNetwork, pSG, fTrunkLocked, &EthHdr); 1524 1824 return fRc; 1525 1825 } … … 1624 1924 { 1625 1925 if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE) 1626 intnetR0I SnoopSourceAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame);1926 intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame); 1627 1927 intnetR0SgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame); 1628 1928 intnetR0NetworkSend(pNetwork, pIf, 0, &Sg, !!pTrunkIf);
Note:
See TracChangeset
for help on using the changeset viewer.