VirtualBox

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

Last change on this file since 78382 was 77993, checked in by vboxsync, 6 years ago

Main/HostDnsService: Some more cleanup and renaming.

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