VirtualBox

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

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

DHCP/NetworkManager: visibility (ack,nak, offer4Client) from public to private.

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