d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/* $Id$ */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/** @file
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * VBoxNetUDP - IntNet UDP Client Routines.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2009-2010 Oracle Corporation
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
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>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdmnetinline.h>
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#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 */
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync PCINTNETHDR pHdr = IntNetRingGetNextFrameToRead(&pBuf->Recv);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if ( !pHdr
3c086cee27d5216042cc045c009537485c0339b5vboxsync || ( pHdr->u8Type != INTNETHDR_TYPE_FRAME
3c086cee27d5216042cc045c009537485c0339b5vboxsync && pHdr->u8Type != INTNETHDR_TYPE_GSO))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync size_t cbFrame = pHdr->cbFrame;
9127c416edfd6f9266e387f7abd7aa9904eecbc9vboxsync const void *pvFrame = IntNetHdrGetFramePtr(pHdr, pBuf);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync PCPDMNETWORKGSO pGso = NULL;
3c086cee27d5216042cc045c009537485c0339b5vboxsync if (pHdr->u8Type == INTNETHDR_TYPE_GSO)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync {
6dd8f5023a9ba7588212331db90059553136fe33vboxsync pGso = (PCPDMNETWORKGSO)pvFrame;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (!PDMNetGsoIsValid(pGso, cbFrame, cbFrame - sizeof(*pGso)))
6dd8f5023a9ba7588212331db90059553136fe33vboxsync return NULL;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /** @todo IPv6 UDP support, goes for this entire function really. Not really
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * important yet since this is currently only used by the DHCP server. */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (pGso->u8Type != PDMNETWORKGSOTYPE_IPV4_UDP)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync return NULL;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync pvFrame = pGso + 1;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync cbFrame -= sizeof(*pGso);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync }
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCRTNETETHERHDR pEthHdr = (PCRTNETETHERHDR)pvFrame;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pHdrs)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pHdrs->pEth = pEthHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#ifdef IN_RING3
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Dump if to stderr/log if that's wanted. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (fFlags & VBOXNETUDP_MATCH_PRINT_STDERR)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync {
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTStrmPrintf(g_pStdErr, "frame: cb=%04x dst=%.6Rhxs src=%.6Rhxs type=%04x%s\n",
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync cbFrame, &pEthHdr->DstMac, &pEthHdr->SrcMac, RT_BE2H_U16(pEthHdr->EtherType),
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync !memcmp(&pEthHdr->DstMac, pDstMac, sizeof(*pDstMac)) ? " Mine!" : "");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync }
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync#endif
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Ethernet matching.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
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
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /*
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * If we're working on a GSO frame, we need to make sure the length fields
6dd8f5023a9ba7588212331db90059553136fe33vboxsync * are set correctly (they are usually set to 0).
6dd8f5023a9ba7588212331db90059553136fe33vboxsync */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (pGso)
bad918bbc587b87deb80ad29dafb6f837b0c538evboxsync PDMNetGsoPrepForDirectUse(pGso, (void *)pvFrame, cbFrame, PDMNETCSUMTYPE_NONE);
6dd8f5023a9ba7588212331db90059553136fe33vboxsync
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;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (!RTNetIPv4IsHdrValid(pIpHdr, cbFrame - offIpHdr, cbFrame - offIpHdr, !pGso /*fChecksum*/))
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /*
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * UDP matching and validation.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uint32_t *)pIpHdr + pIpHdr->ip_hl);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (pHdrs)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pHdrs->pUdp = pUdpHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Destination port */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync if (RT_BE2H_U16(pUdpHdr->uh_dport) != uDstPort)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync return NULL;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (!pGso)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync {
6dd8f5023a9ba7588212331db90059553136fe33vboxsync /* Validate the UDP header according to flags. */
6dd8f5023a9ba7588212331db90059553136fe33vboxsync size_t offUdpHdr = (uintptr_t)pUdpHdr - (uintptr_t)pEthHdr;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (fFlags & (VBOXNETUDP_MATCH_CHECKSUM | VBOXNETUDP_MATCH_REQUIRE_CHECKSUM))
6dd8f5023a9ba7588212331db90059553136fe33vboxsync {
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (!RTNetIPv4IsUDPValid(pIpHdr, pUdpHdr, pUdpHdr + 1, cbFrame - offUdpHdr, true /*fChecksum*/))
6dd8f5023a9ba7588212331db90059553136fe33vboxsync return NULL;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if ( (fFlags & VBOXNETUDP_MATCH_REQUIRE_CHECKSUM)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync && !pUdpHdr->uh_sum)
6dd8f5023a9ba7588212331db90059553136fe33vboxsync return NULL;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync }
6dd8f5023a9ba7588212331db90059553136fe33vboxsync else
6dd8f5023a9ba7588212331db90059553136fe33vboxsync {
6dd8f5023a9ba7588212331db90059553136fe33vboxsync if (!RTNetIPv4IsUDPSizeValid(pIpHdr, pUdpHdr, cbFrame - offUdpHdr))
6dd8f5023a9ba7588212331db90059553136fe33vboxsync return NULL;
6dd8f5023a9ba7588212331db90059553136fe33vboxsync }
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
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/** Internal worker for VBoxNetUDPUnicast and VBoxNetUDPBroadcast. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncstatic int vboxnetudpSend(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 INTNETSEG aSegs[4];
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* the Ethernet header */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync RTNETETHERHDR EtherHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync EtherHdr.DstMac = *pDstMacAddr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync EtherHdr.SrcMac = *pSrcMacAddr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync EtherHdr.EtherType = RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[0].pv = &EtherHdr;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync aSegs[0].cb = sizeof(EtherHdr);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync 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