VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/DHCP/Config.h@ 77099

Last change on this file since 77099 was 76576, checked in by vboxsync, 6 years ago

NetworkServices: scm header guard alignment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.1 KB
Line 
1/* $Id: Config.h 76576 2019-01-01 06:05:25Z vboxsync $ */
2/** @file
3 * Config.h
4 */
5
6/*
7 * Copyright (C) 2013-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef VBOX_INCLUDED_SRC_DHCP_Config_h
19#define VBOX_INCLUDED_SRC_DHCP_Config_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <iprt/asm-math.h>
25#include <iprt/cpp/utils.h>
26
27#include <VBox/com/ptr.h>
28#include <VBox/com/string.h>
29#include <VBox/com/VirtualBox.h>
30
31#include "../NetLib/cpp/utils.h"
32
33
34class RawOption
35{
36public:
37 RawOption()
38 {
39 /** @todo r=bird: this is crazy. */
40 RT_ZERO(*this);
41 }
42 uint8_t u8OptId;
43 uint8_t cbRawOpt;
44 uint8_t au8RawOpt[255];
45};
46
47class ClientData;
48class Client;
49class Lease;
50class BaseConfigEntity;
51
52class NetworkConfigEntity;
53class HostConfigEntity;
54class ClientMatchCriteria;
55class ConfigurationManager;
56
57/*
58 * it's a basic representation of
59 * of out undestanding what client is
60 * XXX: Client might sends Option 61 (RFC2132 9.14 "Client-identifier") signalling
61 * that we may identify it in special way
62 *
63 * XXX: Client might send Option 60 (RFC2132 9.13 "Vendor class undentifier")
64 * in response it's expected server sends Option 43 (RFC2132 8.4. "Vendor Specific Information")
65 */
66class Client
67{
68 friend class Lease;
69 friend class ConfigurationManager;
70
71 public:
72 Client();
73 void initWithMac(const RTMAC& mac);
74 bool operator== (const RTMAC& mac) const;
75 const RTMAC& getMacAddress() const;
76
77 /** Dumps client query */
78 void dump();
79
80 Lease lease();
81 const Lease lease() const;
82
83 public:
84 static const Client NullClient;
85
86 private:
87 Client(ClientData *);
88 SharedPtr<ClientData> m;
89};
90
91
92bool operator== (const Lease&, const Lease&);
93bool operator!= (const Lease&, const Lease&);
94bool operator< (const Lease&, const Lease&);
95
96
97typedef std::map<uint8_t, RawOption> MapOptionId2RawOption;
98typedef MapOptionId2RawOption::iterator MapOptionId2RawOptionIterator;
99typedef MapOptionId2RawOption::const_iterator MapOptionId2RawOptionConstIterator;
100typedef MapOptionId2RawOption::value_type MapOptionId2RawOptionValue;
101
102namespace xml {
103 class ElementNode;
104}
105
106class Lease
107{
108 friend class Client;
109 friend bool operator== (const Lease&, const Lease&);
110 //friend int ConfigurationManager::loadFromFile(const std::string&);
111 friend class ConfigurationManager;
112
113 public:
114 Lease();
115 Lease(const Client&);
116
117 bool isExpired() const;
118 void expire();
119
120 /* Depending on phase *Expiration and phaseStart initialize different values. */
121 void bindingPhase(bool);
122 void phaseStart(uint64_t u64Start);
123 bool isInBindingPhase() const;
124 /* returns 0 if in binding state */
125 uint64_t issued() const;
126
127 void setExpiration(uint32_t);
128 uint32_t getExpiration() const;
129
130 RTNETADDRIPV4 getAddress() const;
131 void setAddress(RTNETADDRIPV4);
132
133 const NetworkConfigEntity *getConfig() const;
134 void setConfig(NetworkConfigEntity *);
135
136 const MapOptionId2RawOption& options() const;
137
138 bool toXML(xml::ElementNode *) const;
139 bool fromXML(const xml::ElementNode *);
140
141 public:
142 static const Lease NullLease;
143
144 private:
145 Lease(ClientData *);
146 SharedPtr<ClientData> m;
147};
148
149
150typedef std::vector<Client> VecClient;
151typedef VecClient::iterator VecClientIterator;
152typedef VecClient::const_iterator VecClientConstIterator;
153
154typedef std::vector<RTMAC> MacAddressContainer;
155typedef MacAddressContainer::iterator MacAddressIterator;
156
157typedef std::vector<RTNETADDRIPV4> Ipv4AddressContainer;
158typedef Ipv4AddressContainer::iterator Ipv4AddressIterator;
159typedef Ipv4AddressContainer::const_iterator Ipv4AddressConstIterator;
160
161typedef std::map<Lease, RTNETADDRIPV4> MapLease2Ip4Address;
162typedef MapLease2Ip4Address::iterator MapLease2Ip4AddressIterator;
163typedef MapLease2Ip4Address::const_iterator MapLease2Ip4AddressConstIterator;
164typedef MapLease2Ip4Address::value_type MapLease2Ip4AddressPair;
165
166/**
167 *
168 */
169class ClientMatchCriteria
170{
171 public:
172 virtual bool check(const Client&) const {return false;};
173};
174
175
176class ORClientMatchCriteria: ClientMatchCriteria
177{
178 ClientMatchCriteria* m_left;
179 ClientMatchCriteria* m_right;
180 ORClientMatchCriteria(ClientMatchCriteria *left, ClientMatchCriteria *right)
181 {
182 m_left = left;
183 m_right = right;
184 }
185
186 virtual bool check(const Client& client) const
187 {
188 return (m_left->check(client) || m_right->check(client));
189 }
190};
191
192
193class ANDClientMatchCriteria: ClientMatchCriteria
194{
195public:
196 ANDClientMatchCriteria(ClientMatchCriteria *left, ClientMatchCriteria *right)
197 {
198 m_left = left;
199 m_right = right;
200 }
201
202 virtual bool check(const Client& client) const
203 {
204 return (m_left->check(client) && m_right->check(client));
205 }
206
207private:
208 ClientMatchCriteria* m_left;
209 ClientMatchCriteria* m_right;
210
211};
212
213
214class AnyClientMatchCriteria: public ClientMatchCriteria
215{
216public:
217 virtual bool check(const Client&) const
218 {
219 return true;
220 }
221};
222
223
224class MACClientMatchCriteria: public ClientMatchCriteria
225{
226public:
227 MACClientMatchCriteria(const RTMAC& mac):m_mac(mac){}
228
229 virtual bool check(const Client& client) const;
230
231private:
232 RTMAC m_mac;
233};
234
235
236#if 0
237/* XXX: Later */
238class VmSlotClientMatchCriteria: public ClientMatchCriteria
239{
240 str::string VmName;
241 uint8_t u8Slot;
242 virtual bool check(const Client& client)
243 {
244 return ( client.VmName == VmName
245 && ( u8Slot == (uint8_t)~0 /* any */
246 || client.u8Slot == u8Slot));
247 }
248};
249#endif
250
251
252/* Option 60 */
253class ClassClientMatchCriteria: ClientMatchCriteria{};
254/* Option 61 */
255class ClientIdentifierMatchCriteria: ClientMatchCriteria{};
256
257
258class BaseConfigEntity
259{
260 public:
261 BaseConfigEntity(const ClientMatchCriteria *criteria = NULL,
262 int matchingLevel = 0)
263 : m_criteria(criteria),
264 m_MatchLevel(matchingLevel){};
265 virtual ~BaseConfigEntity(){};
266 /* XXX */
267 int add(BaseConfigEntity *cfg)
268 {
269 m_children.push_back(cfg);
270 return 0;
271 }
272
273 /* Should return how strong matching */
274 virtual int match(Client& client, BaseConfigEntity **cfg);
275 virtual uint32_t expirationPeriod() const = 0;
276
277 protected:
278 const ClientMatchCriteria *m_criteria;
279 int m_MatchLevel;
280 std::vector<BaseConfigEntity *> m_children;
281};
282
283
284class NullConfigEntity: public BaseConfigEntity
285{
286 public:
287 NullConfigEntity(){}
288 virtual ~NullConfigEntity(){}
289 int add(BaseConfigEntity *) const { return 0;}
290 virtual uint32_t expirationPeriod() const {return 0;}
291};
292
293
294class ConfigEntity: public BaseConfigEntity
295{
296 public:
297 /* range */
298 /* match conditions */
299 ConfigEntity(std::string& name,
300 const BaseConfigEntity *cfg,
301 const ClientMatchCriteria *criteria,
302 int matchingLevel = 0):
303 BaseConfigEntity(criteria, matchingLevel),
304 m_name(name),
305 m_parentCfg(cfg),
306 m_u32ExpirationPeriod(0)
307 {
308 unconst(m_parentCfg)->add(this);
309 }
310
311 virtual uint32_t expirationPeriod() const
312 {
313 if (!m_u32ExpirationPeriod)
314 return m_parentCfg->expirationPeriod();
315 else
316 return m_u32ExpirationPeriod;
317 }
318
319 /* XXX: private:*/
320 std::string m_name;
321 const BaseConfigEntity *m_parentCfg;
322 uint32_t m_u32ExpirationPeriod;
323};
324
325
326/**
327 * Network specific entries
328 */
329class NetworkConfigEntity:public ConfigEntity
330{
331public:
332 /* Address Pool matching with network declaration */
333 NetworkConfigEntity(std::string name,
334 const BaseConfigEntity *cfg,
335 const ClientMatchCriteria *criteria,
336 int matchlvl,
337 const RTNETADDRIPV4& networkID,
338 const RTNETADDRIPV4& networkMask,
339 const RTNETADDRIPV4& lowerIP,
340 const RTNETADDRIPV4& upperIP):
341 ConfigEntity(name, cfg, criteria, matchlvl),
342 m_NetworkID(networkID),
343 m_NetworkMask(networkMask),
344 m_UpperIP(upperIP),
345 m_LowerIP(lowerIP)
346 {
347 };
348
349 NetworkConfigEntity(std::string name,
350 const BaseConfigEntity *cfg,
351 const ClientMatchCriteria *criteria,
352 const RTNETADDRIPV4& networkID,
353 const RTNETADDRIPV4& networkMask):
354 ConfigEntity(name, cfg, criteria, 5),
355 m_NetworkID(networkID),
356 m_NetworkMask(networkMask)
357 {
358 m_UpperIP.u = m_NetworkID.u | (~m_NetworkMask.u);
359 m_LowerIP.u = m_NetworkID.u;
360 };
361
362 const RTNETADDRIPV4& upperIp() const {return m_UpperIP;}
363 const RTNETADDRIPV4& lowerIp() const {return m_LowerIP;}
364 const RTNETADDRIPV4& networkId() const {return m_NetworkID;}
365 const RTNETADDRIPV4& netmask() const {return m_NetworkMask;}
366
367 private:
368 RTNETADDRIPV4 m_NetworkID;
369 RTNETADDRIPV4 m_NetworkMask;
370 RTNETADDRIPV4 m_UpperIP;
371 RTNETADDRIPV4 m_LowerIP;
372};
373
374
375/**
376 * Host specific entry
377 * Address pool is contains one element
378 */
379class HostConfigEntity: public NetworkConfigEntity
380{
381public:
382 HostConfigEntity(const RTNETADDRIPV4& addr,
383 std::string name,
384 const NetworkConfigEntity *cfg,
385 const ClientMatchCriteria *criteria):
386 NetworkConfigEntity(name,
387 static_cast<const ConfigEntity*>(cfg), criteria, 10,
388 cfg->networkId(), cfg->netmask(), addr, addr)
389 {
390 /* upper addr == lower addr */
391 }
392};
393
394class RootConfigEntity: public NetworkConfigEntity
395{
396public:
397 RootConfigEntity(std::string name, uint32_t expirationPeriod);
398 virtual ~RootConfigEntity(){};
399};
400
401
402#if 0
403/**
404 * Shared regions e.g. some of configured networks declarations
405 * are cover each other.
406 * XXX: Shared Network is join on Network config entities with possible
407 * overlaps in address pools. for a moment we won't configure and use them them
408 */
409class SharedNetworkConfigEntity: public NetworkEntity
410{
411public:
412 SharedNetworkConfigEntity(){}
413 int match(const Client& client) const { return m_criteria.match(client)? 3 : 0;}
414
415 SharedNetworkConfigEntity(NetworkEntity& network)
416 {
417 Networks.push_back(network);
418 }
419 virtual ~SharedNetworkConfigEntity(){}
420
421 std::vector<NetworkConfigEntity> Networks;
422};
423#endif
424
425class ConfigurationManager
426{
427public:
428 static ConfigurationManager* getConfigurationManager();
429 static int extractRequestList(PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& rawOpt);
430
431 int loadFromFile(const com::Utf8Str&);
432 int saveToFile();
433 /**
434 *
435 */
436 Client getClientByDhcpPacket(const RTNETBOOTP *pDhcpMsg, size_t cbDhcpMsg);
437
438 /**
439 * XXX: it's could be done on DHCPOFFER or on DHCPACK (rfc2131 gives freedom here
440 * 3.1.2, what is strict that allocation should do address check before real
441 * allocation)...
442 */
443 Lease allocateLease4Client(const Client& client, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg);
444
445 /**
446 * We call this before DHCPACK sent and after DHCPREQUEST received ...
447 * when requested configuration is acceptable.
448 */
449 int commitLease4Client(Client& client);
450
451 /**
452 * Expires client lease.
453 */
454 int expireLease4Client(Client& client);
455
456 static int findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cbDhcpMsg, RawOption& opt);
457
458 NetworkConfigEntity *addNetwork(NetworkConfigEntity *pCfg,
459 const RTNETADDRIPV4& networkId,
460 const RTNETADDRIPV4& netmask,
461 RTNETADDRIPV4& UpperAddress,
462 RTNETADDRIPV4& LowerAddress);
463
464 HostConfigEntity *addHost(NetworkConfigEntity*, const RTNETADDRIPV4&, ClientMatchCriteria*);
465 int addToAddressList(uint8_t u8OptId, RTNETADDRIPV4& address);
466 int flushAddressList(uint8_t u8OptId);
467 int setString(uint8_t u8OptId, const std::string& str);
468 const std::string& getString(uint8_t u8OptId);
469 const Ipv4AddressContainer& getAddressList(uint8_t u8OptId);
470
471private:
472 ConfigurationManager():m(NULL){}
473 void init();
474
475 ~ConfigurationManager();
476 bool isAddressTaken(const RTNETADDRIPV4& addr, Lease& lease);
477 bool isAddressTaken(const RTNETADDRIPV4& addr);
478
479public:
480 /* nulls */
481 const Ipv4AddressContainer m_empty;
482 const std::string m_noString;
483
484private:
485 struct Data;
486 Data *m;
487};
488
489
490class NetworkManager
491{
492public:
493 static NetworkManager *getNetworkManager(ComPtr<IDHCPServer> aDhcpServer = ComPtr<IDHCPServer>());
494
495 const RTNETADDRIPV4& getOurAddress() const;
496 const RTNETADDRIPV4& getOurNetmask() const;
497 const RTMAC& getOurMac() const;
498
499 void setOurAddress(const RTNETADDRIPV4& aAddress);
500 void setOurNetmask(const RTNETADDRIPV4& aNetmask);
501 void setOurMac(const RTMAC& aMac);
502
503 bool handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb);
504 bool handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb);
505 bool handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb);
506 bool handleDhcpReqRelease(PCRTNETBOOTP pDhcpMsg, size_t cb);
507
508 void setService(const VBoxNetHlpUDPService *);
509private:
510 NetworkManager();
511 ~NetworkManager();
512
513 int offer4Client(const Client& lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
514 int ack(const Client& lease, uint32_t u32Xid, uint8_t *pu8ReqList, int cReqList);
515 int nak(const Client& lease, uint32_t u32Xid);
516
517 int prepareReplyPacket4Client(const Client& client, uint32_t u32Xid);
518 int doReply(const Client& client, const std::vector<RawOption>& extra);
519 int processParameterReqList(const Client& client, const uint8_t *pu8ReqList, int cReqList, std::vector<RawOption>& extra);
520
521private:
522 static NetworkManager *g_NetworkManager;
523
524private:
525 struct Data;
526 Data *m;
527
528};
529
530
531extern const ClientMatchCriteria *g_AnyClient;
532extern RootConfigEntity *g_RootConfig;
533extern const NullConfigEntity *g_NullConfig;
534
535/**
536 * Helper class for stuffing DHCP options into a reply packet.
537 */
538class VBoxNetDhcpWriteCursor
539{
540private:
541 uint8_t *m_pbCur; /**< The current cursor position. */
542 uint8_t *m_pbEnd; /**< The end the current option space. */
543 uint8_t *m_pfOverload; /**< Pointer to the flags of the overload option. */
544 uint8_t m_fUsed; /**< Overload fields that have been used. */
545 PRTNETDHCPOPT m_pOpt; /**< The current option. */
546 PRTNETBOOTP m_pDhcp; /**< The DHCP packet. */
547 bool m_fOverflowed; /**< Set if we've overflowed, otherwise false. */
548
549public:
550 /** Instantiate an option cursor for the specified DHCP message. */
551 VBoxNetDhcpWriteCursor(PRTNETBOOTP pDhcp, size_t cbDhcp) :
552 m_pbCur(&pDhcp->bp_vend.Dhcp.dhcp_opts[0]),
553 m_pbEnd((uint8_t *)pDhcp + cbDhcp),
554 m_pfOverload(NULL),
555 m_fUsed(0),
556 m_pOpt(NULL),
557 m_pDhcp(pDhcp),
558 m_fOverflowed(false)
559 {
560 AssertPtr(pDhcp);
561 Assert(cbDhcp > RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts[10]));
562 }
563
564 /** Destructor. */
565 ~VBoxNetDhcpWriteCursor()
566 {
567 m_pbCur = m_pbEnd = m_pfOverload = NULL;
568 m_pOpt = NULL;
569 m_pDhcp = NULL;
570 }
571
572 /**
573 * Try use the bp_file field.
574 * @returns true if not overloaded, false otherwise.
575 */
576 bool useBpFile(void)
577 {
578 if ( m_pfOverload
579 && (*m_pfOverload & 1))
580 return false;
581 m_fUsed |= 1 /* bp_file flag*/;
582 return true;
583 }
584
585
586 /**
587 * Try overload more BOOTP fields
588 */
589 bool overloadMore(void)
590 {
591 /* switch option area. */
592 uint8_t *pbNew;
593 uint8_t *pbNewEnd;
594 uint8_t fField;
595 if (!(m_fUsed & 1))
596 {
597 fField = 1;
598 pbNew = &m_pDhcp->bp_file[0];
599 pbNewEnd = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)];
600 }
601 else if (!(m_fUsed & 2))
602 {
603 fField = 2;
604 pbNew = &m_pDhcp->bp_sname[0];
605 pbNewEnd = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)];
606 }
607 else
608 return false;
609
610 if (!m_pfOverload)
611 {
612 /* Add an overload option. */
613 *m_pbCur++ = RTNET_DHCP_OPT_OPTION_OVERLOAD;
614 *m_pbCur++ = fField;
615 m_pfOverload = m_pbCur;
616 *m_pbCur++ = 1; /* bp_file flag */
617 }
618 else
619 *m_pfOverload |= fField;
620
621 /* pad current option field */
622 while (m_pbCur != m_pbEnd)
623 *m_pbCur++ = RTNET_DHCP_OPT_PAD; /** @todo not sure if this stuff is at all correct... */
624
625 /* switch */
626 m_pbCur = pbNew;
627 m_pbEnd = pbNewEnd;
628 return true;
629 }
630
631 /**
632 * Begin an option.
633 *
634 * @returns true on success, false if we're out of space.
635 *
636 * @param uOption The option number.
637 * @param cb The amount of data.
638 */
639 bool begin(uint8_t uOption, size_t cb)
640 {
641 /* Check that the data of the previous option has all been written. */
642 Assert( !m_pOpt
643 || (m_pbCur - m_pOpt->dhcp_len == (uint8_t *)(m_pOpt + 1)));
644 AssertMsg(cb <= 255, ("%#x\n", cb));
645
646 /* Check if we need to overload more stuff. */
647 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + (m_pfOverload ? 1 : 3))
648 {
649 m_pOpt = NULL;
650 if (!overloadMore())
651 {
652 m_fOverflowed = true;
653 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
654 }
655 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 1)
656 {
657 m_fOverflowed = true;
658 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
659 }
660 }
661
662 /* Emit the option header. */
663 m_pOpt = (PRTNETDHCPOPT)m_pbCur;
664 m_pOpt->dhcp_opt = uOption;
665 m_pOpt->dhcp_len = (uint8_t)cb;
666 m_pbCur += 2;
667 return true;
668 }
669
670 /**
671 * Puts option data.
672 *
673 * @param pvData The data.
674 * @param cb The amount to put.
675 */
676 void put(void const *pvData, size_t cb)
677 {
678 Assert(m_pOpt || m_fOverflowed);
679 if (RT_LIKELY(m_pOpt))
680 {
681 Assert((uintptr_t)m_pbCur - (uintptr_t)(m_pOpt + 1) + cb <= (size_t)m_pOpt->dhcp_len);
682 memcpy(m_pbCur, pvData, cb);
683 m_pbCur += cb;
684 }
685 }
686
687 /**
688 * Puts an IPv4 Address.
689 *
690 * @param IPv4Addr The address.
691 */
692 void putIPv4Addr(RTNETADDRIPV4 IPv4Addr)
693 {
694 put(&IPv4Addr, 4);
695 }
696
697 /**
698 * Adds an IPv4 address option.
699 *
700 * @returns true/false just like begin().
701 *
702 * @param uOption The option number.
703 * @param IPv4Addr The address.
704 */
705 bool optIPv4Addr(uint8_t uOption, RTNETADDRIPV4 IPv4Addr)
706 {
707 if (!begin(uOption, 4))
708 return false;
709 putIPv4Addr(IPv4Addr);
710 return true;
711 }
712
713 /**
714 * Adds an option taking 1 or more IPv4 address.
715 *
716 * If the vector contains no addresses, the option will not be added.
717 *
718 * @returns true/false just like begin().
719 *
720 * @param uOption The option number.
721 * @param rIPv4Addrs Reference to the address vector.
722 */
723 bool optIPv4Addrs(uint8_t uOption, std::vector<RTNETADDRIPV4> const &rIPv4Addrs)
724 {
725 size_t const c = rIPv4Addrs.size();
726 if (!c)
727 return true;
728
729 if (!begin(uOption, 4*c))
730 return false;
731 for (size_t i = 0; i < c; i++)
732 putIPv4Addr(rIPv4Addrs[i]);
733 return true;
734 }
735
736 /**
737 * Puts an 8-bit integer.
738 *
739 * @param u8 The integer.
740 */
741 void putU8(uint8_t u8)
742 {
743 put(&u8, 1);
744 }
745
746 /**
747 * Adds an 8-bit integer option.
748 *
749 * @returns true/false just like begin().
750 *
751 * @param uOption The option number.
752 * @param u8 The integer
753 */
754 bool optU8(uint8_t uOption, uint8_t u8)
755 {
756 if (!begin(uOption, 1))
757 return false;
758 putU8(u8);
759 return true;
760 }
761
762 /**
763 * Puts an 32-bit integer (network endian).
764 *
765 * @param u32 The integer.
766 */
767 void putU32(uint32_t u32)
768 {
769 put(&u32, 4);
770 }
771
772 /**
773 * Adds an 32-bit integer (network endian) option.
774 *
775 * @returns true/false just like begin().
776 *
777 * @param uOption The option number.
778 * @param u32 The integer.
779 */
780 bool optU32(uint8_t uOption, uint32_t u32)
781 {
782 if (!begin(uOption, 4))
783 return false;
784 putU32(u32);
785 return true;
786 }
787
788 /**
789 * Puts a std::string.
790 *
791 * @param rStr Reference to the string.
792 */
793 void putStr(std::string const &rStr)
794 {
795 put(rStr.c_str(), rStr.size());
796 }
797
798 /**
799 * Adds an std::string option if the string isn't empty.
800 *
801 * @returns true/false just like begin().
802 *
803 * @param uOption The option number.
804 * @param rStr Reference to the string.
805 */
806 bool optStr(uint8_t uOption, std::string const &rStr)
807 {
808 const size_t cch = rStr.size();
809 if (!cch)
810 return true;
811
812 if (!begin(uOption, cch))
813 return false;
814 put(rStr.c_str(), cch);
815 return true;
816 }
817
818 /**
819 * Whether we've overflowed.
820 *
821 * @returns true on overflow, false otherwise.
822 */
823 bool hasOverflowed(void) const
824 {
825 return m_fOverflowed;
826 }
827
828 /**
829 * Adds the terminating END option.
830 *
831 * The END will always be added as we're reserving room for it, however, we
832 * might have dropped previous options due to overflows and that is what the
833 * return status indicates.
834 *
835 * @returns true on success, false on a (previous) overflow.
836 */
837 bool optEnd(void)
838 {
839 Assert((uintptr_t)(m_pbEnd - m_pbCur) < 4096);
840 *m_pbCur++ = RTNET_DHCP_OPT_END;
841 return !hasOverflowed();
842 }
843};
844
845#endif /* !VBOX_INCLUDED_SRC_DHCP_Config_h */
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