Changeset 52543 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Aug 31, 2014 11:48:41 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
r52518 r52543 2809 2809 } 2810 2810 2811 2812 /** 2813 * Rewrite VM MAC address with shared host MAC address inside IPv6 2814 * Neighbor Discovery datagrams. 2815 */ 2816 static void intnetR0TrunkSharedMacEditIPv6FromIntNet(PINTNETTRUNKIF pThis, PINTNETIF pIfSender, 2817 PRTNETETHERHDR pEthHdr, uint32_t cb) 2818 { 2819 if (RT_UNLIKELY(cb < sizeof(*pEthHdr))) 2820 return; 2821 2822 /* have IPv6 header */ 2823 PRTNETIPV6 pIPv6 = (PRTNETIPV6)(pEthHdr + 1); 2824 cb -= sizeof(*pEthHdr); 2825 if (RT_UNLIKELY(cb < sizeof(*pIPv6))) 2826 return; 2827 2828 if ( pIPv6->ip6_nxt != RTNETIPV6_PROT_ICMPV6 2829 || pIPv6->ip6_hlim != 0xff) 2830 return; 2831 2832 PRTNETICMPV6HDR pICMPv6 = (PRTNETICMPV6HDR)(pIPv6 + 1); 2833 cb -= sizeof(*pIPv6); 2834 if (RT_UNLIKELY(cb < sizeof(*pICMPv6))) 2835 return; 2836 2837 size_t hdrlen = 0; 2838 uint8_t llaopt = RTNETIPV6_ICMP_ND_SLLA_OPT; 2839 2840 uint8_t type = pICMPv6->icmp6_type; 2841 switch (type) 2842 { 2843 case RTNETIPV6_ICMP_TYPE_RS: 2844 hdrlen = 8; 2845 break; 2846 2847 case RTNETIPV6_ICMP_TYPE_RA: 2848 hdrlen = 16; 2849 break; 2850 2851 case RTNETIPV6_ICMP_TYPE_NS: 2852 hdrlen = 24; 2853 break; 2854 2855 case RTNETIPV6_ICMP_TYPE_NA: 2856 hdrlen = 24; 2857 llaopt = RTNETIPV6_ICMP_ND_TLLA_OPT; 2858 break; 2859 2860 default: 2861 return; 2862 } 2863 2864 AssertReturnVoid(hdrlen > 0); 2865 if (RT_UNLIKELY(cb < hdrlen)) 2866 return; 2867 2868 if (RT_UNLIKELY(pICMPv6->icmp6_code != 0)) 2869 return; 2870 2871 PRTNETNDP_LLA_OPT pLLAOpt = NULL; 2872 char *pOpt = (char *)pICMPv6 + hdrlen; 2873 cb -= hdrlen; 2874 2875 while (cb >= 8) 2876 { 2877 uint8_t opt = ((uint8_t *)pOpt)[0]; 2878 size_t optlen = (size_t)((uint8_t *)pOpt)[1] * 8; 2879 if (RT_UNLIKELY(cb < optlen)) 2880 return; 2881 2882 if (opt == llaopt) 2883 { 2884 if (RT_UNLIKELY(optlen != 8)) 2885 return; 2886 pLLAOpt = (PRTNETNDP_LLA_OPT)pOpt; 2887 break; 2888 } 2889 2890 pOpt += optlen; 2891 cb -= optlen; 2892 } 2893 2894 if (pLLAOpt == NULL) 2895 return; 2896 2897 if (memcmp(&pLLAOpt->lla, &pIfSender->MacAddr, sizeof(RTMAC)) != 0) 2898 return; 2899 2900 /* overwrite VM's MAC with host's MAC */ 2901 pLLAOpt->lla = pThis->MacAddr; 2902 2903 /* recompute the checksum */ 2904 pICMPv6->icmp6_cksum = 0; 2905 pICMPv6->icmp6_cksum = computeIPv6FullChecksum(pIPv6); 2906 } 2907 2908 2811 2909 /** 2812 2910 * Sends a frame down the trunk. … … 2888 2986 } 2889 2987 } 2890 else if (pEthHdr->EtherType == RT_H2 BE_U16(RTNET_ETHERTYPE_IPV6))2988 else if (pEthHdr->EtherType == RT_H2N_U16_C(RTNET_ETHERTYPE_IPV6)) 2891 2989 { 2892 /* 2893 * IPV6 ICMP Neighbor Discovery : replace 2894 * 1) the advertised source mac address in outgoing neighbor sollicitations 2895 * with the HW MAC address of the trunk interface, 2896 * 2) the advertised target mac address in outgoing neighbor advertisements 2897 * with the HW mac address of the trunk interface. 2898 * 2899 * Note that this only applies to traffic going out on the trunk. Incoming 2900 * NS/NA will never advertise any VM mac address, so we do not need to touch 2901 * them. Other VMs on this bridge as well as the host will see and use the VM's 2902 * actual mac addresses. 2903 * 2904 */ 2905 2906 PRTNETIPV6 pIPv6 = (PRTNETIPV6)(pEthHdr + 1); 2907 PRTNETNDP pNd = (PRTNETNDP)(pIPv6 + 1); 2908 PRTNETNDP_SLLA_OPT pLLAOpt = (PRTNETNDP_SLLA_OPT)(pNd + 1); 2909 2910 /* make sure we have enough bytes to work with */ 2911 if(pSG->cbTotal >= (RTNETIPV6_MIN_LEN + RTNETIPV6_ICMPV6_ND_WITH_LLA_OPT_MIN_LEN) && 2912 /* ensure the packet came from our LAN (not gone through any router) */ 2913 pIPv6->ip6_hlim == 0xff && 2914 /* protocol has to be icmpv6 */ 2915 pIPv6->ip6_nxt == RTNETIPV6_PROT_ICMPV6 && 2916 /* we either have a sollicitation with source link layer addr. opt, or */ 2917 ((pNd->icmp6_type == RTNETIPV6_ICMP_NS_TYPE && 2918 pNd->icmp6_code == RTNETIPV6_ICMPV6_CODE_0 && 2919 pLLAOpt->type == RTNETIPV6_ICMP_ND_SLLA_OPT) || 2920 /* an advertisement with target link layer addr. option */ 2921 ((pNd->icmp6_type == RTNETIPV6_ICMP_NA_TYPE && 2922 pNd->icmp6_code == RTNETIPV6_ICMPV6_CODE_0 && 2923 pLLAOpt->type == RTNETIPV6_ICMP_ND_TLLA_OPT)) ) && 2924 pLLAOpt->len == RTNETIPV6_ICMP_ND_LLA_LEN) 2925 { 2926 /* swap the advertised VM MAC address with the trunk's */ 2927 pLLAOpt->slla = pThis->MacAddr; 2928 2929 /* recompute the checksum since we changed the packet */ 2930 pNd->icmp6_cksum = 0; 2931 pNd->icmp6_cksum = computeIPv6FullChecksum(pIPv6); 2932 } 2933 2990 intnetR0TrunkSharedMacEditIPv6FromIntNet(pThis, pIfSender, pEthHdr, pSG->cbTotal); 2934 2991 } 2935 2992 } 2936 2993 2937 2994 /* 2938 * Send the frame, handling the GSO fallback 2939 * .2940 * Note! The trunk implementation will re-check that the trunk is active .2995 * Send the frame, handling the GSO fallback. 2996 * 2997 * Note! The trunk implementation will re-check that the trunk is active 2941 2998 * before sending, so we don't have to duplicate that effort here. 2942 2999 */ … … 3099 3156 if ( pIPv6->ip6_hlim == 0xff 3100 3157 && pIPv6->ip6_nxt == RTNETIPV6_PROT_ICMPV6 3101 && pNd-> icmp6_type == RTNETIPV6_ICMP_NS_TYPE3102 && pNd-> icmp6_code == RTNETIPV6_ICMPV6_CODE_03158 && pNd->Hdr.icmp6_type == RTNETIPV6_ICMP_TYPE_NS 3159 && pNd->Hdr.icmp6_code == 0 3103 3160 && pIPv6->ip6_src.QWords.qw0 == 0 3104 3161 && pIPv6->ip6_src.QWords.qw1 == 0)
Note:
See TracChangeset
for help on using the changeset viewer.