VirtualBox

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

Last change on this file since 55223 was 55223, checked in by vboxsync, 10 years ago

Main/HostDnsService: if VBoxInternal2/HostDNSOrderIgnore global
extradata is set to a value other than "0", don't send notification
when only the order of nameservers changed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.2 KB
Line 
1/* $Id: HostDnsService.cpp 55223 2015-04-13 18:06:30Z 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/thread.h>
27#include <iprt/semaphore.h>
28#include <iprt/critsect.h>
29
30#include <algorithm>
31#include <set>
32#include <string>
33#include "HostDnsService.h"
34
35
36static HostDnsMonitor *g_monitor;
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, bool fDNSOrderIgnore) const
43{
44 if (fDNSOrderIgnore)
45 {
46 std::set<std::string> l(servers.begin(), servers.end());
47 std::set<std::string> r(info.servers.begin(), info.servers.end());
48
49 return (l == r)
50 && (domain == info.domain)
51 && (searchList == info.searchList); // XXX: also ignore order?
52 }
53 else
54 {
55 return (servers == info.servers)
56 && (domain == info.domain)
57 && (searchList == info.searchList);
58 }
59}
60
61inline static void detachVectorOfString(const std::vector<std::string>& v,
62 std::vector<com::Utf8Str> &aArray)
63{
64 aArray.resize(v.size());
65 size_t i = 0;
66 for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it, ++i)
67 aArray[i] = Utf8Str(it->c_str());
68}
69
70struct HostDnsMonitor::Data
71{
72 Data(bool aThreaded)
73 : fDNSOrderIgnore(false),
74 fThreaded(aThreaded)
75 {}
76
77 std::vector<PCHostDnsMonitorProxy> proxies;
78 HostDnsInformation info;
79 bool fDNSOrderIgnore;
80 const bool fThreaded;
81 RTTHREAD hMonitoringThread;
82 RTSEMEVENT hDnsInitEvent;
83};
84
85struct HostDnsMonitorProxy::Data
86{
87 Data(const HostDnsMonitor *aMonitor, VirtualBox *aParent)
88 : info(NULL)
89 , virtualbox(aParent)
90 , monitor(aMonitor)
91 , fModified(true)
92 {}
93
94 virtual ~Data()
95 {
96 if (info)
97 {
98 delete info;
99 info = NULL;
100 }
101 }
102
103 HostDnsInformation *info;
104 VirtualBox *virtualbox;
105 const HostDnsMonitor *monitor;
106 bool fModified;
107};
108
109
110HostDnsMonitor::HostDnsMonitor(bool fThreaded)
111 : m(NULL)
112{
113 m = new HostDnsMonitor::Data(fThreaded);
114}
115
116HostDnsMonitor::~HostDnsMonitor()
117{
118 if (m)
119 {
120 delete m;
121 m = NULL;
122 }
123}
124
125const HostDnsMonitor *HostDnsMonitor::getHostDnsMonitor(VirtualBox *aParent)
126{
127 /* XXX: Moved initialization from HostImpl.cpp */
128 if (!g_monitor)
129 {
130# if defined (RT_OS_DARWIN)
131 g_monitor = new HostDnsServiceDarwin();
132# elif defined(RT_OS_WINDOWS)
133 g_monitor = new HostDnsServiceWin();
134# elif defined(RT_OS_LINUX)
135 g_monitor = new HostDnsServiceLinux();
136# elif defined(RT_OS_SOLARIS)
137 g_monitor = new HostDnsServiceSolaris();
138# elif defined(RT_OS_FREEBSD)
139 g_monitor = new HostDnsServiceFreebsd();
140# elif defined(RT_OS_OS2)
141 g_monitor = new HostDnsServiceOs2();
142# else
143 g_monitor = new HostDnsService();
144# endif
145 g_monitor->init(aParent);
146 }
147
148 return g_monitor;
149}
150
151void HostDnsMonitor::addMonitorProxy(PCHostDnsMonitorProxy proxy) const
152{
153 RTCLock grab(m_LockMtx);
154 m->proxies.push_back(proxy);
155 proxy->notify();
156}
157
158void HostDnsMonitor::releaseMonitorProxy(PCHostDnsMonitorProxy proxy) const
159{
160 RTCLock grab(m_LockMtx);
161 std::vector<PCHostDnsMonitorProxy>::iterator it;
162 it = std::find(m->proxies.begin(), m->proxies.end(), proxy);
163
164 if (it == m->proxies.end())
165 return;
166
167 m->proxies.erase(it);
168}
169
170void HostDnsMonitor::shutdown()
171{
172 if (g_monitor)
173 {
174 delete g_monitor;
175 g_monitor = NULL;
176 }
177}
178
179const HostDnsInformation &HostDnsMonitor::getInfo() const
180{
181 return m->info;
182}
183
184void HostDnsMonitor::setInfo(const HostDnsInformation &info)
185{
186 RTCLock grab(m_LockMtx);
187
188 if (info.equals(m->info))
189 return;
190
191 LogRel(("HostDnsMonitor: old information\n"));
192 dumpHostDnsInformation(m->info);
193 LogRel(("HostDnsMonitor: new information\n"));
194 dumpHostDnsInformation(info);
195
196 bool fIgnore = m->fDNSOrderIgnore && info.equals(m->info, m->fDNSOrderIgnore);
197 m->info = info;
198
199 if (fIgnore)
200 {
201 LogRel(("HostDnsMonitor: order change only, not notifying\n"));
202 return;
203 }
204
205 std::vector<PCHostDnsMonitorProxy>::const_iterator it;
206 for (it = m->proxies.begin(); it != m->proxies.end(); ++it)
207 (*it)->notify();
208}
209
210HRESULT HostDnsMonitor::init(VirtualBox *virtualbox)
211{
212 const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
213 com::Bstr bstrHostDNSOrderIgnore;
214 virtualbox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(),
215 bstrHostDNSOrderIgnore.asOutParam());
216
217 if (bstrHostDNSOrderIgnore.isNotEmpty())
218 {
219 LogRel(("HostDnsMonitor: %ls=%ls\n",
220 bstrHostDNSOrderIgnoreKey.raw(),
221 bstrHostDNSOrderIgnore.raw()));
222
223 if (bstrHostDNSOrderIgnore != "0")
224 m->fDNSOrderIgnore = true;
225 }
226
227 if (m->fThreaded)
228 {
229 int rc = RTSemEventCreate(&m->hDnsInitEvent);
230 AssertRCReturn(rc, E_FAIL);
231
232 rc = RTThreadCreate(&m->hMonitoringThread,
233 HostDnsMonitor::threadMonitoringRoutine,
234 this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
235 AssertRCReturn(rc, E_FAIL);
236
237 RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
238 }
239 return S_OK;
240}
241
242
243void HostDnsMonitor::monitorThreadInitializationDone()
244{
245 RTSemEventSignal(m->hDnsInitEvent);
246}
247
248
249int HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
250{
251 HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
252 return pThis->monitorWorker();
253}
254
255/* HostDnsMonitorProxy */
256HostDnsMonitorProxy::HostDnsMonitorProxy()
257 : m(NULL)
258{
259}
260
261HostDnsMonitorProxy::~HostDnsMonitorProxy()
262{
263 if (m)
264 {
265 if (m->monitor)
266 m->monitor->releaseMonitorProxy(this);
267 delete m;
268 m = NULL;
269 }
270}
271
272void HostDnsMonitorProxy::init(const HostDnsMonitor *mon, VirtualBox* aParent)
273{
274 m = new HostDnsMonitorProxy::Data(mon, aParent);
275 m->monitor->addMonitorProxy(this);
276 updateInfo();
277}
278
279void HostDnsMonitorProxy::notify() const
280{
281 LogRel(("HostDnsMonitorProxy::notify\n"));
282 m->fModified = true;
283 m->virtualbox->i_onHostNameResolutionConfigurationChange();
284}
285
286HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
287{
288 AssertReturn(m && m->info, E_FAIL);
289 RTCLock grab(m_LockMtx);
290
291 if (m->fModified)
292 updateInfo();
293
294 LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
295 dumpHostDnsStrVector("name server", m->info->servers);
296
297 detachVectorOfString(m->info->servers, aNameServers);
298
299 return S_OK;
300}
301
302HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
303{
304 AssertReturn(m && m->info, E_FAIL);
305 RTCLock grab(m_LockMtx);
306
307 if (m->fModified)
308 updateInfo();
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 && m->info, E_FAIL);
321 RTCLock grab(m_LockMtx);
322
323 if (m->fModified)
324 updateInfo();
325
326 LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
327 dumpHostDnsStrVector("search string", m->info->searchList);
328
329 detachVectorOfString(m->info->searchList, aSearchStrings);
330
331 return S_OK;
332}
333
334bool HostDnsMonitorProxy::operator==(PCHostDnsMonitorProxy& rhs)
335{
336 if (!m || !rhs->m)
337 return false;
338
339 /**
340 * we've assigned to the same instance of VirtualBox.
341 */
342 return m->virtualbox == rhs->m->virtualbox;
343}
344
345void HostDnsMonitorProxy::updateInfo()
346{
347 HostDnsInformation *info = new HostDnsInformation(m->monitor->getInfo());
348 HostDnsInformation *old = m->info;
349
350 m->info = info;
351 if (old)
352 {
353 delete old;
354 }
355
356 m->fModified = false;
357}
358
359
360static void dumpHostDnsInformation(const HostDnsInformation& info)
361{
362 dumpHostDnsStrVector("server", info.servers);
363 dumpHostDnsStrVector("search string", info.searchList);
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
371
372static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
373{
374 int i = 1;
375 for (std::vector<std::string>::const_iterator it = v.begin();
376 it != v.end();
377 ++it, ++i)
378 LogRel((" %s %d: %s\n", prefix.c_str(), i, it->c_str()));
379 if (v.empty())
380 LogRel((" no %s entries\n", prefix.c_str()));
381}
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