VirtualBox

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

Last change on this file since 47308 was 47129, checked in by vboxsync, 12 years ago

VBoxNetDHCP: cosmetics.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.8 KB
Line 
1/* $Id: Config.cpp 47129 2013-07-13 11:44:12Z 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_LEASE_TIME;
516 *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(ConfigurationManager::getConfigurationManager()->getLeaseTime());
517 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
518 client->rawOptions.push_back(opt);
519
520 processParameterReqList(session);
521
522 return doReply(session);
523}
524
525
526/**
527 * Network manager creates DHCPACK
528 */
529int NetworkManager::ack(Session& session)
530{
531 RTNETADDRIPV4 address;
532
533 AssertReturn(session.m_state == DHCPACKNAKPREPARED, VERR_INTERNAL_ERROR);
534 prepareReplyPacket4Session(session);
535
536 address = ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
537 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
538
539
540 /* rfc2131 4.3.1 is about DHCPDISCOVER and this value is equal to ciaddr from
541 * DHCPREQUEST or 0 ...
542 * XXX: Using addressHint is not correct way to initialize [cy]iaddress...
543 */
544 BootPReplyMsg.BootPHeader.bp_ciaddr = session.addressHint;
545 BootPReplyMsg.BootPHeader.bp_yiaddr = session.addressHint;
546
547 Assert(BootPReplyMsg.BootPHeader.bp_yiaddr.u);
548
549 /* options:
550 * - IP address lease time (if DHCPREQUEST)
551 * - message type
552 * - server identifier
553 */
554 RawOption opt;
555 RT_ZERO(opt);
556
557 /* XXX: can't store options per session */
558 Client *client = unconst(session.m_pClient);
559 AssertPtr(client);
560
561 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
562 opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK;
563 opt.cbRawOpt = 1;
564 client->rawOptions.push_back(opt);
565
566 /*
567 * XXX: lease time should be conditional. If on dhcprequest then tim should be provided,
568 * else on dhcpinform it mustn't.
569 */
570 opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
571 *(uint32_t *)opt.au8RawOpt =
572 RT_H2N_U32(ConfigurationManager::getConfigurationManager()->getLeaseTime());
573 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
574 client->rawOptions.push_back(opt);
575
576 processParameterReqList(session);
577
578 return doReply(session);
579
580}
581
582
583/**
584 * Network manager creates DHCPNAK
585 */
586int NetworkManager::nak(Session& session)
587{
588 AssertReturn(session.m_state == DHCPACKNAKPREPARED, VERR_INTERNAL_ERROR);
589
590 prepareReplyPacket4Session(session);
591
592 /* this field filed in prepareReplyPacket4Session, and
593 * RFC 2131 require to have it zero fo NAK.
594 */
595 BootPReplyMsg.BootPHeader.bp_yiaddr.u = 0;
596
597 /* options:
598 * - message type (if DHCPREQUEST)
599 * - server identifier
600 */
601 RawOption opt;
602 RT_ZERO(opt);
603
604 /* XXX: can't store options per session */
605 Client *client = unconst(session.m_pClient);
606 AssertPtr(client);
607
608 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
609 opt.au8RawOpt[0] = RTNET_DHCP_MT_NAC;
610 opt.cbRawOpt = 1;
611 client->rawOptions.push_back(opt);
612
613 return doReply(session);
614}
615
616
617/**
618 *
619 */
620int NetworkManager::prepareReplyPacket4Session(const Session& session)
621{
622 memset(&BootPReplyMsg, 0, sizeof(BootPReplyMsg));
623
624 BootPReplyMsg.BootPHeader.bp_op = RTNETBOOTP_OP_REPLY;
625 BootPReplyMsg.BootPHeader.bp_htype = RTNET_ARP_ETHER;
626 BootPReplyMsg.BootPHeader.bp_hlen = sizeof(RTMAC);
627 BootPReplyMsg.BootPHeader.bp_hops = 0;
628 BootPReplyMsg.BootPHeader.bp_xid = session.m_u32Xid;
629 BootPReplyMsg.BootPHeader.bp_secs = 0;
630 /* XXX: bp_flags should be processed specially */
631 BootPReplyMsg.BootPHeader.bp_flags = 0;
632 BootPReplyMsg.BootPHeader.bp_ciaddr.u = 0;
633 BootPReplyMsg.BootPHeader.bp_giaddr.u = 0;
634
635 Assert(session.m_pClient);
636 BootPReplyMsg.BootPHeader.bp_chaddr.Mac = session.m_pClient->m_mac;
637
638 BootPReplyMsg.BootPHeader.bp_yiaddr =
639 ConfigurationManager::getConfigurationManager()->getSessionAddress(session);
640
641 BootPReplyMsg.BootPHeader.bp_siaddr.u = 0;
642
643
644 BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE);
645
646 memset(&BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_opts[0],
647 '\0',
648 RTNET_DHCP_OPT_SIZE);
649
650 return VINF_SUCCESS;
651}
652
653
654int NetworkManager::doReply(const Session& session)
655{
656 int rc;
657
658 /*
659 Options....
660 */
661 VBoxNetDhcpWriteCursor Cursor(&BootPReplyMsg.BootPHeader, RTNET_DHCP_NORMAL_SIZE);
662
663 /* XXX: unconst */
664 Client *cl = unconst(session.m_pClient);
665 AssertPtrReturn(cl, VERR_INTERNAL_ERROR);
666
667 /* The basics */
668
669 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_OurAddress);
670
671 while(!cl->rawOptions.empty())
672 {
673 RawOption opt = cl->rawOptions.back();
674 if (!Cursor.begin(opt.u8OptId, opt.cbRawOpt))
675 break;
676 Cursor.put(opt.au8RawOpt, opt.cbRawOpt);
677
678 cl->rawOptions.pop_back();
679 }
680
681
682 if (!cl->rawOptions.empty())
683 {
684 Log(("Wasn't able to put all options\n"));
685 /* force clean up */
686 cl->rawOptions.clear();
687 }
688
689 Cursor.optEnd();
690
691 switch (session.m_state)
692 {
693 case DHCPOFFERPREPARED:
694 break;
695 case DHCPACKNAKPREPARED:
696 break;
697 default:
698 AssertMsgFailedReturn(("Unsupported state(%d)\n", session.m_state), VERR_INTERNAL_ERROR);
699 }
700
701 /*
702 */
703#if 0
704 if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */
705 {
706 rc = VBoxNetUDPUnicast(m_pSession,
707 m_hIf,
708 m_pIfBuf,
709 m_OurAddress,
710 &m_OurMac,
711 RTNETIPV4_PORT_BOOTPS, /* sender */
712 IPv4AddrBrdCast,
713 &BootPReplyMsg.BootPHeader->bp_chaddr.Mac,
714 RTNETIPV4_PORT_BOOTPC, /* receiver */
715 &BootPReplyMsg, cbBooPReplyMsg);
716 }
717 else
718#endif
719 rc = VBoxNetUDPBroadcast(m_pSession,
720 m_hIf,
721 m_pIfBuf,
722 m_OurAddress,
723 &m_OurMac,
724 RTNETIPV4_PORT_BOOTPS, /* sender */
725 RTNETIPV4_PORT_BOOTPC,
726 &BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
727
728 AssertRCReturn(rc,rc);
729
730 return VINF_SUCCESS;
731}
732
733
734int NetworkManager::processParameterReqList(Session& session)
735{
736 /* request parameter list */
737 RawOption opt;
738 int idxParam = 0;
739
740 uint8_t *pReqList = session.reqParamList.au8RawOpt;
741
742 const NetworkConfigEntity *pNetCfg = dynamic_cast<const NetworkConfigEntity *>(session.m_pCfg);
743
744 /* XXX: can't store options per session */
745 Client *client = unconst(session.m_pClient);
746 AssertPtr(client);
747
748
749 for (idxParam = 0; idxParam < session.reqParamList.cbRawOpt; ++idxParam)
750 {
751
752 RT_ZERO(opt);
753 opt.u8OptId = pReqList[idxParam];
754 switch(pReqList[idxParam])
755 {
756 case RTNET_DHCP_OPT_SUBNET_MASK:
757 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
758 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
759 client->rawOptions.push_back(opt);
760 break;
761
762 case RTNET_DHCP_OPT_ROUTERS:
763 {
764 const Ipv4AddressContainer lst = g_ConfigurationManager->getAddressList(RTNET_DHCP_OPT_ROUTERS);
765 PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
766
767 for (Ipv4AddressConstIterator it = lst.begin();
768 it != lst.end();
769 ++it)
770 {
771 *pAddresses = (*it);
772 pAddresses++;
773 opt.cbRawOpt += sizeof(RTNETADDRIPV4);
774 }
775
776 if (!lst.empty())
777 client->rawOptions.push_back(opt);
778 }
779 break;
780 case RTNET_DHCP_OPT_DOMAIN_NAME:
781 break;
782 case RTNET_DHCP_OPT_DNS:
783 break;
784 default:
785 Log(("opt: %d is ignored\n", pReqList[idxParam]));
786 break;
787 }
788 }
789
790 return VINF_SUCCESS;
791}
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