VirtualBox

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

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

VBoxNetDHCP: Leases shouldn't cache settings which are could be changed at run-time, e.g. DNS settings.

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