VirtualBox

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

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

NetworkServices/DHCP: use Utf8Str

  • 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 50587 2014-02-25 16:37:29Z 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#include <VBox/com/string.h>
24
25#include "../NetLib/cpp/utils.h"
26
27
28static bool operator > (const RTNETADDRIPV4& a, const RTNETADDRIPV4& b)
29{
30 return (b < a);
31}
32
33
34class RawOption
35{
36public:
37 RawOption()
38 {
39 RT_ZERO(*this);
40 }
41 uint8_t u8OptId;
42 uint8_t cbRawOpt;
43 uint8_t au8RawOpt[255];
44};
45
46class ClientData;
47class Client;
48class Lease;
49class BaseConfigEntity;
50
51class NetworkConfigEntity;
52class HostConfigEntity;
53class ClientMatchCriteria;
54class ConfigurationManager;
55
56/*
57 * it's a basic representation of
58 * of out undestanding what client is
59 * XXX: Client might sends Option 61 (RFC2132 9.14 "Client-identifier") signalling
60 * that we may identify it in special way
61 *
62 * XXX: Client might send Option 60 (RFC2132 9.13 "Vendor class undentifier")
63 * in response it's expected server sends Option 43 (RFC2132 8.4. "Vendor Specific Information")
64 */
65class Client
66{
67 friend class Lease;
68 friend class ConfigurationManager;
69
70 public:
71 Client();
72 void initWithMac(const RTMAC& mac);
73 bool operator== (const RTMAC& mac) const;
74 const RTMAC& getMacAddress() const;
75
76 /** Dumps client query */
77 void dump();
78
79 Lease lease();
80 const Lease lease() const;
81
82 public:
83 static const Client NullClient;
84
85 private:
86 Client(ClientData *);
87 SharedPtr<ClientData> m;
88};
89
90
91bool operator== (const Lease&, const Lease&);
92bool operator!= (const Lease&, const Lease&);
93bool operator< (const Lease&, const Lease&);
94
95
96typedef std::map<uint8_t, RawOption> MapOptionId2RawOption;
97typedef MapOptionId2RawOption::iterator MapOptionId2RawOptionIterator;
98typedef MapOptionId2RawOption::const_iterator MapOptionId2RawOptionConstIterator;
99typedef MapOptionId2RawOption::value_type MapOptionId2RawOptionValue;
100
101namespace xml {
102 class ElementNode;
103}
104
105class Lease
106{
107 friend class Client;
108 friend bool operator== (const Lease&, const Lease&);
109 //friend int ConfigurationManager::loadFromFile(const std::string&);
110 friend class ConfigurationManager;
111
112 public:
113 Lease();
114 Lease(const Client&);
115
116 bool isExpired() const;
117 void expire();
118
119 /* Depending on phase *Expiration and phaseStart initialize different values. */
120 void bindingPhase(bool);
121 void phaseStart(uint64_t u64Start);
122 bool isInBindingPhase() const;
123 /* returns 0 if in binding state */
124 uint64_t issued() const;
125
126 void setExpiration(uint32_t);
127 uint32_t getExpiration() const;
128
129 RTNETADDRIPV4 getAddress() const;
130 void setAddress(RTNETADDRIPV4);
131
132 const NetworkConfigEntity *getConfig() const;
133 void setConfig(NetworkConfigEntity *);
134
135 const MapOptionId2RawOption& options() const;
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 com::Utf8Str&);
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, const uint8_t *pu8ReqList, int cReqList, std::vector<RawOption>& extra);
519
520private:
521 struct Data;
522 Data *m;
523
524};
525
526
527extern const ClientMatchCriteria *g_AnyClient;
528extern RootConfigEntity *g_RootConfig;
529extern const NullConfigEntity *g_NullConfig;
530
531/**
532 * Helper class for stuffing DHCP options into a reply packet.
533 */
534class VBoxNetDhcpWriteCursor
535{
536private:
537 uint8_t *m_pbCur; /**< The current cursor position. */
538 uint8_t *m_pbEnd; /**< The end the current option space. */
539 uint8_t *m_pfOverload; /**< Pointer to the flags of the overload option. */
540 uint8_t m_fUsed; /**< Overload fields that have been used. */
541 PRTNETDHCPOPT m_pOpt; /**< The current option. */
542 PRTNETBOOTP m_pDhcp; /**< The DHCP packet. */
543 bool m_fOverflowed; /**< Set if we've overflowed, otherwise false. */
544
545public:
546 /** Instantiate an option cursor for the specified DHCP message. */
547 VBoxNetDhcpWriteCursor(PRTNETBOOTP pDhcp, size_t cbDhcp) :
548 m_pbCur(&pDhcp->bp_vend.Dhcp.dhcp_opts[0]),
549 m_pbEnd((uint8_t *)pDhcp + cbDhcp),
550 m_pfOverload(NULL),
551 m_fUsed(0),
552 m_pOpt(NULL),
553 m_pDhcp(pDhcp),
554 m_fOverflowed(false)
555 {
556 AssertPtr(pDhcp);
557 Assert(cbDhcp > RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts[10]));
558 }
559
560 /** Destructor. */
561 ~VBoxNetDhcpWriteCursor()
562 {
563 m_pbCur = m_pbEnd = m_pfOverload = NULL;
564 m_pOpt = NULL;
565 m_pDhcp = NULL;
566 }
567
568 /**
569 * Try use the bp_file field.
570 * @returns true if not overloaded, false otherwise.
571 */
572 bool useBpFile(void)
573 {
574 if ( m_pfOverload
575 && (*m_pfOverload & 1))
576 return false;
577 m_fUsed |= 1 /* bp_file flag*/;
578 return true;
579 }
580
581
582 /**
583 * Try overload more BOOTP fields
584 */
585 bool overloadMore(void)
586 {
587 /* switch option area. */
588 uint8_t *pbNew;
589 uint8_t *pbNewEnd;
590 uint8_t fField;
591 if (!(m_fUsed & 1))
592 {
593 fField = 1;
594 pbNew = &m_pDhcp->bp_file[0];
595 pbNewEnd = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)];
596 }
597 else if (!(m_fUsed & 2))
598 {
599 fField = 2;
600 pbNew = &m_pDhcp->bp_sname[0];
601 pbNewEnd = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)];
602 }
603 else
604 return false;
605
606 if (!m_pfOverload)
607 {
608 /* Add an overload option. */
609 *m_pbCur++ = RTNET_DHCP_OPT_OPTION_OVERLOAD;
610 *m_pbCur++ = fField;
611 m_pfOverload = m_pbCur;
612 *m_pbCur++ = 1; /* bp_file flag */
613 }
614 else
615 *m_pfOverload |= fField;
616
617 /* pad current option field */
618 while (m_pbCur != m_pbEnd)
619 *m_pbCur++ = RTNET_DHCP_OPT_PAD; /** @todo not sure if this stuff is at all correct... */
620
621 /* switch */
622 m_pbCur = pbNew;
623 m_pbEnd = pbNewEnd;
624 return true;
625 }
626
627 /**
628 * Begin an option.
629 *
630 * @returns true on success, false if we're out of space.
631 *
632 * @param uOption The option number.
633 * @param cb The amount of data.
634 */
635 bool begin(uint8_t uOption, size_t cb)
636 {
637 /* Check that the data of the previous option has all been written. */
638 Assert( !m_pOpt
639 || (m_pbCur - m_pOpt->dhcp_len == (uint8_t *)(m_pOpt + 1)));
640 AssertMsg(cb <= 255, ("%#x\n", cb));
641
642 /* Check if we need to overload more stuff. */
643 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + (m_pfOverload ? 1 : 3))
644 {
645 m_pOpt = NULL;
646 if (!overloadMore())
647 {
648 m_fOverflowed = true;
649 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
650 }
651 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 1)
652 {
653 m_fOverflowed = true;
654 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
655 }
656 }
657
658 /* Emit the option header. */
659 m_pOpt = (PRTNETDHCPOPT)m_pbCur;
660 m_pOpt->dhcp_opt = uOption;
661 m_pOpt->dhcp_len = (uint8_t)cb;
662 m_pbCur += 2;
663 return true;
664 }
665
666 /**
667 * Puts option data.
668 *
669 * @param pvData The data.
670 * @param cb The amount to put.
671 */
672 void put(void const *pvData, size_t cb)
673 {
674 Assert(m_pOpt || m_fOverflowed);
675 if (RT_LIKELY(m_pOpt))
676 {
677 Assert((uintptr_t)m_pbCur - (uintptr_t)(m_pOpt + 1) + cb <= (size_t)m_pOpt->dhcp_len);
678 memcpy(m_pbCur, pvData, cb);
679 m_pbCur += cb;
680 }
681 }
682
683 /**
684 * Puts an IPv4 Address.
685 *
686 * @param IPv4Addr The address.
687 */
688 void putIPv4Addr(RTNETADDRIPV4 IPv4Addr)
689 {
690 put(&IPv4Addr, 4);
691 }
692
693 /**
694 * Adds an IPv4 address option.
695 *
696 * @returns true/false just like begin().
697 *
698 * @param uOption The option number.
699 * @param IPv4Addr The address.
700 */
701 bool optIPv4Addr(uint8_t uOption, RTNETADDRIPV4 IPv4Addr)
702 {
703 if (!begin(uOption, 4))
704 return false;
705 putIPv4Addr(IPv4Addr);
706 return true;
707 }
708
709 /**
710 * Adds an option taking 1 or more IPv4 address.
711 *
712 * If the vector contains no addresses, the option will not be added.
713 *
714 * @returns true/false just like begin().
715 *
716 * @param uOption The option number.
717 * @param rIPv4Addrs Reference to the address vector.
718 */
719 bool optIPv4Addrs(uint8_t uOption, std::vector<RTNETADDRIPV4> const &rIPv4Addrs)
720 {
721 size_t const c = rIPv4Addrs.size();
722 if (!c)
723 return true;
724
725 if (!begin(uOption, 4*c))
726 return false;
727 for (size_t i = 0; i < c; i++)
728 putIPv4Addr(rIPv4Addrs[i]);
729 return true;
730 }
731
732 /**
733 * Puts an 8-bit integer.
734 *
735 * @param u8 The integer.
736 */
737 void putU8(uint8_t u8)
738 {
739 put(&u8, 1);
740 }
741
742 /**
743 * Adds an 8-bit integer option.
744 *
745 * @returns true/false just like begin().
746 *
747 * @param uOption The option number.
748 * @param u8 The integer
749 */
750 bool optU8(uint8_t uOption, uint8_t u8)
751 {
752 if (!begin(uOption, 1))
753 return false;
754 putU8(u8);
755 return true;
756 }
757
758 /**
759 * Puts an 32-bit integer (network endian).
760 *
761 * @param u32Network The integer.
762 */
763 void putU32(uint32_t u32)
764 {
765 put(&u32, 4);
766 }
767
768 /**
769 * Adds an 32-bit integer (network endian) option.
770 *
771 * @returns true/false just like begin().
772 *
773 * @param uOption The option number.
774 * @param u32Network The integer.
775 */
776 bool optU32(uint8_t uOption, uint32_t u32)
777 {
778 if (!begin(uOption, 4))
779 return false;
780 putU32(u32);
781 return true;
782 }
783
784 /**
785 * Puts a std::string.
786 *
787 * @param rStr Reference to the string.
788 */
789 void putStr(std::string const &rStr)
790 {
791 put(rStr.c_str(), rStr.size());
792 }
793
794 /**
795 * Adds an std::string option if the string isn't empty.
796 *
797 * @returns true/false just like begin().
798 *
799 * @param uOption The option number.
800 * @param rStr Reference to the string.
801 */
802 bool optStr(uint8_t uOption, std::string const &rStr)
803 {
804 const size_t cch = rStr.size();
805 if (!cch)
806 return true;
807
808 if (!begin(uOption, cch))
809 return false;
810 put(rStr.c_str(), cch);
811 return true;
812 }
813
814 /**
815 * Whether we've overflowed.
816 *
817 * @returns true on overflow, false otherwise.
818 */
819 bool hasOverflowed(void) const
820 {
821 return m_fOverflowed;
822 }
823
824 /**
825 * Adds the terminating END option.
826 *
827 * The END will always be added as we're reserving room for it, however, we
828 * might have dropped previous options due to overflows and that is what the
829 * return status indicates.
830 *
831 * @returns true on success, false on a (previous) overflow.
832 */
833 bool optEnd(void)
834 {
835 Assert((uintptr_t)(m_pbEnd - m_pbCur) < 4096);
836 *m_pbCur++ = RTNET_DHCP_OPT_END;
837 return !hasOverflowed();
838 }
839};
840
841#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