VirtualBox

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

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

VBoxNetDHCP/Config.h: warnings [-Wunused-parameter]

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

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