VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/DHCP/Config.cpp@ 47020

Last change on this file since 47020 was 47020, checked in by vboxsync, 11 years ago

previous r87050, was re-commit of r86970

DHCP becomes Main client, internals changed to let more flexible managment and describing more complex networks (current state, so it should not brake a lot things, but something could stop working).
more stuff moved to BaseNetworkService class.

and r87051 nukes trailing whitespaces.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.6 KB
Line 
1/* $Id: Config.cpp 47020 2013-07-06 17:42:33Z vboxsync $ */
2
3/**
4 * XXX: license.
5 */
6
7#include <VBox/com/com.h>
8#include <VBox/com/listeners.h>
9#include <VBox/com/string.h>
10#include <VBox/com/Guid.h>
11#include <VBox/com/array.h>
12#include <VBox/com/ErrorInfo.h>
13#include <VBox/com/errorprint.h>
14#include <VBox/com/EventQueue.h>
15#include <VBox/com/VirtualBox.h>
16
17#include <iprt/asm.h>
18#include <iprt/net.h>
19#include <iprt/time.h>
20
21#include <VBox/sup.h>
22#include <VBox/intnet.h>
23#include <VBox/intnetinline.h>
24#include <VBox/vmm/vmm.h>
25#include <VBox/version.h>
26
27#include "../NetLib/VBoxNetLib.h"
28
29#include <list>
30#include <vector>
31#include <map>
32#include <string>
33
34#include "Config.h"
35
36
37const NullConfigEntity *g_NullConfig = new NullConfigEntity();
38const RootConfigEntity *g_RootConfig = new RootConfigEntity(std::string("ROOT"));
39const ClientMatchCriteria *g_AnyClient = new AnyClientMatchCriteria();
40
41static SessionManager *g_SessionManager = SessionManager::getSessionManager();
42static ConfigurationManager *g_ConfigurationManager = ConfigurationManager::getConfigurationManager();
43
44static NetworkManager *g_NetworkManager = NetworkManager::getNetworkManager();
45
46/* Client */
47
48Client::Client(const RTMAC& mac, uint32_t xid)
49{
50 m_mac = mac;
51 // m_sessions.insert(Map2ClientSessionType(xid, Session(this, xid)));
52}
53
54/* Session */
55
56bool Session::operator < (const Session& s) const
57{
58 return (m_u32Xid < s.m_u32Xid);
59}
60
61int Session::switchTo(CLIENTSESSIONSTATE enmState)
62{
63 m_state = enmState;
64 return VINF_SUCCESS;
65}
66
67/* Configs
68 NetworkConfigEntity(std::string name,
69 ConfigEntity* pCfg,
70 ClientMatchCriteria* criteria,
71 RTNETADDRIPV4& networkID,
72 RTNETADDRIPV4& networkMask)
73*/
74static const RTNETADDRIPV4 g_AnyIpv4 = {0};
75static const RTNETADDRIPV4 g_AllIpv4 = {0xffffffff};
76RootConfigEntity::RootConfigEntity(std::string name):
77 NetworkConfigEntity(name, g_NullConfig, g_AnyClient, g_AnyIpv4, g_AllIpv4)
78{
79 m_MatchLevel = 2;
80}
81
82/* Session Manager */
83SessionManager *SessionManager::getSessionManager()
84{
85 if (!g_SessionManager)
86 g_SessionManager = new SessionManager();
87 return g_SessionManager;
88}
89
90/*
91 * XXX: it sounds like a hack, we use packet descriptor to get the session,
92 * instead use corresponding functions in NetworkManager to fetch client identification
93 * (note: it isn't only mac driven) and XID for the session.
94 */
95
96/**
97 * XXX: what about leases ... Lease is a committed Session....
98 */
99Session& SessionManager::getClientSessionByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg)
100{
101
102 VecClientIterator it;
103 bool fDhcpValid = false;
104 uint8_t uMsgType = 0;
105
106 fDhcpValid = RTNetIPv4IsDHCPValid(NULL, pDhcpMsg, cbDhcpMsg, &uMsgType);
107 Assert(fDhcpValid);
108
109 /* 1st. client IDs */
110 for ( it = m_clients.begin();
111 it != m_clients.end();
112 ++it)
113 {
114 /* OK. */
115 if ((*it) == pDhcpMsg->bp_chaddr.Mac)
116 break;
117 }
118
119 const uint32_t xid = pDhcpMsg->bp_xid;
120 if (it == m_clients.end())
121 {
122 /* We hasn't got any session for this client */
123 m_clients.push_back(Client(pDhcpMsg->bp_chaddr.Mac,
124 pDhcpMsg->bp_xid));
125 Client& client = m_clients.back();
126 client.m_sessions.insert(Map2ClientSessionType(xid, Session(&client, xid)));
127 Assert(client.m_sessions[xid].m_pClient);
128 return client.m_sessions[xid];
129 }
130
131 Session& session = it->m_sessions[xid];
132 session.m_pClient = &(*it);
133 session.m_u32Xid = xid;
134
135 RawOption opt;
136 int rc;
137
138 switch(uMsgType)
139 {
140 case RTNET_DHCP_MT_DISCOVER:
141 session.switchTo(DHCPDISCOVERRECEIEVED);
142 /* MAY */
143 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
144 if (RT_SUCCESS(rc))
145 {
146 /* hint for address allocation here */
147 session.addressHint = *(PRTNETADDRIPV4)opt.au8RawOpt;
148 }
149 /* MAY: todo */
150 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_LEASE_TIME, pDhcpMsg, cbDhcpMsg, opt);
151
152 /* MAY: not now */
153 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cbDhcpMsg, opt);
154 /* XXX: MAY
155 ConfigurationManager::findOption(RTNET_DHCP_OPT_VENDOR_CLASS_IDENTIFIER, pDhcpMsg, opt);
156 */
157 /* MAY: well */
158 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, opt);
159 if (RT_SUCCESS(rc))
160 memcpy(&session.reqParamList, &opt, sizeof(RawOption));
161
162 /* MAY: todo */
163 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE, pDhcpMsg, cbDhcpMsg, opt);
164
165 break;
166
167 case RTNET_DHCP_MT_REQUEST:
168 session.switchTo(DHCPREQUESTRECEIVED);
169 /* MUST in (SELECTING. INIT-REBOOT) MUST NOT BOUND. RENEW MAY */
170 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
171 if (RT_SUCCESS(rc))
172 {
173 /* hint for address allocation here */
174 session.addressHint = *(PRTNETADDRIPV4)opt.au8RawOpt;
175 }
176
177 /* MAY */
178 ConfigurationManager::findOption(RTNET_DHCP_OPT_LEASE_TIME, pDhcpMsg, cbDhcpMsg, opt);
179 /* MAY */
180 ConfigurationManager::findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cbDhcpMsg, opt);
181 /* XXX: MAY
182 ConfigurationManager::findOption(RTNET_DHCP_OPT_VENDOR_CLASS_IDENTIFIER, pDhcpMsg, opt);
183 */
184 /* MAY */
185 rc = ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, opt);
186 if (RT_SUCCESS(rc))
187 memcpy(&session.reqParamList, &opt, sizeof(RawOption));
188
189 /* MAY */
190 ConfigurationManager::findOption(RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE, pDhcpMsg, cbDhcpMsg, opt);
191
192 break;
193
194 case RTNET_DHCP_MT_DECLINE:
195 case RTNET_DHCP_MT_OFFER:
196 case RTNET_DHCP_MT_ACK:
197 case RTNET_DHCP_MT_NAC:
198 case RTNET_DHCP_MT_RELEASE:
199 case RTNET_DHCP_MT_INFORM:
200 AssertMsgFailed(("unimplemented"));
201 }
202
203 Assert(session.m_pClient);
204 return session;
205}
206
207void SessionManager::releaseClientSession(Session& session)
208{
209}
210
211void SessionManager::releaseClient(Client& client)
212{
213}
214
215
216/* Configuration Manager */
217ConfigurationManager *ConfigurationManager::getConfigurationManager()
218{
219 if (!g_ConfigurationManager)
220 g_ConfigurationManager = new ConfigurationManager();
221
222 return g_ConfigurationManager;
223}
224
225
226/**
227 * Finds an option.
228 *
229 * @returns On success, a pointer to the first byte in the option data (no none
230 * then it'll be the byte following the 0 size field) and *pcbOpt set
231 * to the option length.
232 * On failure, NULL is returned and *pcbOpt unchanged.
233 *
234 * @param uOption The option to search for.
235 * @param pDhcpMsg The DHCP message.
236 * that this is adjusted if the option length is larger
237 * than the message buffer.
238 */
239int
240ConfigurationManager::findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt)
241{
242 Assert(uOption != RTNET_DHCP_OPT_PAD);
243
244 /*
245 * Validate the DHCP bits and figure the max size of the options in the vendor field.
246 */
247 if (cbDhcpMsg <= RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts))
248 return VERR_INVALID_PARAMETER;
249
250 if (pDhcpMsg->bp_vend.Dhcp.dhcp_cookie != RT_H2N_U32_C(RTNET_DHCP_COOKIE))
251 return VERR_INVALID_PARAMETER;
252
253 size_t cbLeft = cbDhcpMsg - RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts);
254 if (cbLeft > RTNET_DHCP_OPT_SIZE)
255 cbLeft = RTNET_DHCP_OPT_SIZE;
256
257 /*
258 * Search the vendor field.
259 */
260 bool fExtended = false;
261 uint8_t const *pb = &pDhcpMsg->bp_vend.Dhcp.dhcp_opts[0];
262 while (pb && cbLeft > 0)
263 {
264 uint8_t uCur = *pb;
265 if (uCur == RTNET_DHCP_OPT_PAD)
266 {
267 cbLeft--;
268 pb++;
269 }
270 else if (cbLeft <= 1)
271 break;
272 else
273 {
274 size_t cbCur = pb[1];
275 if (cbCur > cbLeft - 2)
276 cbCur = cbLeft - 2;
277 if (uCur == uOption)
278 {
279 opt.u8OptId = uCur;
280 memcpy(opt.au8RawOpt, pb+2, cbCur);
281 opt.cbRawOpt = cbCur;
282 return VINF_SUCCESS;
283 }
284 pb += cbCur + 2;
285 cbLeft -= cbCur - 2;
286 }
287 }
288
289 /** @todo search extended dhcp option field(s) when present */
290
291 return VERR_NOT_FOUND;
292}
293
294
295/**
296 * We've find the config for session ...
297 * XXX: using Session's private members
298 */
299int ConfigurationManager::findConfiguration4Session(Session& session)
300{
301 /* XXX: state switching broken?
302 * XXX: DHCPDECLINE and DHCPINFO should we support them.
303 */
304 AssertReturn( session.m_state == DHCPDISCOVERRECEIEVED
305 || session.m_state == DHCPREQUESTRECEIVED, VERR_INTERNAL_ERROR);
306
307 if (session.m_pCfg)
308 return VINF_SUCCESS;
309
310 Assert(session.m_pClient);
311 if (g_RootConfig->match(*session.m_pClient, &session.m_pCfg) > 0)
312 return VINF_SUCCESS;
313 else
314 return VERR_INTERNAL_ERROR; /* XXX: is it really *internal* error? Perhaps some misconfiguration */
315
316}
317
318/**
319 * What we are archieveing here is non commited lease ()
320 */
321int ConfigurationManager::allocateConfiguration4Session(Session& session)
322{
323 /**
324 * Well, session hasn't get the config.
325 */
326 AssertPtrReturn(session.m_pCfg, VERR_INTERNAL_ERROR);
327
328 bool fWithAddressHint = (session.addressHint.u != 0);
329
330 if (fWithAddressHint)
331 {
332 if (m_allocations[session].u == session.addressHint.u)
333 {
334 /* Good, our hint matches allocation */
335 return VINF_SUCCESS;
336 }
337 /**
338 * This definetly depends on client state ...
339 * AssertMsgFailed(("Debug Me"));
340 * Workaround #1
341 * clear and ignore.
342 */
343 fWithAddressHint = false;
344 session.addressHint.u = 0;
345 }
346
347 /*
348 * We've received DHCPDISCOVER
349 */
350 AssertReturn(session.m_state == DHCPDISCOVERRECEIEVED, VERR_INTERNAL_ERROR);
351
352 /**
353 * XXX: this is wrong allocation check...
354 * session initilized by client shouldn't be equal to lease in STL terms.
355 */
356 MapSession2Ip4AddressIterator it = m_allocations.find(session);
357
358 if (it == m_allocations.end())
359 {
360 /* XXX: not optimal allocation */
361 const NetworkConfigEntity *pNetCfg = dynamic_cast<const NetworkConfigEntity *>(session.m_pCfg);
362
363 /**
364 * Check config class.
365 */
366 AssertPtrReturn(pNetCfg, VERR_INTERNAL_ERROR);
367
368 uint32_t u32Address = RT_N2H_U32(pNetCfg->lowerIp().u);
369 while (u32Address < RT_N2H_U32(pNetCfg->upperIp().u))
370 {
371
372 /* u32Address in host format */
373 MapSession2Ip4AddressIterator addressIterator;
374 bool fFound = false;
375
376 for (addressIterator = m_allocations.begin();
377 addressIterator != m_allocations.end();
378 ++addressIterator)
379 {
380 if (RT_N2H_U32(addressIterator->second.u) == u32Address)
381 {
382 /*
383 * This address is taken
384 * XXX: check if session isn't expired... if expired we can
385 * reuse it for this request
386 */
387 /* XXX: fTakeAddress = true; owning session is expired */
388 fFound = true;
389 break;
390 }
391 } /* end of for over allocations */
392
393 if (!fFound)
394 {
395 RTNETADDRIPV4 address = { RT_H2N_U32_C(u32Address)};
396 m_allocations.insert(MapSession2Ip4AddressPair(session, address));
397 session.switchTo(DHCPOFFERPREPARED);
398 return VINF_SUCCESS;
399 }
400
401 u32Address ++;
402 } /* end of while over candidates */
403
404 }
405
406 /* XXX: really??? */
407 session.switchTo(DHCPOFFERPREPARED);
408 return VINF_SUCCESS;
409}
410
411
412int ConfigurationManager::commitConfiguration4ClientSession(Session& session)
413{
414 /**/
415 session.switchTo(DHCPACKNAKPREPARED);
416
417 /* XXX: clean up the rest of the session, now this session LEASE!!! */
418 return VINF_SUCCESS;
419}
420
421RTNETADDRIPV4 ConfigurationManager::getSessionAddress(const Session& session)
422{
423 return m_allocations[session];
424}
425
426
427NetworkConfigEntity *ConfigurationManager::addNetwork(NetworkConfigEntity *pCfg,
428 const RTNETADDRIPV4& networkId,
429 const RTNETADDRIPV4& netmask,
430 RTNETADDRIPV4& LowerAddress,
431 RTNETADDRIPV4& UpperAddress)
432{
433 static int id;
434 char name[64];
435
436 RTStrPrintf(name, RT_ELEMENTS(name), "network-%d", id);
437 std::string strname(name);
438 id++;
439
440
441 if (!LowerAddress.u)
442 LowerAddress = networkId;
443
444 if (!UpperAddress.u)
445 UpperAddress.u = networkId.u | (~netmask.u);
446
447 return new NetworkConfigEntity(strname,
448 g_RootConfig,
449 g_AnyClient,
450 5,
451 networkId,
452 netmask,
453 LowerAddress,
454 UpperAddress);
455}
456
457HostConfigEntity *ConfigurationManager::addHost(NetworkConfigEntity* pCfg,
458 const RTNETADDRIPV4& address,
459 ClientMatchCriteria *criteria)
460{
461 static int id;
462 char name[64];
463
464 RTStrPrintf(name, RT_ELEMENTS(name), "host-%d", id);
465 std::string strname(name);
466 id++;
467
468 return new HostConfigEntity(address, strname, pCfg, criteria);
469}
470
471/**
472 * Network manager
473 */
474NetworkManager *NetworkManager::getNetworkManager()
475{
476 if (!g_NetworkManager)
477 g_NetworkManager = new NetworkManager();
478
479 return g_NetworkManager;
480}
481
482
483/**
484 * Network manager creates DHCPOFFER datagramm
485 */
486int NetworkManager::offer4Session(Session& session)
487{
488 AssertReturn(session.m_state == DHCPOFFERPREPARED, VERR_INTERNAL_ERROR);
489
490 prepareReplyPacket4Session(session);
491
492 RTNETADDRIPV4 address = ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
493 BootPReplyMsg.BootPHeader.bp_yiaddr = address;
494
495 /* Ubuntu ???*/
496 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
497
498 /* options:
499 * - IP lease time
500 * - message type
501 * - server identifier
502 */
503 RawOption opt;
504 RT_ZERO(opt);
505
506 /* XXX: can't store options per session */
507 Client *client = unconst(session.m_pClient);
508 AssertPtr(client);
509
510 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
511 opt.au8RawOpt[0] = RTNET_DHCP_MT_OFFER;
512 opt.cbRawOpt = 1;
513 client->rawOptions.push_back(opt);
514
515 opt.u8OptId = RTNET_DHCP_OPT_SERVER_ID;
516 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = m_OurAddress.u;
517 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
518 client->rawOptions.push_back(opt);
519
520 opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
521 *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(ConfigurationManager::getConfigurationManager()->getLeaseTime());
522 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
523 client->rawOptions.push_back(opt);
524
525 processParameterReqList(session);
526
527 return doReply(session);
528}
529
530
531/**
532 * Network manager creates DHCPACK
533 */
534int NetworkManager::ack(Session& session)
535{
536 RTNETADDRIPV4 address;
537
538 AssertReturn(session.m_state == DHCPACKNAKPREPARED, VERR_INTERNAL_ERROR);
539 prepareReplyPacket4Session(session);
540
541 address = ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
542 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
543
544
545 /* rfc2131 4.3.1 is about DHCPDISCOVER and this value is equal to ciaddr from
546 * DHCPREQUEST or 0 ...
547 * XXX: Using addressHint is not correct way to initialize [cy]iaddress...
548 */
549 BootPReplyMsg.BootPHeader.bp_ciaddr = session.addressHint;
550 BootPReplyMsg.BootPHeader.bp_yiaddr = session.addressHint;
551
552 Assert(BootPReplyMsg.BootPHeader.bp_yiaddr.u);
553
554 /* options:
555 * - IP address lease time (if DHCPREQUEST)
556 * - message type
557 * - server identifier
558 */
559 RawOption opt;
560 RT_ZERO(opt);
561
562 /* XXX: can't store options per session */
563 Client *client = unconst(session.m_pClient);
564 AssertPtr(client);
565
566 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
567 opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK;
568 opt.cbRawOpt = 1;
569 client->rawOptions.push_back(opt);
570
571 processParameterReqList(session);
572
573 return doReply(session);
574
575}
576
577
578/**
579 * Network manager creates DHCPNAK
580 */
581int NetworkManager::nak(Session& session)
582{
583 AssertReturn(session.m_state == DHCPACKNAKPREPARED, VERR_INTERNAL_ERROR);
584
585 prepareReplyPacket4Session(session);
586
587 /* this field filed in prepareReplyPacket4Session, and
588 * RFC 2131 require to have it zero fo NAK.
589 */
590 BootPReplyMsg.BootPHeader.bp_yiaddr.u = 0;
591
592 /* options:
593 * - message type (if DHCPREQUEST)
594 * - server identifier
595 */
596 RawOption opt;
597 RT_ZERO(opt);
598
599 /* XXX: can't store options per session */
600 Client *client = unconst(session.m_pClient);
601 AssertPtr(client);
602
603 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
604 opt.au8RawOpt[0] = RTNET_DHCP_MT_NAC;
605 opt.cbRawOpt = 1;
606 client->rawOptions.push_back(opt);
607
608 return doReply(session);
609}
610
611
612/**
613 *
614 */
615int NetworkManager::prepareReplyPacket4Session(const Session& session)
616{
617 memset(&BootPReplyMsg, 0, sizeof(BootPReplyMsg));
618
619 BootPReplyMsg.BootPHeader.bp_op = RTNETBOOTP_OP_REPLY;
620 BootPReplyMsg.BootPHeader.bp_htype = RTNET_ARP_ETHER;
621 BootPReplyMsg.BootPHeader.bp_hlen = sizeof(RTMAC);
622 BootPReplyMsg.BootPHeader.bp_hops = 0;
623 BootPReplyMsg.BootPHeader.bp_xid = session.m_u32Xid;
624 BootPReplyMsg.BootPHeader.bp_secs = 0;
625 /* XXX: bp_flags should be processed specially */
626 BootPReplyMsg.BootPHeader.bp_flags = 0;
627 BootPReplyMsg.BootPHeader.bp_ciaddr.u = 0;
628 BootPReplyMsg.BootPHeader.bp_giaddr.u = 0;
629
630 Assert(session.m_pClient);
631 BootPReplyMsg.BootPHeader.bp_chaddr.Mac = session.m_pClient->m_mac;
632
633 BootPReplyMsg.BootPHeader.bp_yiaddr =
634 ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
635
636 BootPReplyMsg.BootPHeader.bp_siaddr.u = 0;
637
638
639 BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE);
640
641 memset(&BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_opts[0],
642 '\0',
643 RTNET_DHCP_OPT_SIZE);
644
645 return VINF_SUCCESS;
646}
647
648
649int NetworkManager::doReply(const Session& session)
650{
651 int rc;
652
653 /*
654 Options....
655 */
656 VBoxNetDhcpWriteCursor Cursor(&BootPReplyMsg.BootPHeader, RTNET_DHCP_NORMAL_SIZE);
657
658 /* XXX: unconst */
659 Client *cl = unconst(session.m_pClient);
660 AssertPtrReturn(cl, VERR_INTERNAL_ERROR);
661
662 /* The basics */
663
664 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_OurAddress);
665
666 while(!cl->rawOptions.empty())
667 {
668 RawOption opt = cl->rawOptions.back();
669 if (!Cursor.begin(opt.u8OptId, opt.cbRawOpt))
670 break;
671 Cursor.put(opt.au8RawOpt, opt.cbRawOpt);
672
673 cl->rawOptions.pop_back();
674 }
675
676
677 if (!cl->rawOptions.empty())
678 {
679 Log(("Wasn't able to put all options\n"));
680 /* force clean up */
681 cl->rawOptions.clear();
682 }
683
684 Cursor.optEnd();
685
686 switch (session.m_state)
687 {
688 case DHCPOFFERPREPARED:
689 break;
690 case DHCPACKNAKPREPARED:
691 break;
692 default:
693 AssertMsgFailedReturn(("Unsupported state(%d)\n", session.m_state), VERR_INTERNAL_ERROR);
694 }
695
696 /*
697 */
698#if 0
699 if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */
700 {
701 rc = VBoxNetUDPUnicast(m_pSession,
702 m_hIf,
703 m_pIfBuf,
704 m_OurAddress,
705 &m_OurMac,
706 RTNETIPV4_PORT_BOOTPS, /* sender */
707 IPv4AddrBrdCast,
708 &BootPReplyMsg.BootPHeader->bp_chaddr.Mac,
709 RTNETIPV4_PORT_BOOTPC, /* receiver */
710 &BootPReplyMsg, cbBooPReplyMsg);
711 }
712 else
713#endif
714 rc = VBoxNetUDPBroadcast(m_pSession,
715 m_hIf,
716 m_pIfBuf,
717 m_OurAddress,
718 &m_OurMac,
719 RTNETIPV4_PORT_BOOTPS, /* sender */
720 RTNETIPV4_PORT_BOOTPC,
721 &BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
722
723 AssertRCReturn(rc,rc);
724
725 return VINF_SUCCESS;
726}
727
728
729int NetworkManager::processParameterReqList(Session& session)
730{
731 /* request parameter list */
732 RawOption opt;
733 int idxParam = 0;
734
735 uint8_t *pReqList = session.reqParamList.au8RawOpt;
736
737 const NetworkConfigEntity *pNetCfg = dynamic_cast<const NetworkConfigEntity *>(session.m_pCfg);
738
739 /* XXX: can't store options per session */
740 Client *client = unconst(session.m_pClient);
741 AssertPtr(client);
742
743
744 for (idxParam = 0; idxParam < session.reqParamList.cbRawOpt; ++idxParam)
745 {
746
747 RT_ZERO(opt);
748 opt.u8OptId = pReqList[idxParam];
749 switch(pReqList[idxParam])
750 {
751 case RTNET_DHCP_OPT_SUBNET_MASK:
752 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
753 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
754 client->rawOptions.push_back(opt);
755 break;
756
757 case RTNET_DHCP_OPT_ROUTERS:
758 {
759 const Ipv4AddressContainer lst = g_ConfigurationManager->getAddressList(RTNET_DHCP_OPT_ROUTERS);
760 PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
761
762 for (Ipv4AddressConstIterator it = lst.begin();
763 it != lst.end();
764 ++it)
765 {
766 *pAddresses = (*it);
767 pAddresses++;
768 opt.cbRawOpt += sizeof(RTNETADDRIPV4);
769 }
770
771 if (!lst.empty())
772 client->rawOptions.push_back(opt);
773 }
774 break;
775 case RTNET_DHCP_OPT_DOMAIN_NAME:
776 break;
777 case RTNET_DHCP_OPT_DNS:
778 break;
779 default:
780 Log(("opt: %d is ignored\n", pReqList[idxParam]));
781 break;
782 }
783 }
784
785 return VINF_SUCCESS;
786}
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