VirtualBox

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

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

Main: Don't use Logging.h.

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