VBoxNetUDP.cpp revision d1a00c93378091ef28db9d959b2d692cc8143a07
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/* $Id$ */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/** @file
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VBoxNetUDP - IntNet UDP Client Routines.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
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 *
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
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*******************************************************************************
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync* Header Files *
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync*******************************************************************************/
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#define LOG_GROUP LOG_GROUP_DEFAULT
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include "VBoxNetLib.h"
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <iprt/stream.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <iprt/string.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <iprt/rand.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#include <VBox/log.h>
6dd8f5023a9ba7588212331db90059553136fe33vboxsync#include <VBox/intnetinline.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Checks if the head of the receive ring is a UDP packet matching the given
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * criteria.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
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.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncvoid *VBoxNetUDPMatch(PINTNETBUF pBuf, unsigned uDstPort, PCRTMAC pDstMac, uint32_t fFlags, PVBOXNETUDPHDRS pHdrs, size_t *pcb)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Clear return values so we can return easier on mismatch.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *pcb = 0;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pHdrs)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync {
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pHdrs->pEth = NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pHdrs->pIpv4 = NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pHdrs->pUdp = NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync }
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Valid IntNet Ethernet frame?
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCINTNETHDR pHdr = INTNETRingGetNextFrameToRead(&pBuf->Recv);
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync if (!pHdr || pHdr->u16Type != INTNETHDR_TYPE_FRAME)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync return NULL;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync size_t cbFrame = pHdr->cbFrame;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync const void *pvFrame = INTNETHdrGetFramePtr(pHdr, pBuf);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pvFrame;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pHdrs)
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync pHdrs->pEth = pEthHdr;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync#ifdef IN_RING3
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* Dump if to stderr/log if that's wanted. */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (fFlags & VBOXNETUDP_MATCH_PRINT_STDERR)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync {
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 }
6dd8f5023a9ba7588212331db90059553136fe33vboxsync#endif
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /*
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * Ethernet matching.
6dd8f5023a9ba7588212331db90059553136fe33vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Ethernet min frame size. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (cbFrame < 64)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Match Ethertype: IPV4? */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /** @todo VLAN tagging? */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pEthHdr->EtherType != RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Match destination address (ethernet) */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if ( ( !(fFlags & VBOXNETUDP_MATCH_UNICAST)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync || memcmp(&pEthHdr->DstMac, pDstMac, sizeof(pEthHdr->DstMac)))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync && ( !(fFlags & VBOXNETUDP_MATCH_BROADCAST)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync || pEthHdr->DstMac.au16[0] != 0xffff
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync || pEthHdr->DstMac.au16[1] != 0xffff
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync || pEthHdr->DstMac.au16[2] != 0xffff))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * IP validation and matching.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCRTNETIPV4 pIpHdr = (PCRTNETIPV4)(pEthHdr + 1);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pHdrs)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pHdrs->pIpv4 = pIpHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Protocol: UDP */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pIpHdr->ip_p != RTNETIPV4_PROT_UDP)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Valid IPv4 header? */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync size_t const offIpHdr = (uintptr_t)pIpHdr - (uintptr_t)pEthHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (!RTNetIPv4IsHdrValid(pIpHdr, cbFrame - offIpHdr, cbFrame - offIpHdr))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * UDP matching and validation.
6dd8f5023a9ba7588212331db90059553136fe33vboxsync */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (pHdrs)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync pHdrs->pUdp = pUdpHdr;
0280e4ae13799a3136778dc90efa5841a3f40cf2vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* Destination port */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (RT_BE2H_U16(pUdpHdr->uh_dport) != uDstPort)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
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 {
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (!RTNetIPv4IsUDPValid(pIpHdr, pUdpHdr, pUdpHdr + 1, cbFrame - offUdpHdr))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if ( (fFlags & VBOXNETUDP_MATCH_REQUIRE_CHECKSUM)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync && !pUdpHdr->uh_sum)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync }
6dd8f5023a9ba7588212331db90059553136fe33vboxsync else
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync {
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (!RTNetIPv4IsUDPSizeValid(pIpHdr, pUdpHdr, cbFrame - offUdpHdr))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync }
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * We've got a match!
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *pcb = pUdpHdr->uh_ulen - sizeof(*pUdpHdr);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return (void *)(pUdpHdr + 1);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
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 void const *pvData, size_t cbData)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync{
6dd8f5023a9ba7588212331db90059553136fe33vboxsync INTNETSEG aSegs[4];
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* the Ethernet header */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync RTNETETHERHDR EtherHdr;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync EtherHdr.DstMac = *pDstMacAddr;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync EtherHdr.SrcMac = *pSrcMacAddr;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync EtherHdr.EtherType = RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync aSegs[0].pv = &EtherHdr;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync aSegs[0].cb = sizeof(EtherHdr);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync aSegs[0].Phys = NIL_RTHCPHYS;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the IP header */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETIPV4 IpHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync unsigned cbIdHdr = RT_UOFFSETOF(RTNETIPV4, ip_options);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_v = 4;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_hl = cbIdHdr >> 2;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_tos = 0;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_len = RT_H2BE_U16((uint16_t)(cbData + sizeof(RTNETUDP) + cbIdHdr));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_id = (uint16_t)RTRandU32();
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_off = 0;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_ttl = 255;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_p = RTNETIPV4_PROT_UDP;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_sum = 0;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_src = SrcIPv4Addr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_dst = DstIPv4Addr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IpHdr.ip_sum = RTNetIPv4HdrChecksum(&IpHdr);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[1].pv = &IpHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[1].cb = cbIdHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[1].Phys = NIL_RTHCPHYS;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the UDP bit */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETUDP UdpHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_sport = RT_H2BE_U16(uSrcPort);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_dport = RT_H2BE_U16(uDstPort);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_ulen = RT_H2BE_U16((uint16_t)(cbData + sizeof(RTNETUDP)));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#if 0
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_sum = 0; /* pretend checksumming is disabled */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#else
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync UdpHdr.uh_sum = RTNetIPv4UDPChecksum(&IpHdr, &UdpHdr, pvData);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#endif
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[2].pv = &UdpHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[2].cb = sizeof(UdpHdr);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[2].Phys = NIL_RTHCPHYS;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the payload */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[3].pv = (void *)pvData;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[3].cb = (uint32_t)cbData;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[3].Phys = NIL_RTHCPHYS;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* send it */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return VBoxNetIntIfSend(pSession, hIf, pBuf, RT_ELEMENTS(aSegs), &aSegs[0], true /* fFlush */);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Sends an unicast UDP packet.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
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.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncint VBoxNetUDPUnicast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 DstIPv4Addr, PCRTMAC pDstMacAddr, unsigned uDstPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync void const *pvData, size_t cbData)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return vboxnetudpSend(pSession, hIf, pBuf,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync SrcIPv4Addr, pSrcMacAddr, uSrcPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync DstIPv4Addr, pDstMacAddr, uDstPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pvData, cbData);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/**
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Sends a broadcast UDP packet.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync *
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.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncint VBoxNetUDPBroadcast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync unsigned uDstPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync void const *pvData, size_t cbData)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync{
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETADDRIPV4 IPv4AddrBrdCast;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IPv4AddrBrdCast.u = UINT32_C(0xffffffff);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTMAC MacBrdCast;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync MacBrdCast.au16[0] = MacBrdCast.au16[1] = MacBrdCast.au16[2] = UINT16_C(0xffff);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return vboxnetudpSend(pSession, hIf, pBuf,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync SrcIPv4Addr, pSrcMacAddr, uSrcPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync IPv4AddrBrdCast, &MacBrdCast, uDstPort,
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pvData, cbData);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync}
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync