VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp@ 49618

Last change on this file since 49618 was 49618, checked in by vboxsync, 12 years ago

Main/DHCPServerImpl: move DHCPServer::Data closer to implementation, because with -std=c++11 DHCPserver::Data::VmSlot2Options cound't be instanciated in-place wwithout full declaration of settings::VmNameSlotKey, because of pair declaraion in STL's <utility> header.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.9 KB
Line 
1/* $Id: DHCPServerImpl.cpp 49618 2013-11-22 02:05:57Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2011 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.215389.xyz. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include <string>
21#include "NetworkServiceRunner.h"
22#include "DHCPServerImpl.h"
23#include "AutoCaller.h"
24#include "Logging.h"
25
26#include <iprt/cpp/utils.h>
27
28#include <VBox/com/array.h>
29#include <VBox/settings.h>
30
31#include "VirtualBoxImpl.h"
32
33// constructor / destructor
34/////////////////////////////////////////////////////////////////////////////
35const std::string DHCPServerRunner::kDsrKeyGateway = "--gateway";
36const std::string DHCPServerRunner::kDsrKeyLowerIp = "--lower-ip";
37const std::string DHCPServerRunner::kDsrKeyUpperIp = "--upper-ip";
38
39
40struct DHCPServer::Data
41{
42 Data() : enabled(FALSE) {}
43
44 Bstr IPAddress;
45 Bstr lowerIP;
46 Bstr upperIP;
47
48 BOOL enabled;
49 DHCPServerRunner dhcp;
50
51 DhcpOptionMap GlobalDhcpOptions;
52 VmSlot2OptionsMap VmSlot2Options;
53};
54
55
56DHCPServer::DHCPServer()
57 : m(NULL), mVirtualBox(NULL)
58{
59 m = new DHCPServer::Data();
60}
61
62
63DHCPServer::~DHCPServer()
64{
65 if (m)
66 {
67 delete m;
68 m = NULL;
69 }
70}
71
72
73HRESULT DHCPServer::FinalConstruct()
74{
75 return BaseFinalConstruct();
76}
77
78
79void DHCPServer::FinalRelease()
80{
81 uninit ();
82
83 BaseFinalRelease();
84}
85
86
87void DHCPServer::uninit()
88{
89 /* Enclose the state transition Ready->InUninit->NotReady */
90 AutoUninitSpan autoUninitSpan(this);
91 if (autoUninitSpan.uninitDone())
92 return;
93
94 unconst(mVirtualBox) = NULL;
95}
96
97
98HRESULT DHCPServer::init(VirtualBox *aVirtualBox, IN_BSTR aName)
99{
100 AssertReturn(aName != NULL, E_INVALIDARG);
101
102 AutoInitSpan autoInitSpan(this);
103 AssertReturn(autoInitSpan.isOk(), E_FAIL);
104
105 /* share VirtualBox weakly (parent remains NULL so far) */
106 unconst(mVirtualBox) = aVirtualBox;
107
108 unconst(mName) = aName;
109 m->IPAddress = "0.0.0.0";
110 m->GlobalDhcpOptions.insert(DhcpOptValuePair(DhcpOpt_SubnetMask, Bstr("0.0.0.0")));
111 m->enabled = FALSE;
112
113 m->lowerIP = "0.0.0.0";
114 m->upperIP = "0.0.0.0";
115
116 /* Confirm a successful initialization */
117 autoInitSpan.setSucceeded();
118
119 return S_OK;
120}
121
122
123HRESULT DHCPServer::init(VirtualBox *aVirtualBox,
124 const settings::DHCPServer &data)
125{
126 /* Enclose the state transition NotReady->InInit->Ready */
127 AutoInitSpan autoInitSpan(this);
128 AssertReturn(autoInitSpan.isOk(), E_FAIL);
129
130 /* share VirtualBox weakly (parent remains NULL so far) */
131 unconst(mVirtualBox) = aVirtualBox;
132
133 unconst(mName) = data.strNetworkName;
134 m->IPAddress = data.strIPAddress;
135 m->enabled = data.fEnabled;
136 m->lowerIP = data.strIPLower;
137 m->upperIP = data.strIPUpper;
138
139 m->GlobalDhcpOptions.clear();
140 m->GlobalDhcpOptions.insert(data.GlobalDhcpOptions.begin(),
141 data.GlobalDhcpOptions.end());
142
143 m->VmSlot2Options.clear();
144 m->VmSlot2Options.insert(data.VmSlot2OptionsM.begin(),
145 data.VmSlot2OptionsM.end());
146
147 autoInitSpan.setSucceeded();
148
149 return S_OK;
150}
151
152
153HRESULT DHCPServer::saveSettings(settings::DHCPServer &data)
154{
155 AutoCaller autoCaller(this);
156 if (FAILED(autoCaller.rc())) return autoCaller.rc();
157
158 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
159
160 data.strNetworkName = mName;
161 data.strIPAddress = m->IPAddress;
162
163 data.fEnabled = !!m->enabled;
164 data.strIPLower = m->lowerIP;
165 data.strIPUpper = m->upperIP;
166
167 data.GlobalDhcpOptions.clear();
168 data.GlobalDhcpOptions.insert(m->GlobalDhcpOptions.begin(),
169 m->GlobalDhcpOptions.end());
170
171 data.VmSlot2OptionsM.clear();
172 data.VmSlot2OptionsM.insert(m->VmSlot2Options.begin(),
173 m->VmSlot2Options.end());
174
175 return S_OK;
176}
177
178
179STDMETHODIMP DHCPServer::COMGETTER(NetworkName) (BSTR *aName)
180{
181 CheckComArgOutPointerValid(aName);
182
183 AutoCaller autoCaller(this);
184 if (FAILED(autoCaller.rc())) return autoCaller.rc();
185
186 mName.cloneTo(aName);
187
188 return S_OK;
189}
190
191
192STDMETHODIMP DHCPServer::COMGETTER(Enabled) (BOOL *aEnabled)
193{
194 CheckComArgOutPointerValid(aEnabled);
195
196 AutoCaller autoCaller(this);
197 if (FAILED(autoCaller.rc())) return autoCaller.rc();
198
199 *aEnabled = m->enabled;
200
201 return S_OK;
202}
203
204
205STDMETHODIMP DHCPServer::COMSETTER(Enabled) (BOOL aEnabled)
206{
207 AutoCaller autoCaller(this);
208 if (FAILED(autoCaller.rc())) return autoCaller.rc();
209
210 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
211 m->enabled = aEnabled;
212
213 // save the global settings; for that we should hold only the VirtualBox lock
214 alock.release();
215 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
216 HRESULT rc = mVirtualBox->saveSettings();
217
218 return rc;
219}
220
221
222STDMETHODIMP DHCPServer::COMGETTER(IPAddress) (BSTR *aIPAddress)
223{
224 CheckComArgOutPointerValid(aIPAddress);
225
226 AutoCaller autoCaller(this);
227 if (FAILED(autoCaller.rc())) return autoCaller.rc();
228
229 m->IPAddress.cloneTo(aIPAddress);
230
231 return S_OK;
232}
233
234
235STDMETHODIMP DHCPServer::COMGETTER(NetworkMask) (BSTR *aNetworkMask)
236{
237 CheckComArgOutPointerValid(aNetworkMask);
238
239 AutoCaller autoCaller(this);
240 if (FAILED(autoCaller.rc())) return autoCaller.rc();
241
242 m->GlobalDhcpOptions[DhcpOpt_SubnetMask].cloneTo(aNetworkMask);
243
244 return S_OK;
245}
246
247
248STDMETHODIMP DHCPServer::COMGETTER(LowerIP) (BSTR *aIPAddress)
249{
250 CheckComArgOutPointerValid(aIPAddress);
251
252 AutoCaller autoCaller(this);
253 if (FAILED(autoCaller.rc())) return autoCaller.rc();
254
255 m->lowerIP.cloneTo(aIPAddress);
256
257 return S_OK;
258}
259
260
261STDMETHODIMP DHCPServer::COMGETTER(UpperIP) (BSTR *aIPAddress)
262{
263 CheckComArgOutPointerValid(aIPAddress);
264
265 AutoCaller autoCaller(this);
266 if (FAILED(autoCaller.rc())) return autoCaller.rc();
267
268 m->upperIP.cloneTo(aIPAddress);
269
270 return S_OK;
271}
272
273
274STDMETHODIMP DHCPServer::SetConfiguration (IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aLowerIP, IN_BSTR aUpperIP)
275{
276 AssertReturn(aIPAddress != NULL, E_INVALIDARG);
277 AssertReturn(aNetworkMask != NULL, E_INVALIDARG);
278 AssertReturn(aLowerIP != NULL, E_INVALIDARG);
279 AssertReturn(aUpperIP != NULL, E_INVALIDARG);
280
281 AutoCaller autoCaller(this);
282 if (FAILED(autoCaller.rc())) return autoCaller.rc();
283
284 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
285 m->IPAddress = aIPAddress;
286 m->GlobalDhcpOptions[DhcpOpt_SubnetMask] = aNetworkMask;
287
288 m->lowerIP = aLowerIP;
289 m->upperIP = aUpperIP;
290
291 // save the global settings; for that we should hold only the VirtualBox lock
292 alock.release();
293 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
294 return mVirtualBox->saveSettings();
295}
296
297
298STDMETHODIMP DHCPServer::AddGlobalOption(DhcpOpt_T aOption, IN_BSTR aValue)
299{
300 CheckComArgStr(aValue);
301 /* store global option */
302 AutoCaller autoCaller(this);
303 if (FAILED(autoCaller.rc())) return autoCaller.rc();
304
305 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
306
307 m->GlobalDhcpOptions.insert(
308 DhcpOptValuePair(aOption, Utf8Str(aValue)));
309
310 /* Indirect way to understand that we're on NAT network */
311 if (aOption == DhcpOpt_Router)
312 m->dhcp.setOption(NetworkServiceRunner::kNsrKeyNeedMain, "on");
313
314 alock.release();
315
316 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
317 return mVirtualBox->saveSettings();
318}
319
320
321STDMETHODIMP DHCPServer::COMGETTER(GlobalOptions)(ComSafeArrayOut(BSTR, aValue))
322{
323 CheckComArgOutSafeArrayPointerValid(aValue);
324
325 AutoCaller autoCaller(this);
326 if (FAILED(autoCaller.rc())) return autoCaller.rc();
327
328 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
329
330 SafeArray<BSTR> sf(m->GlobalDhcpOptions.size());
331 int i = 0;
332
333 for (DhcpOptIterator it = m->GlobalDhcpOptions.begin();
334 it != m->GlobalDhcpOptions.end(); ++it)
335 {
336 Bstr(Utf8StrFmt("%d:%s", (*it).first, (*it).second.c_str())).detachTo(&sf[i]);
337 i++;
338 }
339
340 sf.detachTo(ComSafeArrayOutArg(aValue));
341
342 return S_OK;
343}
344
345
346STDMETHODIMP DHCPServer::COMGETTER(VmConfigs)(ComSafeArrayOut(BSTR, aValue))
347{
348 CheckComArgOutSafeArrayPointerValid(aValue);
349
350 AutoCaller autoCaller(this);
351 if (FAILED(autoCaller.rc())) return autoCaller.rc();
352
353 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
354
355 SafeArray<BSTR> sf(m->VmSlot2Options.size());
356 VmSlot2OptionsIterator it = m->VmSlot2Options.begin();
357 int i = 0;
358 for (;it != m->VmSlot2Options.end(); ++it)
359 {
360 Bstr(Utf8StrFmt("[%s]:%d",
361 it->first.VmName.c_str(),
362 it->first.Slot)).detachTo(&sf[i]);
363 i++;
364 }
365
366 sf.detachTo(ComSafeArrayOutArg(aValue));
367
368 return S_OK;
369}
370
371
372STDMETHODIMP DHCPServer::AddVmSlotOption(IN_BSTR aVmName, LONG aSlot, DhcpOpt_T aOption, IN_BSTR aValue)
373{
374 AutoCaller autoCaller(this);
375 if (FAILED(autoCaller.rc())) return autoCaller.rc();
376 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
377
378 m->VmSlot2Options[settings::VmNameSlotKey(
379 com::Utf8Str(aVmName),
380 aSlot)][aOption] = com::Utf8Str(aValue);
381
382
383 alock.release();
384
385 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
386 return mVirtualBox->saveSettings();
387}
388
389
390STDMETHODIMP DHCPServer::RemoveVmSlotOptions(IN_BSTR aVmName, LONG aSlot)
391{
392 AutoCaller autoCaller(this);
393 if (FAILED(autoCaller.rc())) return autoCaller.rc();
394 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
395
396 DhcpOptionMap& map = findOptMapByVmNameSlot(com::Utf8Str(aVmName), aSlot);
397
398 map.clear();
399
400 alock.release();
401
402 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);
403 return mVirtualBox->saveSettings();
404}
405
406
407/**
408 * this is mapping (vm, slot)
409 */
410STDMETHODIMP DHCPServer::GetVmSlotOptions(IN_BSTR aVmName,
411 LONG aSlot,
412 ComSafeArrayOut(BSTR, aValues))
413{
414 CheckComArgOutSafeArrayPointerValid(aValues);
415 AutoCaller autoCaller(this);
416 if (FAILED(autoCaller.rc())) return autoCaller.rc();
417
418 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
419
420 DhcpOptionMap& map = findOptMapByVmNameSlot(com::Utf8Str(aVmName), aSlot);
421
422 SafeArray<BSTR> sf(map.size());
423 int i = 0;
424
425 for (DhcpOptIterator it = map.begin();
426 it != map.end(); ++it)
427 {
428 Bstr(Utf8StrFmt("%d:%s", (*it).first, (*it).second.c_str())).detachTo(&sf[i]);
429 i++;
430 }
431
432 sf.detachTo(ComSafeArrayOutArg(aValues));
433
434 return S_OK;
435}
436
437
438STDMETHODIMP DHCPServer::GetMacOptions(IN_BSTR aMAC, ComSafeArrayOut(BSTR, aValues))
439{
440 CheckComArgOutSafeArrayPointerValid(aValues);
441
442 AutoCaller autoCaller(this);
443 if (FAILED(autoCaller.rc())) return autoCaller.rc();
444
445 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
446 HRESULT hrc = S_OK;
447
448 ComPtr<IMachine> machine;
449 ComPtr<INetworkAdapter> nic;
450
451 VmSlot2OptionsIterator it;
452 for(it = m->VmSlot2Options.begin();
453 it != m->VmSlot2Options.end();
454 ++it)
455 {
456
457 alock.release();
458 hrc = mVirtualBox->FindMachine(Bstr(it->first.VmName).raw(), machine.asOutParam());
459 alock.acquire();
460
461 if (FAILED(hrc))
462 continue;
463
464 alock.release();
465 hrc = machine->GetNetworkAdapter(it->first.Slot, nic.asOutParam());
466 alock.acquire();
467
468 if (FAILED(hrc))
469 continue;
470
471 com::Bstr mac;
472
473 alock.release();
474 hrc = nic->COMGETTER(MACAddress)(mac.asOutParam());
475 alock.acquire();
476
477 if (FAILED(hrc)) /* no MAC address ??? */
478 break;
479
480 if (!RTStrICmp(com::Utf8Str(mac).c_str(), com::Utf8Str(aMAC).c_str()))
481 return GetVmSlotOptions(Bstr(it->first.VmName).raw(),
482 it->first.Slot,
483 ComSafeArrayOutArg(aValues));
484 } /* end of for */
485
486 return hrc;
487}
488
489
490STDMETHODIMP DHCPServer::COMGETTER(EventSource)(IEventSource **aEventSource)
491{
492 NOREF(aEventSource);
493 ReturnComNotImplemented();
494}
495
496
497STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType)
498{
499 /* Silently ignore attempts to run disabled servers. */
500 if (!m->enabled)
501 return S_OK;
502
503 /* Commmon Network Settings */
504 m->dhcp.setOption(NetworkServiceRunner::kNsrKeyNetwork, Utf8Str(aNetworkName).c_str());
505
506 Bstr tmp(aTrunkName);
507
508 if (!tmp.isEmpty())
509 m->dhcp.setOption(NetworkServiceRunner::kNsrTrunkName, Utf8Str(tmp).c_str());
510 m->dhcp.setOption(NetworkServiceRunner::kNsrKeyTrunkType, Utf8Str(aTrunkType).c_str());
511
512 /* XXX: should this MAC default initialization moved to NetworkServiceRunner? */
513 char strMAC[32];
514 Guid guid;
515 guid.create();
516 RTStrPrintf (strMAC, sizeof(strMAC), "08:00:27:%02X:%02X:%02X",
517 guid.raw()->au8[0],
518 guid.raw()->au8[1],
519 guid.raw()->au8[2]);
520 m->dhcp.setOption(NetworkServiceRunner::kNsrMacAddress, strMAC);
521 m->dhcp.setOption(NetworkServiceRunner::kNsrIpAddress, Utf8Str(m->IPAddress).c_str());
522 m->dhcp.setOption(NetworkServiceRunner::kNsrIpNetmask, Utf8Str(m->GlobalDhcpOptions[DhcpOpt_SubnetMask]).c_str());
523 m->dhcp.setOption(DHCPServerRunner::kDsrKeyLowerIp, Utf8Str(m->lowerIP).c_str());
524 m->dhcp.setOption(DHCPServerRunner::kDsrKeyUpperIp, Utf8Str(m->upperIP).c_str());
525
526 /* XXX: This parameters Dhcp Server will fetch via API */
527 return RT_FAILURE(m->dhcp.start()) ? E_FAIL : S_OK;
528 //m->dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */
529}
530
531
532STDMETHODIMP DHCPServer::Stop (void)
533{
534 return RT_FAILURE(m->dhcp.stop()) ? E_FAIL : S_OK;
535}
536
537
538DhcpOptionMap& DHCPServer::findOptMapByVmNameSlot(const com::Utf8Str& aVmName,
539 LONG aSlot)
540{
541 return m->VmSlot2Options[settings::VmNameSlotKey(
542 com::Utf8Str(aVmName),
543 aSlot)];
544}
Note: See TracBrowser for help on using the repository browser.

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