VirtualBox

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

Last change on this file since 57236 was 56300, checked in by vboxsync, 10 years ago

NetworkServices: Updated (C) year.

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