VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp@ 107621

Last change on this file since 107621 was 107621, checked in by vboxsync, 9 days ago

Main/src-server/darwin/HostDnsServiceDarwin.cpp: Missing member initializer, bugref:3409 [scm]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 KB
Line 
1/* $Id: HostDnsServiceDarwin.cpp 107621 2025-01-10 10:02:43Z vboxsync $ */
2/** @file
3 * Darwin specific DNS information fetching.
4 */
5
6/*
7 * Copyright (C) 2004-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.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#include <VBox/com/string.h>
29#include <VBox/com/ptr.h>
30
31
32#include <iprt/asm.h>
33#include <iprt/errcore.h>
34#include <iprt/thread.h>
35#include <iprt/semaphore.h>
36
37#include <CoreFoundation/CoreFoundation.h>
38#include <SystemConfiguration/SCDynamicStore.h>
39
40#include <iprt/sanitized/string>
41#include <vector>
42#include "../HostDnsService.h"
43
44
45struct HostDnsServiceDarwin::Data
46{
47 Data()
48 : m_store(NULL)
49 , m_DnsWatcher(NULL)
50 , m_RunLoopRef(NULL)
51 , m_SourceStop(NULL)
52 , m_fStop(false)
53 , m_evtStop(NIL_RTSEMEVENT) { }
54
55 SCDynamicStoreRef m_store;
56 CFRunLoopSourceRef m_DnsWatcher;
57 CFRunLoopRef m_RunLoopRef;
58 CFRunLoopSourceRef m_SourceStop;
59 volatile bool m_fStop;
60 RTSEMEVENT m_evtStop;
61 static void performShutdownCallback(void *);
62};
63
64
65static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
66
67
68HostDnsServiceDarwin::HostDnsServiceDarwin()
69 : HostDnsServiceBase(true /* fThreaded */)
70 , m(NULL)
71{
72 m = new HostDnsServiceDarwin::Data();
73}
74
75HostDnsServiceDarwin::~HostDnsServiceDarwin()
76{
77 if (m != NULL)
78 delete m;
79}
80
81HRESULT HostDnsServiceDarwin::init(HostDnsMonitorProxy *pProxy)
82{
83 SCDynamicStoreContext ctx;
84 RT_ZERO(ctx);
85
86 ctx.info = this;
87
88 m->m_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC.HostDNS"),
89 (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
90 &ctx);
91 AssertReturn(m->m_store, E_FAIL);
92
93 m->m_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, m->m_store, 0);
94 if (!m->m_DnsWatcher)
95 return E_OUTOFMEMORY;
96
97 int vrc = RTSemEventCreate(&m->m_evtStop);
98 AssertRCReturn(vrc, E_FAIL);
99
100 CFRunLoopSourceContext sctx;
101 RT_ZERO(sctx);
102 sctx.info = this;
103 sctx.perform = HostDnsServiceDarwin::Data::performShutdownCallback;
104
105 m->m_SourceStop = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sctx);
106 AssertReturn(m->m_SourceStop, E_FAIL);
107
108 HRESULT hrc = HostDnsServiceBase::init(pProxy);
109 return hrc;
110}
111
112void HostDnsServiceDarwin::uninit(void)
113{
114 HostDnsServiceBase::uninit();
115
116 CFRelease(m->m_SourceStop);
117 CFRelease(m->m_RunLoopRef);
118 CFRelease(m->m_DnsWatcher);
119 CFRelease(m->m_store);
120
121 RTSemEventDestroy(m->m_evtStop);
122}
123
124int HostDnsServiceDarwin::monitorThreadShutdown(RTMSINTERVAL uTimeoutMs)
125{
126 RTCLock grab(m_LockMtx);
127 if (!m->m_fStop)
128 {
129 ASMAtomicXchgBool(&m->m_fStop, true);
130 CFRunLoopSourceSignal(m->m_SourceStop);
131 CFRunLoopStop(m->m_RunLoopRef);
132
133 RTSemEventWait(m->m_evtStop, uTimeoutMs);
134 }
135
136 return VINF_SUCCESS;
137}
138
139int HostDnsServiceDarwin::monitorThreadProc(void)
140{
141 m->m_RunLoopRef = CFRunLoopGetCurrent();
142 AssertReturn(m->m_RunLoopRef, VERR_INTERNAL_ERROR);
143
144 CFRetain(m->m_RunLoopRef);
145
146 CFRunLoopAddSource(m->m_RunLoopRef, m->m_SourceStop, kCFRunLoopCommonModes);
147
148 CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
149 (const void **)&kStateNetworkGlobalDNSKey,
150 1, &kCFTypeArrayCallBacks);
151 if (!watchingArrayRef)
152 {
153 CFRelease(m->m_DnsWatcher);
154 return VERR_NO_MEMORY;
155 }
156
157 if (SCDynamicStoreSetNotificationKeys(m->m_store, watchingArrayRef, NULL))
158 CFRunLoopAddSource(CFRunLoopGetCurrent(), m->m_DnsWatcher, kCFRunLoopCommonModes);
159
160 CFRelease(watchingArrayRef);
161
162 onMonitorThreadInitDone();
163
164 /* Trigger initial update. */
165 int vrc = updateInfo();
166 AssertRC(vrc); /* Not fatal in release builds. */ /** @todo r=bird: The function always returns VINF_SUCCESS. */
167
168 while (!ASMAtomicReadBool(&m->m_fStop))
169 {
170 CFRunLoopRun();
171 }
172
173 CFRunLoopRemoveSource(m->m_RunLoopRef, m->m_SourceStop, kCFRunLoopCommonModes);
174
175 /* We're notifying stopper thread. */
176 RTSemEventSignal(m->m_evtStop);
177
178 return VINF_SUCCESS;
179}
180
181int HostDnsServiceDarwin::updateInfo(void)
182{
183 CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(m->m_store, kStateNetworkGlobalDNSKey);
184 /**
185 * # scutil
186 * \> get State:/Network/Global/DNS
187 * \> d.show
188 * \<dictionary\> {
189 * DomainName : vvl-domain
190 * SearchDomains : \<array\> {
191 * 0 : vvl-domain
192 * 1 : de.vvl-domain.com
193 * }
194 * ServerAddresses : \<array\> {
195 * 0 : 192.168.1.4
196 * 1 : 192.168.1.1
197 * 2 : 8.8.4.4
198 * }
199 * }
200 */
201
202 if (!propertyRef)
203 return VINF_SUCCESS;
204
205 HostDnsInformation info;
206 CFStringRef domainNameRef = (CFStringRef)CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyRef), CFSTR("DomainName"));
207 if (domainNameRef)
208 {
209 const char *pszDomainName = CFStringGetCStringPtr(domainNameRef, CFStringGetSystemEncoding());
210 if (pszDomainName)
211 info.domain = pszDomainName;
212 }
213
214 CFArrayRef serverArrayRef = (CFArrayRef)CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyRef),
215 CFSTR("ServerAddresses"));
216 if (serverArrayRef)
217 {
218 CFIndex const cItems = CFArrayGetCount(serverArrayRef);
219 for (CFIndex i = 0; i < cItems; ++i)
220 {
221 CFStringRef serverAddressRef = (CFStringRef)CFArrayGetValueAtIndex(serverArrayRef, i);
222 if (!serverAddressRef)
223 continue;
224
225 /** @todo r=bird: This code is messed up as CFStringGetCStringPtr is documented
226 * to return NULL even if the string is valid. Furthermore, we must have
227 * UTF-8 - some joker might decide latin-1 is better here for all we know
228 * and we'll end up with evil invalid UTF-8 sequences. */
229 const char *pszServerAddress = CFStringGetCStringPtr(serverAddressRef, CFStringGetSystemEncoding());
230 if (!pszServerAddress)
231 continue;
232
233 /** @todo r=bird: Why on earth are we using std::string and not Utf8Str? */
234 info.servers.push_back(std::string(pszServerAddress));
235 }
236 }
237
238 CFArrayRef searchArrayRef = (CFArrayRef)CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyRef),
239 CFSTR("SearchDomains"));
240 if (searchArrayRef)
241 {
242 CFIndex const cItems = CFArrayGetCount(searchArrayRef);
243 for (CFIndex i = 0; i < cItems; ++i)
244 {
245 CFStringRef searchStringRef = (CFStringRef)CFArrayGetValueAtIndex(searchArrayRef, i);
246 if (!searchStringRef)
247 continue;
248
249 /** @todo r=bird: This code is messed up as CFStringGetCStringPtr is documented
250 * to return NULL even if the string is valid. Furthermore, we must have
251 * UTF-8 - some joker might decide latin-1 is better here for all we know
252 * and we'll end up with evil invalid UTF-8 sequences. */
253 const char *pszSearchString = CFStringGetCStringPtr(searchStringRef, CFStringGetSystemEncoding());
254 if (!pszSearchString)
255 continue;
256
257 /** @todo r=bird: Why on earth are we using std::string and not Utf8Str? */
258 info.searchList.push_back(std::string(pszSearchString));
259 }
260 }
261
262 CFRelease(propertyRef);
263
264 setInfo(info);
265
266 return VINF_SUCCESS;
267}
268
269void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *, void *, void *pInfo)
270{
271 HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)pInfo;
272 AssertPtrReturnVoid(pThis);
273
274 RTCLock grab(pThis->m_LockMtx);
275 pThis->updateInfo();
276}
277
278void HostDnsServiceDarwin::Data::performShutdownCallback(void *pInfo)
279{
280 HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)pInfo;
281 AssertPtrReturnVoid(pThis);
282
283 AssertPtrReturnVoid(pThis->m);
284 ASMAtomicXchgBool(&pThis->m->m_fStop, true);
285}
286
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