]> git.saurik.com Git - apple/configd.git/blob - Plugins/KernelEventMonitor/ev_dlil.c
configd-395.7.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / ev_dlil.c
1 /*
2 * Copyright (c) 2002-2006, 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * August 5, 2002 Allan Nathanson <ajn@apple.com>
28 * - split code out from eventmon.c
29 */
30
31 #include "eventmon.h"
32 #include "cache.h"
33 #include "ev_dlil.h"
34
35 static CFStringRef
36 create_interface_key(const char * if_name)
37 {
38 CFStringRef interface;
39 CFStringRef key;
40
41 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
42 key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
43 kSCDynamicStoreDomainState,
44 interface,
45 kSCEntNetLink);
46 CFRelease(interface);
47 return (key);
48 }
49
50
51 static CFMutableDictionaryRef
52 copy_entity(CFStringRef key)
53 {
54 CFDictionaryRef dict;
55 CFMutableDictionaryRef newDict = NULL;
56
57 dict = cache_SCDynamicStoreCopyValue(store, key);
58 if (dict != NULL) {
59 if (isA_CFDictionary(dict) != NULL) {
60 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
61 }
62 CFRelease(dict);
63 }
64 if (newDict == NULL) {
65 newDict = CFDictionaryCreateMutable(NULL,
66 0,
67 &kCFTypeDictionaryKeyCallBacks,
68 &kCFTypeDictionaryValueCallBacks);
69 }
70 return (newDict);
71 }
72
73
74 static void
75 interface_update_status(const char *if_name, CFBooleanRef active,
76 boolean_t attach)
77 {
78 CFStringRef key = NULL;
79 CFMutableDictionaryRef newDict = NULL;
80
81 key = create_interface_key(if_name);
82 newDict = copy_entity(key);
83 /* if new status available, update cache */
84 if (active == NULL) {
85 CFDictionaryRemoveValue(newDict, kSCPropNetLinkActive);
86 } else {
87 CFDictionarySetValue(newDict, kSCPropNetLinkActive, active);
88 }
89 if (attach == TRUE) {
90 /* the interface was attached, remove stale state */
91 CFDictionaryRemoveValue(newDict, kSCPropNetLinkDetaching);
92 }
93
94 /* update status */
95 if (CFDictionaryGetCount(newDict) > 0) {
96 cache_SCDynamicStoreSetValue(store, key, newDict);
97 } else {
98 cache_SCDynamicStoreRemoveValue(store, key);
99 }
100
101 CFRelease(key);
102 CFRelease(newDict);
103 return;
104 }
105
106 __private_extern__
107 void
108 interface_detaching(const char *if_name)
109 {
110 CFStringRef key;
111 CFMutableDictionaryRef newDict;
112
113 key = create_interface_key(if_name);
114 newDict = copy_entity(key);
115 CFDictionarySetValue(newDict, kSCPropNetLinkDetaching,
116 kCFBooleanTrue);
117 cache_SCDynamicStoreSetValue(store, key, newDict);
118 CFRelease(newDict);
119 CFRelease(key);
120 return;
121 }
122
123 static void
124 interface_remove(const char *if_name)
125 {
126 CFStringRef key;
127
128 key = create_interface_key(if_name);
129 cache_SCDynamicStoreRemoveValue(store, key);
130 CFRelease(key);
131 return;
132 }
133
134
135 __private_extern__
136 void
137 link_update_status(const char *if_name, boolean_t attach)
138 {
139 CFBooleanRef active = NULL;
140 struct ifmediareq ifm;
141 int sock;
142
143 sock = dgram_socket(AF_INET);
144 if (sock == -1) {
145 SCLog(TRUE, LOG_NOTICE, CFSTR("link_update_status: socket open failed, %s"), strerror(errno));
146 goto done;
147 }
148 bzero((char *)&ifm, sizeof(ifm));
149 (void) strncpy(ifm.ifm_name, if_name, sizeof(ifm.ifm_name));
150
151 if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifm) == -1) {
152 /* if media status not available for this interface */
153 goto done;
154 }
155
156 if (ifm.ifm_count == 0) {
157 /* no media types */
158 goto done;
159 }
160
161 if (!(ifm.ifm_status & IFM_AVALID)) {
162 /* if active bit not valid */
163 goto done;
164 }
165
166 if (ifm.ifm_status & IFM_ACTIVE) {
167 active = kCFBooleanTrue;
168 } else {
169 active = kCFBooleanFalse;
170 }
171
172 done:
173 interface_update_status(if_name, active, attach);
174 if (sock != -1)
175 close(sock);
176 return;
177 }
178
179
180 __private_extern__
181 void
182 link_add(const char *if_name)
183 {
184 CFStringRef interface;
185 CFStringRef cacheKey;
186 CFDictionaryRef dict;
187 CFMutableDictionaryRef newDict = NULL;
188 CFArrayRef ifList;
189 CFMutableArrayRef newIFList = NULL;
190
191 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
192 cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
193 kSCDynamicStoreDomainState);
194
195 dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
196 if (dict) {
197 if (isA_CFDictionary(dict)) {
198 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
199 ifList = CFDictionaryGetValue(newDict, kSCPropNetInterfaces);
200 if (isA_CFArray(ifList)) {
201 newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
202 }
203 }
204 CFRelease(dict);
205 }
206
207 if (!newDict) {
208 newDict = CFDictionaryCreateMutable(NULL,
209 0,
210 &kCFTypeDictionaryKeyCallBacks,
211 &kCFTypeDictionaryValueCallBacks);
212 }
213
214 if (!newIFList) {
215 newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
216 }
217
218 if (CFArrayContainsValue(newIFList,
219 CFRangeMake(0, CFArrayGetCount(newIFList)),
220 interface) == FALSE) {
221 CFArrayAppendValue(newIFList, interface);
222 CFDictionarySetValue(newDict, kSCPropNetInterfaces, newIFList);
223 }
224 cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
225 link_update_status(if_name, TRUE);
226 CFRelease(cacheKey);
227 CFRelease(interface);
228 if (newDict) CFRelease(newDict);
229 if (newIFList) CFRelease(newIFList);
230
231 return;
232 }
233
234
235 __private_extern__
236 void
237 link_remove(const char *if_name)
238 {
239 CFStringRef interface;
240 CFStringRef cacheKey;
241 CFDictionaryRef dict;
242 CFMutableDictionaryRef newDict = NULL;
243 CFArrayRef ifList;
244 CFMutableArrayRef newIFList = NULL;
245 CFIndex i;
246
247 interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
248 cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
249 kSCDynamicStoreDomainState);
250
251 dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
252 if (dict) {
253 if (isA_CFDictionary(dict)) {
254 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
255 ifList = CFDictionaryGetValue(newDict, kSCPropNetInterfaces);
256 if (isA_CFArray(ifList)) {
257 newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
258 }
259 }
260 CFRelease(dict);
261 }
262
263 if (!newIFList ||
264 ((i = CFArrayGetFirstIndexOfValue(newIFList,
265 CFRangeMake(0, CFArrayGetCount(newIFList)),
266 interface)) == kCFNotFound)
267 ) {
268 /* we're not tracking this interface */
269 goto done;
270 }
271
272 CFArrayRemoveValueAtIndex(newIFList, i);
273 CFDictionarySetValue(newDict, kSCPropNetInterfaces, newIFList);
274 cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
275
276 interface_remove(if_name);
277
278 done:
279
280 CFRelease(cacheKey);
281 CFRelease(interface);
282 if (newDict) CFRelease(newDict);
283 if (newIFList) CFRelease(newIFList);
284
285 return;
286 }