VirtualBox

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

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

HostDnsService: drop repeated NULL test.

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