VirtualBox

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

Last change on this file since 48705 was 48461, checked in by vboxsync, 12 years ago

DHCP + lwip_nat: Domain Name passing on demand.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 KB
Line 
1/* $Id: Config.cpp 48461 2013-09-12 18:14:50Z 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 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
582
583 prepareReplyPacket4Client(client, u32Xid);
584
585 /* this field filed in prepareReplyPacket4Session, and
586 * RFC 2131 require to have it zero fo NAK.
587 */
588 BootPReplyMsg.BootPHeader.bp_yiaddr.u = 0;
589
590 /* options:
591 * - message type (if DHCPREQUEST)
592 * - server identifier
593 */
594 RawOption opt;
595 RT_ZERO(opt);
596
597 opt.u8OptId = RTNET_DHCP_OPT_MSG_TYPE;
598 opt.au8RawOpt[0] = RTNET_DHCP_MT_NAC;
599 opt.cbRawOpt = 1;
600 client->rawOptions.push_back(opt);
601
602 return doReply(client);
603}
604
605
606/**
607 *
608 */
609int NetworkManager::prepareReplyPacket4Client(Client *client, uint32_t u32Xid)
610{
611 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
612 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
613
614 memset(&BootPReplyMsg, 0, sizeof(BootPReplyMsg));
615
616 BootPReplyMsg.BootPHeader.bp_op = RTNETBOOTP_OP_REPLY;
617 BootPReplyMsg.BootPHeader.bp_htype = RTNET_ARP_ETHER;
618 BootPReplyMsg.BootPHeader.bp_hlen = sizeof(RTMAC);
619 BootPReplyMsg.BootPHeader.bp_hops = 0;
620 BootPReplyMsg.BootPHeader.bp_xid = u32Xid;
621 BootPReplyMsg.BootPHeader.bp_secs = 0;
622 /* XXX: bp_flags should be processed specially */
623 BootPReplyMsg.BootPHeader.bp_flags = 0;
624 BootPReplyMsg.BootPHeader.bp_ciaddr.u = 0;
625 BootPReplyMsg.BootPHeader.bp_giaddr.u = 0;
626
627 BootPReplyMsg.BootPHeader.bp_chaddr.Mac = client->m_mac;
628
629 BootPReplyMsg.BootPHeader.bp_yiaddr = client->m_lease->m_address;
630 BootPReplyMsg.BootPHeader.bp_siaddr.u = 0;
631
632
633 BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE);
634
635 memset(&BootPReplyMsg.BootPHeader.bp_vend.Dhcp.dhcp_opts[0],
636 '\0',
637 RTNET_DHCP_OPT_SIZE);
638
639 return VINF_SUCCESS;
640}
641
642
643int NetworkManager::doReply(Client *client)
644{
645 int rc;
646
647 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
648 AssertPtrReturn(client->m_lease, VERR_INTERNAL_ERROR);
649
650 /*
651 Options....
652 */
653 VBoxNetDhcpWriteCursor Cursor(&BootPReplyMsg.BootPHeader, RTNET_DHCP_NORMAL_SIZE);
654
655 /* The basics */
656
657 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_OurAddress);
658
659 while(!client->rawOptions.empty())
660 {
661 RawOption opt = client->rawOptions.back();
662 if (!Cursor.begin(opt.u8OptId, opt.cbRawOpt))
663 break;
664 Cursor.put(opt.au8RawOpt, opt.cbRawOpt);
665
666 client->rawOptions.pop_back();
667 }
668
669
670 if (!client->rawOptions.empty())
671 {
672 Log(("Wasn't able to put all options\n"));
673 /* force clean up */
674 client->rawOptions.clear();
675 }
676
677 Cursor.optEnd();
678
679 /*
680 */
681#if 0
682 if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */
683 {
684 rc = VBoxNetUDPUnicast(m_pSession,
685 m_hIf,
686 m_pIfBuf,
687 m_OurAddress,
688 &m_OurMac,
689 RTNETIPV4_PORT_BOOTPS, /* sender */
690 IPv4AddrBrdCast,
691 &BootPReplyMsg.BootPHeader->bp_chaddr.Mac,
692 RTNETIPV4_PORT_BOOTPC, /* receiver */
693 &BootPReplyMsg, cbBooPReplyMsg);
694 }
695 else
696#endif
697 rc = VBoxNetUDPBroadcast(m_pSession,
698 m_hIf,
699 m_pIfBuf,
700 m_OurAddress,
701 &m_OurMac,
702 RTNETIPV4_PORT_BOOTPS, /* sender */
703 RTNETIPV4_PORT_BOOTPC,
704 &BootPReplyMsg, RTNET_DHCP_NORMAL_SIZE);
705
706 AssertRCReturn(rc,rc);
707
708 return VINF_SUCCESS;
709}
710
711
712int NetworkManager::processParameterReqList(Client* client, uint8_t *pu8ReqList, int cReqList)
713{
714 /* request parameter list */
715 RawOption opt;
716 int idxParam = 0;
717
718 AssertPtrReturn(client, VERR_INTERNAL_ERROR);
719
720 uint8_t *pReqList = pu8ReqList;
721
722 const NetworkConfigEntity *pNetCfg = client->m_lease->pCfg;
723
724 for (idxParam = 0; idxParam < cReqList; ++idxParam)
725 {
726
727 RT_ZERO(opt);
728 opt.u8OptId = pReqList[idxParam];
729 switch(pReqList[idxParam])
730 {
731 case RTNET_DHCP_OPT_SUBNET_MASK:
732 ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
733 opt.cbRawOpt = sizeof(RTNETADDRIPV4);
734 client->rawOptions.push_back(opt);
735 break;
736
737 case RTNET_DHCP_OPT_ROUTERS:
738 case RTNET_DHCP_OPT_DNS:
739 {
740 const Ipv4AddressContainer lst =
741 g_ConfigurationManager->getAddressList(pReqList[idxParam]);
742 PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];
743
744 for (Ipv4AddressConstIterator it = lst.begin();
745 it != lst.end();
746 ++it)
747 {
748 *pAddresses = (*it);
749 pAddresses++;
750 opt.cbRawOpt += sizeof(RTNETADDRIPV4);
751 }
752
753 if (!lst.empty())
754 client->rawOptions.push_back(opt);
755 }
756 break;
757 case RTNET_DHCP_OPT_DOMAIN_NAME:
758 {
759 std::string domainName = g_ConfigurationManager->getString(pReqList[idxParam]);
760 if (domainName == g_ConfigurationManager->m_noString)
761 break;
762
763 char *pszDomainName = (char *)&opt.au8RawOpt[0];
764
765 strcpy(pszDomainName, domainName.c_str());
766 opt.cbRawOpt = domainName.length();
767 client->rawOptions.push_back(opt);
768 }
769 break;
770 default:
771 Log(("opt: %d is ignored\n", pReqList[idxParam]));
772 break;
773 }
774 }
775
776 return VINF_SUCCESS;
777}
Note: See TracBrowser for help on using the repository browser.

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