VirtualBox

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

最後變更 在這個檔案從108422是 108012,由 vboxsync 提交於 6 週 前

Main: Replaced std::string with com::Utf8Str in the HostDnsService code, santizing all the strings.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.1 KB
 
1/* $Id: HostDnsService.cpp 108012 2025-02-01 02:19:11Z vboxsync $ */
2/** @file
3 * Base class for Host DNS & Co services.
4 */
5
6/*
7 * Copyright (C) 2013-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_HOST
29#include <VBox/com/array.h>
30#include <VBox/com/ptr.h>
31#include <VBox/com/string.h>
32
33#include <iprt/cpp/utils.h>
34
35#include "LoggingNew.h"
36#include "VirtualBoxImpl.h"
37#include <iprt/time.h>
38#include <iprt/thread.h>
39#include <iprt/semaphore.h>
40#include <iprt/critsect.h>
41
42#include <algorithm>
43#include <set>
44#include "HostDnsService.h"
45
46
47
48static void dumpHostDnsStrVector(const char *prefix, const std::vector<com::Utf8Str> &v)
49{
50 int i = 1;
51 for (std::vector<com::Utf8Str>::const_iterator it = v.begin(); it != v.end(); ++it, ++i)
52 LogRel((" %s %d: %s\n", prefix, i, it->c_str()));
53 if (v.empty())
54 LogRel((" no %s entries\n", prefix));
55}
56
57static void dumpHostDnsInformation(const HostDnsInformation &info)
58{
59 dumpHostDnsStrVector("server", info.servers);
60
61 if (info.domain.isNotEmpty())
62 LogRel((" domain: %s\n", info.domain.c_str()));
63 else
64 LogRel((" no domain set\n"));
65
66 dumpHostDnsStrVector("search string", info.searchList);
67}
68
69bool HostDnsInformation::equals(const HostDnsInformation &info, uint32_t fLaxComparison) const
70{
71 bool fSameServers;
72 if ((fLaxComparison & IGNORE_SERVER_ORDER) == 0)
73 fSameServers = (servers == info.servers);
74 else
75 {
76 std::set<com::Utf8Str> l(servers.begin(), servers.end());
77 std::set<com::Utf8Str> r(info.servers.begin(), info.servers.end());
78
79 fSameServers = (l == r);
80 }
81
82 bool fSameDomain, fSameSearchList;
83 if ((fLaxComparison & IGNORE_SUFFIXES) == 0)
84 {
85 fSameDomain = (domain == info.domain);
86 fSameSearchList = (searchList == info.searchList);
87 }
88 else
89 fSameDomain = fSameSearchList = true;
90
91 return fSameServers && fSameDomain && fSameSearchList;
92}
93
94struct HostDnsServiceBase::Data
95{
96 Data(bool aThreaded)
97 : pProxy(NULL)
98 , fThreaded(aThreaded)
99 , hMonitorThreadEvent(NIL_RTSEMEVENT)
100 , hMonitorThread(NIL_RTTHREAD)
101 {}
102
103 /** Weak pointer to parent proxy object. */
104 HostDnsMonitorProxy *pProxy;
105 /** Whether the DNS monitor implementation has a dedicated monitoring thread. Optional. */
106 const bool fThreaded;
107 /** Event for the monitor thread, if any. */
108 RTSEMEVENT hMonitorThreadEvent;
109 /** Handle of the monitor thread, if any. */
110 RTTHREAD hMonitorThread;
111 /** Generic host DNS information. */
112 HostDnsInformation info;
113};
114
115struct HostDnsMonitorProxy::Data
116{
117 Data(HostDnsServiceBase *aMonitor, VirtualBox *aParent)
118 : pVirtualBox(aParent)
119 , pMonitorImpl(aMonitor)
120 , uLastExtraDataPoll(0)
121 , fLaxComparison(0)
122 , info()
123 {}
124
125 VirtualBox *pVirtualBox;
126 HostDnsServiceBase *pMonitorImpl;
127
128 uint64_t uLastExtraDataPoll;
129 uint32_t fLaxComparison;
130 HostDnsInformation info;
131};
132
133
134HostDnsServiceBase::HostDnsServiceBase(bool fThreaded)
135 : m(NULL)
136{
137 m = new HostDnsServiceBase::Data(fThreaded);
138}
139
140HostDnsServiceBase::~HostDnsServiceBase()
141{
142 if (m)
143 {
144 delete m;
145 m = NULL;
146 }
147}
148
149/* static */
150HostDnsServiceBase *HostDnsServiceBase::createHostDnsMonitor(void)
151{
152 HostDnsServiceBase *pMonitor = NULL;
153
154#if defined (RT_OS_DARWIN)
155 pMonitor = new HostDnsServiceDarwin();
156#elif defined(RT_OS_WINDOWS)
157 pMonitor = new HostDnsServiceWin();
158#elif defined(RT_OS_LINUX)
159 pMonitor = new HostDnsServiceLinux();
160#elif defined(RT_OS_SOLARIS)
161 pMonitor = new HostDnsServiceSolaris();
162#elif defined(RT_OS_FREEBSD)
163 pMonitor = new HostDnsServiceFreebsd();
164#elif defined(RT_OS_OS2)
165 pMonitor = new HostDnsServiceOs2();
166#else
167 pMonitor = new HostDnsServiceBase();
168#endif
169
170 return pMonitor;
171}
172
173HRESULT HostDnsServiceBase::init(HostDnsMonitorProxy *pProxy)
174{
175 LogRel(("HostDnsMonitor: initializing\n"));
176
177 AssertPtrReturn(pProxy, E_POINTER);
178 m->pProxy = pProxy;
179
180 if (m->fThreaded)
181 {
182 LogRel2(("HostDnsMonitor: starting thread ...\n"));
183
184 int vrc = RTSemEventCreate(&m->hMonitorThreadEvent);
185 AssertRCReturn(vrc, E_FAIL);
186
187 vrc = RTThreadCreate(&m->hMonitorThread,
188 HostDnsServiceBase::threadMonitorProc,
189 this, 128 * _1K, RTTHREADTYPE_IO,
190 RTTHREADFLAGS_WAITABLE, "dns-monitor");
191 AssertRCReturn(vrc, E_FAIL);
192
193 RTSemEventWait(m->hMonitorThreadEvent, RT_INDEFINITE_WAIT);
194
195 LogRel2(("HostDnsMonitor: thread started\n"));
196 }
197
198 return S_OK;
199}
200
201void HostDnsServiceBase::uninit(void)
202{
203 LogRel(("HostDnsMonitor: shutting down ...\n"));
204
205 if (m->fThreaded)
206 {
207 LogRel2(("HostDnsMonitor: waiting for thread ...\n"));
208
209 const RTMSINTERVAL uTimeoutMs = 30 * 1000; /* 30s */
210
211 monitorThreadShutdown(uTimeoutMs);
212
213 int vrc = RTThreadWait(m->hMonitorThread, uTimeoutMs, NULL);
214 if (RT_FAILURE(vrc))
215 LogRel(("HostDnsMonitor: waiting for thread failed with vrc=%Rrc\n", vrc));
216
217 if (m->hMonitorThreadEvent != NIL_RTSEMEVENT)
218 {
219 RTSemEventDestroy(m->hMonitorThreadEvent);
220 m->hMonitorThreadEvent = NIL_RTSEMEVENT;
221 }
222 }
223
224 LogRel(("HostDnsMonitor: shut down\n"));
225}
226
227void HostDnsServiceBase::setInfo(const HostDnsInformation &info)
228{
229 if (m->pProxy != NULL)
230 m->pProxy->notify(info);
231}
232
233/**
234 * Updates HostDnsMonitorProxy::Data::fLaxComparison every 30 seconds, returning
235 * the new value.
236 *
237 * @note This will leave the lock while calling IVirtualBox::GetExtraData.
238 */
239uint32_t HostDnsMonitorProxy::pollGlobalExtraData(AutoWriteLock &aLock)
240{
241 uint32_t fLaxComparison = m->fLaxComparison;
242 VirtualBox *pVirtualBox = m->pVirtualBox;
243 if (pVirtualBox)
244 {
245 uint64_t uNow = RTTimeNanoTS();
246 if (uNow - m->uLastExtraDataPoll >= RT_NS_30SEC || m->uLastExtraDataPoll == 0)
247 {
248 m->uLastExtraDataPoll = uNow;
249
250 /* We cannot do GetExtraData holding this lock, so temporarily release it. */
251 aLock.release();
252
253 /*
254 * Should we ignore the order of DNS servers?
255 */
256 const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
257 com::Bstr bstrHostDNSOrderIgnore;
258 pVirtualBox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(), bstrHostDNSOrderIgnore.asOutParam());
259 uint32_t fDNSOrderIgnore = 0;
260 if (bstrHostDNSOrderIgnore.isNotEmpty() && bstrHostDNSOrderIgnore != "0")
261 fDNSOrderIgnore = HostDnsInformation::IGNORE_SERVER_ORDER;
262
263 if (fDNSOrderIgnore != (fLaxComparison & HostDnsInformation::IGNORE_SERVER_ORDER))
264 {
265 fLaxComparison ^= HostDnsInformation::IGNORE_SERVER_ORDER;
266 LogRel(("HostDnsMonitor: %ls=%ls\n", bstrHostDNSOrderIgnoreKey.raw(), bstrHostDNSOrderIgnore.raw()));
267 }
268
269 /*
270 * Should we ignore changes to the domain name or the search list?
271 */
272 const com::Bstr bstrHostDNSSuffixesIgnoreKey("VBoxInternal2/HostDNSSuffixesIgnore");
273 com::Bstr bstrHostDNSSuffixesIgnore;
274 pVirtualBox->GetExtraData(bstrHostDNSSuffixesIgnoreKey.raw(), bstrHostDNSSuffixesIgnore.asOutParam());
275 uint32_t fDNSSuffixesIgnore = 0;
276 if (bstrHostDNSSuffixesIgnore.isNotEmpty() && bstrHostDNSSuffixesIgnore != "0")
277 fDNSSuffixesIgnore = HostDnsInformation::IGNORE_SUFFIXES;
278
279 if (fDNSSuffixesIgnore != (fLaxComparison & HostDnsInformation::IGNORE_SUFFIXES))
280 {
281 fLaxComparison ^= HostDnsInformation::IGNORE_SUFFIXES;
282 LogRel(("HostDnsMonitor: %ls=%ls\n", bstrHostDNSSuffixesIgnoreKey.raw(), bstrHostDNSSuffixesIgnore.raw()));
283 }
284
285 aLock.acquire();
286 m->fLaxComparison = fLaxComparison;
287 }
288 }
289 return fLaxComparison;
290}
291
292void HostDnsServiceBase::onMonitorThreadInitDone(void)
293{
294 if (!m->fThreaded) /* If non-threaded, bail out, nothing to do here. */
295 return;
296
297 RTSemEventSignal(m->hMonitorThreadEvent);
298}
299
300DECLCALLBACK(int) HostDnsServiceBase::threadMonitorProc(RTTHREAD, void *pvUser)
301{
302 HostDnsServiceBase *pThis = static_cast<HostDnsServiceBase *>(pvUser);
303 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
304 return pThis->monitorThreadProc();
305}
306
307/* HostDnsMonitorProxy */
308HostDnsMonitorProxy::HostDnsMonitorProxy()
309 : m(NULL)
310 , m_ObjectLock(LOCKCLASS_OTHEROBJECT, "HostDnsMonitorProxy")
311{
312}
313
314HostDnsMonitorProxy::~HostDnsMonitorProxy()
315{
316 uninit();
317}
318
319HRESULT HostDnsMonitorProxy::init(VirtualBox *aParent)
320{
321 AssertMsgReturn(m == NULL, ("DNS monitor proxy already initialized\n"), E_FAIL);
322
323 HostDnsServiceBase *pMonitorImpl = HostDnsServiceBase::createHostDnsMonitor();
324 AssertPtrReturn(pMonitorImpl, E_OUTOFMEMORY);
325
326 Assert(m == NULL); /* Paranoia. */
327 m = new HostDnsMonitorProxy::Data(pMonitorImpl, aParent);
328 AssertPtrReturn(m, E_OUTOFMEMORY);
329
330 return m->pMonitorImpl->init(this);
331}
332
333void HostDnsMonitorProxy::uninit(void)
334{
335 if (m)
336 {
337 if (m->pMonitorImpl)
338 {
339 m->pMonitorImpl->uninit();
340
341 delete m->pMonitorImpl;
342 m->pMonitorImpl = NULL;
343 }
344
345 delete m;
346 m = NULL;
347 }
348}
349
350util::LockHandle *HostDnsMonitorProxy::lockHandle() const
351{
352 return &m_ObjectLock;
353}
354
355void HostDnsMonitorProxy::notify(const HostDnsInformation &info)
356{
357 const bool fNotify = updateInfo(info);
358 if (fNotify)
359 m->pVirtualBox->i_onHostNameResolutionConfigurationChange();
360}
361
362HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
363{
364 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
365 AssertReturn(m != NULL, E_FAIL);
366
367 LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
368 dumpHostDnsStrVector("name server", m->info.servers);
369
370 aNameServers = m->info.servers;
371
372 return S_OK;
373}
374
375HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
376{
377 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
378 AssertReturn(m != NULL, E_FAIL);
379
380 LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n", m->info.domain.isEmpty() ? "no domain set" : m->info.domain.c_str()));
381 *pDomainName = m->info.domain.c_str();
382
383 return S_OK;
384}
385
386HRESULT HostDnsMonitorProxy::GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
387{
388 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
389 AssertReturn(m != NULL, E_FAIL);
390
391 LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
392 dumpHostDnsStrVector("search string", m->info.searchList);
393
394 aSearchStrings = m->info.searchList;
395
396 return S_OK;
397}
398
399bool HostDnsMonitorProxy::updateInfo(const HostDnsInformation &info)
400{
401 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
402 LogRel(("HostDnsMonitor: updating information\n"));
403
404 if (info.equals(m->info))
405 {
406 LogRel(("HostDnsMonitor: unchanged\n"));
407 return false;
408 }
409
410 uint32_t const fLaxComparison = pollGlobalExtraData(alock);
411
412 LogRel(("HostDnsMonitor: old information\n"));
413 dumpHostDnsInformation(m->info);
414 LogRel(("HostDnsMonitor: new information\n"));
415 dumpHostDnsInformation(info);
416
417 bool fIgnore = fLaxComparison != 0 && info.equals(m->info, fLaxComparison);
418 m->info = info;
419
420 if (fIgnore)
421 {
422 LogRel(("HostDnsMonitor: lax comparison %#x, not notifying\n", m->fLaxComparison));
423 return false;
424 }
425
426 return true;
427}
428
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette