VirtualBox

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

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

Main: warnings

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