VirtualBox

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

Last change on this file since 94134 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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