VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp@ 75568

Last change on this file since 75568 was 75568, checked in by vboxsync, 6 years ago

Main/DHCPD: bugref:9288 Use new implementation of DHCP server (VCC 10 and older GCC support).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.8 KB
Line 
1/* $Id: VBoxNetDhcpd.cpp 75568 2018-11-19 11:52:10Z vboxsync $ */
2/** @file
3 * VBoxNetDhcpd - DHCP server for host-only and NAT networks.
4 */
5
6/*
7 * Copyright (C) 2009-2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/cdefs.h>
19#include <iprt/param.h>
20#include <iprt/err.h>
21
22#include <iprt/initterm.h>
23#include <iprt/message.h>
24
25#include <iprt/net.h>
26#include <iprt/path.h>
27#include <iprt/stream.h>
28
29#include <VBox/sup.h>
30#include <VBox/vmm/vmm.h>
31#include <VBox/vmm/pdmnetinline.h>
32#include <VBox/intnet.h>
33#include <VBox/intnetinline.h>
34
35#include "VBoxLwipCore.h"
36#include "Config.h"
37#include "DHCPD.h"
38#include "DhcpMessage.h"
39
40extern "C"
41{
42#include "lwip/sys.h"
43#include "lwip/pbuf.h"
44#include "lwip/netif.h"
45#include "lwip/tcpip.h"
46#include "lwip/udp.h"
47#include "netif/etharp.h"
48}
49
50#include <string>
51#include <vector>
52#include <memory>
53
54#ifdef RT_OS_WINDOWS /* WinMain */
55#undef htonl
56#undef ntohl
57# include <iprt/win/windows.h>
58#endif
59
60struct delete_pbuf
61{
62 delete_pbuf() {}
63 void operator()(struct pbuf *p) const { pbuf_free(p); }
64};
65
66typedef std::unique_ptr<pbuf, delete_pbuf> unique_ptr_pbuf;
67
68
69#define CALL_VMMR0(op, req) \
70 (SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, (op), 0, &(req).Hdr))
71
72
73class VBoxNetDhcpd
74{
75 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(VBoxNetDhcpd);
76
77private:
78 PRTLOGGER m_pStderrReleaseLogger;
79
80 /* intnet plumbing */
81 PSUPDRVSESSION m_pSession;
82 INTNETIFHANDLE m_hIf;
83 PINTNETBUF m_pIfBuf;
84
85 /* lwip stack connected to the intnet */
86 struct netif m_LwipNetif;
87
88 Config *m_Config;
89
90 /* listening pcb */
91 struct udp_pcb *m_Dhcp4Pcb;
92
93 DHCPD m_server;
94
95public:
96 VBoxNetDhcpd();
97 ~VBoxNetDhcpd();
98
99 int main(int argc, char **argv);
100
101private:
102 int logInitStderr();
103
104 /*
105 * Boilerplate code.
106 */
107 int r3Init();
108 void r3Fini();
109
110 int vmmInit();
111
112 int ifInit(const std::string &strNetwork,
113 const std::string &strTrunk = std::string(),
114 INTNETTRUNKTYPE enmTrunkType = kIntNetTrunkType_WhateverNone);
115 int ifOpen(const std::string &strNetwork,
116 const std::string &strTrunk,
117 INTNETTRUNKTYPE enmTrunkType);
118 int ifGetBuf();
119 int ifActivate();
120
121 int ifWait(uint32_t cMillies = RT_INDEFINITE_WAIT);
122 int ifProcessInput();
123 int ifFlush();
124
125 int ifClose();
126
127 void ifPump();
128 int ifInput(void *pvSegFrame, uint32_t cbSegFrame);
129
130 int ifOutput(PCINTNETSEG paSegs, size_t cSegs, size_t cbFrame);
131
132
133 /*
134 * lwIP callbacks
135 */
136 static DECLCALLBACK(void) lwipInitCB(void *pvArg);
137 void lwipInit();
138
139 static err_t netifInitCB(netif *pNetif);
140 err_t netifInit(netif *pNetif);
141
142 static err_t netifLinkOutputCB(netif *pNetif, pbuf *pPBuf);
143 err_t netifLinkOutput(pbuf *pPBuf);
144
145 static void dhcp4RecvCB(void *arg, struct udp_pcb *pcb, struct pbuf *p,
146 ip_addr_t *addr, u16_t port);
147 void dhcp4Recv(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
148};
149
150
151VBoxNetDhcpd::VBoxNetDhcpd()
152 : m_pStderrReleaseLogger(NULL),
153 m_pSession(NIL_RTR0PTR),
154 m_hIf(INTNET_HANDLE_INVALID),
155 m_pIfBuf(NULL),
156 m_LwipNetif(),
157 m_Config(NULL),
158 m_Dhcp4Pcb(NULL)
159{
160 int rc;
161
162 logInitStderr();
163
164 rc = r3Init();
165 if (RT_FAILURE(rc))
166 return;
167
168 vmmInit();
169}
170
171
172VBoxNetDhcpd::~VBoxNetDhcpd()
173{
174 ifClose();
175 r3Fini();
176}
177
178
179/*
180 * We don't know the name of the release log file until we parse our
181 * configuration because we use network name as basename. To get
182 * early logging to work, start with stderr-only release logger.
183 *
184 * We disable "sup" for this logger to avoid spam from SUPR3Init().
185 */
186int VBoxNetDhcpd::logInitStderr()
187{
188 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
189
190 PRTLOGGER pLogger;
191 int rc;
192
193 uint32_t fFlags = 0;
194#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
195 fFlags |= RTLOGFLAGS_USECRLF;
196#endif
197
198 rc = RTLogCreate(&pLogger, fFlags,
199 "all -sup all.restrict -default.restrict",
200 NULL, /* environment base */
201 RT_ELEMENTS(s_apszGroups), s_apszGroups,
202 RTLOGDEST_STDERR, NULL);
203 if (RT_FAILURE(rc))
204 {
205 RTPrintf("Failed to init stderr logger: %Rrs\n", rc);
206 return rc;
207 }
208
209 m_pStderrReleaseLogger = pLogger;
210 RTLogRelSetDefaultInstance(m_pStderrReleaseLogger);
211
212 return VINF_SUCCESS;
213}
214
215
216int VBoxNetDhcpd::r3Init()
217{
218 AssertReturn(m_pSession == NIL_RTR0PTR, VERR_GENERAL_FAILURE);
219
220 int rc = SUPR3Init(&m_pSession);
221 return rc;
222}
223
224
225void VBoxNetDhcpd::r3Fini()
226{
227 if (m_pSession == NIL_RTR0PTR)
228 return;
229
230 SUPR3Term();
231 m_pSession = NIL_RTR0PTR;
232}
233
234
235int VBoxNetDhcpd::vmmInit()
236{
237 int rc;
238 try {
239 std::vector<char> vExecDir(RTPATH_MAX);
240 rc = RTPathExecDir(&vExecDir.front(), vExecDir.size());
241 if (RT_FAILURE(rc))
242 return rc;
243 std::string strPath(&vExecDir.front());
244 strPath.append("/VMMR0.r0");
245
246 rc = SUPR3LoadVMM(strPath.c_str());
247 if (RT_FAILURE(rc))
248 return rc;
249
250 rc = VINF_SUCCESS;
251 }
252 catch (...)
253 {
254 rc = VERR_GENERAL_FAILURE;
255 }
256
257 return rc;
258}
259
260
261int VBoxNetDhcpd::ifInit(const std::string &strNetwork,
262 const std::string &strTrunk,
263 INTNETTRUNKTYPE enmTrunkType)
264{
265 int rc;
266
267 rc = ifOpen(strNetwork, strTrunk, enmTrunkType);
268 if (RT_FAILURE(rc))
269 return rc;
270
271 rc = ifGetBuf();
272 if (RT_FAILURE(rc))
273 return rc;
274
275 rc = ifActivate();
276 if (RT_FAILURE(rc))
277 return rc;
278
279 return VINF_SUCCESS;
280}
281
282
283int VBoxNetDhcpd::ifOpen(const std::string &strNetwork,
284 const std::string &strTrunk,
285 INTNETTRUNKTYPE enmTrunkType)
286{
287 AssertReturn(m_pSession != NIL_RTR0PTR, VERR_GENERAL_FAILURE);
288 AssertReturn(m_hIf == INTNET_HANDLE_INVALID, VERR_GENERAL_FAILURE);
289
290 INTNETOPENREQ OpenReq;
291 int rc;
292
293 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
294 OpenReq.Hdr.cbReq = sizeof(OpenReq);
295 OpenReq.pSession = m_pSession;
296
297 strncpy(OpenReq.szNetwork, strNetwork.c_str(), sizeof(OpenReq.szNetwork));
298 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0';
299
300 strncpy(OpenReq.szTrunk, strTrunk.c_str(), sizeof(OpenReq.szTrunk));
301 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0';
302
303 if (enmTrunkType != kIntNetTrunkType_Invalid)
304 OpenReq.enmTrunkType = enmTrunkType;
305 else
306 OpenReq.enmTrunkType = kIntNetTrunkType_WhateverNone;
307
308 OpenReq.fFlags = 0;
309 OpenReq.cbSend = 128 * _1K;
310 OpenReq.cbRecv = 256 * _1K;
311
312 OpenReq.hIf = INTNET_HANDLE_INVALID;
313
314 rc = CALL_VMMR0(VMMR0_DO_INTNET_OPEN, OpenReq);
315 if (RT_FAILURE(rc))
316 return rc;
317
318 m_hIf = OpenReq.hIf;
319 AssertReturn(m_hIf != INTNET_HANDLE_INVALID, VERR_GENERAL_FAILURE);
320
321 return VINF_SUCCESS;
322}
323
324
325int VBoxNetDhcpd::ifGetBuf()
326{
327 AssertReturn(m_pSession != NIL_RTR0PTR, VERR_GENERAL_FAILURE);
328 AssertReturn(m_hIf != INTNET_HANDLE_INVALID, VERR_GENERAL_FAILURE);
329 AssertReturn(m_pIfBuf == NULL, VERR_GENERAL_FAILURE);
330
331 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq;
332 int rc;
333
334 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
335 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq);
336 GetBufferPtrsReq.pSession = m_pSession;
337 GetBufferPtrsReq.hIf = m_hIf;
338
339 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR;
340 GetBufferPtrsReq.pRing3Buf = NULL;
341
342 rc = CALL_VMMR0(VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, GetBufferPtrsReq);
343 if (RT_FAILURE(rc))
344 return rc;
345
346 m_pIfBuf = GetBufferPtrsReq.pRing3Buf;
347 AssertReturn(m_pIfBuf != NULL, VERR_GENERAL_FAILURE);
348
349 return VINF_SUCCESS;
350}
351
352
353int VBoxNetDhcpd::ifActivate()
354{
355 AssertReturn(m_pSession != NIL_RTR0PTR, VERR_GENERAL_FAILURE);
356 AssertReturn(m_hIf != INTNET_HANDLE_INVALID, VERR_GENERAL_FAILURE);
357 AssertReturn(m_pIfBuf != NULL, VERR_GENERAL_FAILURE);
358
359 INTNETIFSETACTIVEREQ ActiveReq;
360 int rc;
361
362 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
363 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
364 ActiveReq.pSession = m_pSession;
365 ActiveReq.hIf = m_hIf;
366
367 ActiveReq.fActive = 1;
368
369 rc = CALL_VMMR0(VMMR0_DO_INTNET_IF_SET_ACTIVE, ActiveReq);
370 return rc;
371}
372
373
374void VBoxNetDhcpd::ifPump()
375{
376 for (;;)
377 {
378 int rc = ifWait();
379
380 if (RT_UNLIKELY(rc == VERR_INTERRUPTED))
381 continue;
382
383#if 0 /* we wait indefinitely */
384 if (rc == VERR_TIMEOUT)
385 ...;
386#endif
387
388 if (RT_FAILURE(rc))
389 return;
390
391 ifProcessInput();
392 }
393}
394
395
396int VBoxNetDhcpd::ifWait(uint32_t cMillies)
397{
398 AssertReturn(m_pSession != NIL_RTR0PTR, VERR_GENERAL_FAILURE);
399 AssertReturn(m_hIf != INTNET_HANDLE_INVALID, VERR_GENERAL_FAILURE);
400
401 INTNETIFWAITREQ WaitReq;
402 int rc;
403
404 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
405 WaitReq.Hdr.cbReq = sizeof(WaitReq);
406 WaitReq.pSession = m_pSession;
407 WaitReq.hIf = m_hIf;
408
409 WaitReq.cMillies = cMillies;
410
411 rc = CALL_VMMR0(VMMR0_DO_INTNET_IF_WAIT, WaitReq);
412 return rc;
413}
414
415
416int VBoxNetDhcpd::ifProcessInput()
417{
418 AssertReturn(m_pSession != NIL_RTR0PTR, VERR_GENERAL_FAILURE);
419 AssertReturn(m_hIf != INTNET_HANDLE_INVALID, VERR_GENERAL_FAILURE);
420 AssertReturn(m_pIfBuf != NULL, VERR_GENERAL_FAILURE);
421
422 for (PCINTNETHDR pHdr;
423 (pHdr = IntNetRingGetNextFrameToRead(&m_pIfBuf->Recv)) != NULL;
424 IntNetRingSkipFrame(&m_pIfBuf->Recv))
425 {
426 const uint8_t u8Type = pHdr->u8Type;
427 void *pvSegFrame;
428 uint32_t cbSegFrame;
429
430 if (u8Type == INTNETHDR_TYPE_FRAME)
431 {
432 pvSegFrame = IntNetHdrGetFramePtr(pHdr, m_pIfBuf);
433 cbSegFrame = pHdr->cbFrame;
434
435 ifInput(pvSegFrame, cbSegFrame);
436 }
437 else if (u8Type == INTNETHDR_TYPE_GSO)
438 {
439 PCPDMNETWORKGSO pGso;
440 size_t cbGso = pHdr->cbFrame;
441 size_t cbFrame = cbGso - sizeof(PDMNETWORKGSO);
442
443 pGso = IntNetHdrGetGsoContext(pHdr, m_pIfBuf);
444 if (!PDMNetGsoIsValid(pGso, cbGso, cbFrame))
445 continue;
446
447 const uint32_t cSegs = PDMNetGsoCalcSegmentCount(pGso, cbFrame);
448 for (uint32_t i = 0; i < cSegs; ++i)
449 {
450 uint8_t abHdrScratch[256];
451 pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)(pGso + 1), cbFrame,
452 abHdrScratch,
453 i, cSegs,
454 &cbSegFrame);
455 ifInput(pvSegFrame, (uint32_t)cbFrame);
456 }
457 }
458 }
459
460 return VINF_SUCCESS;
461}
462
463
464/*
465 * Got a frame from the internal network, feed it to the lwIP stack.
466 */
467int VBoxNetDhcpd::ifInput(void *pvFrame, uint32_t cbFrame)
468{
469 if (pvFrame == NULL)
470 return VERR_INVALID_PARAMETER;
471
472 if ( cbFrame <= sizeof(RTNETETHERHDR)
473 || cbFrame > UINT16_MAX - ETH_PAD_SIZE)
474 return VERR_INVALID_PARAMETER;
475
476 struct pbuf *p = pbuf_alloc(PBUF_RAW, (u16_t)cbFrame + ETH_PAD_SIZE, PBUF_POOL);
477 if (RT_UNLIKELY(p == NULL))
478 return VERR_NO_MEMORY;
479
480 /*
481 * The code below is inlined version of:
482 *
483 * pbuf_header(p, -ETH_PAD_SIZE); // hide padding
484 * pbuf_take(p, pvFrame, cbFrame);
485 * pbuf_header(p, ETH_PAD_SIZE); // reveal padding
486 */
487 struct pbuf *q = p;
488 uint8_t *pu8Chunk = (uint8_t *)pvFrame;
489 do {
490 uint8_t *payload = (uint8_t *)q->payload;
491 size_t len = q->len;
492
493#if ETH_PAD_SIZE
494 if (RT_LIKELY(q == p)) /* single pbuf is large enough */
495 {
496 payload += ETH_PAD_SIZE;
497 len -= ETH_PAD_SIZE;
498 }
499#endif
500 memcpy(payload, pu8Chunk, len);
501 pu8Chunk += len;
502 q = q->next;
503 } while (RT_UNLIKELY(q != NULL));
504
505 m_LwipNetif.input(p, &m_LwipNetif);
506 return VINF_SUCCESS;
507}
508
509
510/*
511 * Got a frame from the lwIP stack, feed it to the internal network.
512 */
513err_t VBoxNetDhcpd::netifLinkOutput(pbuf *pPBuf)
514{
515 PINTNETHDR pHdr;
516 void *pvFrame;
517 u16_t cbFrame;
518 int rc;
519
520 if (pPBuf->tot_len < sizeof(struct eth_hdr)) /* includes ETH_PAD_SIZE */
521 return ERR_ARG;
522
523 cbFrame = pPBuf->tot_len - ETH_PAD_SIZE;
524 rc = IntNetRingAllocateFrame(&m_pIfBuf->Send, cbFrame, &pHdr, &pvFrame);
525 if (RT_FAILURE(rc))
526 return ERR_MEM;
527
528 pbuf_copy_partial(pPBuf, pvFrame, cbFrame, ETH_PAD_SIZE);
529 IntNetRingCommitFrameEx(&m_pIfBuf->Send, pHdr, cbFrame);
530
531 ifFlush();
532 return ERR_OK;
533}
534
535
536int VBoxNetDhcpd::ifFlush()
537{
538 INTNETIFSENDREQ SendReq;
539 int rc;
540
541 SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
542 SendReq.Hdr.cbReq = sizeof(SendReq);
543 SendReq.pSession = m_pSession;
544
545 SendReq.hIf = m_hIf;
546
547 rc = CALL_VMMR0(VMMR0_DO_INTNET_IF_SEND, SendReq);
548 return rc;
549}
550
551
552int VBoxNetDhcpd::ifClose()
553{
554 if (m_hIf == INTNET_HANDLE_INVALID)
555 return VINF_SUCCESS;
556
557 INTNETIFCLOSEREQ CloseReq;
558
559 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
560 CloseReq.Hdr.cbReq = sizeof(CloseReq);
561 CloseReq.pSession = m_pSession;
562
563 CloseReq.hIf = m_hIf;
564
565 m_hIf = INTNET_HANDLE_INVALID;
566 m_pIfBuf = NULL;
567
568 CALL_VMMR0(VMMR0_DO_INTNET_IF_CLOSE, CloseReq);
569 return VINF_SUCCESS;
570}
571
572
573/* static */ DECLCALLBACK(void) VBoxNetDhcpd::lwipInitCB(void *pvArg)
574{
575 AssertPtrReturnVoid(pvArg);
576
577 VBoxNetDhcpd *self = static_cast<VBoxNetDhcpd *>(pvArg);
578 self->lwipInit();
579}
580
581
582/* static */ err_t VBoxNetDhcpd::netifInitCB(netif *pNetif)
583{
584 AssertPtrReturn(pNetif, ERR_ARG);
585
586 VBoxNetDhcpd *self = static_cast<VBoxNetDhcpd *>(pNetif->state);
587 return self->netifInit(pNetif);
588}
589
590
591/* static */ err_t VBoxNetDhcpd::netifLinkOutputCB(netif *pNetif, pbuf *pPBuf)
592{
593 AssertPtrReturn(pNetif, ERR_ARG);
594 AssertPtrReturn(pPBuf, ERR_ARG);
595
596 VBoxNetDhcpd *self = static_cast<VBoxNetDhcpd *>(pNetif->state);
597 AssertPtrReturn(self, ERR_IF);
598
599 return self->netifLinkOutput(pPBuf);
600}
601
602
603/* static */ void VBoxNetDhcpd::dhcp4RecvCB(void *arg, struct udp_pcb *pcb,
604 struct pbuf *p,
605 ip_addr_t *addr, u16_t port)
606{
607 AssertPtrReturnVoid(arg);
608
609 VBoxNetDhcpd *self = static_cast<VBoxNetDhcpd *>(arg);
610 self->dhcp4Recv(pcb, p, addr, port);
611 pbuf_free(p);
612}
613
614
615
616
617
618int VBoxNetDhcpd::main(int argc, char **argv)
619{
620 int rc;
621
622 ClientId::registerFormat();
623
624 if (argc < 2)
625 m_Config = Config::hardcoded();
626 else if (strcmp(argv[1], "--config") == 0)
627 m_Config = Config::create(argc, argv);
628 else
629 m_Config = Config::compat(argc, argv);
630
631 if (m_Config == NULL)
632 return VERR_GENERAL_FAILURE;
633
634 rc = m_server.init(m_Config);
635
636 /* connect to the intnet */
637 rc = ifInit(m_Config->getNetwork(),
638 m_Config->getTrunk(),
639 m_Config->getTrunkType());
640 if (RT_FAILURE(rc))
641 return rc;
642
643 /* setup lwip */
644 rc = vboxLwipCoreInitialize(lwipInitCB, this);
645 if (RT_FAILURE(rc))
646 return rc;
647
648 ifPump();
649 return VINF_SUCCESS;
650}
651
652
653void VBoxNetDhcpd::lwipInit()
654{
655 err_t error;
656
657 ip_addr_t addr, mask;
658 ip4_addr_set_u32(&addr, m_Config->getIPv4Address().u);
659 ip4_addr_set_u32(&mask, m_Config->getIPv4Netmask().u);
660
661 netif *pNetif = netif_add(&m_LwipNetif,
662 &addr, &mask,
663 IP_ADDR_ANY, /* gateway */
664 this, /* state */
665 VBoxNetDhcpd::netifInitCB, /* netif_init_fn */
666 tcpip_input); /* netif_input_fn */
667 if (pNetif == NULL)
668 return;
669
670 netif_set_up(pNetif);
671 netif_set_link_up(pNetif);
672
673 m_Dhcp4Pcb = udp_new();
674 if (RT_UNLIKELY(m_Dhcp4Pcb == NULL))
675 return; /* XXX? */
676
677 ip_set_option(m_Dhcp4Pcb, SOF_BROADCAST);
678 udp_recv(m_Dhcp4Pcb, dhcp4RecvCB, this);
679
680 error = udp_bind(m_Dhcp4Pcb, IP_ADDR_ANY, RTNETIPV4_PORT_BOOTPS);
681 if (error != ERR_OK)
682 {
683 udp_remove(m_Dhcp4Pcb);
684 m_Dhcp4Pcb = NULL;
685 return; /* XXX? */
686 }
687}
688
689
690err_t VBoxNetDhcpd::netifInit(netif *pNetif)
691{
692 pNetif->hwaddr_len = sizeof(RTMAC);
693 memcpy(pNetif->hwaddr, &m_Config->getMacAddress(), sizeof(RTMAC));
694
695 pNetif->mtu = 1500;
696
697 pNetif->flags = NETIF_FLAG_BROADCAST
698 | NETIF_FLAG_ETHARP
699 | NETIF_FLAG_ETHERNET;
700
701 pNetif->linkoutput = netifLinkOutputCB;
702 pNetif->output = etharp_output;
703
704 netif_set_default(pNetif);
705 return ERR_OK;
706}
707
708
709void VBoxNetDhcpd::dhcp4Recv(struct udp_pcb *pcb, struct pbuf *p,
710 ip_addr_t *addr, u16_t port)
711{
712 err_t error;
713 int rc;
714
715 RT_NOREF(pcb, addr, port);
716
717 if (RT_UNLIKELY(p->next != NULL))
718 return; /* XXX: we want it in one chunk */
719
720 bool broadcasted = ip_addr_cmp(ip_current_dest_addr(), &ip_addr_broadcast)
721 || ip_addr_cmp(ip_current_dest_addr(), &ip_addr_any);
722
723 DhcpClientMessage *msgIn = DhcpClientMessage::parse(broadcasted, p->payload, p->len);
724 if (msgIn == NULL)
725 return;
726
727 std::unique_ptr<DhcpClientMessage> autoFreeMsgIn(msgIn);
728
729 DhcpServerMessage *msgOut = m_server.process(*msgIn);
730 if (msgOut == NULL)
731 return;
732
733 std::unique_ptr<DhcpServerMessage> autoFreeMsgOut(msgOut);
734
735 ip_addr_t dst = { msgOut->dst().u };
736 if (ip_addr_isany(&dst))
737 ip_addr_copy(dst, ip_addr_broadcast);
738
739 octets_t data;
740 rc = msgOut->encode(data);
741 if (RT_FAILURE(rc))
742 return;
743
744 unique_ptr_pbuf q ( pbuf_alloc(PBUF_RAW, (u16_t)data.size(), PBUF_RAM) );
745 if (q == nullptr)
746 return;
747
748 error = pbuf_take(q.get(), &data.front(), (u16_t)data.size());
749 if (error != ERR_OK)
750 return;
751
752 error = udp_sendto(pcb, q.get(), &dst, RTNETIPV4_PORT_BOOTPC);
753 if (error != ERR_OK)
754 return;
755}
756
757
758
759
760/*
761 * Entry point.
762 */
763extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv)
764{
765 VBoxNetDhcpd Dhcpd;
766 int rc = Dhcpd.main(argc, argv);
767
768 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
769}
770
771
772#ifndef VBOX_WITH_HARDENING
773
774int main(int argc, char **argv)
775{
776 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
777 if (RT_FAILURE(rc))
778 return RTMsgInitFailure(rc);
779
780 return TrustedMain(argc, argv);
781}
782
783
784# ifdef RT_OS_WINDOWS
785/** (We don't want a console usually.) */
786int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
787{
788 RT_NOREF(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
789
790 return main(__argc, __argv);
791}
792# endif /* RT_OS_WINDOWS */
793
794#endif /* !VBOX_WITH_HARDENING */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette