VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp@ 17416

Last change on this file since 17416 was 17403, checked in by vboxsync, 16 years ago

VBoxNetDHCP: fixes and logging.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 KB
Line 
1/* $Id: VBoxNetDHCP.cpp 17403 2009-03-05 14:49:41Z vboxsync $ */
2/** @file
3 * VBoxNetDHCP - DHCP Service for connecting to IntNet.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/** @page pg_net_dhcp VBoxNetDHCP
23 *
24 * Write a few words...
25 *
26 */
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/initterm.h>
32#include <iprt/net.h>
33#include <iprt/err.h>
34#include <iprt/time.h>
35#include <iprt/stream.h>
36#include <iprt/path.h>
37#include <iprt/param.h>
38#include <iprt/getopt.h>
39
40#include <VBox/sup.h>
41#include <VBox/intnet.h>
42#include <VBox/vmm.h>
43#include <VBox/version.h>
44
45#include "../UDPLib/VBoxNetUDP.h"
46
47#include <vector>
48#include <string>
49
50
51/*******************************************************************************
52* Structures and Typedefs *
53*******************************************************************************/
54
55/**
56 * DHCP configuration item.
57 *
58 * This is all public data because I'm too lazy to do it propertly right now.
59 */
60class VBoxNetDhcpCfg
61{
62public:
63 /** The etheret addresses this matches config applies to.
64 * An empty vector means 'ANY'. */
65 std::vector<RTMAC> m_MacAddresses;
66 /** The upper address in the range. */
67 RTNETADDRIPV4 m_UpperAddr;
68 /** The lower address in the range. */
69 RTNETADDRIPV4 m_LowerAddr;
70
71 /** Option 1: The net mask. */
72 RTNETADDRIPV4 m_SubnetMask;
73 /* * Option 2: The time offset. */
74 /** Option 3: Routers for the subnet. */
75 std::vector<RTNETADDRIPV4> m_Routers;
76 /* * Option 4: Time server. */
77 /* * Option 5: Name server. */
78 /** Option 6: Domain Name Server (DNS) */
79 std::vector<RTNETADDRIPV4> m_DNSes;
80 /* * Option 7: Log server. */
81 /* * Option 8: Cookie server. */
82 /* * Option 9: LPR server. */
83 /* * Option 10: Impress server. */
84 /* * Option 11: Resource location server. */
85 /* * Option 12: Host name. */
86 //std::string<char> m_HostName;
87 /* * Option 13: Boot file size option. */
88 /* * Option 14: Merit dump file. */
89 /** Option 15: Domain name. */
90 std::string m_DomainName;
91 /* * Option 16: Swap server. */
92 /* * Option 17: Root path. */
93 /* * Option 18: Extension path. */
94 /* * Option 19: IP forwarding enable/disable. */
95 /* * Option 20: Non-local routing enable/disable. */
96 /* * Option 21: Policy filter. */
97 /* * Option 22: Maximum datagram reassembly size (MRS). */
98 /* * Option 23: Default IP time-to-live. */
99 /* * Option 24: Path MTU aging timeout. */
100 /* * Option 25: Path MTU plateau table. */
101 /* * Option 26: Interface MTU. */
102 /* * Option 27: All subnets are local. */
103 /* * Option 28: Broadcast address. */
104 /* * Option 29: Perform maximum discovery. */
105 /* * Option 30: Mask supplier. */
106 /* * Option 31: Perform route discovery. */
107 /* * Option 32: Router solicitation address. */
108 /* * Option 33: Static route. */
109 /* * Option 34: Trailer encapsulation. */
110 /* * Option 35: ARP cache timeout. */
111 /* * Option 36: Ethernet encapsulation. */
112 /* * Option 37: TCP Default TTL. */
113 /* * Option 38: TCP Keepalive Interval. */
114 /* * Option 39: TCP Keepalive Garbage. */
115 /* * Option 40: Network Information Service (NIS) Domain. */
116 /* * Option 41: Network Information Servers. */
117 /* * Option 42: Network Time Protocol Servers. */
118 /* * Option 43: Vendor Specific Information. */
119 /* * Option 44: NetBIOS over TCP/IP Name Server (NBNS). */
120 /* * Option 45: NetBIOS over TCP/IP Datagram distribution Server (NBDD). */
121 /* * Option 46: NetBIOS over TCP/IP Node Type. */
122 /* * Option 47: NetBIOS over TCP/IP Scope. */
123 /* * Option 48: X Window System Font Server. */
124 /* * Option 49: X Window System Display Manager. */
125
126 /** Option 51: IP Address Lease Time. */
127 uint32_t m_cSecLease;
128
129 /* * Option 64: Network Information Service+ Domain. */
130 /* * Option 65: Network Information Service+ Servers. */
131 /** Option 66: TFTP server name. */
132 std::string m_TftpServer;
133 /** Option 67: Bootfile name. */
134 std::string m_BootfileName;
135
136 /* * Option 68: Mobile IP Home Agent. */
137 /* * Option 69: Simple Mail Transport Protocol (SMPT) Server. */
138 /* * Option 70: Post Office Protocol (POP3) Server. */
139 /* * Option 71: Network News Transport Protocol (NNTP) Server. */
140 /* * Option 72: Default World Wide Web (WWW) Server. */
141 /* * Option 73: Default Finger Server. */
142 /* * Option 74: Default Internet Relay Chat (IRC) Server. */
143 /* * Option 75: StreetTalk Server. */
144
145 /* * Option 119: Domain Search. */
146
147
148 VBoxNetDhcpCfg()
149 {
150 m_UpperAddr.u = UINT32_MAX;
151 m_LowerAddr.u = UINT32_MAX;
152 m_SubnetMask.u = UINT32_MAX;
153 m_cSecLease = 60*60; /* 1 hour */
154 }
155
156 /** Validates the configuration.
157 * @returns 0 on success, exit code + error message to stderr on failure. */
158 int validate(void)
159 {
160 if ( m_UpperAddr.u == UINT32_MAX
161 || m_LowerAddr.u == UINT32_MAX
162 || m_SubnetMask.u == UINT32_MAX)
163 {
164 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: Config is missing:");
165 if (m_UpperAddr.u == UINT32_MAX)
166 RTStrmPrintf(g_pStdErr, " --upper-ip");
167 if (m_LowerAddr.u == UINT32_MAX)
168 RTStrmPrintf(g_pStdErr, " --lower-ip");
169 if (m_SubnetMask.u == UINT32_MAX)
170 RTStrmPrintf(g_pStdErr, " --netmask");
171 return 2;
172 }
173 return 0;
174 }
175
176};
177
178/**
179 * DHCP lease.
180 */
181class VBoxNetDhcpLease
182{
183public:
184 /** The client MAC address. */
185 RTMAC m_MacAddress;
186 /** The lease expiration time. */
187 RTTIMESPEC m_ExpireTime;
188};
189
190/**
191 * DHCP server instance.
192 */
193class VBoxNetDhcp
194{
195public:
196 VBoxNetDhcp();
197 virtual ~VBoxNetDhcp();
198
199 int parseArgs(int argc, char **argv);
200 int tryGoOnline(void);
201 int run(void);
202
203protected:
204 int addConfig(VBoxNetDhcpCfg *pCfg);
205 bool handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb);
206
207 inline void debugPrint( int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const;
208 void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const;
209 static const char *debugDhcpName(uint8_t uMsgType);
210
211protected:
212 /** @name The server configuration data members.
213 * @{ */
214 std::string m_Name;
215 std::string m_Network;
216 RTMAC m_MacAddress;
217 RTNETADDRIPV4 m_IpAddress;
218 /** @} */
219
220 /** The current configs. */
221 std::vector<VBoxNetDhcpCfg> m_Cfgs;
222
223 /** The current leases. */
224 std::vector<VBoxNetDhcpLease> m_Leases;
225
226 /** @name The network interface
227 * @{ */
228 PSUPDRVSESSION m_pSession;
229 uint32_t m_cbSendBuf;
230 uint32_t m_cbRecvBuf;
231 INTNETIFHANDLE m_hIf; /**< The handle to the network interface. */
232 PINTNETBUF m_pIfBuf; /**< Interface buffer. */
233 /** @} */
234
235 /** @name Debug stuff
236 * @{ */
237 int32_t m_cVerbosity;
238 uint8_t m_uCurMsgType;
239 uint16_t m_cbCurMsg;
240 PCRTNETBOOTP m_pCurMsg;
241 VBOXNETUDPHDRS m_CurHdrs;
242 /** @} */
243};
244
245
246/*******************************************************************************
247* Global Variables *
248*******************************************************************************/
249/** Pointer to the DHCP server. */
250static VBoxNetDhcp *g_pDhcp;
251
252
253
254/**
255 * Construct a DHCP server with a default configuration.
256 */
257VBoxNetDhcp::VBoxNetDhcp()
258{
259 m_Name = "VBoxNetDhcp";
260 m_Network = "VBoxNetDhcp";
261 m_MacAddress.au8[0] = 0x08;
262 m_MacAddress.au8[1] = 0x00;
263 m_MacAddress.au8[2] = 0x27;
264 m_MacAddress.au8[3] = 0x40;
265 m_MacAddress.au8[4] = 0x41;
266 m_MacAddress.au8[5] = 0x42;
267 m_IpAddress.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 5)));
268
269 m_pSession = NULL;
270 m_cbSendBuf = 8192;
271 m_cbRecvBuf = 51200; /** @todo tune to 64 KB with help from SrvIntR0 */
272 m_hIf = INTNET_HANDLE_INVALID;
273 m_pIfBuf = NULL;
274
275 m_cVerbosity = 0;
276 m_uCurMsgType = UINT8_MAX;
277 m_cbCurMsg = 0;
278 m_pCurMsg = NULL;
279 memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs));
280
281#if 1 /* while hacking. */
282 VBoxNetDhcpCfg DefCfg;
283 DefCfg.m_LowerAddr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2,100)));
284 DefCfg.m_UpperAddr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2,250)));
285 DefCfg.m_SubnetMask.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(255,255,255, 0)));
286 RTNETADDRIPV4 Addr;
287 Addr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 1)));
288 DefCfg.m_Routers.push_back(Addr);
289 Addr.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 2)));
290 DefCfg.m_DNSes.push_back(Addr);
291 DefCfg.m_DomainName = "vboxnetdhcp.org";
292 DefCfg.m_cSecLease = 60*60; /* 1 hour */
293 DefCfg.m_TftpServer = "10.0.2.3"; //??
294#endif
295}
296
297
298/**
299 * Destruct a DHCP server.
300 */
301VBoxNetDhcp::~VBoxNetDhcp()
302{
303 /*
304 * Close the interface connection.
305 */
306 if (m_hIf != INTNET_HANDLE_INVALID)
307 {
308 INTNETIFCLOSEREQ CloseReq;
309 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
310 CloseReq.Hdr.cbReq = sizeof(CloseReq);
311 CloseReq.pSession = m_pSession;
312 CloseReq.hIf = m_hIf;
313 m_hIf = INTNET_HANDLE_INVALID;
314 int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
315 AssertRC(rc);
316 }
317
318 if (m_pSession)
319 {
320 SUPTerm(false /* not forced */);
321 m_pSession = NULL;
322 }
323}
324
325
326/**
327 * Adds a config to the tail.
328 *
329 * @returns See VBoxNetDHCP::validate().
330 * @param pCfg The config too add.
331 * This object will be consumed by this call!
332 */
333int VBoxNetDhcp::addConfig(VBoxNetDhcpCfg *pCfg)
334{
335 int rc = 0;
336 if (pCfg)
337 {
338 rc = pCfg->validate();
339 if (!rc)
340 m_Cfgs.push_back(*pCfg);
341 delete pCfg;
342 }
343 return rc;
344}
345
346
347/**
348 * Parse the arguments.
349 *
350 * @returns 0 on success, fully bitched exit code on failure.
351 *
352 * @param argc Argument count.
353 * @param argv Argument vector.
354 */
355int VBoxNetDhcp::parseArgs(int argc, char **argv)
356{
357 static const RTGETOPTDEF s_aOptionDefs[] =
358 {
359 { "--name", 'N', RTGETOPT_REQ_STRING },
360 { "--network", 'n', RTGETOPT_REQ_STRING },
361/// @todo { "--mac-address", 'a', RTGETOPT_REQ_MACADDR },
362 { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR },
363 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
364
365 { "--begin-config", 'b', RTGETOPT_REQ_NOTHING },
366 { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR },
367 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR },
368 { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR },
369 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR },
370
371 { "--help", 'h', RTGETOPT_REQ_NOTHING },
372 { "--version ", 'V', RTGETOPT_REQ_NOTHING },
373 };
374
375 RTGETOPTSTATE State;
376 int rc = RTGetOptInit(&State, argc, argv, &s_aOptionDefs[0], RT_ELEMENTS(s_aOptionDefs), 0, 0);
377 AssertRCReturn(rc, 49);
378
379 VBoxNetDhcpCfg *pCurCfg = NULL;
380 for (;;)
381 {
382 RTGETOPTUNION Val;
383 rc = RTGetOpt(&State, &Val);
384 if (!rc)
385 break;
386 switch (rc)
387 {
388 case 'N':
389 m_Name = Val.psz;
390 break;
391 case 'n':
392 m_Network = Val.psz;
393 break;
394 case 'a':
395AssertFailed();
396// m_MacAddress = Val.Mac;
397 break;
398 case 'i':
399 m_IpAddress = Val.IPv4Addr;
400 break;
401
402 case 'v':
403 m_cVerbosity++;
404 break;
405
406 /* Begin config. */
407 case 'b':
408 rc = addConfig(pCurCfg);
409 if (rc)
410 break;
411 pCurCfg = NULL;
412 /* fall thru */
413
414 /* config specific ones. */
415 case 'g':
416 case 'l':
417 case 'u':
418 case 'm':
419 if (!pCurCfg)
420 {
421 pCurCfg = new VBoxNetDhcpCfg();
422 if (!pCurCfg)
423 {
424 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxDhcpCfg failed\n");
425 rc = 1;
426 break;
427 }
428 }
429
430 switch (rc)
431 {
432 case 'g':
433 pCurCfg->m_Routers.push_back(Val.IPv4Addr);
434 break;
435
436 case 'l':
437 pCurCfg->m_LowerAddr = Val.IPv4Addr;
438 break;
439
440 case 'u':
441 pCurCfg->m_UpperAddr = Val.IPv4Addr;
442 break;
443
444 case 'm':
445 pCurCfg->m_SubnetMask = Val.IPv4Addr;
446 break;
447
448 case 0: /* ignore */ break;
449 default:
450 AssertMsgFailed(("%d", rc));
451 rc = 1;
452 break;
453 }
454 break;
455
456 case 'V':
457 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBOX_SVN_REV);
458 rc = 0;
459 break;
460
461 case 'h':
462 RTPrintf("VBoxNetDHCP Version %s\n"
463 "(C) 2009 Sun Microsystems, Inc.\n"
464 "All rights reserved\n"
465 "\n"
466 "Usage:\n"
467 " TODO\n",
468 VBOX_VERSION_STRING);
469 rc = 1;
470 break;
471
472 default:
473 break;
474 }
475 }
476
477 return rc;
478}
479
480
481/**
482 * Tries to connect to the internal network.
483 *
484 * @returns 0 on success, exit code + error message to stderr on failure.
485 */
486int VBoxNetDhcp::tryGoOnline(void)
487{
488 /*
489 * Open the session, load ring-0 and issue the request.
490 */
491 int rc = SUPR3Init(&m_pSession);
492 if (RT_FAILURE(rc))
493 {
494 m_pSession = NULL;
495 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3Init -> %Rrc", rc);
496 return 1;
497 }
498
499 char szPath[RTPATH_MAX];
500 rc = RTPathProgram(szPath, sizeof(szPath) - sizeof("/VMMR0.r0"));
501 if (RT_FAILURE(rc))
502 {
503 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: RTPathProgram -> %Rrc", rc);
504 return 1;
505 }
506
507 rc = SUPLoadVMM(strcat(szPath, "/VMMR0.r0"));
508 if (RT_FAILURE(rc))
509 {
510 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPLoadVMM(\"%s\") -> %Rrc", szPath, rc);
511 return 1;
512 }
513
514 /*
515 * Create the open request.
516 */
517 INTNETOPENREQ OpenReq;
518 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
519 OpenReq.Hdr.cbReq = sizeof(OpenReq);
520 OpenReq.pSession = m_pSession;
521 strncpy(OpenReq.szNetwork, m_Network.c_str(), sizeof(OpenReq.szNetwork));
522 OpenReq.szTrunk[0] = '\0';
523 OpenReq.enmTrunkType = kIntNetTrunkType_WhateverNone;
524 OpenReq.fFlags = 0; /** @todo check this */
525 OpenReq.cbSend = m_cbSendBuf;
526 OpenReq.cbRecv = m_cbRecvBuf;
527 OpenReq.hIf = INTNET_HANDLE_INVALID;
528
529 /*
530 * Issue the request.
531 */
532 debugPrint(2, false, "attempting to open/create network \"%s\"...", OpenReq.szNetwork);
533 rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
534 if (RT_SUCCESS(rc))
535 {
536 m_hIf = OpenReq.hIf;
537 debugPrint(1, false, "successfully opened/created \"%s\" - hIf=%#x", OpenReq.szNetwork, m_hIf);
538
539 /*
540 * Get the ring-3 address of the shared interface buffer.
541 */
542 INTNETIFGETRING3BUFFERREQ GetRing3BufferReq;
543 GetRing3BufferReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
544 GetRing3BufferReq.Hdr.cbReq = sizeof(GetRing3BufferReq);
545 GetRing3BufferReq.pSession = m_pSession;
546 GetRing3BufferReq.hIf = m_hIf;
547 GetRing3BufferReq.pRing3Buf = NULL;
548 rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
549 if (RT_SUCCESS(rc))
550 {
551 PINTNETBUF pBuf = GetRing3BufferReq.pRing3Buf;
552 debugPrint(1, false, "pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d",
553 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv);
554 m_pIfBuf = pBuf;
555
556 /*
557 * Activate the interface.
558 */
559 INTNETIFSETACTIVEREQ ActiveReq;
560 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
561 ActiveReq.Hdr.cbReq = sizeof(ActiveReq);
562 ActiveReq.pSession = m_pSession;
563 ActiveReq.hIf = m_hIf;
564 ActiveReq.fActive = true;
565 rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
566 if (RT_SUCCESS(rc))
567 return 0;
568
569 /* bail out */
570 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPCallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc);
571 }
572 else
573 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPCallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_RING3_BUFFER,) failed, rc=%Rrc\n", rc);
574 }
575 else
576 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPCallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc);
577
578 return RT_SUCCESS(rc) ? 0 : 1;
579}
580
581
582/**
583 * Runs the DHCP server.
584 *
585 * @returns exit code + error message to stderr on failure, won't return on
586 * success (you must kill this process).
587 */
588int VBoxNetDhcp::run(void)
589{
590 /*
591 * The loop.
592 */
593 PINTNETRINGBUF pRingBuf = &m_pIfBuf->Recv;
594 for (;;)
595 {
596 /*
597 * Wait for a packet to become available.
598 */
599 INTNETIFWAITREQ WaitReq;
600 WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
601 WaitReq.Hdr.cbReq = sizeof(WaitReq);
602 WaitReq.pSession = m_pSession;
603 WaitReq.hIf = m_hIf;
604 WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */ /** @todo fix interruptability in SrvIntNet! */
605 int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
606 if (RT_FAILURE(rc))
607 {
608 if (rc == VERR_TIMEOUT)
609 continue;
610 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: VMMR0_DO_INTNET_IF_WAIT returned %Rrc\n", rc);
611 return 1;
612 }
613
614 /*
615 * Process the receive buffer.
616 */
617 while (INTNETRingGetReadable(pRingBuf) > 0)
618 {
619 size_t cb;
620 void *pv = VBoxNetUDPMatch(m_pIfBuf, 67 /* bootps */, &m_MacAddress,
621 VBOXNETUDP_MATCH_UNICAST | VBOXNETUDP_MATCH_BROADCAST | VBOXNETUDP_MATCH_CHECKSUM
622 | (m_cVerbosity > 2 ? VBOXNETUDP_MATCH_PRINT_STDERR : 0),
623 &m_CurHdrs, &cb);
624 if (pv && cb)
625 {
626 PCRTNETBOOTP pDhcpMsg = (PCRTNETBOOTP)pv;
627 m_pCurMsg = pDhcpMsg;
628 m_cbCurMsg = cb;
629
630 uint8_t uMsgType;
631 if (RTNetIPv4IsDHCPValid(NULL /* why is this here? */, pDhcpMsg, cb, &uMsgType))
632 {
633 m_uCurMsgType = uMsgType;
634 handleDhcpMsg(uMsgType, pDhcpMsg, cb);
635 m_uCurMsgType = UINT8_MAX;
636 }
637 else
638 debugPrint(1, true, "VBoxNetDHCP: Skipping invalid DHCP packet.\n");
639
640 m_pCurMsg = NULL;
641 m_cbCurMsg = 0;
642 }
643
644 /* Advance to the next frame. */
645 INTNETRingSkipFrame(m_pIfBuf, pRingBuf);
646 }
647 }
648
649 return 0;
650}
651
652
653/**
654 * Handles a DHCP message.
655 *
656 * @returns true if handled, false if not.
657 * @param uMsgType The message type.
658 * @param pDhcpMsg The DHCP message.
659 * @param cb The size of the DHCP message.
660 */
661bool VBoxNetDhcp::handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb)
662{
663 debugPrint(0, true, "todo");
664 return false;
665}
666
667
668/**
669 * Print debug message depending on the m_cVerbosity level.
670 *
671 * @param iMinLevel The minimum m_cVerbosity level for this message.
672 * @param fMsg Whether to dump parts for the current DHCP message.
673 * @param pszFmt The message format string.
674 * @param ... Optional arguments.
675 */
676inline void VBoxNetDhcp::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const
677{
678 if (iMinLevel <= m_cVerbosity)
679 {
680 va_list va;
681 va_start(va, pszFmt);
682 debugPrintV(iMinLevel, fMsg, pszFmt, va);
683 va_end(va);
684 }
685}
686
687
688/**
689 * Print debug message depending on the m_cVerbosity level.
690 *
691 * @param iMinLevel The minimum m_cVerbosity level for this message.
692 * @param fMsg Whether to dump parts for the current DHCP message.
693 * @param pszFmt The message format string.
694 * @param va Optional arguments.
695 */
696void VBoxNetDhcp::debugPrintV(int iMinLevel, bool fMsg, const char *pszFmt, va_list va) const
697{
698 if (iMinLevel <= m_cVerbosity)
699 {
700 va_list vaCopy; /* This dude is *very* special, thus the copy. */
701 va_copy(vaCopy, va);
702 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy);
703 va_end(vaCopy);
704
705 if ( fMsg
706 && m_cVerbosity >= 2
707 && m_pCurMsg)
708 {
709 const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
710 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d\n",
711 pszMsg,
712 &m_pCurMsg->bp_chaddr,
713 m_pCurMsg->bp_ciaddr.au8[0], m_pCurMsg->bp_ciaddr.au8[1], m_pCurMsg->bp_ciaddr.au8[2], m_pCurMsg->bp_ciaddr.au8[3],
714 m_pCurMsg->bp_yiaddr.au8[0], m_pCurMsg->bp_yiaddr.au8[1], m_pCurMsg->bp_yiaddr.au8[2], m_pCurMsg->bp_yiaddr.au8[3],
715 m_pCurMsg->bp_siaddr.au8[0], m_pCurMsg->bp_siaddr.au8[1], m_pCurMsg->bp_siaddr.au8[2], m_pCurMsg->bp_siaddr.au8[3]);
716 }
717 }
718}
719
720
721/**
722 * Gets the name of given DHCP message type.
723 *
724 * @returns Readonly name.
725 * @param uMsgType The message number.
726 */
727/* static */ const char *VBoxNetDhcp::debugDhcpName(uint8_t uMsgType)
728{
729 switch (uMsgType)
730 {
731 case 0: return "MT_00";
732 case RTNET_DHCP_MT_DISCOVER: return "DISCOVER";
733 case RTNET_DHCP_MT_OFFER: return "OFFER";
734 case RTNET_DHCP_MT_REQUEST: return "REQUEST";
735 case RTNET_DHCP_MT_DECLINE: return "DECLINE";
736 case RTNET_DHCP_MT_ACK: return "ACK";
737 case RTNET_DHCP_MT_NAC: return "NAC";
738 case RTNET_DHCP_MT_RELEASE: return "RELEASE";
739 case RTNET_DHCP_MT_INFORM: return "INFORM";
740 case 9: return "MT_09";
741 case 10: return "MT_0a";
742 case 11: return "MT_0b";
743 case 12: return "MT_0c";
744 case 13: return "MT_0d";
745 case 14: return "MT_0e";
746 case 15: return "MT_0f";
747 case 16: return "MT_10";
748 case 17: return "MT_11";
749 case 18: return "MT_12";
750 case 19: return "MT_13";
751 case UINT8_MAX: return "MT_ff";
752 default: return "UNKNOWN";
753 }
754}
755
756
757
758/**
759 * Entry point.
760 */
761extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
762{
763 /*
764 * Instantiate the DHCP server and hand it the options.
765 */
766 VBoxNetDhcp *pDhcp = new VBoxNetDhcp();
767 if (!pDhcp)
768 {
769 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxNetDhcp failed!\n");
770 return 1;
771 }
772 int rc = pDhcp->parseArgs(argc - 1, argv + 1);
773 if (rc)
774 return rc;
775
776 /*
777 * Try connect the server to the network.
778 */
779 rc = pDhcp->tryGoOnline();
780 if (rc)
781 {
782 delete pDhcp;
783 return rc;
784 }
785
786 /*
787 * Process requests.
788 */
789 g_pDhcp = pDhcp;
790 rc = pDhcp->run();
791 g_pDhcp = NULL;
792 delete pDhcp;
793
794 return rc;
795}
796
797
798
799#ifndef VBOX_WITH_HARDENING
800
801int main(int argc, char **argv, char **envp)
802{
803 int rc = RTR3InitAndSUPLib();
804 if (RT_FAILURE(rc))
805 {
806 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: RTR3InitAndSupLib failed, rc=%Rrc\n", rc);
807 return 1;
808 }
809
810 return TrustedMain(argc, argv, envp);
811}
812
813#endif /* !VBOX_WITH_HARDENING */
814
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