VirtualBox

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

Last change on this file since 57438 was 57425, checked in by vboxsync, 9 years ago

DECLCALLBACK

  • 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 57425 2015-08-18 12:41:48Z vboxsync $ */
2/** @file
3 * Base class for Host DNS & Co services.
4 */
5
6/*
7 * Copyright (C) 2013-2015 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 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 : uLastExtraDataPoll(0),
85 fLaxComparison(0),
86 fThreaded(aThreaded),
87 virtualbox(NULL)
88 {}
89
90 std::vector<PCHostDnsMonitorProxy> proxies;
91 HostDnsInformation info;
92 uint64_t uLastExtraDataPoll;
93 uint32_t fLaxComparison;
94 const bool fThreaded;
95 RTTHREAD hMonitoringThread;
96 RTSEMEVENT hDnsInitEvent;
97 VirtualBox *virtualbox;
98};
99
100struct HostDnsMonitorProxy::Data
101{
102 Data(const HostDnsMonitor *aMonitor, VirtualBox *aParent)
103 : info(NULL)
104 , virtualbox(aParent)
105 , monitor(aMonitor)
106 , fModified(true)
107 {}
108
109 virtual ~Data()
110 {
111 if (info)
112 {
113 delete info;
114 info = NULL;
115 }
116 }
117
118 HostDnsInformation *info;
119 VirtualBox *virtualbox;
120 const HostDnsMonitor *monitor;
121 bool fModified;
122};
123
124
125HostDnsMonitor::HostDnsMonitor(bool fThreaded)
126 : m(NULL)
127{
128 m = new HostDnsMonitor::Data(fThreaded);
129}
130
131HostDnsMonitor::~HostDnsMonitor()
132{
133 if (m)
134 {
135 delete m;
136 m = NULL;
137 }
138}
139
140const HostDnsMonitor *HostDnsMonitor::getHostDnsMonitor(VirtualBox *aParent)
141{
142 /* XXX: Moved initialization from HostImpl.cpp */
143 if (!g_monitor)
144 {
145# if defined (RT_OS_DARWIN)
146 g_monitor = new HostDnsServiceDarwin();
147# elif defined(RT_OS_WINDOWS)
148 g_monitor = new HostDnsServiceWin();
149# elif defined(RT_OS_LINUX)
150 g_monitor = new HostDnsServiceLinux();
151# elif defined(RT_OS_SOLARIS)
152 g_monitor = new HostDnsServiceSolaris();
153# elif defined(RT_OS_FREEBSD)
154 g_monitor = new HostDnsServiceFreebsd();
155# elif defined(RT_OS_OS2)
156 g_monitor = new HostDnsServiceOs2();
157# else
158 g_monitor = new HostDnsService();
159# endif
160 g_monitor->init(aParent);
161 }
162
163 return g_monitor;
164}
165
166void HostDnsMonitor::addMonitorProxy(PCHostDnsMonitorProxy proxy) const
167{
168 RTCLock grab(m_LockMtx);
169 m->proxies.push_back(proxy);
170 proxy->notify();
171}
172
173void HostDnsMonitor::releaseMonitorProxy(PCHostDnsMonitorProxy proxy) const
174{
175 RTCLock grab(m_LockMtx);
176 std::vector<PCHostDnsMonitorProxy>::iterator it;
177 it = std::find(m->proxies.begin(), m->proxies.end(), proxy);
178
179 if (it == m->proxies.end())
180 return;
181
182 m->proxies.erase(it);
183}
184
185void HostDnsMonitor::shutdown()
186{
187 if (g_monitor)
188 {
189 delete g_monitor;
190 g_monitor = NULL;
191 }
192}
193
194const HostDnsInformation &HostDnsMonitor::getInfo() const
195{
196 return m->info;
197}
198
199void HostDnsMonitor::setInfo(const HostDnsInformation &info)
200{
201 RTCLock grab(m_LockMtx);
202
203 pollGlobalExtraData();
204
205 if (info.equals(m->info))
206 return;
207
208 LogRel(("HostDnsMonitor: old information\n"));
209 dumpHostDnsInformation(m->info);
210 LogRel(("HostDnsMonitor: new information\n"));
211 dumpHostDnsInformation(info);
212
213 bool fIgnore = m->fLaxComparison && info.equals(m->info, m->fLaxComparison);
214 m->info = info;
215
216 if (fIgnore)
217 {
218 LogRel(("HostDnsMonitor: lax comparison %#x, not notifying\n", m->fLaxComparison));
219 return;
220 }
221
222 std::vector<PCHostDnsMonitorProxy>::const_iterator it;
223 for (it = m->proxies.begin(); it != m->proxies.end(); ++it)
224 (*it)->notify();
225}
226
227HRESULT HostDnsMonitor::init(VirtualBox *virtualbox)
228{
229 m->virtualbox = virtualbox;
230
231 pollGlobalExtraData();
232
233 if (m->fThreaded)
234 {
235 int rc = RTSemEventCreate(&m->hDnsInitEvent);
236 AssertRCReturn(rc, E_FAIL);
237
238 rc = RTThreadCreate(&m->hMonitoringThread,
239 HostDnsMonitor::threadMonitoringRoutine,
240 this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
241 AssertRCReturn(rc, E_FAIL);
242
243 RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
244 }
245 return S_OK;
246}
247
248
249void HostDnsMonitor::pollGlobalExtraData()
250{
251 uint64_t uNow = RTTimeNanoTS();
252 if (m->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 m->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 m->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 if (m->monitor)
327 m->monitor->releaseMonitorProxy(this);
328 delete m;
329 m = NULL;
330 }
331}
332
333void HostDnsMonitorProxy::init(const HostDnsMonitor *mon, VirtualBox* aParent)
334{
335 m = new HostDnsMonitorProxy::Data(mon, aParent);
336 m->monitor->addMonitorProxy(this);
337 updateInfo();
338}
339
340void HostDnsMonitorProxy::notify() const
341{
342 LogRel(("HostDnsMonitorProxy::notify\n"));
343 m->fModified = true;
344 m->virtualbox->i_onHostNameResolutionConfigurationChange();
345}
346
347HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
348{
349 AssertReturn(m && m->info, E_FAIL);
350 RTCLock grab(m_LockMtx);
351
352 if (m->fModified)
353 updateInfo();
354
355 LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
356 dumpHostDnsStrVector("name server", m->info->servers);
357
358 detachVectorOfString(m->info->servers, aNameServers);
359
360 return S_OK;
361}
362
363HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
364{
365 AssertReturn(m && m->info, E_FAIL);
366 RTCLock grab(m_LockMtx);
367
368 if (m->fModified)
369 updateInfo();
370
371 LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n",
372 m->info->domain.empty() ? "no domain set" : m->info->domain.c_str()));
373
374 *pDomainName = m->info->domain.c_str();
375
376 return S_OK;
377}
378
379HRESULT HostDnsMonitorProxy::GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
380{
381 AssertReturn(m && m->info, E_FAIL);
382 RTCLock grab(m_LockMtx);
383
384 if (m->fModified)
385 updateInfo();
386
387 LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
388 dumpHostDnsStrVector("search string", m->info->searchList);
389
390 detachVectorOfString(m->info->searchList, aSearchStrings);
391
392 return S_OK;
393}
394
395bool HostDnsMonitorProxy::operator==(PCHostDnsMonitorProxy& rhs)
396{
397 if (!m || !rhs->m)
398 return false;
399
400 /**
401 * we've assigned to the same instance of VirtualBox.
402 */
403 return m->virtualbox == rhs->m->virtualbox;
404}
405
406void HostDnsMonitorProxy::updateInfo()
407{
408 HostDnsInformation *info = new HostDnsInformation(m->monitor->getInfo());
409 HostDnsInformation *old = m->info;
410
411 m->info = info;
412 if (old)
413 {
414 delete old;
415 }
416
417 m->fModified = false;
418}
419
420
421static void dumpHostDnsInformation(const HostDnsInformation& info)
422{
423 dumpHostDnsStrVector("server", info.servers);
424 dumpHostDnsStrVector("search string", info.searchList);
425
426 if (!info.domain.empty())
427 LogRel((" domain: %s\n", info.domain.c_str()));
428 else
429 LogRel((" no domain set\n"));
430}
431
432
433static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
434{
435 int i = 1;
436 for (std::vector<std::string>::const_iterator it = v.begin();
437 it != v.end();
438 ++it, ++i)
439 LogRel((" %s %d: %s\n", prefix.c_str(), i, it->c_str()));
440 if (v.empty())
441 LogRel((" no %s entries\n", prefix.c_str()));
442}
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