VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.cpp@ 79763

最後變更 在這個檔案從79763是 79763,由 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. [build fix] bugref:9288

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 13.4 KB
 
1/* $Id: DhcpOptions.cpp 79763 2019-07-14 03:59:56Z 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
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include "DhcpdInternal.h"
23#include "DhcpOptions.h"
24#ifndef IN_VBOXSVC
25# include "DhcpMessage.h"
26#endif
27
28#include <iprt/cidr.h>
29
30
31#ifndef IN_VBOXSVC
32
33optmap_t &operator<<(optmap_t &optmap, DhcpOption *option)
34{
35 if (option == NULL)
36 return optmap;
37
38 if (option->present())
39 optmap[option->optcode()] = std::shared_ptr<DhcpOption>(option);
40 else
41 optmap.erase(option->optcode());
42
43 return optmap;
44}
45
46
47optmap_t &operator<<(optmap_t &optmap, const std::shared_ptr<DhcpOption> &option)
48{
49 if (!option)
50 return optmap;
51
52 if (option->present())
53 optmap[option->optcode()] = option;
54 else
55 optmap.erase(option->optcode());
56
57 return optmap;
58}
59
60#endif /* !IN_VBOXSVC */
61
62
63int DhcpOption::encode(octets_t &dst) const
64{
65 if (!m_fPresent)
66 return VERR_INVALID_STATE;
67
68 size_t cbOrig = dst.size();
69
70 append(dst, m_OptCode);
71 appendLength(dst, 0); /* placeholder */
72
73 ssize_t cbValue = encodeValue(dst);
74 if (cbValue < 0 || UINT8_MAX <= cbValue)
75 {
76 dst.resize(cbOrig); /* undo */
77 return VERR_INVALID_PARAMETER;
78 }
79
80 dst[cbOrig+1] = (uint8_t)cbValue;
81 return VINF_SUCCESS;
82}
83
84
85/* static */
86const octets_t *DhcpOption::findOption(const rawopts_t &aOptMap, uint8_t aOptCode)
87{
88 rawopts_t::const_iterator it(aOptMap.find(aOptCode));
89 if (it == aOptMap.end())
90 return NULL;
91
92 return &it->second;
93}
94
95
96int DhcpOption::decode(const rawopts_t &map)
97{
98 const octets_t *rawopt = DhcpOption::findOption(map, m_OptCode);
99 if (rawopt == NULL)
100 return VERR_NOT_FOUND;
101
102 int rc = decodeValue(*rawopt, rawopt->size());
103 if (RT_FAILURE(rc))
104 return VERR_INVALID_PARAMETER;
105
106 return VINF_SUCCESS;
107}
108
109
110#ifndef IN_VBOXSVC
111int DhcpOption::decode(const DhcpClientMessage &req)
112{
113 return decode(req.rawopts());
114}
115#endif
116
117
118int DhcpOption::parse1(bool &aValue, const char *pcszValue)
119{
120 pcszValue = RTStrStripL(pcszValue);
121 if ( strcmp(pcszValue, "true") == 0
122 || strcmp(pcszValue, "1") == 0
123 || strcmp(pcszValue, "yes") == 0
124 || strcmp(pcszValue, "on") == 0 )
125 {
126 aValue = true;
127 return VINF_SUCCESS;
128 }
129
130 if ( strcmp(pcszValue, "false") == 0
131 || strcmp(pcszValue, "0") == 0
132 || strcmp(pcszValue, "no") == 0
133 || strcmp(pcszValue, "off") == 0 )
134 {
135 aValue = false;
136 return VINF_SUCCESS;
137 }
138
139 uint8_t bTmp;
140 int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &bTmp);
141 if (rc == VERR_TRAILING_SPACES)
142 rc = VINF_SUCCESS;
143 if (RT_SUCCESS(rc))
144 aValue = bTmp != 0;
145
146 return rc;
147}
148
149
150int DhcpOption::parse1(uint8_t &aValue, const char *pcszValue)
151{
152 int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &aValue);
153 if (rc == VERR_TRAILING_SPACES)
154 rc = VINF_SUCCESS;
155 return rc;
156}
157
158
159int DhcpOption::parse1(uint16_t &aValue, const char *pcszValue)
160{
161 int rc = RTStrToUInt16Full(RTStrStripL(pcszValue), 10, &aValue);
162
163 if (rc == VERR_TRAILING_SPACES)
164 rc = VINF_SUCCESS;
165 return rc;
166}
167
168
169int DhcpOption::parse1(uint32_t &aValue, const char *pcszValue)
170{
171 int rc = RTStrToUInt32Full(RTStrStripL(pcszValue), 10, &aValue);
172
173 if (rc == VERR_TRAILING_SPACES)
174 rc = VINF_SUCCESS;
175 return rc;
176}
177
178
179int DhcpOption::parse1(RTNETADDRIPV4 &aValue, const char *pcszValue)
180{
181 return RTNetStrToIPv4Addr(pcszValue, &aValue);
182}
183
184
185int DhcpOption::parse1(DhcpIpv4AddrAndMask &aValue, const char *pcszValue)
186{
187 return RTCidrStrToIPv4(pcszValue, &aValue.Ipv4, &aValue.Mask);
188}
189
190
191template <typename a_Type>
192/*static*/ int DhcpOption::parseList(std::vector<a_Type> &aList, const char *pcszValue)
193{
194 std::vector<a_Type> vecTmp;
195
196 pcszValue = RTStrStripL(pcszValue);
197 for (;;)
198 {
199 /* Assume space, tab, comma or semicolon is used as separator (superset of RTStrStrip): */
200 const char *pszNext = strpbrk(pcszValue, " ,;:\t\n\r");
201 char szTmp[256];
202 if (pszNext)
203 {
204 size_t cchToCopy = pszNext - pcszValue;
205 if (cchToCopy >= sizeof(szTmp))
206 return VERR_INVALID_PARAMETER;
207 memcpy(szTmp, pcszValue, cchToCopy);
208 szTmp[cchToCopy] = '\0';
209 pcszValue = szTmp;
210
211 /* Advance pszNext past the separator character and fluff: */
212 char ch;
213 do
214 pszNext++;
215 while ((ch = *pszNext) == ' ' || ch == ':' || ch == ';' || ch == '\t' || ch == '\n' || ch == '\r');
216 if (ch == '\0')
217 pszNext = NULL;
218 }
219
220 /* Try convert it: */
221 a_Type Value;
222 int rc = DhcpOption::parse1(Value, pcszValue);
223 if (RT_SUCCESS(rc))
224 vecTmp.push_back(Value);
225 else
226 return VERR_INVALID_PARAMETER;
227
228 if (pszNext)
229 pcszValue = pszNext;
230 else
231 break;
232 }
233
234 aList.swap(vecTmp);
235 return VINF_SUCCESS;
236
237}
238
239/** ASSUME that uint8_t means hex byte strings. */
240template <>
241/*static*/ int DhcpOption::parseList(std::vector<uint8_t> &aList, const char *pcszValue)
242{
243 uint8_t abBuf[256];
244 const char *pszNext = NULL;
245 size_t cbReturned = 0;
246 int rc = RTStrConvertHexBytesEx(RTStrStripL(pcszValue), abBuf, sizeof(abBuf), RTSTRCONVERTHEXBYTES_F_SEP_COLON,
247 &pszNext, &cbReturned);
248 if (RT_SUCCESS(rc))
249 {
250 if (pszNext)
251 pszNext = RTStrStripL(pszNext);
252 if (*pszNext)
253 {
254 for (size_t i = 0; i < cbReturned; i++)
255 aList.push_back(abBuf[i]);
256 return VINF_SUCCESS;
257 }
258 rc = VERR_TRAILING_CHARS;
259 }
260 return rc;
261}
262
263
264
265/*
266 * XXX: See DHCPServer::encodeOption()
267 */
268int DhcpOption::parseHex(octets_t &aRawValue, const char *pcszValue)
269{
270 octets_t data;
271 char *pszNext;
272 int rc;
273
274 if (pcszValue == NULL || *pcszValue == '\0')
275 return VERR_INVALID_PARAMETER;
276
277 while (*pcszValue != '\0')
278 {
279 if (data.size() > UINT8_MAX)
280 return VERR_INVALID_PARAMETER;
281
282 uint8_t u8Byte;
283 rc = RTStrToUInt8Ex(pcszValue, &pszNext, 16, &u8Byte);
284 if (!RT_SUCCESS(rc))
285 return rc;
286
287 if (*pszNext == ':')
288 ++pszNext;
289 else if (*pszNext != '\0')
290 return VERR_PARSE_ERROR;
291
292 data.push_back(u8Byte);
293 pcszValue = pszNext;
294 }
295
296 aRawValue.swap(data);
297 return VINF_SUCCESS;
298}
299
300
301DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc /*= NULL*/)
302{
303 int rcIgn;
304 if (!prc)
305 prc = &rcIgn;
306
307 switch (aEnc)
308 {
309 case 0: /* DhcpOptEncoding_Legacy */
310 switch (aOptCode)
311 {
312#define HANDLE(a_OptClass) \
313 case a_OptClass::optcode: \
314 return a_OptClass::parse(pcszValue, prc)
315
316 HANDLE(OptSubnetMask); // 1
317 HANDLE(OptTimeOffset); // 2
318 HANDLE(OptRouters); // 3
319 HANDLE(OptTimeServers); // 4
320 HANDLE(OptNameServers); // 5
321 HANDLE(OptDNSes); // 6
322 HANDLE(OptLogServers); // 7
323 HANDLE(OptCookieServers); // 8
324 HANDLE(OptLPRServers); // 9
325 HANDLE(OptImpressServers); // 10
326 HANDLE(OptResourceLocationServers); // 11
327 HANDLE(OptHostName); // 12
328 HANDLE(OptBootFileSize); // 13
329 HANDLE(OptMeritDumpFile); // 14
330 HANDLE(OptDomainName); // 15
331 HANDLE(OptSwapServer); // 16
332 HANDLE(OptRootPath); // 17
333 HANDLE(OptExtensionPath); // 18
334 HANDLE(OptIPForwarding); // 19
335 HANDLE(OptNonLocalSourceRouting); // 20
336 HANDLE(OptPolicyFilter); // 21
337 HANDLE(OptMaxDatagramReassemblySize); // 22
338 HANDLE(OptDefaultIPTTL); // 23
339 HANDLE(OptDefaultPathMTUAgingTimeout); // 24
340 HANDLE(OptPathMTUPlateauTable); // 25
341 HANDLE(OptInterfaceMTU); // 26
342 HANDLE(OptAllSubnetsAreLocal); // 27
343 HANDLE(OptBroadcastAddress); // 28
344 HANDLE(OptPerformMaskDiscovery); // 29
345 HANDLE(OptMaskSupplier); // 30
346 HANDLE(OptPerformRouterDiscovery); // 31
347 HANDLE(OptRouterSolicitationAddress); // 32
348 HANDLE(OptStaticRoute); // 33
349 HANDLE(OptTrailerEncapsulation); // 34
350 HANDLE(OptARPCacheTimeout); // 35
351 HANDLE(OptEthernetEncapsulation); // 36
352 HANDLE(OptTCPDefaultTTL); // 37
353 HANDLE(OptTCPKeepaliveInterval); // 38
354 HANDLE(OptTCPKeepaliveGarbage); // 39
355 HANDLE(OptNISDomain); // 40
356 HANDLE(OptNISServers); // 41
357 HANDLE(OptNTPServers); // 42
358 HANDLE(OptVendorSpecificInfo); // 43
359 HANDLE(OptNetBIOSNameServers); // 44
360 HANDLE(OptNetBIOSDatagramServers); // 45
361 HANDLE(OptNetBIOSNodeType); // 46
362 HANDLE(OptNetBIOSScope); // 47
363 HANDLE(OptXWindowsFontServers); // 48
364 HANDLE(OptXWindowsDisplayManager); // 49
365#ifndef IN_VBOXSVC /* Don't allow these in new configs */
366 // OptRequestedAddress (50) is client only and not configurable.
367 HANDLE(OptLeaseTime); // 51 - for historical reasons? Configuable elsewhere now.
368 // OptOptionOverload (52) is part of the protocol and not configurable.
369 // OptMessageType (53) is part of the protocol and not configurable.
370 // OptServerId (54) is the IP address of the server and configurable elsewhere.
371 // OptParameterRequest (55) is client only and not configurable.
372 // OptMessage (56) is server failure message and not configurable.
373 // OptMaxDHCPMessageSize (57) is client only (?) and not configurable.
374 HANDLE(OptRenewalTime); // 58 - for historical reasons?
375 HANDLE(OptRebindingTime); // 59 - for historical reasons?
376 // OptVendorClassId (60) is client only and not configurable.
377 // OptClientId (61) is client only and not configurable.
378#endif
379 HANDLE(OptNetWareIPDomainName); // 62
380 HANDLE(OptNetWareIPInformation); // 63
381 HANDLE(OptNISPlusDomain); // 64
382 HANDLE(OptNISPlusServers); // 65
383 HANDLE(OptTFTPServer); // 66 - perhaps we should use an alternative way to configure these.
384 HANDLE(OptBootFileName); // 67 - perhaps we should use an alternative way to configure these.
385 HANDLE(OptMobileIPHomeAgents); // 68
386 HANDLE(OptSMTPServers); // 69
387 HANDLE(OptPOP3Servers); // 70
388 HANDLE(OptNNTPServers); // 71
389 HANDLE(OptWWWServers); // 72
390 HANDLE(OptFingerServers); // 73
391 HANDLE(OptIRCServers); // 74
392 HANDLE(OptStreetTalkServers); // 75
393 HANDLE(OptSTDAServers); // 76
394 // OptUserClassId (77) is client only and not configurable.
395 HANDLE(OptSLPDirectoryAgent); // 78
396 HANDLE(OptSLPServiceScope); // 79
397 // OptRapidCommit (80) is not configurable.
398
399#undef HANDLE
400 default:
401 if (prc)
402 *prc = VERR_NOT_IMPLEMENTED;
403 return NULL;
404 }
405 break;
406
407 case 1:
408 return RawOption::parse(aOptCode, pcszValue, prc);
409
410 default:
411 if (prc)
412 *prc = VERR_WRONG_TYPE;
413 return NULL;
414 }
415}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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