VBoxNetUDP.cpp revision d1a00c93378091ef28db9d959b2d692cc8143a07
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VBoxNetUDP - IntNet UDP Client Routines.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * available from http://www.virtualbox.org. This file is free software;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * you can redistribute it and/or modify it under the terms of the GNU
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * General Public License (GPL) as published by the Free Software
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * additional information or have any questions.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*******************************************************************************
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync* Header Files *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync*******************************************************************************/
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Checks if the head of the receive ring is a UDP packet matching the given
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * criteria.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @returns Pointer to the data if it matches.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pBuf The IntNet buffers.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param uDstPort The destination port to match.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pDstMac The destination address to match if
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VBOXNETUDP_MATCH_UNICAST is specied.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param fFlags Flags indicating what to match and some debug stuff.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * See VBOXNETUDP_MATCH_*.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pHdrs Where to return the pointers to the headers.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Optional.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pcb Where to return the size of the data on success.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncvoid *VBoxNetUDPMatch(PINTNETBUF pBuf, unsigned uDstPort, PCRTMAC pDstMac, uint32_t fFlags, PVBOXNETUDPHDRS pHdrs, size_t *pcb)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Clear return values so we can return easier on mismatch.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Valid IntNet Ethernet frame?
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCINTNETHDR pHdr = INTNETRingGetNextFrameToRead(&pBuf->Recv);
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync if (!pHdr || pHdr->u16Type != INTNETHDR_TYPE_FRAME)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync const void *pvFrame = INTNETHdrGetFramePtr(pHdr, pBuf);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pvFrame;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* Dump if to stderr/log if that's wanted. */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync RTStrmPrintf(g_pStdErr, "frame: cb=%04x dst=%.6Rhxs src=%.6Rhxs type=%04x%s\n",
6dd8f5023a9ba7588212331db90059553136fe33vboxsync cbFrame, &pEthHdr->DstMac, &pEthHdr->SrcMac, RT_BE2H_U16(pEthHdr->EtherType),
6dd8f5023a9ba7588212331db90059553136fe33vboxsync !memcmp(&pEthHdr->DstMac, pDstMac, sizeof(*pDstMac)) ? " Mine!" : "");
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * Ethernet matching.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Ethernet min frame size. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Match Ethertype: IPV4? */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /** @todo VLAN tagging? */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pEthHdr->EtherType != RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Match destination address (ethernet) */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync || memcmp(&pEthHdr->DstMac, pDstMac, sizeof(pEthHdr->DstMac)))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * IP validation and matching.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Protocol: UDP */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Valid IPv4 header? */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync size_t const offIpHdr = (uintptr_t)pIpHdr - (uintptr_t)pEthHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (!RTNetIPv4IsHdrValid(pIpHdr, cbFrame - offIpHdr, cbFrame - offIpHdr))
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * UDP matching and validation.
6dd8f5023a9ba7588212331db90059553136fe33vboxsync PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* Destination port */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Validate the UDP header according to flags. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync size_t offUdpHdr = (uintptr_t)pUdpHdr - (uintptr_t)pEthHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (fFlags & (VBOXNETUDP_MATCH_CHECKSUM | VBOXNETUDP_MATCH_REQUIRE_CHECKSUM))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (!RTNetIPv4IsUDPValid(pIpHdr, pUdpHdr, pUdpHdr + 1, cbFrame - offUdpHdr))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (!RTNetIPv4IsUDPSizeValid(pIpHdr, pUdpHdr, cbFrame - offUdpHdr))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * We've got a match!
6dd8f5023a9ba7588212331db90059553136fe33vboxsync/** Internal worker for VBoxNetUDPUnicast and VBoxNetUDPBroadcast. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncstatic int vboxnetudpSend(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
6dd8f5023a9ba7588212331db90059553136fe33vboxsync RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
6dd8f5023a9ba7588212331db90059553136fe33vboxsync RTNETADDRIPV4 DstIPv4Addr, PCRTMAC pDstMacAddr, unsigned uDstPort,
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* the Ethernet header */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync EtherHdr.EtherType = RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the IP header */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync unsigned cbIdHdr = RT_UOFFSETOF(RTNETIPV4, ip_options);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_len = RT_H2BE_U16((uint16_t)(cbData + sizeof(RTNETUDP) + cbIdHdr));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the UDP bit */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_ulen = RT_H2BE_U16((uint16_t)(cbData + sizeof(RTNETUDP)));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_sum = 0; /* pretend checksumming is disabled */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_sum = RTNetIPv4UDPChecksum(&IpHdr, &UdpHdr, pvData);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the payload */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* send it */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return VBoxNetIntIfSend(pSession, hIf, pBuf, RT_ELEMENTS(aSegs), &aSegs[0], true /* fFlush */);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Sends an unicast UDP packet.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @returns VBox status code.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pSession The support driver session handle.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param hIf The interface handle.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pBuf The interface buffer.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param SrcIPv4Addr The source IPv4 address.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pSrcMacAddr The source MAC address.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param uSrcPort The source port number.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param DstIPv4Addr The destination IPv4 address. Can be broadcast.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pDstMacAddr The destination MAC address.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param uDstPort The destination port number.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pvData The data payload.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param cbData The size of the data payload.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncint VBoxNetUDPUnicast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 DstIPv4Addr, PCRTMAC pDstMacAddr, unsigned uDstPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Sends a broadcast UDP packet.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @returns VBox status code.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pSession The support driver session handle.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param hIf The interface handle.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pBuf The interface buffer.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param SrcIPv4Addr The source IPv4 address.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pSrcMacAddr The source MAC address.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param uSrcPort The source port number.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param uDstPort The destination port number.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pvData The data payload.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param cbData The size of the data payload.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncint VBoxNetUDPBroadcast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync MacBrdCast.au16[0] = MacBrdCast.au16[1] = MacBrdCast.au16[2] = UINT16_C(0xffff);