VirtualBox

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

Last change on this file since 52945 was 52901, checked in by vboxsync, 11 years ago

Main: trailing spaces + warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: HostDnsServiceDarwin.cpp 52901 2014-09-30 15:32:03Z vboxsync $ */
2/** @file
3 * Darwin specific DNS information fetching.
4 */
5
6/*
7 * Copyright (C) 2004-2013 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#include <VBox/log.h>
21
22
23#include <iprt/err.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 <string>
31#include <vector>
32#include "../HostDnsService.h"
33
34
35struct HostDnsServiceDarwin::Data
36{
37 SCDynamicStoreRef m_store;
38 CFRunLoopSourceRef m_DnsWatcher;
39 CFRunLoopRef m_RunLoopRef;
40 CFRunLoopSourceRef m_Stopper;
41 bool m_fStop;
42 RTSEMEVENT m_evtStop;
43 static void performShutdownCallback(void *);
44};
45
46
47static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
48
49
50HostDnsServiceDarwin::HostDnsServiceDarwin():HostDnsMonitor(true),m(NULL)
51{
52 m = new HostDnsServiceDarwin::Data();
53}
54
55
56HostDnsServiceDarwin::~HostDnsServiceDarwin()
57{
58 if (!m)
59 return;
60
61 monitorThreadShutdown();
62
63 CFRelease(m->m_RunLoopRef);
64
65 CFRelease(m->m_DnsWatcher);
66
67 CFRelease(m->m_store);
68
69 RTSemEventDestroy(m->m_evtStop);
70
71 delete m;
72 m = NULL;
73}
74
75
76void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *, void *, void *info)
77{
78 HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
79
80 ALock l(pThis);
81 pThis->updateInfo();
82 pThis->notifyAll();
83}
84
85
86HRESULT HostDnsServiceDarwin::init()
87{
88 SCDynamicStoreContext ctx;
89 RT_ZERO(ctx);
90
91 ctx.info = this;
92
93 m->m_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
94 (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
95 &ctx);
96 AssertReturn(m->m_store, E_FAIL);
97
98 m->m_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, m->m_store, 0);
99 if (!m->m_DnsWatcher)
100 return E_OUTOFMEMORY;
101
102 int rc = RTSemEventCreate(&m->m_evtStop);
103 AssertRCReturn(rc, E_FAIL);
104
105 CFRunLoopSourceContext sctx;
106 RT_ZERO(sctx);
107 sctx.perform = HostDnsServiceDarwin::Data::performShutdownCallback;
108 m->m_Stopper = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sctx);
109 AssertReturn(m->m_Stopper, E_FAIL);
110
111 HRESULT hrc = HostDnsMonitor::init();
112 AssertComRCReturn(hrc, hrc);
113
114 return updateInfo();
115}
116
117
118void HostDnsServiceDarwin::monitorThreadShutdown()
119{
120 ALock l(this);
121 if (!m->m_fStop)
122 {
123 CFRunLoopSourceSignal(m->m_Stopper);
124 CFRunLoopWakeUp(m->m_RunLoopRef);
125
126 RTSemEventWait(m->m_evtStop, RT_INDEFINITE_WAIT);
127 }
128}
129
130
131int HostDnsServiceDarwin::monitorWorker()
132{
133 m->m_RunLoopRef = CFRunLoopGetCurrent();
134 AssertReturn(m->m_RunLoopRef, VERR_INTERNAL_ERROR);
135
136 CFRetain(m->m_RunLoopRef);
137
138 CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
139 (const void **)&kStateNetworkGlobalDNSKey,
140 1, &kCFTypeArrayCallBacks);
141 if (!watchingArrayRef)
142 {
143 CFRelease(m->m_DnsWatcher);
144 return E_OUTOFMEMORY;
145 }
146
147 if(SCDynamicStoreSetNotificationKeys(m->m_store, watchingArrayRef, NULL))
148 CFRunLoopAddSource(CFRunLoopGetCurrent(), m->m_DnsWatcher, kCFRunLoopCommonModes);
149
150 CFRelease(watchingArrayRef);
151
152 monitorThreadInitializationDone();
153
154 while (!m->m_fStop)
155 {
156 CFRunLoopRun();
157 }
158
159 CFRelease(m->m_RunLoopRef);
160
161 /* We're notifying stopper thread. */
162 RTSemEventSignal(m->m_evtStop);
163
164 return VINF_SUCCESS;
165}
166
167
168static wchar_t *darwinCFStringToUtf16(CFStringRef pStringRef)
169{
170 /* Number of characters (UTF16 encoded, 2 bytes) in the pStringRef. */
171 CFIndex ccStringRef = CFStringGetLength(pStringRef);
172
173 if (ccStringRef > 0)
174 {
175 size_t cbTmpBuf = (size_t)ccStringRef * sizeof(wchar_t) + 1 /* end of string */;
176 wchar_t *pTmpBuf = (wchar_t *)RTMemAlloc(cbTmpBuf);
177 if (pTmpBuf)
178 {
179 CFIndex ccConverted = CFStringGetBytes(pStringRef,
180 CFRangeMake(0, ccStringRef),
181 kCFStringEncodingUTF16,
182 0,
183 false,
184 (UInt8 *)pTmpBuf,
185 (CFIndex)cbTmpBuf - 1 /* w/o end of string */,
186 NULL);
187 if (ccConverted > 0)
188 {
189 /* Set end of string. */
190 pTmpBuf[ccConverted] = 0;
191 return pTmpBuf;
192 }
193
194 RTMemFree(pTmpBuf);
195 }
196 }
197
198 return NULL;
199}
200
201
202HRESULT HostDnsServiceDarwin::updateInfo()
203{
204 CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(m->m_store,
205 kStateNetworkGlobalDNSKey);
206 /**
207 * 0:vvl@nb-mbp-i7-2(0)# scutil
208 * > get State:/Network/Global/DNS
209 * > d.show
210 * <dictionary> {
211 * DomainName : vvl-domain
212 * SearchDomains : <array> {
213 * 0 : vvl-domain
214 * 1 : de.vvl-domain.com
215 * }
216 * ServerAddresses : <array> {
217 * 0 : 192.168.1.4
218 * 1 : 192.168.1.1
219 * 2 : 8.8.4.4
220 * }
221 * }
222 */
223
224 if (!propertyRef)
225 return S_OK;
226
227 HostDnsInformation info;
228 CFStringRef domainNameRef = (CFStringRef)CFDictionaryGetValue(
229 static_cast<CFDictionaryRef>(propertyRef), CFSTR("DomainName"));
230 if (domainNameRef)
231 {
232 wchar_t *pwszDomainName = darwinCFStringToUtf16(domainNameRef);
233 if (pwszDomainName)
234 {
235 info.domain = std::wstring(pwszDomainName);
236 RTMemFree(pwszDomainName);
237 }
238 }
239
240 int i, arrayCount;
241 CFArrayRef serverArrayRef = (CFArrayRef)CFDictionaryGetValue(
242 static_cast<CFDictionaryRef>(propertyRef), CFSTR("ServerAddresses"));
243 if (serverArrayRef)
244 {
245 arrayCount = CFArrayGetCount(serverArrayRef);
246 for (i = 0; i < arrayCount; ++i)
247 {
248 CFStringRef serverAddressRef = (CFStringRef)CFArrayGetValueAtIndex(serverArrayRef, i);
249 if (!serverArrayRef)
250 continue;
251
252 wchar_t *pwszServerAddress = darwinCFStringToUtf16(serverAddressRef);
253 if (!pwszServerAddress)
254 continue;
255
256 info.servers.push_back(std::wstring(pwszServerAddress));
257 RTMemFree(pwszServerAddress);
258 }
259 }
260
261 CFArrayRef searchArrayRef = (CFArrayRef)CFDictionaryGetValue(
262 static_cast<CFDictionaryRef>(propertyRef), CFSTR("SearchDomains"));
263 if (searchArrayRef)
264 {
265 arrayCount = CFArrayGetCount(searchArrayRef);
266
267 for (i = 0; i < arrayCount; ++i)
268 {
269 CFStringRef searchStringRef = (CFStringRef)CFArrayGetValueAtIndex(searchArrayRef, i);
270 if (!searchArrayRef)
271 continue;
272
273 wchar_t *pwszSearchString = darwinCFStringToUtf16(searchStringRef);
274 if (!pwszSearchString)
275 continue;
276
277 info.searchList.push_back(std::wstring(pwszSearchString));
278 RTMemFree(pwszSearchString);
279 }
280 }
281
282 CFRelease(propertyRef);
283
284 setInfo(info);
285
286 return S_OK;
287}
288
289void HostDnsServiceDarwin::Data::performShutdownCallback(void *info)
290{
291 HostDnsServiceDarwin::Data *pThis = static_cast<HostDnsServiceDarwin::Data *>(info);
292 pThis->m_fStop = true;
293}
Note: See TracBrowser for help on using the repository browser.

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