VirtualBox

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

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

spaces

  • 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 50213 2014-01-24 08:23:12Z 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
526extern const ClientMatchCriteria *g_AnyClient;
527extern RootConfigEntity *g_RootConfig;
528extern const NullConfigEntity *g_NullConfig;
529
530/**
531 * Helper class for stuffing DHCP options into a reply packet.
532 */
533class VBoxNetDhcpWriteCursor
534{
535private:
536 uint8_t *m_pbCur; /**< The current cursor position. */
537 uint8_t *m_pbEnd; /**< The end the current option space. */
538 uint8_t *m_pfOverload; /**< Pointer to the flags of the overload option. */
539 uint8_t m_fUsed; /**< Overload fields that have been used. */
540 PRTNETDHCPOPT m_pOpt; /**< The current option. */
541 PRTNETBOOTP m_pDhcp; /**< The DHCP packet. */
542 bool m_fOverflowed; /**< Set if we've overflowed, otherwise false. */
543
544public:
545 /** Instantiate an option cursor for the specified DHCP message. */
546 VBoxNetDhcpWriteCursor(PRTNETBOOTP pDhcp, size_t cbDhcp) :
547 m_pbCur(&pDhcp->bp_vend.Dhcp.dhcp_opts[0]),
548 m_pbEnd((uint8_t *)pDhcp + cbDhcp),
549 m_pfOverload(NULL),
550 m_fUsed(0),
551 m_pOpt(NULL),
552 m_pDhcp(pDhcp),
553 m_fOverflowed(false)
554 {
555 AssertPtr(pDhcp);
556 Assert(cbDhcp > RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts[10]));
557 }
558
559 /** Destructor. */
560 ~VBoxNetDhcpWriteCursor()
561 {
562 m_pbCur = m_pbEnd = m_pfOverload = NULL;
563 m_pOpt = NULL;
564 m_pDhcp = NULL;
565 }
566
567 /**
568 * Try use the bp_file field.
569 * @returns true if not overloaded, false otherwise.
570 */
571 bool useBpFile(void)
572 {
573 if ( m_pfOverload
574 && (*m_pfOverload & 1))
575 return false;
576 m_fUsed |= 1 /* bp_file flag*/;
577 return true;
578 }
579
580
581 /**
582 * Try overload more BOOTP fields
583 */
584 bool overloadMore(void)
585 {
586 /* switch option area. */
587 uint8_t *pbNew;
588 uint8_t *pbNewEnd;
589 uint8_t fField;
590 if (!(m_fUsed & 1))
591 {
592 fField = 1;
593 pbNew = &m_pDhcp->bp_file[0];
594 pbNewEnd = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)];
595 }
596 else if (!(m_fUsed & 2))
597 {
598 fField = 2;
599 pbNew = &m_pDhcp->bp_sname[0];
600 pbNewEnd = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)];
601 }
602 else
603 return false;
604
605 if (!m_pfOverload)
606 {
607 /* Add an overload option. */
608 *m_pbCur++ = RTNET_DHCP_OPT_OPTION_OVERLOAD;
609 *m_pbCur++ = fField;
610 m_pfOverload = m_pbCur;
611 *m_pbCur++ = 1; /* bp_file flag */
612 }
613 else
614 *m_pfOverload |= fField;
615
616 /* pad current option field */
617 while (m_pbCur != m_pbEnd)
618 *m_pbCur++ = RTNET_DHCP_OPT_PAD; /** @todo not sure if this stuff is at all correct... */
619
620 /* switch */
621 m_pbCur = pbNew;
622 m_pbEnd = pbNewEnd;
623 return true;
624 }
625
626 /**
627 * Begin an option.
628 *
629 * @returns true on success, false if we're out of space.
630 *
631 * @param uOption The option number.
632 * @param cb The amount of data.
633 */
634 bool begin(uint8_t uOption, size_t cb)
635 {
636 /* Check that the data of the previous option has all been written. */
637 Assert( !m_pOpt
638 || (m_pbCur - m_pOpt->dhcp_len == (uint8_t *)(m_pOpt + 1)));
639 AssertMsg(cb <= 255, ("%#x\n", cb));
640
641 /* Check if we need to overload more stuff. */
642 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + (m_pfOverload ? 1 : 3))
643 {
644 m_pOpt = NULL;
645 if (!overloadMore())
646 {
647 m_fOverflowed = true;
648 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
649 }
650 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 1)
651 {
652 m_fOverflowed = true;
653 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false);
654 }
655 }
656
657 /* Emit the option header. */
658 m_pOpt = (PRTNETDHCPOPT)m_pbCur;
659 m_pOpt->dhcp_opt = uOption;
660 m_pOpt->dhcp_len = (uint8_t)cb;
661 m_pbCur += 2;
662 return true;
663 }
664
665 /**
666 * Puts option data.
667 *
668 * @param pvData The data.
669 * @param cb The amount to put.
670 */
671 void put(void const *pvData, size_t cb)
672 {
673 Assert(m_pOpt || m_fOverflowed);
674 if (RT_LIKELY(m_pOpt))
675 {
676 Assert((uintptr_t)m_pbCur - (uintptr_t)(m_pOpt + 1) + cb <= (size_t)m_pOpt->dhcp_len);
677 memcpy(m_pbCur, pvData, cb);
678 m_pbCur += cb;
679 }
680 }
681
682 /**
683 * Puts an IPv4 Address.
684 *
685 * @param IPv4Addr The address.
686 */
687 void putIPv4Addr(RTNETADDRIPV4 IPv4Addr)
688 {
689 put(&IPv4Addr, 4);
690 }
691
692 /**
693 * Adds an IPv4 address option.
694 *
695 * @returns true/false just like begin().
696 *
697 * @param uOption The option number.
698 * @param IPv4Addr The address.
699 */
700 bool optIPv4Addr(uint8_t uOption, RTNETADDRIPV4 IPv4Addr)
701 {
702 if (!begin(uOption, 4))
703 return false;
704 putIPv4Addr(IPv4Addr);
705 return true;
706 }
707
708 /**
709 * Adds an option taking 1 or more IPv4 address.
710 *
711 * If the vector contains no addresses, the option will not be added.
712 *
713 * @returns true/false just like begin().
714 *
715 * @param uOption The option number.
716 * @param rIPv4Addrs Reference to the address vector.
717 */
718 bool optIPv4Addrs(uint8_t uOption, std::vector<RTNETADDRIPV4> const &rIPv4Addrs)
719 {
720 size_t const c = rIPv4Addrs.size();
721 if (!c)
722 return true;
723
724 if (!begin(uOption, 4*c))
725 return false;
726 for (size_t i = 0; i < c; i++)
727 putIPv4Addr(rIPv4Addrs[i]);
728 return true;
729 }
730
731 /**
732 * Puts an 8-bit integer.
733 *
734 * @param u8 The integer.
735 */
736 void putU8(uint8_t u8)
737 {
738 put(&u8, 1);
739 }
740
741 /**
742 * Adds an 8-bit integer option.
743 *
744 * @returns true/false just like begin().
745 *
746 * @param uOption The option number.
747 * @param u8 The integer
748 */
749 bool optU8(uint8_t uOption, uint8_t u8)
750 {
751 if (!begin(uOption, 1))
752 return false;
753 putU8(u8);
754 return true;
755 }
756
757 /**
758 * Puts an 32-bit integer (network endian).
759 *
760 * @param u32Network The integer.
761 */
762 void putU32(uint32_t u32)
763 {
764 put(&u32, 4);
765 }
766
767 /**
768 * Adds an 32-bit integer (network endian) option.
769 *
770 * @returns true/false just like begin().
771 *
772 * @param uOption The option number.
773 * @param u32Network The integer.
774 */
775 bool optU32(uint8_t uOption, uint32_t u32)
776 {
777 if (!begin(uOption, 4))
778 return false;
779 putU32(u32);
780 return true;
781 }
782
783 /**
784 * Puts a std::string.
785 *
786 * @param rStr Reference to the string.
787 */
788 void putStr(std::string const &rStr)
789 {
790 put(rStr.c_str(), rStr.size());
791 }
792
793 /**
794 * Adds an std::string option if the string isn't empty.
795 *
796 * @returns true/false just like begin().
797 *
798 * @param uOption The option number.
799 * @param rStr Reference to the string.
800 */
801 bool optStr(uint8_t uOption, std::string const &rStr)
802 {
803 const size_t cch = rStr.size();
804 if (!cch)
805 return true;
806
807 if (!begin(uOption, cch))
808 return false;
809 put(rStr.c_str(), cch);
810 return true;
811 }
812
813 /**
814 * Whether we've overflowed.
815 *
816 * @returns true on overflow, false otherwise.
817 */
818 bool hasOverflowed(void) const
819 {
820 return m_fOverflowed;
821 }
822
823 /**
824 * Adds the terminating END option.
825 *
826 * The END will always be added as we're reserving room for it, however, we
827 * might have dropped previous options due to overflows and that is what the
828 * return status indicates.
829 *
830 * @returns true on success, false on a (previous) overflow.
831 */
832 bool optEnd(void)
833 {
834 Assert((uintptr_t)(m_pbEnd - m_pbCur) < 4096);
835 *m_pbCur++ = RTNET_DHCP_OPT_END;
836 return !hasOverflowed();
837 }
838};
839
840#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