Changeset 52518 in vbox
- Timestamp:
- Aug 28, 2014 3:42:09 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
r52445 r52518 2956 2956 2957 2957 /** 2958 * Work around the issue with WiFi routers that replace IPv6 multicast 2959 * Ethernet addresses with unicast ones. We check IPv6 destination address 2960 * to determine if the packet originally had a multicast address, and if so 2961 * we restore the original address and treat the modified packet as being a 2962 * broadcast. 2963 * 2958 * Detect broadcasts packaged as unicast and convert them back to broadcast. 2959 * 2960 * WiFi routers try to use ethernet unicast instead of broadcast or 2961 * multicast when possible. Look inside the packet and fix up 2962 * ethernet destination to be proper broadcast or multicast if 2963 * necessary. 2964 * 2965 * @returns true broadcast (pEthHdr & pSG are modified), false if not. 2964 2966 * @param pNetwork The network the frame is being sent to. 2965 * @param pSG Pointer to the gather list for the frame. 2966 * @param pEthHdr Pointer to the ethernet header. 2967 */ 2968 static bool intnetR0NetworkDetectAndFixNdBroadcast(PINTNETNETWORK pNetwork, PINTNETSG pSG, PRTNETETHERHDR pEthHdr) 2967 * @param pSG Pointer to the gather list for the frame. The 2968 * ethernet destination address is modified when 2969 * returning true. 2970 * @param pEthHdr Pointer to the ethernet header. The ethernet 2971 * destination address is modified when returning true. 2972 */ 2973 static bool intnetR0NetworkSharedMacDetectAndFixBroadcast(PINTNETNETWORK pNetwork, PINTNETSG pSG, PRTNETETHERHDR pEthHdr) 2969 2974 { 2970 2975 NOREF(pNetwork); 2971 2976 2972 if (RT_BE2H_U16(pEthHdr->EtherType) != RTNET_ETHERTYPE_IPV6) 2973 return false; 2974 /* 2975 * Check the minimum size and get a linear copy of the thing to work on, 2976 * using the temporary buffer if necessary. 2977 */ 2978 if (RT_UNLIKELY(pSG->cbTotal < sizeof(RTNETETHERHDR) + sizeof(RTNETIPV6) + 2979 sizeof(RTNETNDP))) 2980 return false; 2981 uint8_t bTmp[sizeof(RTNETIPV6) + sizeof(RTNETNDP)]; 2982 PRTNETIPV6 pIPv6 = (PRTNETIPV6)((uint8_t *)pSG->aSegs[0].pv + sizeof(RTNETETHERHDR)); 2983 if ( pSG->cSegsUsed != 1 2984 && pSG->aSegs[0].cb < sizeof(RTNETETHERHDR) + sizeof(RTNETIPV6) + 2985 sizeof(RTNETNDP)) 2986 { 2987 Log6(("fw: Copying IPv6 pkt %u\n", sizeof(RTNETIPV6))); 2988 if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR), sizeof(RTNETIPV6) 2989 + sizeof(RTNETNDP), bTmp)) 2977 switch (pEthHdr->EtherType) 2978 { 2979 case RT_H2N_U16_C(RTNET_ETHERTYPE_ARP): 2980 { 2981 uint16_t ar_oper; 2982 if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR) + RT_OFFSETOF(RTNETARPHDR, ar_oper), 2983 sizeof(ar_oper), &ar_oper)) 2984 return false; 2985 2986 if (ar_oper == RT_H2N_U16_C(RTNET_ARPOP_REQUEST)) 2987 { 2988 /* change to broadcast */ 2989 pEthHdr->DstMac.au16[0] = 0xffff; 2990 pEthHdr->DstMac.au16[1] = 0xffff; 2991 pEthHdr->DstMac.au16[2] = 0xffff; 2992 } 2993 else 2994 return false; 2995 break; 2996 } 2997 2998 case RT_H2N_U16_C(RTNET_ETHERTYPE_IPV4): 2999 { 3000 RTNETADDRIPV4 ip_dst; 3001 if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR) + RT_OFFSETOF(RTNETIPV4, ip_dst), 3002 sizeof(ip_dst), &ip_dst)) 3003 return false; 3004 3005 if (ip_dst.u == 0xffffffff) /* 255.255.255.255? */ 3006 { 3007 /* change to broadcast */ 3008 pEthHdr->DstMac.au16[0] = 0xffff; 3009 pEthHdr->DstMac.au16[1] = 0xffff; 3010 pEthHdr->DstMac.au16[2] = 0xffff; 3011 } 3012 else if ((ip_dst.au8[0] & 0xf0) == 0xe0) /* IPv4 multicast? */ 3013 { 3014 /* change to 01:00:5e:xx:xx:xx multicast ... */ 3015 pEthHdr->DstMac.au8[0] = 0x01; 3016 pEthHdr->DstMac.au8[1] = 0x00; 3017 pEthHdr->DstMac.au8[2] = 0x5e; 3018 /* ... with lower 23 bits from the multicast IP address */ 3019 pEthHdr->DstMac.au8[3] = ip_dst.au8[1] & 0x7f; 3020 pEthHdr->DstMac.au8[4] = ip_dst.au8[2]; 3021 pEthHdr->DstMac.au8[5] = ip_dst.au8[3]; 3022 } 3023 else 3024 return false; 3025 break; 3026 } 3027 3028 case RT_H2N_U16_C(RTNET_ETHERTYPE_IPV6): 3029 { 3030 RTNETADDRIPV6 ip6_dst; 3031 if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR) + RT_OFFSETOF(RTNETIPV6, ip6_dst), 3032 sizeof(ip6_dst), &ip6_dst)) 3033 return false; 3034 3035 if (ip6_dst.au8[0] == 0xff) /* IPv6 multicast? */ 3036 { 3037 pEthHdr->DstMac.au16[0] = 0x3333; 3038 pEthHdr->DstMac.au16[1] = ip6_dst.au16[6]; 3039 pEthHdr->DstMac.au16[2] = ip6_dst.au16[7]; 3040 } 3041 else 3042 return false; 3043 break; 3044 } 3045 3046 default: 2990 3047 return false; 2991 pIPv6 = (PRTNETIPV6)bTmp; 2992 } 2993 2994 /* Check IPv6 destination address if it is a multicast address. */ 2995 static uint8_t auSolicitedNodeMulticastPrefix[] = 2996 { 2997 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2998 0x00, 0x00, 0x00, 0x01, 0xff 2999 }; 3000 if (memcmp(pIPv6->ip6_dst.au8, auSolicitedNodeMulticastPrefix, 3001 sizeof(auSolicitedNodeMulticastPrefix)) == 0) 3002 { 3003 /* 3004 * The original must have been composed of 0x3333 followed by the last 3005 * four bytes of the solicited-node multicast address. 3006 */ 3007 if (pSG->aSegs[0].cb < sizeof(RTNETETHERHDR)) 3008 { 3009 RTMAC DstMac; 3010 DstMac.au16[0] = 0x3333; 3011 DstMac.au16[1] = pIPv6->ip6_dst.au16[6]; 3012 DstMac.au16[2] = pIPv6->ip6_dst.au16[7]; 3013 return intnetR0SgWritePart(pSG, RT_OFFSETOF(RTNETETHERHDR, DstMac), sizeof(RTMAC), &DstMac); 3014 } 3015 pEthHdr = (PRTNETETHERHDR)pSG->aSegs[0].pv; 3016 pEthHdr->DstMac.au16[0] = 0x3333; 3017 pEthHdr->DstMac.au16[1] = pIPv6->ip6_dst.au16[6]; 3018 pEthHdr->DstMac.au16[2] = pIPv6->ip6_dst.au16[7]; 3019 return true; 3020 } 3021 3022 return false; 3048 } 3049 3050 3051 /* 3052 * Update ethernet destination in the segment. 3053 */ 3054 intnetR0SgWritePart(pSG, RT_OFFSETOF(RTNETETHERHDR, DstMac), sizeof(pEthHdr->DstMac), &pEthHdr->DstMac); 3055 3056 return true; 3023 3057 } 3024 3058 … … 3706 3740 else if (fSrc & INTNETTRUNKDIR_WIRE) 3707 3741 { 3708 if (intnetR0Network DetectAndFixNdBroadcast(pNetwork, pSG, &EthHdr))3742 if (intnetR0NetworkSharedMacDetectAndFixBroadcast(pNetwork, pSG, &EthHdr)) 3709 3743 enmSwDecision = intnetR0NetworkSharedMacFixAndSwitchBroadcast(pNetwork, fSrc, pIfSender, pSG, &EthHdr, pDstTab); 3710 3744 else
Note:
See TracChangeset
for help on using the changeset viewer.