VirtualBox

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

Last change on this file since 79509 was 79509, checked in by vboxsync, 5 years ago

Dhcpd: Ditched std:vector<char> + catch with wrong slash non-sense in VBoxNetDhcpd::vmmInit(). Misc cleanups.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.9 KB
Line 
1/* $Id: VBoxNetDhcpd.cpp 79509 2019-07-03 15:41:17Z vboxsync $ */
2/** @file
3 * VBoxNetDhcpd - DHCP server for host-only and NAT networks.
4 */
5
6/*
7 * Copyright (C) 2009-2019 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
20/*
21 * Need to get host/network order conversion stuff from Windows headers,
22 * so we do not define them in LWIP and then try to re-define them in
23 * Windows headers.
24 */
25#ifdef RT_OS_WINDOWS
26# include <iprt/win/winsock2.h>
27#endif
28
29
30#include <iprt/param.h>
31#include <iprt/errcore.h>
32
33#include <iprt/initterm.h>
34#include <iprt/message.h>
35
36#include <iprt/net.h>
37#include <iprt/path.h>
38#include <iprt/stream.h>
39
40#include <VBox/sup.h>
41#include <VBox/vmm/vmm.h>
42#include <VBox/vmm/pdmnetinline.h>
43#include <VBox/intnet.h>
44#include <VBox/intnetinline.h>
45
46#include "VBoxLwipCore.h"
47#include "Config.h"
48#include "DHCPD.h"
49#include "DhcpMessage.h"
50
51extern "C"
52{
53#include "lwip/sys.h"
54#include "lwip/pbuf.h"
55#include "lwip/netif.h"
56#include "lwip/tcpip.h"
57#include "lwip/udp.h"
58#include "netif/etharp.h"
59}
60
61#include <string>
62#include <vector>
63#include <memory>
64
65#ifdef RT_OS_WINDOWS
66# include <iprt/win/windows.h>
67#endif
68
69struct delete_pbuf
70{
71 delete_pbuf() {}
72 void operator()(struct pbuf *p) const { pbuf_free(p); }
73};
74
75typedef std::unique_ptr<pbuf, delete_pbuf> unique_ptr_pbuf;
76
77
78#define CALL_VMMR0(op, req) \
79 (SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, (op), 0, &(req).Hdr))
80
81
82class VBoxNetDhcpd
83{
84 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(VBoxNetDhcpd);
85
86private:
87 PRTLOGGER m_pStderrReleaseLogger;
88
89 /* intnet plumbing */
90 PSUPDRVSESSION m_pSession;
91 INTNETIFHANDLE m_hIf;
92 PINTNETBUF m_pIfBuf;
93
94 /* lwip stack connected to the intnet */
95 struct netif m_LwipNetif;
96
97 Config *m_Config;
98
99 /* listening pcb */
100 struct udp_pcb *m_Dhcp4Pcb;
101
102 DHCPD m_server;
103
104public:
105 VBoxNetDhcpd();
106 ~VBoxNetDhcpd();
107
108 int main(int argc, char **argv);
109
110private:
111 int logInitStderr();
112
113 /*
114 * Boilerplate code.
115 */
116 int r3Init();
117 void r3Fini();
118
119 int vmmInit();
120
121 int ifInit(const std::string &strNetwork,
122 const std::string &strTrunk = std::string(),
123 INTNETTRUNKTYPE enmTrunkType = kIntNetTrunkType_WhateverNone);
124 int ifOpen(const std::string &strNetwork,
125 const std::string &strTrunk,
126 INTNETTRUNKTYPE enmTrunkType);
127 int ifGetBuf();
128 int ifActivate();
129
130 int ifWait(uint32_t cMillies = RT_INDEFINITE_WAIT);
131 int ifProcessInput();
132 int ifFlush();
133
134 int ifClose();
135
136 void ifPump();
137 int ifInput(void *pvSegFrame, uint32_t cbSegFrame);
138
139 int ifOutput(PCINTNETSEG paSegs, size_t cSegs, size_t cbFrame);
140
141
142 /*
143 * lwIP callbacks
144 */
145 static DECLCALLBACK(void) lwipInitCB(void *pvArg);
146 void lwipInit();
147
148 static err_t netifInitCB(netif *pNetif);
149 err_t netifInit(netif *pNetif);
150
151 static err_t netifLinkOutputCB(netif *pNetif, pbuf *pPBuf);
152 err_t netifLinkOutput(pbuf *pPBuf);
153
154 static void dhcp4RecvCB(void *arg, struct udp_pcb *pcb, struct pbuf *p,
155 ip_addr_t *addr, u16_t port);
156 void dhcp4Recv(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
157};
158
159
160VBoxNetDhcpd::VBoxNetDhcpd()
161 : m_pStderrReleaseLogger(NULL),
162 m_pSession(NIL_RTR0PTR),
163 m_hIf(INTNET_HANDLE_INVALID),
164 m_pIfBuf(NULL),
165 m_LwipNetif(),
166 m_Config(NULL),
167 m_Dhcp4Pcb(NULL)
168{
169 int rc;
170
171 logInitStderr();
172
173 rc = r3Init();
174 if (RT_FAILURE(rc))
175 return;
176
177 vmmInit();
178}
179
180
181VBoxNetDhcpd::~VBoxNetDhcpd()
182{
183 ifClose();
184 r3Fini();
185}
186
187
188/*
189 * We don't know the name of the release log file until we parse our
190 * configuration because we use network name as basename. To get
191 * early logging to work, start with stderr-only release logger.
192 *
193 * We disable "sup" for this logger to avoid spam from SUPR3Init().
194 */
195int VBoxNetDhcpd::logInitStderr()
196{
197 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
198
199 PRTLOGGER pLogger;
200 int rc;
201
202 uint32_t fFlags = 0;
203#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
204 fFlags |= RTLOGFLAGS_USECRLF;
205#endif
206
207 rc = RTLogCreate(&pLogger, fFlags,
208 "all -sup all.restrict -default.restrict",
209 NULL, /* environment base */
210 RT_ELEMENTS(s_apszGroups), s_apszGroups,
211 RTLOGDEST_STDERR, NULL);
212 if (RT_FAILURE(rc))
213 {
214 RTPrintf("Failed to init stderr logger: %Rrs\n", rc);
215 return rc;
216 }
217
218 m_pStderrReleaseLogger = pLogger;
219 RTLogRelSetDefaultInstance(m_pStderrReleaseLogger);
220
221 return VINF_SUCCESS;
222}
223
224
225int VBoxNetDhcpd::r3Init()
226{
227 AssertReturn(m_pSession == NIL_RTR0PTR, VERR_GENERAL_FAILURE);
228
229 int rc = SUPR3Init(&m_pSession);
230 return rc;
231}
232
233
234void VBoxNetDhcpd::r3Fini()
235{
236 if (m_pSession == NIL_RTR0PTR)
237 return;
238
239 SUPR3Term();
240 m_pSession = NIL_RTR0PTR;
241}
242
243
244int VBoxNetDhcpd::vmmInit()
245{
246 char szPathVMMR0[RTPATH_MAX];
247 int rc = RTPathExecDir(szPathVMMR0, sizeof(szPathVMMR0));
248 if (RT_SUCCESS(rc))
249 rc = RTPathAppend(szPathVMMR0, sizeof(szPathVMMR0), "VMMR0.r0");
250 if (RT_SUCCESS(rc))
251 rc = SUPR3LoadVMM(szPathVMMR0);
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 = _128K;
305 OpenReq.cbRecv = _256K;
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 *pbChunk = (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, pbChunk, len);
496 pbChunk += 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 /* XXX: We no longer need hardcoded and compat methods. We should remove them soon. */
620 if (argc < 2)
621 m_Config = Config::hardcoded();
622 else if ( strcmp(argv[1], "--config") == 0
623 || strcmp(argv[1], "--comment") == 0)
624 m_Config = Config::create(argc, argv);
625 else
626 m_Config = Config::compat(argc, argv);
627
628 if (m_Config == NULL)
629 return VERR_GENERAL_FAILURE;
630
631 rc = m_server.init(m_Config);
632
633 /* connect to the intnet */
634 rc = ifInit(m_Config->getNetwork(),
635 m_Config->getTrunk(),
636 m_Config->getTrunkType());
637 if (RT_FAILURE(rc))
638 return rc;
639
640 /* setup lwip */
641 rc = vboxLwipCoreInitialize(lwipInitCB, this);
642 if (RT_FAILURE(rc))
643 return rc;
644
645 ifPump();
646 return VINF_SUCCESS;
647}
648
649
650void VBoxNetDhcpd::lwipInit()
651{
652 err_t error;
653
654 ip_addr_t addr, mask;
655 ip4_addr_set_u32(&addr, m_Config->getIPv4Address().u);
656 ip4_addr_set_u32(&mask, m_Config->getIPv4Netmask().u);
657
658 netif *pNetif = netif_add(&m_LwipNetif,
659 &addr, &mask,
660 IP_ADDR_ANY, /* gateway */
661 this, /* state */
662 VBoxNetDhcpd::netifInitCB, /* netif_init_fn */
663 tcpip_input); /* netif_input_fn */
664 if (pNetif == NULL)
665 return;
666
667 netif_set_up(pNetif);
668 netif_set_link_up(pNetif);
669
670 m_Dhcp4Pcb = udp_new();
671 if (RT_UNLIKELY(m_Dhcp4Pcb == NULL))
672 return; /* XXX? */
673
674 ip_set_option(m_Dhcp4Pcb, SOF_BROADCAST);
675 udp_recv(m_Dhcp4Pcb, dhcp4RecvCB, this);
676
677 error = udp_bind(m_Dhcp4Pcb, IP_ADDR_ANY, RTNETIPV4_PORT_BOOTPS);
678 if (error != ERR_OK)
679 {
680 udp_remove(m_Dhcp4Pcb);
681 m_Dhcp4Pcb = NULL;
682 return; /* XXX? */
683 }
684}
685
686
687err_t VBoxNetDhcpd::netifInit(netif *pNetif)
688{
689 pNetif->hwaddr_len = sizeof(RTMAC);
690 memcpy(pNetif->hwaddr, &m_Config->getMacAddress(), sizeof(RTMAC));
691
692 pNetif->mtu = 1500;
693
694 pNetif->flags = NETIF_FLAG_BROADCAST
695 | NETIF_FLAG_ETHARP
696 | NETIF_FLAG_ETHERNET;
697
698 pNetif->linkoutput = netifLinkOutputCB;
699 pNetif->output = etharp_output;
700
701 netif_set_default(pNetif);
702 return ERR_OK;
703}
704
705
706void VBoxNetDhcpd::dhcp4Recv(struct udp_pcb *pcb, struct pbuf *p,
707 ip_addr_t *addr, u16_t port)
708{
709 err_t error;
710 int rc;
711
712 RT_NOREF(pcb, addr, port);
713
714 if (RT_UNLIKELY(p->next != NULL))
715 return; /* XXX: we want it in one chunk */
716
717 bool broadcasted = ip_addr_cmp(ip_current_dest_addr(), &ip_addr_broadcast)
718 || ip_addr_cmp(ip_current_dest_addr(), &ip_addr_any);
719
720 DhcpClientMessage *msgIn = DhcpClientMessage::parse(broadcasted, p->payload, p->len);
721 if (msgIn == NULL)
722 return;
723
724 std::unique_ptr<DhcpClientMessage> autoFreeMsgIn(msgIn);
725
726 DhcpServerMessage *msgOut = m_server.process(*msgIn);
727 if (msgOut == NULL)
728 return;
729
730 std::unique_ptr<DhcpServerMessage> autoFreeMsgOut(msgOut);
731
732 ip_addr_t dst = { msgOut->dst().u };
733 if (ip_addr_cmp(&dst, &ip_addr_any))
734 ip_addr_copy(dst, ip_addr_broadcast);
735
736 octets_t data;
737 rc = msgOut->encode(data);
738 if (RT_FAILURE(rc))
739 return;
740
741 unique_ptr_pbuf q ( pbuf_alloc(PBUF_RAW, (u16_t)data.size(), PBUF_RAM) );
742 if (!q)
743 return;
744
745 error = pbuf_take(q.get(), &data.front(), (u16_t)data.size());
746 if (error != ERR_OK)
747 return;
748
749 error = udp_sendto(pcb, q.get(), &dst, RTNETIPV4_PORT_BOOTPC);
750 if (error != ERR_OK)
751 return;
752}
753
754
755
756
757/*
758 * Entry point.
759 */
760extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv)
761{
762 VBoxNetDhcpd Dhcpd;
763 int rc = Dhcpd.main(argc, argv);
764
765 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
766}
767
768
769#ifndef VBOX_WITH_HARDENING
770
771int main(int argc, char **argv)
772{
773 int rc = RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
774 if (RT_FAILURE(rc))
775 return RTMsgInitFailure(rc);
776
777 return TrustedMain(argc, argv);
778}
779
780
781# ifdef RT_OS_WINDOWS
782/** (We don't want a console usually.) */
783int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
784{
785 RT_NOREF(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
786
787 return main(__argc, __argv);
788}
789# endif /* RT_OS_WINDOWS */
790
791#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