VirtualBox

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

Last change on this file since 83547 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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