VirtualBox

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

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

HostDnsService: introduce a local variable to simplify future change.

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