VirtualBox

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

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

HostDnsService: Don't store a reference to the virtualbox object in
the monitor.

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