VirtualBox

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

Last change on this file since 49409 was 49328, checked in by vboxsync, 11 years ago

NetServices/DHCP: XML lease serialization/deserialization.

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