VirtualBox

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

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

NetworkServices: Whitespace (including tabs!) and svn:keywords cleanups by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 KB
Line 
1/* $Id: Config.cpp 48956 2013-10-07 22:00:27Z 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();
38RootConfigEntity *g_RootConfig = new RootConfigEntity(std::string("ROOT"), 1200 /* 20 min. */);
39const ClientMatchCriteria *g_AnyClient = new AnyClientMatchCriteria();
40
41static ConfigurationManager *g_ConfigurationManager = ConfigurationManager::getConfigurationManager();
42
43static NetworkManager *g_NetworkManager = NetworkManager::getNetworkManager();
44
45int BaseConfigEntity::match(Client& client, BaseConfigEntity **cfg)
46{
47 int iMatch = (m_criteria && m_criteria->check(client)? m_MatchLevel: 0);
48 if (m_children.empty())
49 {
50 if (iMatch > 0)
51 {
52 *cfg = this;
53 return iMatch;
54 }
55 }
56 else
57 {
58 *cfg = this;
59 /* XXX: hack */
60 BaseConfigEntity *matching = this;
61 int matchingLevel = m_MatchLevel;
62
63 for (std::vector<BaseConfigEntity *>::iterator it = m_children.begin();
64 it != m_children.end();
65 ++it)
66 {
67 iMatch = (*it)->match(client, &matching);
68 if (iMatch > matchingLevel)
69 {
70 *cfg = matching;
71 matchingLevel = iMatch;
72 }
73 }
74 return matchingLevel;
75 }
76 return iMatch;
77}
78
79/* Client */
80
81Client::Client(const RTMAC& mac)
82{
83 m_mac = mac;
84 m_lease = NULL;
85}
86
87/* Configs
88 NetworkConfigEntity(std::string name,
89 ConfigEntity* pCfg,
90 ClientMatchCriteria* criteria,
91 RTNETADDRIPV4& networkID,
92 RTNETADDRIPV4& networkMask)
93*/
94static const RTNETADDRIPV4 g_AnyIpv4 = {0};
95static const RTNETADDRIPV4 g_AllIpv4 = {0xffffffff};
96RootConfigEntity::RootConfigEntity(std::string name, uint32_t expPeriod):
97 NetworkConfigEntity(name, g_NullConfig, g_AnyClient, g_AnyIpv4, g_AllIpv4)
98{
99 m_MatchLevel = 2;
100 m_u32ExpirationPeriod = expPeriod;
101}
102
103
104/* Configuration Manager */
105ConfigurationManager *ConfigurationManager::getConfigurationManager()
106{
107 if (!g_ConfigurationManager)
108 g_ConfigurationManager = new ConfigurationManager();
109
110 return g_ConfigurationManager;
111}
112
113
114int ConfigurationManager::extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt)
115{
116 return ConfigurationManager::findOption(RTNET_DHCP_OPT_PARAM_REQ_LIST, pDhcpMsg, cbDhcpMsg, rawOpt);
117}
118
119
120Client *ConfigurationManager::getClientByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg)
121{
122
123 VecClientIterator it;
124 bool fDhcpValid = false;
125 uint8_t uMsgType = 0;
126
127 fDhcpValid = RTNetIPv4IsDHCPValid(NULL, pDhcpMsg, cbDhcpMsg, &uMsgType);
128 AssertReturn(fDhcpValid, NULL);
129
130 LogFlowFunc(("dhcp:mac:%RTmac\n", &pDhcpMsg->bp_chaddr.Mac));
131 /* 1st. client IDs */
132 for ( it = m_clients.begin();
133 it != m_clients.end();
134 ++it)
135 {
136 if (*(*it) == pDhcpMsg->bp_chaddr.Mac)
137 {
138 LogFlowFunc(("client:mac:%RTmac\n", &(*it)->m_mac));
139 /* check timestamp that request wasn't expired. */
140 return (*it);
141 }
142 }
143
144 if (it == m_clients.end())
145 {
146 /* We hasn't got any session for this client */
147 m_clients.push_back(new Client(pDhcpMsg->bp_chaddr.Mac));
148 return m_clients.back();
149 }
150
151 return NULL;
152}
153
154/**
155 * Finds an option.
156 *
157 * @returns On success, a pointer to the first byte in the option data (no none
158 * then it'll be the byte following the 0 size field) and *pcbOpt set
159 * to the option length.
160 * On failure, NULL is returned and *pcbOpt unchanged.
161 *
162 * @param uOption The option to search for.
163 * @param pDhcpMsg The DHCP message.
164 * that this is adjusted if the option length is larger
165 * than the message buffer.
166 */
167int
168ConfigurationManager::findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt)
169{
170 Assert(uOption != RTNET_DHCP_OPT_PAD);
171
172 /*
173 * Validate the DHCP bits and figure the max size of the options in the vendor field.
174 */
175 if (cbDhcpMsg <= RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts))
176 return VERR_INVALID_PARAMETER;
177
178 if (pDhcpMsg->bp_vend.Dhcp.dhcp_cookie != RT_H2N_U32_C(RTNET_DHCP_COOKIE))
179 return VERR_INVALID_PARAMETER;
180
181 size_t cbLeft = cbDhcpMsg - RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts);
182 if (cbLeft > RTNET_DHCP_OPT_SIZE)
183 cbLeft = RTNET_DHCP_OPT_SIZE;
184
185 /*
186 * Search the vendor field.
187 */
188 bool fExtended = false;
189 uint8_t const *pb = &pDhcpMsg->bp_vend.Dhcp.dhcp_opts[0];
190 while (pb && cbLeft > 0)
191 {
192 uint8_t uCur = *pb;
193 if (uCur == RTNET_DHCP_OPT_PAD)
194 {
195 cbLeft--;
196 pb++;
197 }
198 else if (cbLeft <= 1)
199 break;
200 else
201 {
202 size_t cbCur = pb[1];
203 if (cbCur > cbLeft - 2)
204 cbCur = cbLeft - 2;
205 if (uCur == uOption)
206 {
207 opt.u8OptId = uCur;
208 memcpy(opt.au8RawOpt, pb+2, cbCur);
209 opt.cbRawOpt = cbCur;
210 return VINF_SUCCESS;
211 }
212 pb += cbCur + 2;
213 cbLeft -= cbCur - 2;
214 }
215 }
216
217 /** @todo search extended dhcp option field(s) when present */
218
219 return VERR_NOT_FOUND;
220}
221
222
223/**
224 * We bind lease for client till it continue with it on DHCPREQUEST.
225 */
226Lease *ConfigurationManager::allocateLease4Client(Client *client, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg)
227{
228 /**
229 * Well, session hasn't get the config.
230 */
231 AssertPtrReturn(client, NULL);
232
233 /**
234 * This mean that client has already bound or commited lease.
235 * If we've it happens it means that we received DHCPDISCOVER twice.
236 */
237 if (client->m_lease)
238 {
239 if (client->m_lease->isExpired())
240 expireLease4Client(client);
241 else
242 {
243 AssertReturn(client->m_lease->m_address.u != 0,NULL);
244 return client->m_lease;
245 }
246 }
247
248 RTNETADDRIPV4 hintAddress;
249 RawOption opt;
250 Lease *please = NULL;
251
252 NetworkConfigEntity *pNetCfg;
253
254 AssertReturn(g_RootConfig->match(*client, (BaseConfigEntity **)&pNetCfg) > 0, NULL);
255
256 /* DHCPDISCOVER MAY contain request address */
257 hintAddress.u = 0;
258 int rc = findOption(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cbDhcpMsg, opt);
259 if (RT_SUCCESS(rc))
260 {
261 hintAddress.u = *(uint32_t *)opt.au8RawOpt;
262 if ( RT_H2N_U32(hintAddress.u) < RT_H2N_U32(pNetCfg->lowerIp().u)
263 || RT_H2N_U32(hintAddress.u) > RT_H2N_U32(pNetCfg->upperIp().u))
264 hintAddress.u = 0; /* clear hint */
265 }
266
267 if ( hintAddress.u
268 && !isAddressTaken(hintAddress, NULL))
269 {
270 please = new Lease();
271 please->pCfg = pNetCfg;
272 please->m_client = client;
273 client->m_lease = please;
274 client->m_lease->m_address = hintAddress;
275 m_allocations[please] = hintAddress;
276 return please;
277 }
278
279 uint32_t u32 = 0;
280 for(u32 = RT_H2N_U32(pNetCfg->lowerIp().u);
281 u32 <= RT_H2N_U32(pNetCfg->upperIp().u);
282 ++u32)
283 {
284 RTNETADDRIPV4 address;
285 address.u = RT_H2N_U32(u32);
286 if (!isAddressTaken(address, NULL))
287 {
288 please = new Lease();
289 please->pCfg = pNetCfg;
290 please->m_client = client;
291 client->m_lease = please;
292 client->m_lease->m_address = address;
293 m_allocations[please] = client->m_lease->m_address;
294 return please;
295 }
296 }
297
298 return NULL;
299}
300
301
302int ConfigurationManager::commitLease4Client(Client *client)
303{
304 client->m_lease->u64TimestampBindingStarted = 0;
305 client->m_lease->u32LeaseExpirationPeriod = client->m_lease->pCfg->expirationPeriod();
306 client->m_lease->u64TimestampLeasingStarted = RTTimeMilliTS();
307 client->m_lease->fBinding = false;
308 return VINF_SUCCESS;
309}
310
311int ConfigurationManager::expireLease4Client(Client *client)
312{
313 MapLease2Ip4AddressIterator it = m_allocations.find(client->m_lease);
314 AssertReturn(it != m_allocations.end(), VERR_NOT_FOUND);
315
316 m_allocations.erase(it);
317
318 delete client->m_lease;
319 client->m_lease = NULL;
320
321 return VINF_SUCCESS;
322}
323
324bool ConfigurationManager::isAddressTaken(const RTNETADDRIPV4& addr, Lease** ppLease)
325{
326 MapLease2Ip4AddressIterator it;
327
328 for (it = m_allocations.begin();
329 it != m_allocations.end();
330 ++it)
331 {
332 if (it->second.u == addr.u)
333 {
334 if (ppLease)
335 *ppLease = it->first;
336
337 return true;
338 }
339 }
340 return false;
341}
342
343NetworkConfigEntity *ConfigurationManager::addNetwork(NetworkConfigEntity *pCfg,
344 const RTNETADDRIPV4& networkId,
345 const RTNETADDRIPV4& netmask,
346 RTNETADDRIPV4& LowerAddress,
347 RTNETADDRIPV4& UpperAddress)
348{
349 static int id;
350 char name[64];
351
352 RTStrPrintf(name, RT_ELEMENTS(name), "network-%d", id);
353 std::string strname(name);
354 id++;
355
356
357 if (!LowerAddress.u)
358 LowerAddress = networkId;
359
360 if (!UpperAddress.u)
361 UpperAddress.u = networkId.u | (~netmask.u);
362
363 return new NetworkConfigEntity(strname,
364 g_RootConfig,
365 g_AnyClient,
366 5,
367 networkId,
368 netmask,
369 LowerAddress,
370 UpperAddress);
371}
372
373HostConfigEntity *ConfigurationManager::addHost(NetworkConfigEntity* pCfg,
374 const RTNETADDRIPV4& address,
375 ClientMatchCriteria *criteria)
376{
377 static int id;
378 char name[64];
379
380 RTStrPrintf(name, RT_ELEMENTS(name), "host-%d", id);
381 std::string strname(name);
382 id++;
383
384 return new HostConfigEntity(address, strname, pCfg, criteria);
385}
386
387int ConfigurationManager::addToAddressList(uint8_t u8OptId, RTNETADDRIPV4& address)
388{
389 switch(u8OptId)
390 {
391 case RTNET_DHCP_OPT_DNS:
392 m_nameservers.push_back(address);
393 break;
394 case RTNET_DHCP_OPT_ROUTERS:
395 m_routers.push_back(address);
396 break;
397 default:
398 Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
399 }
400 return VINF_SUCCESS;
401}
402
403int ConfigurationManager::flushAddressList(uint8_t u8OptId)
404{
405 switch(u8OptId)
406 {
407 case RTNET_DHCP_OPT_DNS:
408 m_nameservers.clear();
409 break;
410 case RTNET_DHCP_OPT_ROUTERS:
411 m_routers.clear();
412 break;
413 default:
414 Log(("dhcp-opt: list (%d) unsupported\n", u8OptId));
415 }
416 return VINF_SUCCESS;
417}
418
419const Ipv4AddressContainer& ConfigurationManager::getAddressList(uint8_t u8OptId)
420{
421 switch(u8OptId)
422 {
423 case RTNET_DHCP_OPT_DNS:
424 return m_nameservers;
425
426 case RTNET_DHCP_OPT_ROUTERS:
427 return m_routers;
428
429 }
430 /* XXX: Grrr !!! */
431 return m_empty;
432}
433
434int ConfigurationManager::setString(uint8_t u8OptId, const std::string& str)
435{
436 switch (u8OptId)
437 {
438 case RTNET_DHCP_OPT_DOMAIN_NAME:
439 m_domainName = str;
440 break;
441 default:
442 break;
443 }
444
445 return VINF_SUCCESS;
446}
447
448const std::string& ConfigurationManager::getString(uint8_t u8OptId)
449{
450 switch (u8OptId)
451 {
452 case RTNET_DHCP_OPT_DOMAIN_NAME:
453 if (m_domainName.length())
454 return m_domainName;
455 else
456 return m_noString;
457 default:
458 break;
459 }
460
461 return m_noString;
462}
463
464/**
465 * Network manager
466 */
467NetworkManager *NetworkManager::getNetworkManager()
468{
469 if (!g_NetworkManager)
470 g_NetworkManager = new NetworkManager();
471
472 return g_NetworkManager;
473}
474
475
476/**
477 * Network manager creates DHCPOFFER datagramm
478 */
479int NetworkManager::offer4Client(Client *client, uint32_t u32Xid,
480 uint8_t *pu8ReqList, int cReqList)
481{
482 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
483 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
484
485 prepareReplyPacket4Client(client, u32Xid);
486
487
488 RTNETADDRIPV4 address = client->m_lease->m_address;
489 BootPReplyMsg.BootPHeader.bp_yiaddr = address;
490
491 /* Ubuntu ???*/
492 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
493
494 /* options:
495 * - IP lease time
496 * - message type
497 * - server identifier
498 */
499 RawOption opt;
500 RT_ZERO(opt);
501
502 /* XXX: can't store options per session */
503 AssertPtr(client);
504
505 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
506 opt.au8RawOpt[0] = RTNET_DHCP_MT_OFFER;
507 opt.cbRawOpt = 1;
508 client->rawOptions.push_back(opt);
509
510 opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
511 *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(client->m_lease->pCfg->expirationPeriod());
512 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
513 client->rawOptions.push_back(opt);
514
515 processParameterReqList(client, pu8ReqList, cReqList);
516
517 return doReply(client);
518}
519
520
521/**
522 * Network manager creates DHCPACK
523 */
524int NetworkManager::ack(Client *client, uint32_t u32Xid,
525 uint8_t *pu8ReqList, int cReqList)
526{
527 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
528 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
529
530 RTNETADDRIPV4 address;
531
532 prepareReplyPacket4Client(client, u32Xid);
533
534 address = client->m_lease->m_address;
535 BootPReplyMsg.BootPHeader.bp_ciaddr = address;
536
537
538 /* rfc2131 4.3.1 is about DHCPDISCOVER and this value is equal to ciaddr from
539 * DHCPREQUEST or 0 ...
540 * XXX: Using addressHint is not correct way to initialize [cy]iaddress...
541 */
542 BootPReplyMsg.BootPHeader.bp_ciaddr = client->m_lease->m_address;
543 BootPReplyMsg.BootPHeader.bp_yiaddr = client->m_lease->m_address;
544
545 Assert(BootPReplyMsg.BootPHeader.bp_yiaddr.u);
546
547 /* options:
548 * - IP address lease time (if DHCPREQUEST)
549 * - message type
550 * - server identifier
551 */
552 RawOption opt;
553 RT_ZERO(opt);
554
555 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
556 opt.au8RawOpt[0] = RTNET_DHCP_MT_ACK;
557 opt.cbRawOpt = 1;
558 client->rawOptions.push_back(opt);
559
560 /*
561 * XXX: lease time should be conditional. If on dhcprequest then tim should be provided,
562 * else on dhcpinform it mustn't.
563 */
564 opt.u8OptId = RTNET_DHCP_OPT_LEASE_TIME;
565 *(uint32_t *)opt.au8RawOpt = RT_H2N_U32(client->m_lease->u32LeaseExpirationPeriod);
566 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
567 client->rawOptions.push_back(opt);
568
569 processParameterReqList(client, pu8ReqList, cReqList);
570
571 return doReply(client);
572}
573
574
575/**
576 * Network manager creates DHCPNAK
577 */
578int NetworkManager::nak(Client* client, uint32_t u32Xid)
579{
580 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
581
582 if (!client->m_lease)
583 return VERR_INTERNAL_ERROR;
584
585 prepareReplyPacket4Client(client, u32Xid);
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 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
600 opt.au8RawOpt[0] = RTNET_DHCP_MT_NAC;
601 opt.cbRawOpt = 1;
602 client->rawOptions.push_back(opt);
603
604 return doReply(client);
605}
606
607
608/**
609 *
610 */
611int NetworkManager::prepareReplyPacket4Client(Client *client, uint32_t u32Xid)
612{
613 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
614 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
615
616 memset(&BootPReplyMsg, 0, sizeof(BootPReplyMsg));
617
618 BootPReplyMsg.BootPHeader.bp_op = RTNETBOOTP_OP_REPLY;
619 BootPReplyMsg.BootPHeader.bp_htype = RTNET_ARP_ETHER;
620 BootPReplyMsg.BootPHeader.bp_hlen = sizeof(RTMAC);
621 BootPReplyMsg.BootPHeader.bp_hops = 0;
622 BootPReplyMsg.BootPHeader.bp_xid = u32Xid;
623 BootPReplyMsg.BootPHeader.bp_secs = 0;
624 /* XXX: bp_flags should be processed specially */
625 BootPReplyMsg.BootPHeader.bp_flags = 0;
626 BootPReplyMsg.BootPHeader.bp_ciaddr.u = 0;
627 BootPReplyMsg.BootPHeader.bp_giaddr.u = 0;
628
629 BootPReplyMsg.BootPHeader.bp_chaddr.Mac = client->m_mac;
630
631 BootPReplyMsg.BootPHeader.bp_yiaddr = client->m_lease->m_address;
632 BootPReplyMsg.BootPHeader.bp_siaddr.u = 0;
633
634
635 BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE);
636
637 memset(&BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_opts[0],
638 '\0',
639 RTNET_DHCP_OPT_SIZE);
640
641 return VINF_SUCCESS;
642}
643
644
645int NetworkManager::doReply(Client *client)
646{
647 int rc;
648
649 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
650 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
651
652 /*
653 Options....
654 */
655 VBoxNetDhcpWriteCursor Cursor(&BootPReplyMsg.BootPHeader, RTNET_DHCP_NORMAL_SIZE);
656
657 /* The basics */
658
659 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_OurAddress);
660
661 while(!client->rawOptions.empty())
662 {
663 RawOption opt = client->rawOptions.back();
664 if (!Cursor.begin(opt.u8OptId, opt.cbRawOpt))
665 break;
666 Cursor.put(opt.au8RawOpt, opt.cbRawOpt);
667
668 client->rawOptions.pop_back();
669 }
670
671
672 if (!client->rawOptions.empty())
673 {
674 Log(("Wasn't able to put all options\n"));
675 /* force clean up */
676 client->rawOptions.clear();
677 }
678
679 Cursor.optEnd();
680
681 /*
682 */
683#if 0
684 if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */
685 {
686 rc = VBoxNetUDPUnicast(m_pSession,
687 m_hIf,
688 m_pIfBuf,
689 m_OurAddress,
690 &m_OurMac,
691 RTNETIPV4_PORT_BOOTPS, /* sender */
692 IPv4AddrBrdCast,
693 &BootPReplyMsg.BootPHeader->bp_chaddr.Mac,
694 RTNETIPV4_PORT_BOOTPC, /* receiver */
695 &BootPReplyMsg, cbBooPReplyMsg);
696 }
697 else
698#endif
699 rc = VBoxNetUDPBroadcast(m_pSession,
700 m_hIf,
701 m_pIfBuf,
702 m_OurAddress,
703 &m_OurMac,
704 RTNETIPV4_PORT_BOOTPS, /* sender */
705 RTNETIPV4_PORT_BOOTPC,
706 &BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
707
708 AssertRCReturn(rc,rc);
709
710 return VINF_SUCCESS;
711}
712
713
714int NetworkManager::processParameterReqList(Client* client, uint8_t *pu8ReqList, int cReqList)
715{
716 /* request parameter list */
717 RawOption opt;
718 int idxParam = 0;
719
720 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
721
722 uint8_t *pReqList = pu8ReqList;
723
724 const NetworkConfigEntity *pNetCfg = client->m_lease->pCfg;
725
726 for (idxParam = 0; idxParam < cReqList; ++idxParam)
727 {
728
729 RT_ZERO(opt);
730 opt.u8OptId = pReqList[idxParam];
731 switch(pReqList[idxParam])
732 {
733 case RTNET_DHCP_OPT_SUBNET_MASK:
734 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
735 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
736 client->rawOptions.push_back(opt);
737 break;
738
739 case RTNET_DHCP_OPT_ROUTERS:
740 case RTNET_DHCP_OPT_DNS:
741 {
742 const Ipv4AddressContainer lst =
743 g_ConfigurationManager->getAddressList(pReqList[idxParam]);
744 PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
745
746 for (Ipv4AddressConstIterator it = lst.begin();
747 it != lst.end();
748 ++it)
749 {
750 *pAddresses = (*it);
751 pAddresses++;
752 opt.cbRawOpt += sizeof(RTNETADDRIPV4);
753 }
754
755 if (!lst.empty())
756 client->rawOptions.push_back(opt);
757 }
758 break;
759 case RTNET_DHCP_OPT_DOMAIN_NAME:
760 {
761 std::string domainName = g_ConfigurationManager->getString(pReqList[idxParam]);
762 if (domainName == g_ConfigurationManager->m_noString)
763 break;
764
765 char *pszDomainName = (char *)&opt.au8RawOpt[0];
766
767 strcpy(pszDomainName, domainName.c_str());
768 opt.cbRawOpt = domainName.length();
769 client->rawOptions.push_back(opt);
770 }
771 break;
772 default:
773 Log(("opt: %d is ignored\n", pReqList[idxParam]));
774 break;
775 }
776 }
777
778 return VINF_SUCCESS;
779}
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