VirtualBox

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

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

Main/Network: DHCP server has got the ear in Main, and we able create/describe more complex infrostructures. DHCP server together with Lwip NAT can handle per vm/slot configuration and store them in xml settings.

place-holder: Host interface nameserver list, domain name and search strings, I suppose that this functions should be used on initialization stage and then on host configuration change even or directly from event.

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