VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.h@ 79761

最後變更 在這個檔案從79761是 79761,由 vboxsync 提交於 6 年 前

Main/DHCPServer,Dhcpd,VBoxManage: Added --log option to the DHCP server so we can start logging early. Added log rotation and limits. Put the config file next to the log and leases file. Validate DHCP options by reusing the parser code from the server, adding a bunch more DHCP options to the parser. Removed legacy and hardcoded configuration options from the dhcp server, it's all config file now. Fixed a bug in the option parsing of the VBoxManage dhcpserver add/modify commands. bugref:9288

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 21.1 KB
 
1/* $Id: DhcpOptions.h 79761 2019-07-14 03:18:41Z vboxsync $ */
2/** @file
3 * DHCP server - DHCP options
4 */
5
6/*
7 * Copyright (C) 2017-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 VBOX_INCLUDED_SRC_Dhcpd_DhcpOptions_h
19#define VBOX_INCLUDED_SRC_Dhcpd_DhcpOptions_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include "DhcpdInternal.h"
25
26#include <iprt/asm.h>
27#include <iprt/err.h>
28#include <iprt/net.h>
29#include <iprt/string.h>
30#include <iprt/cpp/ministring.h>
31
32
33class DhcpClientMessage;
34
35typedef struct DhcpIpv4AddrAndMask
36{
37 RTNETADDRIPV4 Ipv4;
38 RTNETADDRIPV4 Mask;
39} DhcpIpv4AddrAndMask;
40
41
42class DhcpOption
43{
44protected:
45 uint8_t m_OptCode;
46 bool m_fPresent;
47
48public:
49 explicit DhcpOption(uint8_t aOptCode)
50 : m_OptCode(aOptCode), m_fPresent(true)
51 {}
52
53 DhcpOption(uint8_t aOptCode, bool fPresent)
54 : m_OptCode(aOptCode), m_fPresent(fPresent)
55 {}
56
57 virtual DhcpOption *clone() const = 0;
58
59 virtual ~DhcpOption()
60 {}
61
62public:
63 static DhcpOption *parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc = NULL);
64
65public:
66 uint8_t optcode() const RT_NOEXCEPT { return m_OptCode; }
67 bool present() const RT_NOEXCEPT { return m_fPresent; }
68
69public:
70 int encode(octets_t &dst) const;
71
72 int decode(const rawopts_t &map);
73 int decode(const DhcpClientMessage &req);
74
75protected:
76 virtual ssize_t encodeValue(octets_t &dst) const = 0;
77 virtual int decodeValue(const octets_t &src, size_t cb) = 0;
78
79protected:
80 static const octets_t *findOption(const rawopts_t &aOptMap, uint8_t aOptCode);
81
82protected:
83 /** @name Serialization
84 * @{ */
85 static void append(octets_t &aDst, bool aValue)
86 {
87 uint8_t b = aValue ? 1 : 0;
88 aDst.push_back(b);
89 }
90
91 static void append(octets_t &aDst, uint8_t aValue)
92 {
93 aDst.push_back(aValue);
94 }
95
96 static void append(octets_t &aDst, uint16_t aValue)
97 {
98 RTUINT16U u16 = { RT_H2N_U16(aValue) };
99 aDst.insert(aDst.end(), u16.au8, u16.au8 + sizeof(aValue));
100 }
101
102 static void append(octets_t &aDst, uint32_t aValue)
103 {
104 RTUINT32U u32 = { RT_H2N_U32(aValue) };
105 aDst.insert(aDst.end(), u32.au8, u32.au8 + sizeof(aValue));
106 }
107
108 static void append(octets_t &aDst, RTNETADDRIPV4 aIPv4)
109 {
110 aDst.insert(aDst.end(), aIPv4.au8, aIPv4.au8 + sizeof(aIPv4));
111 }
112
113 static void append(octets_t &aDst, DhcpIpv4AddrAndMask aIPv4)
114 {
115 aDst.insert(aDst.end(), (uint8_t *)&aIPv4, (uint8_t *)&aIPv4 + sizeof(aIPv4));
116 }
117
118 static void append(octets_t &aDst, const char *pszString, size_t cb)
119 {
120 aDst.insert(aDst.end(), pszString, pszString + cb);
121 }
122
123 static void append(octets_t &aDst, const RTCString &str)
124 {
125 append(aDst, str.c_str(), str.length());
126 }
127
128 /* non-overloaded name to avoid ambiguity */
129 static void appendLength(octets_t &aDst, size_t cb)
130 {
131 append(aDst, static_cast<uint8_t>(cb));
132 }
133
134 /** @} */
135
136
137 /** @name Deserialization
138 * @{ */
139 static void extract(bool &aValue, octets_t::const_iterator &pos)
140 {
141 aValue = *pos != 0;
142 pos += sizeof(uint8_t);
143 }
144
145 static void extract(uint8_t &aValue, octets_t::const_iterator &pos)
146 {
147 aValue = *pos;
148 pos += sizeof(uint8_t);
149 }
150
151 static void extract(uint16_t &aValue, octets_t::const_iterator &pos)
152 {
153 RTUINT16U u16;
154 memcpy(u16.au8, &pos[0], sizeof(uint16_t));
155 aValue = RT_N2H_U16(u16.u);
156 pos += sizeof(uint16_t);
157 }
158
159 static void extract(uint32_t &aValue, octets_t::const_iterator &pos)
160 {
161 RTUINT32U u32;
162 memcpy(u32.au8, &pos[0], sizeof(uint32_t));
163 aValue = RT_N2H_U32(u32.u);
164 pos += sizeof(uint32_t);
165 }
166
167 static void extract(RTNETADDRIPV4 &aValue, octets_t::const_iterator &pos)
168 {
169 memcpy(aValue.au8, &pos[0], sizeof(RTNETADDRIPV4));
170 pos += sizeof(RTNETADDRIPV4);
171 }
172
173 static void extract(DhcpIpv4AddrAndMask &aValue, octets_t::const_iterator &pos)
174 {
175 memcpy(&aValue, &pos[0], sizeof(aValue));
176 pos += sizeof(aValue);
177 }
178
179#if 0 /** @todo fix me */
180 static void extract(RTCString &aString, octets_t::const_iterator &pos, size_t cb)
181 {
182 aString.replace(aString.begin(), aString.end(), &pos[0], &pos[cb]);
183 pos += cb;
184 }
185#endif
186
187 /** @} */
188
189 /** @name Parse textual representation (e.g. in config file)
190 * @{ */
191 static int parse1(bool &aValue, const char *pcszValue);
192 static int parse1(uint8_t &aValue, const char *pcszValue);
193 static int parse1(uint16_t &aValue, const char *pcszValue);
194 static int parse1(uint32_t &aValue, const char *pcszValue);
195 static int parse1(RTNETADDRIPV4 &aValue, const char *pcszValue);
196 static int parse1(DhcpIpv4AddrAndMask &aValue, const char *pcszValue);
197
198 template <typename a_Type> static int parseList(std::vector<a_Type> &aList, const char *pcszValue);
199
200 static int parseHex(octets_t &aRawValue, const char *pcszValue);
201
202 /** @} */
203};
204
205
206inline octets_t &operator<<(octets_t &dst, const DhcpOption &option)
207{
208 option.encode(dst);
209 return dst;
210}
211
212
213optmap_t &operator<<(optmap_t &optmap, DhcpOption *option);
214optmap_t &operator<<(optmap_t &optmap, const std::shared_ptr<DhcpOption> &option);
215
216
217
218/**
219 * Only for << OptEnd() syntactic sugar...
220 */
221struct OptEnd {};
222inline octets_t &operator<<(octets_t &dst, const OptEnd &end)
223{
224 RT_NOREF(end);
225
226 dst.push_back(RTNET_DHCP_OPT_END);
227 return dst;
228}
229
230
231
232/**
233 * Option that has no value
234 */
235class OptNoValueBase
236 : public DhcpOption
237{
238public:
239 explicit OptNoValueBase(uint8_t aOptCode)
240 : DhcpOption(aOptCode, false)
241 {}
242
243 OptNoValueBase(uint8_t aOptCode, bool fPresent)
244 : DhcpOption(aOptCode, fPresent)
245 {}
246
247 OptNoValueBase(uint8_t aOptCode, const DhcpClientMessage &req)
248 : DhcpOption(aOptCode, false)
249 {
250 decode(req);
251 }
252
253 virtual OptNoValueBase *clone() const
254 {
255 return new OptNoValueBase(*this);
256 }
257
258protected:
259 virtual ssize_t encodeValue(octets_t &dst) const
260 {
261 RT_NOREF(dst);
262 return 0;
263 }
264
265public:
266 static bool isLengthValid(size_t cb)
267 {
268 return cb == 0;
269 }
270
271 virtual int decodeValue(const octets_t &src, size_t cb)
272 {
273 RT_NOREF(src);
274
275 if (!isLengthValid(cb))
276 return VERR_INVALID_PARAMETER;
277
278 m_fPresent = true;
279 return VINF_SUCCESS;
280 }
281};
282
283template <uint8_t _OptCode>
284class OptNoValue
285 : public OptNoValueBase
286{
287public:
288 static const uint8_t optcode = _OptCode;
289
290 OptNoValue()
291 : OptNoValueBase(optcode)
292 {}
293
294 explicit OptNoValue(bool fPresent) /* there's no overloaded ctor with value */
295 : OptNoValueBase(optcode, fPresent)
296 {}
297
298 explicit OptNoValue(const DhcpClientMessage &req)
299 : OptNoValueBase(optcode, req)
300 {}
301};
302
303
304
305/*
306 * Option that contains single value of fixed-size type T
307 */
308template <typename T>
309class OptValueBase
310 : public DhcpOption
311{
312public:
313 typedef T value_t;
314
315protected:
316 T m_Value;
317
318 explicit OptValueBase(uint8_t aOptCode)
319 : DhcpOption(aOptCode, false), m_Value()
320 {}
321
322 OptValueBase(uint8_t aOptCode, const T &aOptValue)
323 : DhcpOption(aOptCode), m_Value(aOptValue)
324 {}
325
326 OptValueBase(uint8_t aOptCode, const DhcpClientMessage &req)
327 : DhcpOption(aOptCode, false), m_Value()
328 {
329 decode(req);
330 }
331
332public:
333 virtual OptValueBase *clone() const
334 {
335 return new OptValueBase(*this);
336 }
337
338public:
339 T &value() { return m_Value; }
340 const T &value() const { return m_Value; }
341
342protected:
343 virtual ssize_t encodeValue(octets_t &dst) const
344 {
345 append(dst, m_Value);
346 return sizeof(T);
347 }
348
349public:
350 static bool isLengthValid(size_t cb)
351 {
352 return cb == sizeof(T);
353 }
354
355 virtual int decodeValue(const octets_t &src, size_t cb)
356 {
357 if (!isLengthValid(cb))
358 return VERR_INVALID_PARAMETER;
359
360 octets_t::const_iterator pos(src.begin());
361 extract(m_Value, pos);
362
363 m_fPresent = true;
364 return VINF_SUCCESS;
365 }
366};
367
368template<uint8_t _OptCode, typename T>
369class OptValue
370 : public OptValueBase<T>
371{
372public:
373 using typename OptValueBase<T>::value_t;
374
375public:
376 static const uint8_t optcode = _OptCode;
377
378 OptValue()
379 : OptValueBase<T>(optcode)
380 {}
381
382 explicit OptValue(const T &aOptValue)
383 : OptValueBase<T>(optcode, aOptValue)
384 {}
385
386 explicit OptValue(const DhcpClientMessage &req)
387 : OptValueBase<T>(optcode, req)
388 {}
389
390 static OptValue *parse(const char *pcszValue, int *prc)
391 {
392 typename OptValueBase<T>::value_t v;
393 int rc = DhcpOption::parse1(v, pcszValue);
394 *prc = rc;
395 if (RT_SUCCESS(rc))
396 return new OptValue(v);
397 return NULL;
398 }
399};
400
401
402
403/**
404 * Option that contains a string.
405 */
406class OptStringBase
407 : public DhcpOption
408{
409public:
410 typedef RTCString value_t;
411
412protected:
413 RTCString m_String;
414
415 explicit OptStringBase(uint8_t aOptCode)
416 : DhcpOption(aOptCode, false), m_String()
417 {}
418
419 OptStringBase(uint8_t aOptCode, const RTCString &aOptString)
420 : DhcpOption(aOptCode), m_String(aOptString)
421 {}
422
423 OptStringBase(uint8_t aOptCode, const DhcpClientMessage &req)
424 : DhcpOption(aOptCode, false), m_String()
425 {
426 decode(req);
427 }
428
429public:
430 virtual OptStringBase *clone() const
431 {
432 return new OptStringBase(*this);
433 }
434
435public:
436 RTCString &value() { return m_String; }
437 const RTCString &value() const { return m_String; }
438
439protected:
440 virtual ssize_t encodeValue(octets_t &dst) const
441 {
442 if (!isLengthValid(m_String.length()))
443 return -1;
444
445 append(dst, m_String);
446 return m_String.length();
447 }
448
449public:
450 static bool isLengthValid(size_t cb)
451 {
452 return cb <= UINT8_MAX;
453 }
454
455 virtual int decodeValue(const octets_t &src, size_t cb)
456 {
457 if (!isLengthValid(cb))
458 return VERR_INVALID_PARAMETER;
459
460 int rc = m_String.assignNoThrow((char *)&src.front(), cb); /** @todo encoding. */
461 m_fPresent = true;
462 return rc;
463 }
464};
465
466template<uint8_t _OptCode>
467class OptString
468 : public OptStringBase
469{
470public:
471 static const uint8_t optcode = _OptCode;
472
473 OptString()
474 : OptStringBase(optcode)
475 {}
476
477 explicit OptString(const RTCString &aOptString)
478 : OptStringBase(optcode, aOptString)
479 {}
480
481 explicit OptString(const DhcpClientMessage &req)
482 : OptStringBase(optcode, req)
483 {}
484
485 static OptString *parse(const char *pcszValue, int *prc)
486 {
487 *prc = VINF_SUCCESS;
488 return new OptString(pcszValue);
489 }
490};
491
492
493
494/*
495 * Option that contains a list of values of type T
496 */
497template <typename T>
498class OptListBase
499 : public DhcpOption
500{
501public:
502 typedef std::vector<T> value_t;
503
504protected:
505 std::vector<T> m_List;
506
507 explicit OptListBase(uint8_t aOptCode)
508 : DhcpOption(aOptCode, false), m_List()
509 {}
510
511 OptListBase(uint8_t aOptCode, const T &aOptSingle)
512 : DhcpOption(aOptCode), m_List(1, aOptSingle)
513 {}
514
515 OptListBase(uint8_t aOptCode, const std::vector<T> &aOptList)
516 : DhcpOption(aOptCode), m_List(aOptList)
517 {}
518
519 OptListBase(uint8_t aOptCode, const DhcpClientMessage &req)
520 : DhcpOption(aOptCode, false), m_List()
521 {
522 decode(req);
523 }
524
525public:
526 virtual OptListBase *clone() const
527 {
528 return new OptListBase(*this);
529 }
530
531public:
532 std::vector<T> &value() { return m_List; }
533 const std::vector<T> &value() const { return m_List; }
534
535protected:
536 virtual ssize_t encodeValue(octets_t &dst) const
537 {
538 const size_t cbItem = sizeof(T);
539 size_t cbValue = 0;
540
541 for (size_t i = 0; i < m_List.size(); ++i)
542 {
543 if (cbValue + cbItem > UINT8_MAX)
544 break;
545
546 append(dst, m_List[i]);
547 cbValue += cbItem;
548 }
549
550 return cbValue;
551 }
552
553public:
554 static bool isLengthValid(size_t cb)
555 {
556 return cb % sizeof(T) == 0;
557 }
558
559 virtual int decodeValue(const octets_t &src, size_t cb)
560 {
561 if (!isLengthValid(cb))
562 return VERR_INVALID_PARAMETER;
563
564 m_List.erase(m_List.begin(), m_List.end());
565
566 octets_t::const_iterator pos(src.begin());
567 for (size_t i = 0; i < cb / sizeof(T); ++i)
568 {
569 T item;
570 extract(item, pos);
571 m_List.push_back(item);
572 }
573 m_fPresent = true;
574 return VINF_SUCCESS;
575 }
576};
577
578template<uint8_t _OptCode, typename T>
579class OptList
580 : public OptListBase<T>
581
582{
583public:
584 using typename OptListBase<T>::value_t;
585
586public:
587 static const uint8_t optcode = _OptCode;
588
589 OptList()
590 : OptListBase<T>(optcode)
591 {}
592
593 explicit OptList(const T &aOptSingle)
594 : OptListBase<T>(optcode, aOptSingle)
595 {}
596
597 explicit OptList(const std::vector<T> &aOptList)
598 : OptListBase<T>(optcode, aOptList)
599 {}
600
601 explicit OptList(const DhcpClientMessage &req)
602 : OptListBase<T>(optcode, req)
603 {}
604
605 static OptList *parse(const char *pcszValue, int *prc)
606 {
607 typename OptListBase<T>::value_t v;
608 int rc = DhcpOption::parseList<T>(v, pcszValue);
609 if (RT_SUCCESS(rc))
610 {
611 if (!v.empty())
612 {
613 *prc = rc;
614 return new OptList(v);
615 }
616 rc = VERR_NO_DATA;
617 }
618 *prc = rc;
619 return NULL;
620 }
621};
622
623
624template<uint8_t _OptCode, typename T>
625class OptPairList
626 : public OptListBase<T>
627
628{
629public:
630 using typename OptListBase<T>::value_t;
631
632public:
633 static const uint8_t optcode = _OptCode;
634
635 OptPairList()
636 : OptListBase<T>(optcode)
637 {}
638
639 explicit OptPairList(const T &aOptSingle)
640 : OptListBase<T>(optcode, aOptSingle)
641 {}
642
643 explicit OptPairList(const std::vector<T> &aOptList)
644 : OptListBase<T>(optcode, aOptList)
645 {}
646
647 explicit OptPairList(const DhcpClientMessage &req)
648 : OptListBase<T>(optcode, req)
649 {}
650
651 static OptPairList *parse(const char *pcszValue, int *prc)
652 {
653 typename OptListBase<T>::value_t v;
654 int rc = DhcpOption::parseList<T>(v, pcszValue);
655 if (RT_SUCCESS(rc))
656 {
657 if (!v.empty())
658 {
659 if ((v.size() & 1) == 0)
660 {
661 *prc = rc;
662 return new OptPairList(v);
663 }
664 rc = VERR_UNEVEN_INPUT;
665 }
666 else
667 rc = VERR_NO_DATA;
668 }
669 *prc = rc;
670 return NULL;
671 }
672};
673
674
675/*
676 * Options specified by raw binary data that we don't know how to
677 * interpret.
678 */
679class RawOption
680 : public DhcpOption
681{
682protected:
683 octets_t m_Data;
684
685public:
686 explicit RawOption(uint8_t aOptCode)
687 : DhcpOption(aOptCode, false), m_Data()
688 {}
689
690 RawOption(uint8_t aOptCode, const octets_t &aSrc)
691 : DhcpOption(aOptCode), m_Data(aSrc)
692 {}
693
694public:
695 virtual RawOption *clone() const
696 {
697 return new RawOption(*this);
698 }
699
700
701protected:
702 virtual ssize_t encodeValue(octets_t &dst) const
703 {
704 dst.insert(dst.end(), m_Data.begin(), m_Data.end());
705 return m_Data.size();
706 }
707
708 virtual int decodeValue(const octets_t &src, size_t cb)
709 {
710 octets_t::const_iterator beg(src.begin());
711 octets_t data(beg, beg + cb);
712 m_Data.swap(data);
713
714 m_fPresent = true;
715 return VINF_SUCCESS;
716 }
717
718public:
719 static RawOption *parse(uint8_t aOptCode, const char *pcszValue, int *prc)
720 {
721 octets_t data;
722 int rc = DhcpOption::parseHex(data, pcszValue);
723 *prc = rc;
724 if (RT_SUCCESS(rc))
725 return new RawOption(aOptCode, data);
726 return NULL;
727 }
728};
729
730
731
732/** @name The DHCP options types.
733 * @{
734 */
735typedef OptValue<1, RTNETADDRIPV4> OptSubnetMask;
736typedef OptValue<2, uint32_t> OptTimeOffset;
737typedef OptList<3, RTNETADDRIPV4> OptRouters;
738typedef OptList<4, RTNETADDRIPV4> OptTimeServers;
739typedef OptList<5, RTNETADDRIPV4> OptNameServers;
740typedef OptList<6, RTNETADDRIPV4> OptDNSes;
741typedef OptList<7, RTNETADDRIPV4> OptLogServers;
742typedef OptList<8, RTNETADDRIPV4> OptCookieServers;
743typedef OptList<9, RTNETADDRIPV4> OptLPRServers;
744typedef OptList<10, RTNETADDRIPV4> OptImpressServers;
745typedef OptList<11, RTNETADDRIPV4> OptResourceLocationServers;
746typedef OptString<12> OptHostName;
747typedef OptValue<13, uint16_t> OptBootFileSize;
748typedef OptString<14> OptMeritDumpFile;
749typedef OptString<15> OptDomainName;
750typedef OptValue<16, RTNETADDRIPV4> OptSwapServer;
751typedef OptString<17> OptRootPath;
752typedef OptString<18> OptExtensionPath;
753typedef OptValue<19, bool> OptIPForwarding;
754typedef OptValue<20, bool> OptNonLocalSourceRouting;
755typedef OptList<21, DhcpIpv4AddrAndMask> OptPolicyFilter;
756typedef OptValue<22, uint16_t> OptMaxDatagramReassemblySize;
757typedef OptValue<23, uint16_t> OptDefaultIPTTL;
758typedef OptValue<24, uint32_t> OptDefaultPathMTUAgingTimeout;
759typedef OptList<25, uint16_t> OptPathMTUPlateauTable;
760typedef OptValue<26, uint16_t> OptInterfaceMTU;
761typedef OptValue<27, bool> OptAllSubnetsAreLocal;
762typedef OptValue<28, RTNETADDRIPV4> OptBroadcastAddress;
763typedef OptValue<29, bool> OptPerformMaskDiscovery;
764typedef OptValue<30, bool> OptMaskSupplier;
765typedef OptValue<31, bool> OptPerformRouterDiscovery;
766typedef OptValue<32, RTNETADDRIPV4> OptRouterSolicitationAddress;
767typedef OptPairList<33, RTNETADDRIPV4> OptStaticRoute;
768typedef OptValue<34, bool> OptTrailerEncapsulation;
769typedef OptValue<35, uint32_t> OptARPCacheTimeout;
770typedef OptValue<36, bool> OptEthernetEncapsulation;
771typedef OptValue<37, uint8_t> OptTCPDefaultTTL;
772typedef OptValue<38, uint32_t> OptTCPKeepaliveInterval;
773typedef OptValue<39, bool> OptTCPKeepaliveGarbage;
774typedef OptString<40> OptNISDomain;
775typedef OptList<41, RTNETADDRIPV4> OptNISServers;
776typedef OptList<42, RTNETADDRIPV4> OptNTPServers;
777/* DHCP related options: */
778typedef OptList<43, uint8_t> OptVendorSpecificInfo;
779typedef OptList<44, RTNETADDRIPV4> OptNetBIOSNameServers;
780typedef OptList<45, RTNETADDRIPV4> OptNetBIOSDatagramServers;
781typedef OptValue<46, uint8_t> OptNetBIOSNodeType;
782typedef OptList<47, uint8_t> OptNetBIOSScope; /**< uint8_t or string? */
783typedef OptList<48, RTNETADDRIPV4> OptXWindowsFontServers;
784typedef OptList<49, RTNETADDRIPV4> OptXWindowsDisplayManager;
785typedef OptValue<50, RTNETADDRIPV4> OptRequestedAddress;
786typedef OptValue<51, uint32_t> OptLeaseTime;
787/* 52 - option overload is syntactic and handled internally */
788typedef OptValue<53, uint8_t> OptMessageType;
789typedef OptValue<54, RTNETADDRIPV4> OptServerId;
790typedef OptList<55, uint8_t> OptParameterRequest;
791typedef OptString<56> OptMessage;
792typedef OptValue<57, uint16_t> OptMaxDHCPMessageSize;
793typedef OptValue<58, uint32_t> OptRenewalTime;
794typedef OptValue<59, uint32_t> OptRebindingTime;
795typedef OptList<60, uint8_t> OptVendorClassId;
796typedef OptList<61, uint8_t> OptClientId;
797typedef OptString<62> OptNetWareIPDomainName; /**< RFC2242 */
798typedef OptList<63, uint8_t> OptNetWareIPInformation; /**< complicated, so just byte list for now. RFC2242 */
799typedef OptString<64> OptNISPlusDomain;
800typedef OptString<65> OptNISPlusServers;
801typedef OptString<66> OptTFTPServer; /**< when overloaded */
802typedef OptString<67> OptBootFileName; /**< when overloaded */
803typedef OptList<68, RTNETADDRIPV4> OptMobileIPHomeAgents;
804typedef OptList<69, RTNETADDRIPV4> OptSMTPServers;
805typedef OptList<70, RTNETADDRIPV4> OptPOP3Servers;
806typedef OptList<71, RTNETADDRIPV4> OptNNTPServers;
807typedef OptList<72, RTNETADDRIPV4> OptWWWServers;
808typedef OptList<73, RTNETADDRIPV4> OptFingerServers;
809typedef OptList<74, RTNETADDRIPV4> OptIRCServers;
810typedef OptList<75, RTNETADDRIPV4> OptStreetTalkServers;
811typedef OptList<76, RTNETADDRIPV4> OptSTDAServers;
812typedef OptList<77, uint8_t> OptUserClassId;
813typedef OptList<78, uint8_t> OptSLPDirectoryAgent; /**< complicated, so just byte list for now. RFC2610 */
814typedef OptList<79, uint8_t> OptSLPServiceScope; /**< complicated, so just byte list for now. RFC2610 */
815typedef OptNoValue<80> OptRapidCommit; /**< RFC4039 */
816/** @} */
817
818#endif /* !VBOX_INCLUDED_SRC_Dhcpd_DhcpOptions_h */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette