VirtualBox

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

Last change on this file since 78333 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.4 KB
Line 
1/* $Id: DhcpOptions.cpp 76553 2019-01-01 01:45:53Z 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.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#include "DhcpOptions.h"
19#include "DhcpMessage.h"
20
21
22optmap_t &operator<<(optmap_t &optmap, DhcpOption *option)
23{
24 if (option == NULL)
25 return optmap;
26
27 if (option->present())
28 optmap[option->optcode()] = std::shared_ptr<DhcpOption>(option);
29 else
30 optmap.erase(option->optcode());
31
32 return optmap;
33}
34
35
36optmap_t &operator<<(optmap_t &optmap, const std::shared_ptr<DhcpOption> &option)
37{
38 if (!option)
39 return optmap;
40
41 if (option->present())
42 optmap[option->optcode()] = option;
43 else
44 optmap.erase(option->optcode());
45
46 return optmap;
47}
48
49
50int DhcpOption::encode(octets_t &dst) const
51{
52 if (!m_fPresent)
53 return VERR_INVALID_STATE;
54
55 size_t cbOrig = dst.size();
56
57 append(dst, m_OptCode);
58 appendLength(dst, 0); /* placeholder */
59
60 ssize_t cbValue = encodeValue(dst);
61 if (cbValue < 0 || UINT8_MAX <= cbValue)
62 {
63 dst.resize(cbOrig); /* undo */
64 return VERR_INVALID_PARAMETER;
65 }
66
67 dst[cbOrig+1] = cbValue;
68 return VINF_SUCCESS;
69}
70
71
72/* static */
73const octets_t *DhcpOption::findOption(const rawopts_t &aOptMap, uint8_t aOptCode)
74{
75 rawopts_t::const_iterator it(aOptMap.find(aOptCode));
76 if (it == aOptMap.end())
77 return NULL;
78
79 return &it->second;
80}
81
82
83int DhcpOption::decode(const rawopts_t &map)
84{
85 const octets_t *rawopt = DhcpOption::findOption(map, m_OptCode);
86 if (rawopt == NULL)
87 return VERR_NOT_FOUND;
88
89 int rc = decodeValue(*rawopt, rawopt->size());
90 if (RT_FAILURE(rc))
91 return VERR_INVALID_PARAMETER;
92
93 return VINF_SUCCESS;
94}
95
96
97int DhcpOption::decode(const DhcpClientMessage &req)
98{
99 return decode(req.rawopts());
100}
101
102
103int DhcpOption::parse1(uint8_t &aValue, const char *pcszValue)
104{
105 int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &aValue);
106
107 if (rc == VERR_TRAILING_SPACES)
108 rc = VINF_SUCCESS;
109 return rc;
110}
111
112
113int DhcpOption::parse1(uint16_t &aValue, const char *pcszValue)
114{
115 int rc = RTStrToUInt16Full(RTStrStripL(pcszValue), 10, &aValue);
116
117 if (rc == VERR_TRAILING_SPACES)
118 rc = VINF_SUCCESS;
119 return rc;
120}
121
122
123int DhcpOption::parse1(uint32_t &aValue, const char *pcszValue)
124{
125 int rc = RTStrToUInt32Full(RTStrStripL(pcszValue), 10, &aValue);
126
127 if (rc == VERR_TRAILING_SPACES)
128 rc = VINF_SUCCESS;
129 return rc;
130}
131
132
133int DhcpOption::parse1(RTNETADDRIPV4 &aValue, const char *pcszValue)
134{
135 return RTNetStrToIPv4Addr(pcszValue, &aValue);
136}
137
138
139int DhcpOption::parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue)
140{
141 std::vector<RTNETADDRIPV4> l;
142 int rc;
143
144 pcszValue = RTStrStripL(pcszValue);
145 do {
146 RTNETADDRIPV4 Addr;
147 char *pszNext;
148
149 rc = RTNetStrToIPv4AddrEx(pcszValue, &Addr, &pszNext);
150 if (RT_FAILURE(rc))
151 return VERR_INVALID_PARAMETER;
152
153 if (rc == VWRN_TRAILING_CHARS)
154 {
155 pcszValue = RTStrStripL(pszNext);
156 if (pcszValue == pszNext) /* garbage after address */
157 return VERR_INVALID_PARAMETER;
158 }
159
160 l.push_back(Addr);
161
162 /*
163 * If we got VINF_SUCCESS or VWRN_TRAILING_SPACES then this
164 * was the last address and we are done.
165 */
166 } while (rc == VWRN_TRAILING_CHARS);
167
168 aList.swap(l);
169 return VINF_SUCCESS;
170}
171
172
173/*
174 * XXX: See DHCPServer::encodeOption()
175 */
176int DhcpOption::parseHex(octets_t &aRawValue, const char *pcszValue)
177{
178 octets_t data;
179 char *pszNext;
180 int rc;
181
182 if (pcszValue == NULL || *pcszValue == '\0')
183 return VERR_INVALID_PARAMETER;
184
185 while (*pcszValue != '\0')
186 {
187 if (data.size() > UINT8_MAX)
188 return VERR_INVALID_PARAMETER;
189
190 uint8_t u8Byte;
191 rc = RTStrToUInt8Ex(pcszValue, &pszNext, 16, &u8Byte);
192 if (!RT_SUCCESS(rc))
193 return rc;
194
195 if (*pszNext == ':')
196 ++pszNext;
197 else if (*pszNext != '\0')
198 return VERR_PARSE_ERROR;
199
200 data.push_back(u8Byte);
201 pcszValue = pszNext;
202 }
203
204 aRawValue.swap(data);
205 return VINF_SUCCESS;
206}
207
208
209DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue)
210{
211 switch (aEnc)
212 {
213 case 0: /* DhcpOptEncoding_Legacy */
214 switch (aOptCode)
215 {
216#define HANDLE(_OptClass) \
217 case _OptClass::optcode: \
218 return _OptClass::parse(pcszValue);
219
220 HANDLE(OptSubnetMask);
221 HANDLE(OptRouter);
222 HANDLE(OptDNS);
223 HANDLE(OptHostName);
224 HANDLE(OptDomainName);
225 HANDLE(OptRootPath);
226 HANDLE(OptLeaseTime);
227 HANDLE(OptRenewalTime);
228 HANDLE(OptRebindingTime);
229
230#undef HANDLE
231 default:
232 return NULL;
233 }
234 break;
235
236 case 1:
237 return RawOption::parse(aOptCode, pcszValue);
238
239 default:
240 return NULL;
241 }
242}
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