VirtualBox

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

Last change on this file since 106683 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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