VirtualBox

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

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

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

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