VirtualBox

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

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