VirtualBox

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

Last change on this file since 63266 was 63266, checked in by vboxsync, 8 years ago

NetworkServices: warnings

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