VirtualBox

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

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

VBoxNetDHCP/Config.h uses shared declaration of "<" operator.

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