VirtualBox

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

Last change on this file since 72395 was 72395, checked in by vboxsync, 7 years ago

HostDnsService: don't pretend there can be multiple proxies.
while here, drop some bogus const.

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