]> git.saurik.com Git - apple/configd.git/blob - Plugins/IPMonitor/serviceIDNumber.c
configd-1061.40.2.tar.gz
[apple/configd.git] / Plugins / IPMonitor / serviceIDNumber.c
1 /*
2 * Copyright (c) 2019 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 * serviceID_number.c
26 * - assigns numbers to serviceID strings
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32
33 #include "serviceIDNumber.h"
34 #include <CoreFoundation/CFDictionary.h>
35
36 #if TEST_SERVICEID_NUMBER
37 #include <SystemConfiguration/SCPrivate.h>
38 #endif /* TEST_SERVICEID_NUMBER */
39
40
41 /* dictionary to hold serviceIDNumber: key is the serviceID */
42 static CFMutableDictionaryRef S_serviceID_to_number_dict;
43
44 /* dictionary to hold serviceID: key is the serviceIDNumber */
45 static CFMutableDictionaryRef S_number_to_serviceID_dict;
46
47 static Boolean
48 serviceIDNumberEqual(const void * ptr1, const void * ptr2)
49 {
50 return (((serviceIDNumber)ptr1) == ((serviceIDNumber)ptr2));
51 }
52
53 static CFStringRef
54 serviceIDNumberCopyDescription(const void * ptr)
55 {
56 return CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"),
57 (serviceIDNumber)ptr);
58 }
59
60 static CFHashCode
61 serviceIDNumberHash(const void * ptr) {
62 return (CFHashCode)((serviceIDNumber)ptr);
63 }
64
65 static const CFDictionaryValueCallBacks kserviceIDNumberValueCallBacks = {
66 0, NULL, NULL, serviceIDNumberCopyDescription, serviceIDNumberEqual
67 };
68
69 static const CFDictionaryKeyCallBacks kserviceIDNumberKeyCallBacks = {
70 0, NULL, NULL, serviceIDNumberCopyDescription, serviceIDNumberEqual,
71 serviceIDNumberHash
72 };
73
74 /**
75 ** S_serviceID_numbers
76 **/
77
78 __private_extern__ Boolean
79 serviceIDNumberGetIfPresent(CFStringRef serviceID, serviceIDNumber *sidn)
80 {
81 Boolean has_number;
82 const void * val;
83
84 has_number = CFDictionaryGetValueIfPresent(S_serviceID_to_number_dict,
85 serviceID, &val);
86 if (has_number) {
87 *sidn = (serviceIDNumber)val;
88 }
89 return (has_number);
90 }
91
92 /*
93 * Function: serviceIDNumberGet
94 * Purpose:
95 * Return the currently assigned serviceIDNumber for the given serviceID.
96 * If one is already assigned, return that. If one isn't assigned, check
97 * the next integer value after 'current_sidn', but skip zero.
98 * If that number is assigned, pick the next one.
99 */
100 static serviceIDNumber S_current_sidn;
101
102 __private_extern__ serviceIDNumber
103 serviceIDNumberGet(CFStringRef serviceID)
104 {
105 serviceIDNumber sidn;
106
107 if (serviceIDNumberGetIfPresent(serviceID, &sidn)) {
108 return (sidn);
109 }
110 while (1) {
111 /* assign a number to the serviceID */
112 S_current_sidn++;
113 if (S_current_sidn == kserviceIDNumberZero) {
114 /* skip zero */
115 S_current_sidn++;
116 }
117 /* if it's in use, skip to the next value */
118 if (CFDictionaryContainsKey(S_number_to_serviceID_dict,
119 (const void *)S_current_sidn)) {
120 continue;
121 }
122 /* it's not in use, use it */
123 sidn = S_current_sidn;
124 CFDictionarySetValue(S_serviceID_to_number_dict,
125 serviceID, (const void *)sidn);
126 CFDictionarySetValue(S_number_to_serviceID_dict,
127 (const void *)sidn, serviceID);
128 break;
129 }
130 return (sidn);
131 }
132
133
134 __private_extern__ void
135 serviceIDNumberRemove(CFStringRef serviceID)
136 {
137 const void * val;
138
139 if (CFDictionaryGetValueIfPresent(S_serviceID_to_number_dict, serviceID,
140 &val)) {
141 #if TEST_SERVICEID_NUMBER
142 SCPrint(TRUE, stdout, CFSTR("Removing %@ %ld\n"),
143 serviceID, (serviceIDNumber)val);
144 #endif
145 CFDictionaryRemoveValue(S_serviceID_to_number_dict, serviceID);
146 CFDictionaryRemoveValue(S_number_to_serviceID_dict, val);
147 }
148 }
149
150 __private_extern__ void
151 serviceIDNumberInit(void)
152 {
153 S_serviceID_to_number_dict
154 = CFDictionaryCreateMutable(NULL, 0,
155 &kCFTypeDictionaryKeyCallBacks,
156 &kserviceIDNumberValueCallBacks);
157 S_number_to_serviceID_dict
158 = CFDictionaryCreateMutable(NULL, 0,
159 &kserviceIDNumberKeyCallBacks,
160 &kCFTypeDictionaryValueCallBacks);
161 }
162
163 #if TEST_SERVICEID_NUMBER
164
165 static CFStringRef
166 my_CFUUIDStringCreate(CFAllocatorRef alloc)
167 {
168 CFUUIDRef uuid;
169 CFStringRef uuid_str;
170
171 uuid = CFUUIDCreate(alloc);
172 uuid_str = CFUUIDCreateString(alloc, uuid);
173 CFRelease(uuid);
174 return (uuid_str);
175 }
176
177 int
178 main()
179 {
180 #define N_LIST 10
181 CFStringRef serviceID_list[N_LIST];
182
183 serviceIDNumberInit();
184 for (int i = 0; i < N_LIST; i++) {
185 CFStringRef serviceID = my_CFUUIDStringCreate(NULL);
186 serviceIDNumber sidn;
187
188 /* force a collision */
189 S_current_sidn = -1;
190
191 sidn = serviceIDNumberGet(serviceID);
192 SCPrint(TRUE, stdout, CFSTR("%d: %@ %ld\n"),
193 i, serviceID, sidn);
194 serviceID_list[i] = serviceID;
195
196 }
197 for (int i = 0; i < N_LIST; i++) {
198 CFStringRef serviceID = serviceID_list[i];
199 serviceIDNumber sidn;
200
201 if (!serviceIDNumberGetIfPresent(serviceID, &sidn)) {
202 SCPrint(TRUE, stderr, CFSTR("Failed to find %@\n"),
203 serviceID);
204 exit(1);
205 }
206 SCPrint(TRUE, stdout, CFSTR("%@ => %ld\n"), serviceID, sidn);
207 }
208 {
209 serviceIDNumber sidn;
210
211 if (serviceIDNumberGetIfPresent(CFSTR("blah"), &sidn)) {
212 fprintf(stderr,
213 "Shouldn't have been able to look that up\n");
214 exit(1);
215 }
216 }
217
218 for (int i = 0; i < N_LIST / 2; i++) {
219 CFStringRef serviceID = serviceID_list[i];
220 serviceIDNumber sidn;
221
222 serviceIDNumberRemove(serviceID);
223 if (serviceIDNumberGetIfPresent(serviceID, &sidn)) {
224 SCPrint(TRUE, stderr,
225 CFSTR("Found %@, but shouldn't have\n"),
226 serviceID);
227 exit(1);
228 }
229 }
230
231 for (int i = 0; i < N_LIST; i++) {
232 CFStringRef serviceID = serviceID_list[i];
233 serviceIDNumber sidn;
234
235 sidn = serviceIDNumberGet(serviceID);
236 SCPrint(TRUE, stdout, CFSTR("%d: %@ %ld\n"),
237 i, serviceID, sidn);
238 }
239 exit(0);
240 }
241 #endif /* TEST_SERVICEID_NUMBER */