Index: /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp	(revision 17779)
+++ /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp	(revision 17780)
@@ -1548,5 +1548,23 @@
      * Send it.
      */
-
+    int rc;
+#if 0
+    if (pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)
+    {
+        RTNETADDRIPV4 IPv4AddrBrdCast;
+        IPv4AddrBrdCast.u = UINT32_C(0xffffffff); /* broadcast IP */
+        rc = VBoxNetUDPUnicast(m_pSession, m_hIf, m_pIfBuf,
+                               m_Ipv4Address, &m_MacAddress, RTNETIPV4_PORT_BOOTPS,                 /* sender */
+                               IPv4AddrBrdCast, &pDhcpMsg->bp_chaddr.Mac, RTNETIPV4_PORT_BOOTPC,    /* receiver */
+                               pReply, cbReply);
+    }
+    else
+#endif
+        rc = VBoxNetUDPBroadcast(m_pSession, m_hIf, m_pIfBuf,
+                                 m_Ipv4Address, &m_MacAddress, RTNETIPV4_PORT_BOOTPS,               /* sender */
+                                 RTNETIPV4_PORT_BOOTPC,                                             /* receiver port */
+                                 pReply, cbReply);
+    if (RT_FAILURE(rc))
+        debugPrint(0, true, "error %Rrc when sending the reply", rc);
 }
 
Index: /trunk/src/VBox/NetworkServices/UDPLib/VBoxNetUDP.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/UDPLib/VBoxNetUDP.cpp	(revision 17779)
+++ /trunk/src/VBox/NetworkServices/UDPLib/VBoxNetUDP.cpp	(revision 17780)
@@ -23,7 +23,11 @@
 *   Header Files                                                               *
 *******************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT
 #include "VBoxNetUDP.h"
 #include <iprt/stream.h>
 #include <iprt/string.h>
+#include <iprt/rand.h>
+#include <VBox/vmm.h>
+#include <VBox/log.h>
 
 
@@ -151,2 +155,274 @@
 }
 
+
+/**
+ * Flushes the send buffer.
+ *
+ * @returns VBox status code.
+ * @param   pSession        The support driver session.
+ * @param   hIf             The interface handle to flush.
+ */
+static int vboxnetudpFlush(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf)
+{
+    INTNETIFSENDREQ SendReq;
+    SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+    SendReq.Hdr.cbReq    = sizeof(SendReq);
+    SendReq.pSession     = pSession;
+    SendReq.hIf          = hIf;
+    return SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
+}
+
+
+/**
+ * Copys the SG segments into the specified fram.
+ *
+ * @param   pvFrame     The frame buffer.
+ * @param   cSegs       The number of segments.
+ * @param   paSegs      The segments.
+ */
+static void vboxnetudpCopySG(void *pvFrame, size_t cSegs, PCINTNETSEG paSegs)
+{
+    uint8_t *pbDst = (uint8_t *)pvFrame;
+    for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
+    {
+        memcpy(pbDst, paSegs[iSeg].pv, paSegs[iSeg].cb);
+        pbDst += paSegs[iSeg].cb;
+    }
+}
+
+
+/**
+ * Writes a frame packet to the buffer.
+ *
+ * @returns VBox status code.
+ * @param   pBuf        The buffer.
+ * @param   pRingBuf    The ring buffer to read from.
+ * @param   cSegs       The number of segments.
+ * @param   paSegs      The segments.
+ * @remark  This is the same as INTNETRingWriteFrame and
+ *          drvIntNetRingWriteFrame.
+ */
+static int vboxnetudpRingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf,
+                                    size_t cSegs, PCINTNETSEG paSegs)
+{
+    /*
+     * Validate input.
+     */
+    Assert(pBuf);
+    Assert(pRingBuf);
+    uint32_t offWrite = pRingBuf->offWrite;
+    Assert(offWrite == RT_ALIGN_32(offWrite, sizeof(INTNETHDR)));
+    uint32_t offRead = pRingBuf->offRead;
+    Assert(offRead == RT_ALIGN_32(offRead, sizeof(INTNETHDR)));
+    AssertPtr(paSegs);
+    Assert(cSegs > 0);
+
+    /* Calc frame size. */
+    uint32_t cbFrame = 0;
+    for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
+        cbFrame += paSegs[iSeg].cb;
+
+    Assert(cbFrame >= sizeof(RTMAC) * 2);
+
+
+    const uint32_t cb = RT_ALIGN_32(cbFrame, sizeof(INTNETHDR));
+    if (offRead <= offWrite)
+    {
+        /*
+         * Try fit it all before the end of the buffer.
+         */
+        if (pRingBuf->offEnd - offWrite >= cb + sizeof(INTNETHDR))
+        {
+            PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
+            pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
+            pHdr->cbFrame  = cbFrame;
+            pHdr->offFrame = sizeof(INTNETHDR);
+
+            vboxnetudpCopySG(pHdr + 1, cSegs, paSegs);
+
+            offWrite += cb + sizeof(INTNETHDR);
+            Assert(offWrite <= pRingBuf->offEnd && offWrite >= pRingBuf->offStart);
+            if (offWrite >= pRingBuf->offEnd)
+                offWrite = pRingBuf->offStart;
+            Log2(("WriteFrame: offWrite: %#x -> %#x (1)\n", pRingBuf->offWrite, offWrite));
+            ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
+            return VINF_SUCCESS;
+        }
+
+        /*
+         * Try fit the frame at the start of the buffer.
+         * (The header fits before the end of the buffer because of alignment.)
+         */
+        AssertMsg(pRingBuf->offEnd - offWrite >= sizeof(INTNETHDR), ("offEnd=%x offWrite=%x\n", pRingBuf->offEnd, offWrite));
+        if (offRead - pRingBuf->offStart > cb) /* not >= ! */
+        {
+            PINTNETHDR  pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
+            void       *pvFrameOut = (PINTNETHDR)((uint8_t *)pBuf + pRingBuf->offStart);
+            pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
+            pHdr->cbFrame  = cbFrame;
+            pHdr->offFrame = (intptr_t)pvFrameOut - (intptr_t)pHdr;
+
+            vboxnetudpCopySG(pvFrameOut, cSegs, paSegs);
+
+            offWrite = pRingBuf->offStart + cb;
+            ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
+            Log2(("WriteFrame: offWrite: %#x -> %#x (2)\n", pRingBuf->offWrite, offWrite));
+            return VINF_SUCCESS;
+        }
+    }
+    /*
+     * The reader is ahead of the writer, try fit it into that space.
+     */
+    else if (offRead - offWrite > cb + sizeof(INTNETHDR)) /* not >= ! */
+    {
+        PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
+        pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
+        pHdr->cbFrame  = cbFrame;
+        pHdr->offFrame = sizeof(INTNETHDR);
+
+        vboxnetudpCopySG(pHdr + 1, cSegs, paSegs);
+
+        offWrite += cb + sizeof(INTNETHDR);
+        ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
+        Log2(("WriteFrame: offWrite: %#x -> %#x (3)\n", pRingBuf->offWrite, offWrite));
+        return VINF_SUCCESS;
+    }
+
+    /* (it didn't fit) */
+    /** @todo stats */
+    return VERR_BUFFER_OVERFLOW;
+}
+
+
+/** Internal worker for VBoxNetUDPUnicast and VBoxNetUDPBroadcast. */
+static int vboxnetudpSend(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
+                          RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
+                          RTNETADDRIPV4 DstIPv4Addr, PCRTMAC pDstMacAddr, unsigned uDstPort,
+                          void const *pvData, size_t cbData)
+{
+    INTNETSEG aSegs[4];
+
+    /* the Ethernet header */
+    RTNETETHERHDR EtherHdr;
+    EtherHdr.DstMac     = *pDstMacAddr;
+    EtherHdr.SrcMac     = *pSrcMacAddr;
+    EtherHdr.EtherType  = RT_H2BE_U16_C(RTNET_ETHERTYPE_IPV4);
+
+    aSegs[0].pv   = &EtherHdr;
+    aSegs[0].cb   = sizeof(EtherHdr);
+    aSegs[0].Phys = NIL_RTHCPHYS;
+
+    /* the IP header */
+    RTNETIPV4 IpHdr;
+    IpHdr.ip_v          = 4;
+    IpHdr.ip_hl         = sizeof(RTNETIPV4) / sizeof(uint32_t);
+    IpHdr.ip_tos        = 0;
+    IpHdr.ip_len        = RT_H2BE_U16(cbData + sizeof(RTNETUDP) + sizeof(RTNETIPV4));
+    IpHdr.ip_id         = (uint16_t)RTRandU32();
+    IpHdr.ip_off        = 0;
+    IpHdr.ip_ttl        = 255;
+    IpHdr.ip_p          = RTNETIPV4_PROT_UDP;
+    IpHdr.ip_sum        = 0;
+    IpHdr.ip_src.u      = 0;
+    IpHdr.ip_dst.u      = UINT32_C(0xffffffff); /* broadcast */
+    IpHdr.ip_sum        = RTNetIPv4HdrChecksum(&IpHdr);
+
+    aSegs[1].pv   = &IpHdr;
+    aSegs[1].cb   = sizeof(IpHdr);
+    aSegs[1].Phys = NIL_RTHCPHYS;
+
+
+    /* the UDP bit */
+    RTNETUDP UdpHdr;
+    UdpHdr.uh_sport     = RT_H2BE_U16(uSrcPort);
+    UdpHdr.uh_dport     = RT_H2BE_U16(uDstPort);
+    UdpHdr.uh_ulen      = RT_H2BE_U16(cbData + sizeof(RTNETUDP));
+#if 0
+    UdpHdr.uh_sum       = 0; /* pretend checksumming is disabled */
+#else
+    UdpHdr.uh_sum       = RTNetIPv4UDPChecksum(&IpHdr, &UdpHdr, pvData);
+#endif
+
+    aSegs[2].pv   = &UdpHdr;
+    aSegs[2].cb   = sizeof(UdpHdr);
+    aSegs[2].Phys = NIL_RTHCPHYS;
+
+    /* the payload */
+    aSegs[3].pv   = (void *)pvData;
+    aSegs[3].cb   = cbData;
+    aSegs[3].Phys = NIL_RTHCPHYS;
+
+
+    /* write it */
+    int rc = vboxnetudpRingWriteFrame(pBuf, &pBuf->Send, RT_ELEMENTS(aSegs), &aSegs[0]);
+    int rc2 = vboxnetudpFlush(pSession, hIf);
+    if (RT_FAILURE(rc))
+    {
+        rc = vboxnetudpRingWriteFrame(pBuf, &pBuf->Send, RT_ELEMENTS(aSegs), &aSegs[0]);
+        rc2 = vboxnetudpFlush(pSession, hIf);
+    }
+
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+    return rc;
+}
+
+
+/**
+ * Sends an unicast UDP packet.
+ *
+ * @returns VBox status code.
+ * @param   pSession        The support driver session handle.
+ * @param   hIf             The interface handle.
+ * @param   pBuf            The interface buffer.
+ * @param   SrcIPv4Addr     The source IPv4 address.
+ * @param   pSrcMacAddr     The source MAC address.
+ * @param   uSrcPort        The source port number.
+ * @param   DstIPv4Addr     The destination IPv4 address. Can be broadcast.
+ * @param   pDstMacAddr     The destination MAC address.
+ * @param   uDstPort        The destination port number.
+ * @param   pvData          The data payload.
+ * @param   cbData          The size of the data payload.
+ */
+int     VBoxNetUDPUnicast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
+                          RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
+                          RTNETADDRIPV4 DstIPv4Addr, PCRTMAC pDstMacAddr, unsigned uDstPort,
+                          void const *pvData, size_t cbData)
+{
+    return vboxnetudpSend(pSession, hIf, pBuf,
+                          SrcIPv4Addr, pSrcMacAddr, uSrcPort,
+                          DstIPv4Addr, pDstMacAddr, uDstPort,
+                          pvData, cbData);
+}
+
+
+/**
+ * Sends a broadcast UDP packet.
+ *
+ * @returns VBox status code.
+ * @param   pSession        The support driver session handle.
+ * @param   hIf             The interface handle.
+ * @param   pBuf            The interface buffer.
+ * @param   SrcIPv4Addr     The source IPv4 address.
+ * @param   pSrcMacAddr     The source MAC address.
+ * @param   uSrcPort        The source port number.
+ * @param   uDstPort        The destination port number.
+ * @param   pvData          The data payload.
+ * @param   cbData          The size of the data payload.
+ */
+int     VBoxNetUDPBroadcast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
+                            RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC pSrcMacAddr, unsigned uSrcPort,
+                            unsigned uDstPort,
+                            void const *pvData, size_t cbData)
+{
+    RTNETADDRIPV4   IPv4AddrBrdCast;
+    IPv4AddrBrdCast.u = UINT32_C(0xffffffff);
+    RTMAC           MacBrdCast;
+    MacBrdCast.au16[0] = MacBrdCast.au16[1] = MacBrdCast.au16[2] = UINT16_C(0xffff);
+
+    return vboxnetudpSend(pSession, hIf, pBuf,
+                          SrcIPv4Addr, pSrcMacAddr, uSrcPort,
+                          IPv4AddrBrdCast, &MacBrdCast, uDstPort,
+                          pvData, cbData);
+}
+
Index: /trunk/src/VBox/NetworkServices/UDPLib/VBoxNetUDP.h
===================================================================
--- /trunk/src/VBox/NetworkServices/UDPLib/VBoxNetUDP.h	(revision 17779)
+++ /trunk/src/VBox/NetworkServices/UDPLib/VBoxNetUDP.h	(revision 17780)
@@ -51,6 +51,13 @@
 /** @}  */
 
-void *VBoxNetUDPMatch(PCINTNETBUF pBuf, unsigned uDstPort, PCRTMAC pDstMac, uint32_t fFlags, PVBOXNETUDPHDRS pHdrs, size_t *pcb);
-
+void *  VBoxNetUDPMatch(PCINTNETBUF pBuf, unsigned uDstPort, PCRTMAC pDstMac, uint32_t fFlags, PVBOXNETUDPHDRS pHdrs, size_t *pcb);
+int     VBoxNetUDPUnicast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
+                          RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC SrcMacAddr, unsigned uSrcPort,
+                          RTNETADDRIPV4 DstIPv4Addr, PCRTMAC DstMacAddr, unsigned uDstPort,
+                          void const *pvData, size_t cbData);
+int     VBoxNetUDPBroadcast(PSUPDRVSESSION pSession, INTNETIFHANDLE hIf, PINTNETBUF pBuf,
+                            RTNETADDRIPV4 SrcIPv4Addr, PCRTMAC SrcMacAddr, unsigned uSrcPort,
+                            unsigned uDstPort,
+                            void const *pvData, size_t cbData);
 
 __END_DECLS
