VirtualBox

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

最後變更 在這個檔案從49327是 49327,由 vboxsync 提交於 11 年 前

NetworkService/DHCP: refactoring:

  1. Client and Lease are use shared data.
  2. data moved to closer to implementations and accessible via accessors.
  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 26.2 KB
 
1/* $Id: Config.cpp 49327 2013-10-30 04:45:35Z vboxsync $ */
2
3/**
4 * XXX: license.
5 */
6
7#include <iprt/asm.h>
8#include <iprt/net.h>
9#include <iprt/time.h>
10
11#include <VBox/sup.h>
12#include <VBox/intnet.h>
13#include <VBox/intnetinline.h>
14#include <VBox/vmm/vmm.h>
15#include <VBox/version.h>
16
17#include <VBox/com/string.h>
18
19#include <iprt/cpp/xml.h>
20
21#include "../NetLib/VBoxNetLib.h"
22#include "../NetLib/shared_ptr.h"
23
24#include <list>
25#include <vector>
26#include <map>
27#include <string>
28
29#include "Config.h"
30
31/* types */
32class ClientData
33{
34public:
35 ClientData()
36 {
37 m_address.u = 0;
38 m_network.u = 0;
39 fHasLease = false;
40 fHasClient = false;
41 fBinding = true;
42 u64TimestampBindingStarted = 0;
43 u64TimestampLeasingStarted = 0;
44 u32LeaseExpirationPeriod = 0;
45 u32BindExpirationPeriod = 0;
46 pCfg = NULL;
47
48 }
49 ~ClientData(){}
50
51 /* client information */
52 RTNETADDRIPV4 m_address;
53 RTNETADDRIPV4 m_network;
54 RTMAC m_mac;
55
56 bool fHasClient;
57
58 /* Lease part */
59 bool fHasLease;
60 /** lease isn't commited */
61 bool fBinding;
62
63 /** Timestamp when lease commited. */
64 uint64_t u64TimestampLeasingStarted;
65 /** Period when lease is expired in secs. */
66 uint32_t u32LeaseExpirationPeriod;
67
68 /** timestamp when lease was bound */
69 uint64_t u64TimestampBindingStarted;
70 /* Period when binding is expired in secs. */
71 uint32_t u32BindExpirationPeriod;
72
73 MapOptionId2RawOption options;
74
75 NetworkConfigEntity *pCfg;
76};
77
78
79bool operator== (const Lease& lhs, const Lease& rhs)
80{
81 return (lhs.m.get() == rhs.m.get());
82}
83
84
85bool operator!= (const Lease& lhs, const Lease& rhs)
86{
87 return !(lhs == rhs);
88}
89
90
91bool operator< (const Lease& lhs, const Lease& rhs)
92{
93 return ( (lhs.getAddress() < rhs.getAddress())
94 || (lhs.issued() < rhs.issued()));
95}
96/* consts */
97
98const NullConfigEntity *g_NullConfig = new NullConfigEntity();
99RootConfigEntity *g_RootConfig = new RootConfigEntity(std::string("ROOT"), 1200 /* 20 min. */);
100const ClientMatchCriteria *g_AnyClient = new AnyClientMatchCriteria();
101
102static ConfigurationManager *g_ConfigurationManager = ConfigurationManager::getConfigurationManager();
103
104static NetworkManager *g_NetworkManager = NetworkManager::getNetworkManager();
105
106int BaseConfigEntity::match(Client& client, BaseConfigEntity **cfg)
107{
108 int iMatch = (m_criteria && m_criteria->check(client)? m_MatchLevel: 0);
109 if (m_children.empty())
110 {
111 if (iMatch > 0)
112 {
113 *cfg = this;
114 return iMatch;
115 }
116 }
117 else
118 {
119 *cfg = this;
120 /* XXX: hack */
121 BaseConfigEntity *matching = this;
122 int matchingLevel = m_MatchLevel;
123
124 for (std::vector<BaseConfigEntity *>::iterator it = m_children.begin();
125 it != m_children.end();
126 ++it)
127 {
128 iMatch = (*it)->match(client, &matching);
129 if (iMatch > matchingLevel)
130 {
131 *cfg = matching;
132 matchingLevel = iMatch;
133 }
134 }
135 return matchingLevel;
136 }
137 return iMatch;
138}
139
140/* Client */
141/* Configs
142 NetworkConfigEntity(std::string name,
143 ConfigEntity* pCfg,
144 ClientMatchCriteria* criteria,
145 RTNETADDRIPV4& networkID,
146 RTNETADDRIPV4& networkMask)
147*/
148static const RTNETADDRIPV4 g_AnyIpv4 = {0};
149static const RTNETADDRIPV4 g_AllIpv4 = {0xffffffff};
150RootConfigEntity::RootConfigEntity(std::string name, uint32_t expPeriod):
151 NetworkConfigEntity(name, g_NullConfig, g_AnyClient, g_AnyIpv4, g_AllIpv4)
152{
153 m_MatchLevel = 2;
154 m_u32ExpirationPeriod = expPeriod;
155}
156
157/* Configuration Manager */
158struct ConfigurationManager::Data
159{
160 Data():fFileExists(false){}
161
162 MapLease2Ip4Address m_allocations;
163 Ipv4AddressContainer m_nameservers;
164 Ipv4AddressContainer m_routers;
165
166 std::string m_domainName;
167 VecClient m_clients;
168
169 bool fFileExists;
170};
171
172ConfigurationManager *ConfigurationManager::getConfigurationManager()
173{
174 if (!g_ConfigurationManager)
175 {
176 g_ConfigurationManager = new ConfigurationManager();
177 g_ConfigurationManager->init();
178 }
179
180 return g_ConfigurationManager;
181}
182
183
184int ConfigurationManager::extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt)
185{
186 return ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, rawOpt);
187}
188
189
190Client ConfigurationManager::getClientByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg)
191{
192
193 VecClientIterator it;
194 bool fDhcpValid = false;
195 uint8_t uMsgType = 0;
196
197 fDhcpValid = RTNetIPv4IsDHCPValid(NULL, pDhcpMsg, cbDhcpMsg, &uMsgType);
198 AssertReturn(fDhcpValid, Client::NullClient);
199
200 LogFlowFunc(("dhcp:mac:%RTmac\n", &pDhcpMsg->bp_chaddr.Mac));
201 /* 1st. client IDs */
202 for ( it = m->m_clients.begin();
203 it != m->m_clients.end();
204 ++it)
205 {
206 if ((*it) == pDhcpMsg->bp_chaddr.Mac)
207 {
208 LogFlowFunc(("client:mac:%RTmac\n", it->getMacAddress()));
209 /* check timestamp that request wasn't expired. */
210 return (*it);
211 }
212 }
213
214 if (it == m->m_clients.end())
215 {
216 /* We hasn't got any session for this client */
217 Client c;
218 c.initWithMac(pDhcpMsg->bp_chaddr.Mac);
219 m->m_clients.push_back(c);
220 return m->m_clients.back();
221 }
222
223 return Client::NullClient;
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 bind lease for client till it continue with it on DHCPREQUEST.
297 */
298Lease ConfigurationManager::allocateLease4Client(const Client& client, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg)
299{
300 {
301 /**
302 * This mean that client has already bound or commited lease.
303 * If we've it happens it means that we received DHCPDISCOVER twice.
304 */
305 const Lease l = client.lease();
306 if (l != Lease::NullLease)
307 {
308 /* Here we should take lease from the m_allocation which was feed with leases
309 * on start
310 */
311 if (l.isExpired())
312 {
313 expireLease4Client(const_cast<Client&>(client));
314 if (!l.isExpired())
315 return l;
316 }
317 else
318 {
319 AssertReturn(l.getAddress().u != 0, Lease::NullLease);
320 return l;
321 }
322 }
323 }
324
325 RTNETADDRIPV4 hintAddress;
326 RawOption opt;
327 NetworkConfigEntity *pNetCfg;
328
329 Client cl(client);
330 AssertReturn(g_RootConfig->match(cl, (BaseConfigEntity **)&pNetCfg) > 0, Lease::NullLease);
331
332 /* DHCPDISCOVER MAY contain request address */
333 hintAddress.u = 0;
334 int rc = findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
335 if (RT_SUCCESS(rc))
336 {
337 hintAddress.u = *(uint32_t *)opt.au8RawOpt;
338 if ( RT_H2N_U32(hintAddress.u) < RT_H2N_U32(pNetCfg->lowerIp().u)
339 || RT_H2N_U32(hintAddress.u) > RT_H2N_U32(pNetCfg->upperIp().u))
340 hintAddress.u = 0; /* clear hint */
341 }
342
343 if ( hintAddress.u
344 && !isAddressTaken(hintAddress))
345 {
346 Lease l(cl);
347 l.setConfig(pNetCfg);
348 l.setAddress(hintAddress);
349 m->m_allocations.insert(MapLease2Ip4AddressPair(l, hintAddress));
350 return l;
351 }
352
353 uint32_t u32 = 0;
354 for(u32 = RT_H2N_U32(pNetCfg->lowerIp().u);
355 u32 <= RT_H2N_U32(pNetCfg->upperIp().u);
356 ++u32)
357 {
358 RTNETADDRIPV4 address;
359 address.u = RT_H2N_U32(u32);
360 if (!isAddressTaken(address))
361 {
362 Lease l(cl);
363 l.setConfig(pNetCfg);
364 l.setAddress(address);
365 m->m_allocations.insert(MapLease2Ip4AddressPair(l, address));
366 return l;
367 }
368 }
369
370 return Lease::NullLease;
371}
372
373
374int ConfigurationManager::commitLease4Client(Client& client)
375{
376 Lease l = client.lease();
377 AssertReturn(l != Lease::NullLease, VERR_INTERNAL_ERROR);
378
379 l.bindingPhase(false);
380 const NetworkConfigEntity *pCfg = l.getConfig();
381
382 AssertPtr(pCfg);
383 l.setExpiration(pCfg->expirationPeriod());
384 l.phaseStart(RTTimeMilliTS());
385
386 return VINF_SUCCESS;
387}
388
389int ConfigurationManager::expireLease4Client(Client& client)
390{
391 Lease l = client.lease();
392 AssertReturn(l != Lease::NullLease, VERR_INTERNAL_ERROR);
393
394 if (l.isInBindingPhase())
395 {
396
397 MapLease2Ip4AddressIterator it = m->m_allocations.find(l);
398 AssertReturn(it != m->m_allocations.end(), VERR_NOT_FOUND);
399
400 /*
401 * XXX: perhaps it better to keep this allocation ????
402 */
403 m->m_allocations.erase(it);
404
405 l.expire();
406 return VINF_SUCCESS;
407 }
408
409 l = Lease(client); /* re-new */
410 return VINF_SUCCESS;
411}
412
413bool ConfigurationManager::isAddressTaken(const RTNETADDRIPV4& addr, Lease& lease)
414{
415 MapLease2Ip4AddressIterator it;
416
417 for (it = m->m_allocations.begin();
418 it != m->m_allocations.end();
419 ++it)
420 {
421 if (it->second.u == addr.u)
422 {
423 if (lease != Lease::NullLease)
424 lease = it->first;
425
426 return true;
427 }
428 }
429 lease = Lease::NullLease;
430 return false;
431}
432
433
434NetworkConfigEntity *ConfigurationManager::addNetwork(NetworkConfigEntity *,
435 const RTNETADDRIPV4& networkId,
436 const RTNETADDRIPV4& netmask,
437 RTNETADDRIPV4& LowerAddress,
438 RTNETADDRIPV4& UpperAddress)
439{
440 static int id;
441 char name[64];
442
443 RTStrPrintf(name, RT_ELEMENTS(name), "network-%d", id);
444 std::string strname(name);
445 id++;
446
447
448 if (!LowerAddress.u)
449 LowerAddress = networkId;
450
451 if (!UpperAddress.u)
452 UpperAddress.u = networkId.u | (~netmask.u);
453
454 return new NetworkConfigEntity(strname,
455 g_RootConfig,
456 g_AnyClient,
457 5,
458 networkId,
459 netmask,
460 LowerAddress,
461 UpperAddress);
462}
463
464HostConfigEntity *ConfigurationManager::addHost(NetworkConfigEntity* pCfg,
465 const RTNETADDRIPV4& address,
466 ClientMatchCriteria *criteria)
467{
468 static int id;
469 char name[64];
470
471 RTStrPrintf(name, RT_ELEMENTS(name), "host-%d", id);
472 std::string strname(name);
473 id++;
474
475 return new HostConfigEntity(address, strname, pCfg, criteria);
476}
477
478int ConfigurationManager::addToAddressList(uint8_t u8OptId, RTNETADDRIPV4& address)
479{
480 switch(u8OptId)
481 {
482 case RTNET_DHCP_OPT_DNS:
483 m->m_nameservers.push_back(address);
484 break;
485 case RTNET_DHCP_OPT_ROUTERS:
486 m->m_routers.push_back(address);
487 break;
488 default:
489 Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
490 }
491 return VINF_SUCCESS;
492}
493
494
495int ConfigurationManager::flushAddressList(uint8_t u8OptId)
496{
497 switch(u8OptId)
498 {
499 case RTNET_DHCP_OPT_DNS:
500 m->m_nameservers.clear();
501 break;
502 case RTNET_DHCP_OPT_ROUTERS:
503 m->m_routers.clear();
504 break;
505 default:
506 Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
507 }
508 return VINF_SUCCESS;
509}
510
511
512const Ipv4AddressContainer& ConfigurationManager::getAddressList(uint8_t u8OptId)
513{
514 switch(u8OptId)
515 {
516 case RTNET_DHCP_OPT_DNS:
517 return m->m_nameservers;
518
519 case RTNET_DHCP_OPT_ROUTERS:
520 return m->m_routers;
521
522 }
523 /* XXX: Grrr !!! */
524 return m_empty;
525}
526
527
528int ConfigurationManager::setString(uint8_t u8OptId, const std::string& str)
529{
530 switch (u8OptId)
531 {
532 case RTNET_DHCP_OPT_DOMAIN_NAME:
533 m->m_domainName = str;
534 break;
535 default:
536 break;
537 }
538
539 return VINF_SUCCESS;
540}
541
542
543const std::string& ConfigurationManager::getString(uint8_t u8OptId)
544{
545 switch (u8OptId)
546 {
547 case RTNET_DHCP_OPT_DOMAIN_NAME:
548 if (m->m_domainName.length())
549 return m->m_domainName;
550 else
551 return m_noString;
552 default:
553 break;
554 }
555
556 return m_noString;
557}
558
559
560void ConfigurationManager::init()
561{
562 m = new ConfigurationManager::Data();
563}
564
565
566ConfigurationManager::~ConfigurationManager() { if (m) delete m; }
567
568/**
569 * Network manager
570 */
571NetworkManager *NetworkManager::getNetworkManager()
572{
573 if (!g_NetworkManager)
574 g_NetworkManager = new NetworkManager();
575
576 return g_NetworkManager;
577}
578
579
580/**
581 * Network manager creates DHCPOFFER datagramm
582 */
583int NetworkManager::offer4Client(const Client& client, uint32_t u32Xid,
584 uint8_t *pu8ReqList, int cReqList)
585{
586 Lease l(client); /* XXX: oh, it looks badly, but now we have lease */
587 prepareReplyPacket4Client(client, u32Xid);
588
589 RTNETADDRIPV4 address = l.getAddress();
590 BootPReplyMsg.BootPHeader.bp_yiaddr = address;
591
592 /* Ubuntu ???*/
593 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
594
595 /* options:
596 * - IP lease time
597 * - message type
598 * - server identifier
599 */
600 RawOption opt;
601 RT_ZERO(opt);
602
603 std::vector<RawOption> extra(2);
604 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
605 opt.au8RawOpt[0] = RTNET_DHCP_MT_OFFER;
606 opt.cbRawOpt = 1;
607 extra.push_back(opt);
608
609 opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
610
611 const NetworkConfigEntity *pCfg = l.getConfig();
612 AssertPtr(pCfg);
613
614 *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(pCfg->expirationPeriod());
615 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
616
617 extra.push_back(opt);
618
619 processParameterReqList(client, pu8ReqList, cReqList);
620
621 return doReply(client, extra);
622}
623
624
625/**
626 * Network manager creates DHCPACK
627 */
628int NetworkManager::ack(const Client& client, uint32_t u32Xid,
629 uint8_t *pu8ReqList, int cReqList)
630{
631 RTNETADDRIPV4 address;
632
633 prepareReplyPacket4Client(client, u32Xid);
634
635 Lease l = client.lease();
636 address = l.getAddress();
637 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
638
639
640 /* rfc2131 4.3.1 is about DHCPDISCOVER and this value is equal to ciaddr from
641 * DHCPREQUEST or 0 ...
642 * XXX: Using addressHint is not correct way to initialize [cy]iaddress...
643 */
644 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
645 BootPReplyMsg.BootPHeader.bp_yiaddr = address;
646
647 Assert(BootPReplyMsg.BootPHeader.bp_yiaddr.u);
648
649 /* options:
650 * - IP address lease time (if DHCPREQUEST)
651 * - message type
652 * - server identifier
653 */
654 RawOption opt;
655 RT_ZERO(opt);
656
657 std::vector<RawOption> extra(2);
658 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
659 opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK;
660 opt.cbRawOpt = 1;
661 extra.push_back(opt);
662
663 /*
664 * XXX: lease time should be conditional. If on dhcprequest then tim should be provided,
665 * else on dhcpinform it mustn't.
666 */
667 opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
668 *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(l.getExpiration());
669 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
670 extra.push_back(opt);
671
672 processParameterReqList(client, pu8ReqList, cReqList);
673
674 return doReply(client, extra);
675}
676
677
678/**
679 * Network manager creates DHCPNAK
680 */
681int NetworkManager::nak(const Client& client, uint32_t u32Xid)
682{
683
684 Lease l = client.lease();
685 if (l == Lease::NullLease)
686 return VERR_INTERNAL_ERROR;
687
688 prepareReplyPacket4Client(client, u32Xid);
689
690 /* this field filed in prepareReplyPacket4Session, and
691 * RFC 2131 require to have it zero fo NAK.
692 */
693 BootPReplyMsg.BootPHeader.bp_yiaddr.u = 0;
694
695 /* options:
696 * - message type (if DHCPREQUEST)
697 * - server identifier
698 */
699 RawOption opt;
700 std::vector<RawOption> extra;
701
702 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
703 opt.au8RawOpt[0] = RTNET_DHCP_MT_NAC;
704 opt.cbRawOpt = 1;
705 extra.push_back(opt);
706
707 return doReply(client, extra);
708}
709
710
711/**
712 *
713 */
714int NetworkManager::prepareReplyPacket4Client(const Client& client, uint32_t u32Xid)
715{
716 memset(&BootPReplyMsg, 0, sizeof(BootPReplyMsg));
717
718 BootPReplyMsg.BootPHeader.bp_op = RTNETBOOTP_OP_REPLY;
719 BootPReplyMsg.BootPHeader.bp_htype = RTNET_ARP_ETHER;
720 BootPReplyMsg.BootPHeader.bp_hlen = sizeof(RTMAC);
721 BootPReplyMsg.BootPHeader.bp_hops = 0;
722 BootPReplyMsg.BootPHeader.bp_xid = u32Xid;
723 BootPReplyMsg.BootPHeader.bp_secs = 0;
724 /* XXX: bp_flags should be processed specially */
725 BootPReplyMsg.BootPHeader.bp_flags = 0;
726 BootPReplyMsg.BootPHeader.bp_ciaddr.u = 0;
727 BootPReplyMsg.BootPHeader.bp_giaddr.u = 0;
728
729 BootPReplyMsg.BootPHeader.bp_chaddr.Mac = client.getMacAddress();
730
731 const Lease l = client.lease();
732 BootPReplyMsg.BootPHeader.bp_yiaddr = l.getAddress();
733 BootPReplyMsg.BootPHeader.bp_siaddr.u = 0;
734
735
736 BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE);
737
738 memset(&BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_opts[0],
739 '\0',
740 RTNET_DHCP_OPT_SIZE);
741
742 return VINF_SUCCESS;
743}
744
745
746int NetworkManager::doReply(const Client& client, const std::vector<RawOption>& extra)
747{
748 int rc;
749
750 /*
751 Options....
752 */
753 VBoxNetDhcpWriteCursor Cursor(&BootPReplyMsg.BootPHeader, RTNET_DHCP_NORMAL_SIZE);
754
755 /* The basics */
756
757 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_OurAddress);
758
759 const Lease l = client.lease();
760 const std::map<uint8_t, RawOption>& options = l.options();
761
762 for(std::vector<RawOption>::const_iterator it = extra.begin();
763 it != extra.end(); ++it)
764 {
765 if (!Cursor.begin(it->u8OptId, it->cbRawOpt))
766 break;
767 Cursor.put(it->au8RawOpt, it->cbRawOpt);
768
769 }
770
771 for(std::map<uint8_t, RawOption>::const_iterator it = options.begin();
772 it != options.end(); ++it)
773 {
774 if (!Cursor.begin(it->second.u8OptId, it->second.cbRawOpt))
775 break;
776 Cursor.put(it->second.au8RawOpt, it->second.cbRawOpt);
777
778 }
779
780 Cursor.optEnd();
781
782 /*
783 */
784#if 0
785 /** @todo need to see someone set this flag to check that it's correct. */
786 if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST))
787 {
788 rc = VBoxNetUDPUnicast(m_pSession,
789 m_hIf,
790 m_pIfBuf,
791 m_OurAddress,
792 &m_OurMac,
793 RTNETIPV4_PORT_BOOTPS, /* sender */
794 IPv4AddrBrdCast,
795 &BootPReplyMsg.BootPHeader->bp_chaddr.Mac,
796 RTNETIPV4_PORT_BOOTPC, /* receiver */
797 &BootPReplyMsg, cbBooPReplyMsg);
798 }
799 else
800#endif
801 rc = VBoxNetUDPBroadcast(m_pSession,
802 m_hIf,
803 m_pIfBuf,
804 m_OurAddress,
805 &m_OurMac,
806 RTNETIPV4_PORT_BOOTPS, /* sender */
807 RTNETIPV4_PORT_BOOTPC,
808 &BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
809
810 AssertRCReturn(rc,rc);
811
812 return VINF_SUCCESS;
813}
814
815
816int NetworkManager::processParameterReqList(const Client& client, uint8_t *pu8ReqList, int cReqList)
817{
818 /* request parameter list */
819 RawOption opt;
820 int idxParam = 0;
821
822 uint8_t *pReqList = pu8ReqList;
823
824 const Lease const_l = client.lease();
825 Lease l = Lease(const_l);
826
827 const NetworkConfigEntity *pNetCfg = l.getConfig();
828
829 for (idxParam = 0; idxParam < cReqList; ++idxParam)
830 {
831
832 bool fIgnore = false;
833 RT_ZERO(opt);
834 opt.u8OptId = pReqList[idxParam];
835
836 switch(pReqList[idxParam])
837 {
838 case RTNET_DHCP_OPT_SUBNET_MASK:
839 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
840 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
841
842 break;
843
844 case RTNET_DHCP_OPT_ROUTERS:
845 case RTNET_DHCP_OPT_DNS:
846 {
847 const Ipv4AddressContainer lst =
848 g_ConfigurationManager->getAddressList(pReqList[idxParam]);
849 PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
850
851 for (Ipv4AddressConstIterator it = lst.begin();
852 it != lst.end();
853 ++it)
854 {
855 *pAddresses = (*it);
856 pAddresses++;
857 opt.cbRawOpt += sizeof(RTNETADDRIPV4);
858 }
859
860 if (lst.empty())
861 fIgnore = true;
862 }
863 break;
864 case RTNET_DHCP_OPT_DOMAIN_NAME:
865 {
866 std::string domainName = g_ConfigurationManager->getString(pReqList[idxParam]);
867 if (domainName == g_ConfigurationManager->m_noString)
868 {
869 fIgnore = true;
870 break;
871 }
872
873 char *pszDomainName = (char *)&opt.au8RawOpt[0];
874
875 strcpy(pszDomainName, domainName.c_str());
876 opt.cbRawOpt = domainName.length();
877 }
878 break;
879 default:
880 Log(("opt: %d is ignored\n", pReqList[idxParam]));
881 fIgnore = true;
882 break;
883 }
884
885 if (!fIgnore)
886 l.options().insert(std::map<uint8_t, RawOption>::value_type(opt.u8OptId, opt));
887
888 }
889
890 return VINF_SUCCESS;
891}
892
893/* Utility */
894bool operator== (const RTMAC& lhs, const RTMAC& rhs)
895{
896 return ( lhs.au16[0] == rhs.au16[0]
897 && lhs.au16[1] == rhs.au16[1]
898 && lhs.au16[2] == rhs.au16[2]);
899}
900
901
902/* Client */
903Client::Client()
904{
905 m = SharedPtr<ClientData>();
906}
907
908
909void Client::initWithMac(const RTMAC& mac)
910{
911 m = SharedPtr<ClientData>(new ClientData());
912 m->m_mac = mac;
913}
914
915
916bool Client::operator== (const RTMAC& mac) const
917{
918 return (m.get() && m->m_mac == mac);
919}
920
921
922const RTMAC& Client::getMacAddress() const
923{
924 return m->m_mac;
925}
926
927
928Lease Client::lease()
929{
930 if (!m.get()) return Lease::NullLease;
931
932 if (m->fHasLease)
933 return Lease(*this);
934 else
935 return Lease::NullLease;
936}
937
938
939const Lease Client::lease() const
940{
941 return const_cast<Client *>(this)->lease();
942}
943
944
945Client::Client(ClientData *data):m(SharedPtr<ClientData>(data)){}
946
947/* Lease */
948Lease::Lease()
949{
950 m = SharedPtr<ClientData>();
951}
952
953
954Lease::Lease (const Client& c)
955{
956 m = SharedPtr<ClientData>(c.m);
957 if ( !m->fHasLease
958 || ( isExpired()
959 && !isInBindingPhase()))
960 {
961 m->fHasLease = true;
962 m->fBinding = true;
963 phaseStart(RTTimeMilliTS());
964 }
965}
966
967
968bool Lease::isExpired() const
969{
970 AssertPtrReturn(m.get(), false);
971
972 if (!m->fBinding)
973 return (ASMDivU64ByU32RetU32(RTTimeMilliTS() - m->u64TimestampLeasingStarted, 1000)
974 > m->u32LeaseExpirationPeriod);
975 else
976 return (ASMDivU64ByU32RetU32(RTTimeMilliTS() - m->u64TimestampBindingStarted, 1000)
977 > m->u32BindExpirationPeriod);
978}
979
980
981void Lease::expire()
982{
983 /* XXX: TODO */
984}
985
986
987void Lease::phaseStart(uint64_t u64Start)
988{
989 if (m->fBinding)
990 m->u64TimestampBindingStarted = u64Start;
991 else
992 m->u64TimestampLeasingStarted = u64Start;
993}
994
995
996void Lease::bindingPhase(bool fOnOff)
997{
998 m->fBinding = fOnOff;
999}
1000
1001
1002bool Lease::isInBindingPhase() const
1003{
1004 return m->fBinding;
1005}
1006
1007
1008uint64_t Lease::issued() const
1009{
1010 return m->u64TimestampLeasingStarted;
1011}
1012
1013
1014void Lease::setExpiration(uint32_t exp)
1015{
1016 if (m->fBinding)
1017 m->u32BindExpirationPeriod = exp;
1018 else
1019 m->u32LeaseExpirationPeriod = exp;
1020}
1021
1022
1023uint32_t Lease::getExpiration() const
1024{
1025 if (m->fBinding)
1026 return m->u32BindExpirationPeriod;
1027 else
1028 return m->u32LeaseExpirationPeriod;
1029}
1030
1031
1032RTNETADDRIPV4 Lease::getAddress() const
1033{
1034 return m->m_address;
1035}
1036
1037
1038void Lease::setAddress(RTNETADDRIPV4 address)
1039{
1040 m->m_address = address;
1041}
1042
1043
1044const NetworkConfigEntity *Lease::getConfig() const
1045{
1046 return m->pCfg;
1047}
1048
1049
1050void Lease::setConfig(NetworkConfigEntity *pCfg)
1051{
1052 m->pCfg = pCfg;
1053}
1054
1055
1056const MapOptionId2RawOption& Lease::options() const
1057{
1058 return m->options;
1059}
1060
1061
1062MapOptionId2RawOption& Lease::options()
1063{
1064 return m->options;
1065}
1066
1067
1068Lease::Lease(ClientData *pd):m(SharedPtr<ClientData>(pd)){}
1069
1070
1071const Lease Lease::NullLease;
1072
1073
1074const Client Client::NullClient;
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette