VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostDnsService.cpp@ 67954

Last change on this file since 67954 was 62485, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1/* $Id: HostDnsService.cpp 62485 2016-07-22 18:36:43Z vboxsync $ */
2/** @file
3 * Base class for Host DNS & Co services.
4 */
5
6/*
7 * Copyright (C) 2013-2016 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 <VBox/com/array.h>
19#include <VBox/com/ptr.h>
20#include <VBox/com/string.h>
21
22#include <iprt/cpp/utils.h>
23
24#include "Logging.h"
25#include "VirtualBoxImpl.h"
26#include <iprt/time.h>
27#include <iprt/thread.h>
28#include <iprt/semaphore.h>
29#include <iprt/critsect.h>
30
31#include <algorithm>
32#include <set>
33#include <string>
34#include "HostDnsService.h"
35
36
37static HostDnsMonitor *g_monitor;
38
39static void dumpHostDnsInformation(const HostDnsInformation&);
40static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&);
41
42
43bool HostDnsInformation::equals(const HostDnsInformation &info, uint32_t fLaxComparison) const
44{
45 bool fSameServers;
46 if ((fLaxComparison & IGNORE_SERVER_ORDER) == 0)
47 {
48 fSameServers = (servers == info.servers);
49 }
50 else
51 {
52 std::set<std::string> l(servers.begin(), servers.end());
53 std::set<std::string> r(info.servers.begin(), info.servers.end());
54
55 fSameServers = (l == r);
56 }
57
58 bool fSameDomain, fSameSearchList;
59 if ((fLaxComparison & IGNORE_SUFFIXES) == 0)
60 {
61 fSameDomain = (domain == info.domain);
62 fSameSearchList = (searchList == info.searchList);
63 }
64 else
65 {
66 fSameDomain = fSameSearchList = true;
67 }
68
69 return fSameServers && fSameDomain && fSameSearchList;
70}
71
72inline static void detachVectorOfString(const std::vector<std::string>& v,
73 std::vector<com::Utf8Str> &aArray)
74{
75 aArray.resize(v.size());
76 size_t i = 0;
77 for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it, ++i)
78 aArray[i] = Utf8Str(it->c_str());
79}
80
81struct HostDnsMonitor::Data
82{
83 Data(bool aThreaded)
84 : uLastExtraDataPoll(0),
85 fLaxComparison(0),
86 fThreaded(aThreaded),
87 virtualbox(NULL)
88 {}
89
90 std::vector<PCHostDnsMonitorProxy> proxies;
91 HostDnsInformation info;
92 uint64_t uLastExtraDataPoll;
93 uint32_t fLaxComparison;
94 const bool fThreaded;
95 RTTHREAD hMonitoringThread;
96 RTSEMEVENT hDnsInitEvent;
97 VirtualBox *virtualbox;
98};
99
100struct HostDnsMonitorProxy::Data
101{
102 Data(const HostDnsMonitor *aMonitor, VirtualBox *aParent)
103 : info(NULL)
104 , virtualbox(aParent)
105 , monitor(aMonitor)
106 , fModified(true)
107 {}
108
109 virtual ~Data()
110 {
111 if (info)
112 {
113 delete info;
114 info = NULL;
115 }
116 }
117
118 HostDnsInformation *info;
119 VirtualBox *virtualbox;
120 const HostDnsMonitor *monitor;
121 bool fModified;
122};
123
124
125HostDnsMonitor::HostDnsMonitor(bool fThreaded)
126 : m(NULL)
127{
128 m = new HostDnsMonitor::Data(fThreaded);
129}
130
131HostDnsMonitor::~HostDnsMonitor()
132{
133 if (m)
134 {
135 delete m;
136 m = NULL;
137 }
138}
139
140const HostDnsMonitor *HostDnsMonitor::getHostDnsMonitor(VirtualBox *aParent)
141{
142 /* XXX: Moved initialization from HostImpl.cpp */
143 if (!g_monitor)
144 {
145# if defined (RT_OS_DARWIN)
146 g_monitor = new HostDnsServiceDarwin();
147# elif defined(RT_OS_WINDOWS)
148 g_monitor = new HostDnsServiceWin();
149# elif defined(RT_OS_LINUX)
150 g_monitor = new HostDnsServiceLinux();
151# elif defined(RT_OS_SOLARIS)
152 g_monitor = new HostDnsServiceSolaris();
153# elif defined(RT_OS_FREEBSD)
154 g_monitor = new HostDnsServiceFreebsd();
155# elif defined(RT_OS_OS2)
156 g_monitor = new HostDnsServiceOs2();
157# else
158 g_monitor = new HostDnsService();
159# endif
160 g_monitor->init(aParent);
161 }
162
163 return g_monitor;
164}
165
166void HostDnsMonitor::addMonitorProxy(PCHostDnsMonitorProxy proxy) const
167{
168 RTCLock grab(m_LockMtx);
169 m->proxies.push_back(proxy);
170 proxy->notify();
171}
172
173void HostDnsMonitor::releaseMonitorProxy(PCHostDnsMonitorProxy proxy) const
174{
175 RTCLock grab(m_LockMtx);
176 std::vector<PCHostDnsMonitorProxy>::iterator it;
177 it = std::find(m->proxies.begin(), m->proxies.end(), proxy);
178
179 if (it == m->proxies.end())
180 return;
181
182 m->proxies.erase(it);
183}
184
185void HostDnsMonitor::shutdown()
186{
187 /** @todo never called.
188 * HostDnsMonitor should be referenced by HostDnsMonitorProxy objects and the Host object
189 * and automatically deleted when not referenced anymore.
190 * Currently HostDnsMonitor can use already deleted m->virtualbox.
191 */
192 if (g_monitor)
193 {
194 delete g_monitor;
195 g_monitor = NULL;
196 }
197}
198
199const HostDnsInformation &HostDnsMonitor::getInfo() const
200{
201 return m->info;
202}
203
204void HostDnsMonitor::setInfo(const HostDnsInformation &info)
205{
206 RTCLock grab(m_LockMtx);
207
208 pollGlobalExtraData();
209
210 if (info.equals(m->info))
211 return;
212
213 LogRel(("HostDnsMonitor: old information\n"));
214 dumpHostDnsInformation(m->info);
215 LogRel(("HostDnsMonitor: new information\n"));
216 dumpHostDnsInformation(info);
217
218 bool fIgnore = m->fLaxComparison && info.equals(m->info, m->fLaxComparison);
219 m->info = info;
220
221 if (fIgnore)
222 {
223 LogRel(("HostDnsMonitor: lax comparison %#x, not notifying\n", m->fLaxComparison));
224 return;
225 }
226
227 std::vector<PCHostDnsMonitorProxy>::const_iterator it;
228 for (it = m->proxies.begin(); it != m->proxies.end(); ++it)
229 (*it)->notify();
230}
231
232HRESULT HostDnsMonitor::init(VirtualBox *virtualbox)
233{
234 m->virtualbox = virtualbox;
235
236 pollGlobalExtraData();
237
238 if (m->fThreaded)
239 {
240 int rc = RTSemEventCreate(&m->hDnsInitEvent);
241 AssertRCReturn(rc, E_FAIL);
242
243 rc = RTThreadCreate(&m->hMonitoringThread,
244 HostDnsMonitor::threadMonitoringRoutine,
245 this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
246 AssertRCReturn(rc, E_FAIL);
247
248 RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
249 }
250 return S_OK;
251}
252
253
254void HostDnsMonitor::pollGlobalExtraData()
255{
256 uint64_t uNow = RTTimeNanoTS();
257 if (m->virtualbox && (uNow - m->uLastExtraDataPoll >= RT_NS_30SEC || m->uLastExtraDataPoll == 0))
258 {
259 m->uLastExtraDataPoll = uNow;
260
261 /*
262 * Should we ignore the order of DNS servers?
263 */
264 const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
265 com::Bstr bstrHostDNSOrderIgnore;
266 m->virtualbox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(),
267 bstrHostDNSOrderIgnore.asOutParam());
268 uint32_t fDNSOrderIgnore = 0;
269 if (bstrHostDNSOrderIgnore.isNotEmpty())
270 {
271 if (bstrHostDNSOrderIgnore != "0")
272 fDNSOrderIgnore = HostDnsInformation::IGNORE_SERVER_ORDER;
273 }
274
275 if (fDNSOrderIgnore != (m->fLaxComparison & HostDnsInformation::IGNORE_SERVER_ORDER))
276 {
277
278 m->fLaxComparison ^= HostDnsInformation::IGNORE_SERVER_ORDER;
279 LogRel(("HostDnsMonitor: %ls=%ls\n",
280 bstrHostDNSOrderIgnoreKey.raw(),
281 bstrHostDNSOrderIgnore.raw()));
282 }
283
284 /*
285 * Should we ignore changes to the domain name or the search list?
286 */
287 const com::Bstr bstrHostDNSSuffixesIgnoreKey("VBoxInternal2/HostDNSSuffixesIgnore");
288 com::Bstr bstrHostDNSSuffixesIgnore;
289 m->virtualbox->GetExtraData(bstrHostDNSSuffixesIgnoreKey.raw(),
290 bstrHostDNSSuffixesIgnore.asOutParam());
291 uint32_t fDNSSuffixesIgnore = 0;
292 if (bstrHostDNSSuffixesIgnore.isNotEmpty())
293 {
294 if (bstrHostDNSSuffixesIgnore != "0")
295 fDNSSuffixesIgnore = HostDnsInformation::IGNORE_SUFFIXES;
296 }
297
298 if (fDNSSuffixesIgnore != (m->fLaxComparison & HostDnsInformation::IGNORE_SUFFIXES))
299 {
300
301 m->fLaxComparison ^= HostDnsInformation::IGNORE_SUFFIXES;
302 LogRel(("HostDnsMonitor: %ls=%ls\n",
303 bstrHostDNSSuffixesIgnoreKey.raw(),
304 bstrHostDNSSuffixesIgnore.raw()));
305 }
306 }
307}
308
309void HostDnsMonitor::monitorThreadInitializationDone()
310{
311 RTSemEventSignal(m->hDnsInitEvent);
312}
313
314
315DECLCALLBACK(int) HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
316{
317 HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
318 return pThis->monitorWorker();
319}
320
321/* HostDnsMonitorProxy */
322HostDnsMonitorProxy::HostDnsMonitorProxy()
323 : m(NULL)
324{
325}
326
327HostDnsMonitorProxy::~HostDnsMonitorProxy()
328{
329 if (m)
330 {
331 if (m->monitor)
332 m->monitor->releaseMonitorProxy(this);
333 delete m;
334 m = NULL;
335 }
336}
337
338void HostDnsMonitorProxy::init(const HostDnsMonitor *mon, VirtualBox* aParent)
339{
340 m = new HostDnsMonitorProxy::Data(mon, aParent);
341 m->monitor->addMonitorProxy(this);
342 updateInfo();
343}
344
345void HostDnsMonitorProxy::notify() const
346{
347 LogRel(("HostDnsMonitorProxy::notify\n"));
348 m->fModified = true;
349 m->virtualbox->i_onHostNameResolutionConfigurationChange();
350}
351
352HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
353{
354 AssertReturn(m && m->info, E_FAIL);
355 RTCLock grab(m_LockMtx);
356
357 if (m->fModified)
358 updateInfo();
359
360 LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
361 dumpHostDnsStrVector("name server", m->info->servers);
362
363 detachVectorOfString(m->info->servers, aNameServers);
364
365 return S_OK;
366}
367
368HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
369{
370 AssertReturn(m && m->info, E_FAIL);
371 RTCLock grab(m_LockMtx);
372
373 if (m->fModified)
374 updateInfo();
375
376 LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n",
377 m->info->domain.empty() ? "no domain set" : m->info->domain.c_str()));
378
379 *pDomainName = m->info->domain.c_str();
380
381 return S_OK;
382}
383
384HRESULT HostDnsMonitorProxy::GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
385{
386 AssertReturn(m && m->info, E_FAIL);
387 RTCLock grab(m_LockMtx);
388
389 if (m->fModified)
390 updateInfo();
391
392 LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
393 dumpHostDnsStrVector("search string", m->info->searchList);
394
395 detachVectorOfString(m->info->searchList, aSearchStrings);
396
397 return S_OK;
398}
399
400bool HostDnsMonitorProxy::operator==(PCHostDnsMonitorProxy& rhs)
401{
402 if (!m || !rhs->m)
403 return false;
404
405 /**
406 * we've assigned to the same instance of VirtualBox.
407 */
408 return m->virtualbox == rhs->m->virtualbox;
409}
410
411void HostDnsMonitorProxy::updateInfo()
412{
413 HostDnsInformation *info = new HostDnsInformation(m->monitor->getInfo());
414 HostDnsInformation *old = m->info;
415
416 m->info = info;
417 if (old)
418 {
419 delete old;
420 }
421
422 m->fModified = false;
423}
424
425
426static void dumpHostDnsInformation(const HostDnsInformation& info)
427{
428 dumpHostDnsStrVector("server", info.servers);
429
430 if (!info.domain.empty())
431 LogRel((" domain: %s\n", info.domain.c_str()));
432 else
433 LogRel((" no domain set\n"));
434
435 dumpHostDnsStrVector("search string", info.searchList);
436}
437
438
439static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
440{
441 int i = 1;
442 for (std::vector<std::string>::const_iterator it = v.begin();
443 it != v.end();
444 ++it, ++i)
445 LogRel((" %s %d: %s\n", prefix.c_str(), i, it->c_str()));
446 if (v.empty())
447 LogRel((" no %s entries\n", prefix.c_str()));
448}
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