1 | /* |
2 | * Copyright (c) 2023 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_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. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | #ifndef _NET_STRICT_TYPE_CNV_PRIVATE_H_ |
29 | #define _NET_STRICT_TYPE_CNV_PRIVATE_H_ |
30 | |
31 | #ifdef XNU_KERNEL_PRIVATE |
32 | |
33 | #include <sys/mcache.h> |
34 | #include <sys/socket.h> |
35 | #include <os/log.h> |
36 | |
37 | /* |
38 | * Only include this header file from <net/sockaddr_utils.h> |
39 | */ |
40 | #ifndef __NET_SOCKADDR_UTILS_H_INCLUDED |
41 | #error "do not include <net/strict_type_cnv_private.h> directly, use <net/sockaddr_utils.h> instead." |
42 | #endif |
43 | |
44 | |
45 | |
46 | /* |
47 | * Debug mode. If defined, disables certain optimizations, |
48 | * and introduces a "conversion failed" upcall, |
49 | * which can be set for testing. |
50 | */ |
51 | //#define __STC_DEBUG |
52 | |
53 | /* |
54 | * Attributes for the conversion functions. |
55 | */ |
56 | #if defined(__STC_DEBUG) |
57 | #define __STC_CONV_ATTRS__ __attribute__((__noinline__)) |
58 | #else /* !defined(__STC_DEBUG) */ |
59 | #define __STC_CONV_ATTRS__ __attribute__((always_inline)) __pure2 |
60 | #endif /* defined(__STC_DEBUG)*/ |
61 | |
62 | #define __WCAST_ALIGN "clang diagnostic ignored \"-Wcast-align\"" |
63 | #define __WITH_SUPPRESSION(SUPPRESSION, ...) ({ \ |
64 | _Pragma("clang diagnostic push"); \ |
65 | _Pragma(SUPPRESSION); \ |
66 | __VA_ARGS__ \ |
67 | _Pragma("clang diagnostic pop"); \ |
68 | }) |
69 | /* |
70 | * Converts `const struct STYPE * VAL' to `struct DTYPE *'. |
71 | */ |
72 | #define __STC_DECONST_AND_CONVERT(STAG, STYPE, DTAG, DTYPE, VAL) ({ \ |
73 | STAG STYPE *__single __sau_deconst_val; \ |
74 | __sau_deconst_val = __DECONST(STAG STYPE * __single, (VAL)); \ |
75 | __WITH_SUPPRESSION(__WCAST_ALIGN, (DTAG DTYPE * __single)(__sau_deconst_val)); \ |
76 | }) |
77 | |
78 | /* |
79 | * Converts `struct STYPE * VAL' to `struct DTYPE *'. |
80 | */ |
81 | #define __STC_CONV_TO(STAG, STYPE, DTAG, DTYPE, VAL) ({ \ |
82 | __WITH_SUPPRESSION(__WCAST_ALIGN, (DTAG DTYPE * __single)((VAL))); \ |
83 | }) |
84 | |
85 | /* |
86 | * Converts `const struct STYPE * VAL' to `const struct DTYPE *'. |
87 | */ |
88 | #define __STC_CONV_CONST_TO_CONST(STYPE, DTYPE, VAL) ({ \ |
89 | __WITH_SUPPRESSION(__WCAST_ALIGN, (const struct DTYPE * __single)((VAL))); \ |
90 | }) |
91 | |
92 | /* |
93 | * Converts `[const] struct STYPE * VAL' to |
94 | * `uint8_t* __bidi_indexable', bounded by MAX_LEN |
95 | */ |
96 | #define __STC_CONV_TO_BYTES_LEN(VAL, MAX_LEN) ({ \ |
97 | __WITH_SUPPRESSION(__WCAST_ALIGN, __unsafe_forge_bidi_indexable(uint8_t*, (VAL), (MAX_LEN))); \ |
98 | }) |
99 | |
100 | |
101 | /* |
102 | * Converts `uint8_t* __bidi_indexable' to `[const] struct DTYPE'. |
103 | * Returns NULL if the conversion is not possible. |
104 | */ |
105 | #define __STC_CONV_FROM_BYTES_LEN(DTAG, DTYPE, VAL, LEN) ({ \ |
106 | __WITH_SUPPRESSION(__WCAST_ALIGN, __unsafe_forge_single(DTAG DTYPE *, (VAL))); \ |
107 | }) |
108 | |
109 | |
110 | /* |
111 | * Converter function names, used both to generate the inline stubs, |
112 | * and in the generic dispatch expressions. |
113 | */ |
114 | #define __STC_OBJ_TO_BY_CNV(T) __stc_convert_##T##_to_bytes |
115 | #define __STC_COBJ_TO_CBY_CNV(T) __stc_convert_const_##T##_to_const_bytes |
116 | #define __STC_BY_TO_OBJ_CNV(T) __stc_convert_bytes_to_##T |
117 | #define __STC_CBY_TO_COBJ_CNV(T) __stc_convert_const_bytes_to_const_##T |
118 | #define __STC_CBY_TO_CBY_CNV() __stc_convert_const_bytes_to_const_bytes |
119 | #define __STC_BY_TO_BY_CNV() __stc_convert_bytes_to_bytes |
120 | #define __STC_TY_TY_CNV_F(F, T) __stc_convert_##F##_to_##T |
121 | #define __STC_CTY_TY_CNV_F(F, T) __stc_convert_const_##F##_to_##T |
122 | #define __STC_CTY_CTY_CNV_F(F, T) __stc_convert_const_##F##_to_const_##T |
123 | #define __STC_TY_ID_CNV_F(F) __stc_convert_##F##_identity |
124 | #define __STC_CTY_ID_CNV_F(F) __stc_convert_const_##F##_identity |
125 | #define __STC_CTY_CID_CNV_F(F) __stc_convert_##F##_const_identity |
126 | |
127 | |
128 | /************************************************************************************************* |
129 | * Conversion building blocks, used below for converter definitions. |
130 | */ |
131 | |
132 | #if __has_ptrcheck |
133 | #define __STC_ENFORCE_MIN_LEN(BTYPE, MIN_LEN, PTR) do { \ |
134 | if ((PTR)) { \ |
135 | BTYPE * __ensure_minimal_len __sized_by(MIN_LEN) = (PTR); \ |
136 | (void)__ensure_minimal_len; \ |
137 | } \ |
138 | } while(0) |
139 | |
140 | #define __STC_CONVERT_INDEXABLE_PTR_TO(T, P) \ |
141 | __unsafe_forge_bidi_indexable(T, (P), __ptr_upper_bound((P)) - (P)); |
142 | |
143 | #else /* !__has_ptrcheck */ |
144 | #define __STC_ENFORCE_MIN_LEN(BTYPE, MIN_LEN, PTR) do {} while (0) |
145 | |
146 | #define __STC_CONVERT_INDEXABLE_PTR_TO(T, P) ((T)(P)) |
147 | |
148 | #endif /* !__has_ptrcheck */ |
149 | |
150 | |
151 | #define __STC_OBJ_TO_BYTES_CNV_IMPL(CV, TAG, TYPE, MAX_LEN, CNV_F) \ |
152 | __STC_CONV_ATTRS__ \ |
153 | static inline CV uint8_t* __indexable \ |
154 | CNV_F(const TAG TYPE *ptr __single) \ |
155 | { \ |
156 | return __STC_CONV_TO_BYTES_LEN(__DECONST(TAG TYPE *__single, ptr), (MAX_LEN)); \ |
157 | } |
158 | |
159 | #define __STC_BYTES_TO_OBJ_CNV_IMPL(CV, TAG, TYPE, BTYPE, MIN_LEN, CNV_F) \ |
160 | static inline CV TAG TYPE * __single \ |
161 | __attribute__((overloadable)) \ |
162 | CNV_F(CV BTYPE * data __header_indexable) \ |
163 | { \ |
164 | __STC_ENFORCE_MIN_LEN(CV BTYPE, MIN_LEN, data); \ |
165 | return __STC_CONV_FROM_BYTES_LEN(CV TAG, TYPE, data, (MIN_LEN)); \ |
166 | } |
167 | |
168 | |
169 | /* |
170 | * Converts `[CV] STAG STYPE *__single' to `[CV] DTAG DTYPE *__single', using CNV_F. |
171 | */ |
172 | #define __STC_OBJ_TO_OBJ_CNV_IMPL(CV, STAG, STYPE, DTAG, DTYPE, CNV_F) \ |
173 | __STC_CONV_ATTRS__ \ |
174 | static inline CV DTAG DTYPE * __single \ |
175 | __attribute__((overloadable)) \ |
176 | CNV_F(CV STAG STYPE *ptr __single) \ |
177 | { \ |
178 | return __STC_CONV_TO(CV STAG, STYPE, CV DTAG, DTYPE, ptr); \ |
179 | } |
180 | |
181 | |
182 | /* |
183 | * Converts `const STAG STYPE *__single' to `DTAG DTYPE *__single', using CNV_F. |
184 | */ |
185 | #define __STC_COBJ_TO_OBJ_CNV_IMPL(STAG, STYPE, DTAG, DTYPE, CNV_F) \ |
186 | __STC_CONV_ATTRS__ \ |
187 | static inline DTAG DTYPE * __single \ |
188 | __attribute__((overloadable)) \ |
189 | CNV_F(const STAG STYPE *ptr __single) \ |
190 | { \ |
191 | return __STC_DECONST_AND_CONVERT(STAG, STYPE, DTAG, DTYPE, ptr); \ |
192 | } |
193 | |
194 | |
195 | /************************************************************************************************* |
196 | * Statically typed converters. |
197 | */ |
198 | |
199 | /* |
200 | * Conversions between different variants of pointers to sockaddr objects |
201 | * that have the different types. |
202 | * |
203 | * Given tuple (STAG, STYPE, DTAG, DTYPE), defines the converters: |
204 | * 0. "Forward": STAG STYPE *__single -> DTAG DTYPE *__single |
205 | * 1. "Reverse": DTAG DTYPE *__single -> STAG STYPE *__single |
206 | * 2. "Forward const": const STAG STYPE *__single -> const DTAG DTYPE *__single |
207 | * 3. "Reverse const": const DTAG DTYPE *__single -> const STAG STYPE *__single |
208 | * 4. "Forward deconst": const STAG STYPE *__single -> DTAG DTYPE *__single |
209 | * 5. "Reverse deconst": const DTAG DTYPE *__single -> STAG STYPE *__single |
210 | */ |
211 | #define __STC_DEFINE_OBJECT_CONVERTERS(STAG, STYPE, DTAG, DTYPE) \ |
212 | /* [0] ("Forward") */ \ |
213 | __STC_OBJ_TO_OBJ_CNV_IMPL(, STAG, STYPE, DTAG, DTYPE, __STC_TY_TY_CNV_F(STYPE, DTYPE)) \ |
214 | \ |
215 | /* [1] ("Reverse") */ \ |
216 | __STC_OBJ_TO_OBJ_CNV_IMPL(, DTAG, DTYPE, STAG, STYPE, __STC_TY_TY_CNV_F(DTYPE, STYPE)) \ |
217 | \ |
218 | /* [2] ("Forward const") */ \ |
219 | __STC_OBJ_TO_OBJ_CNV_IMPL(const, STAG, STYPE, DTAG, DTYPE, __STC_CTY_CTY_CNV_F(STYPE, DTYPE)) \ |
220 | \ |
221 | /* [3] ("Reverse const") */ \ |
222 | __STC_OBJ_TO_OBJ_CNV_IMPL(const, DTAG, DTYPE, STAG, STYPE, __STC_CTY_CTY_CNV_F(DTYPE, STYPE)) \ |
223 | \ |
224 | /* [4] ("Forward deconst") */ \ |
225 | __STC_COBJ_TO_OBJ_CNV_IMPL(STAG, STYPE, DTAG, DTYPE, __STC_CTY_TY_CNV_F(STYPE, DTYPE)) \ |
226 | \ |
227 | /* [5] ("Reverse deconst") */ \ |
228 | __STC_COBJ_TO_OBJ_CNV_IMPL(DTAG, DTYPE, STAG, STYPE, __STC_CTY_TY_CNV_F(DTYPE, STYPE)) |
229 | |
230 | |
231 | /* |
232 | * Conversions between different variants of pointers to sockaddr objects |
233 | * that have the same type. |
234 | * |
235 | * Given tuple (TAG, TYPE), defines the edge case converters: |
236 | * 0. "Identity": TAG TYPE *__single -> TAG TYPE *__single |
237 | * 1. "Const identity": const TAG TYPE *__single -> const TAG TYPE *__single |
238 | * 2. "Deconst identity": const TAG TYPE *__single -> TAG DTYPE *__single |
239 | */ |
240 | #define __STC_DEFINE_SELF_CONVERTERS(DTAG, DTYPE) \ |
241 | /* [0] ("Identity") */ \ |
242 | __STC_CONV_ATTRS__ \ |
243 | static inline DTAG DTYPE *__single \ |
244 | __STC_TY_ID_CNV_F(DTYPE)(DTAG DTYPE *sin __single) \ |
245 | { \ |
246 | return sin; \ |
247 | } \ |
248 | \ |
249 | /* [1] ("Const identity") */ \ |
250 | __STC_CONV_ATTRS__ \ |
251 | static inline const DTAG DTYPE *__single \ |
252 | __STC_CTY_CID_CNV_F(DTYPE)(const DTAG DTYPE *sin __single) \ |
253 | { \ |
254 | return sin; \ |
255 | } \ |
256 | \ |
257 | /* [2] ("Deconst identity") */ \ |
258 | __STC_CONV_ATTRS__ \ |
259 | static inline DTAG DTYPE *__single \ |
260 | __STC_CTY_ID_CNV_F(DTYPE)(const DTAG DTYPE *sin __single) \ |
261 | { \ |
262 | return __DECONST(DTAG DTYPE *__single, sin); \ |
263 | } |
264 | |
265 | |
266 | /* |
267 | * Conversions between byte arrays and pointers to sockaddr objects |
268 | * |
269 | * Given tuple (TAG, TYPE, MIN_LEN, MAX_LEN), defines |
270 | * the edge case converters: |
271 | * 0. "Type to bytes": TAG TYPE * __single -> uint8_t *__sized_by(MAX_LEN) |
272 | * 1. "Const type to const bytes": const TAG TYPE * __single -> const uint8_t *__sized_by(MAX_LEN) |
273 | * 2. "Bytes to type": uint8_t *__sized_by(MIN_LEN) -> TAG TYPE * __single |
274 | * 3. "Const bytes to const type": const uint8_t *__sized_by(MIN_LEN) -> const TAG TYPE * __single |
275 | * |
276 | * NOTE: Type-to-bytes converters use MAX_LEN; |
277 | * bytes-to-type converters use MIN_LEN |
278 | */ |
279 | #define __STC_DEFINE_BYTE_TO_OBJ_CNVS(TAG, TYPE, MIN_LEN, MAX_LEN) \ |
280 | /* [0] ("Type to bytes") */ \ |
281 | __STC_OBJ_TO_BYTES_CNV_IMPL(, TAG, TYPE, MAX_LEN, __STC_OBJ_TO_BY_CNV(TYPE)) \ |
282 | \ |
283 | /* [1] ("Const type to const bytes") */ \ |
284 | __STC_OBJ_TO_BYTES_CNV_IMPL(, TAG, TYPE, MAX_LEN, __STC_COBJ_TO_CBY_CNV(TYPE)) \ |
285 | \ |
286 | /* [2] ("Bytes to type") */ \ |
287 | __STC_BYTES_TO_OBJ_CNV_IMPL(, TAG, TYPE, void, MIN_LEN, __STC_BY_TO_OBJ_CNV(TYPE)) \ |
288 | \ |
289 | /* [3] ("Const bytes to const type") */ \ |
290 | __STC_BYTES_TO_OBJ_CNV_IMPL(const, TAG, TYPE, void, MIN_LEN, __STC_CBY_TO_COBJ_CNV(TYPE)) |
291 | |
292 | |
293 | /* |
294 | * Edge condition between different variants of byte pointers to uint8_t. |
295 | * These are used by the SOCKADDR_{COPY,ZERO,CMP} operations. |
296 | */ |
297 | __STC_CONV_ATTRS__ |
298 | static inline const uint8_t * __header_indexable |
299 | __attribute__((overloadable)) |
300 | __STC_CBY_TO_CBY_CNV()(const void * data __header_indexable) |
301 | { |
302 | const uint8_t * __header_indexable cdata = data; |
303 | return __STC_CONVERT_INDEXABLE_PTR_TO(const uint8_t*, cdata); |
304 | } |
305 | |
306 | __STC_CONV_ATTRS__ |
307 | static inline const uint8_t * __header_indexable |
308 | __attribute__((overloadable)) |
309 | __STC_CBY_TO_CBY_CNV()(const char * data __header_indexable) |
310 | { |
311 | return __STC_CONVERT_INDEXABLE_PTR_TO(const uint8_t*, data); |
312 | } |
313 | |
314 | __STC_CONV_ATTRS__ |
315 | static inline const uint8_t * __header_indexable |
316 | __attribute__((overloadable)) |
317 | __STC_CBY_TO_CBY_CNV()(const uint8_t * data __header_indexable) |
318 | { |
319 | return data; |
320 | } |
321 | |
322 | __STC_CONV_ATTRS__ |
323 | static inline uint8_t * __header_indexable |
324 | __attribute__((overloadable)) |
325 | __STC_BY_TO_BY_CNV()(void * data __header_indexable) |
326 | { |
327 | uint8_t * __header_indexable cdata = data; |
328 | return __STC_CONVERT_INDEXABLE_PTR_TO(uint8_t*, cdata); |
329 | } |
330 | |
331 | __STC_CONV_ATTRS__ |
332 | static inline uint8_t * __header_indexable |
333 | __attribute__((overloadable)) |
334 | __STC_BY_TO_BY_CNV()(uint8_t * data __header_indexable) |
335 | { |
336 | return data; |
337 | } |
338 | |
339 | __STC_CONV_ATTRS__ |
340 | static inline uint8_t * __header_indexable |
341 | __attribute__((overloadable)) |
342 | __STC_BY_TO_BY_CNV()(char * data __header_indexable) |
343 | { |
344 | return __STC_CONVERT_INDEXABLE_PTR_TO(uint8_t*, data); |
345 | } |
346 | |
347 | |
348 | |
349 | /************************************************************************************************* |
350 | * Dispatch block definitions. |
351 | * |
352 | * The dispatch blocks below are meant to be composed into a single generic selection expression. |
353 | * See the definition of `__SA_UTILS_CONV_TO_SOCKADDR` for an example. |
354 | * |
355 | * Each dispatch block defines several type expressions and the corresponding conversion macros. |
356 | * |
357 | * Wnen compiled with `-fbounds-safety', the dispatch block accepst sized and single pointers. |
358 | * When compiled without `-fbounds-safety', each dispatch block accepts only a pointer to the type. |
359 | */ |
360 | |
361 | |
362 | /* |
363 | * Basic building block for associating a CNV_F function with a pointer to CV TAG TYPE. |
364 | * Depending on whehter `-fbounds-safety' is enabled, the match block is extended to sized pointers. |
365 | */ |
366 | #if __has_ptrcheck |
367 | #define __STC_GENERIC_CV_CNV_CLAUSE(CV, TAG, TYPE, CNV_F) \ |
368 | CV TAG TYPE * __single: CNV_F, \ |
369 | CV TAG TYPE * __bidi_indexable: CNV_F, \ |
370 | CV TAG TYPE * __indexable: CNV_F |
371 | #else /* !__has_ptrcheck */ |
372 | #define __STC_GENERIC_CV_CNV_CLAUSE(CV, TAG, TYPE, CNV_F) \ |
373 | CV TAG TYPE * : CNV_F |
374 | #endif /* !__has_ptrcheck */ |
375 | |
376 | |
377 | /** |
378 | * __STC_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE) |
379 | * |
380 | * Matches its argument against `STYPE' (`STAG' indicates struct or union), and upon a type match, |
381 | * converts the argument to `DTYPE'. |
382 | * |
383 | * If the argument type is `const STAG STYPE *', the argument will be converted |
384 | * to `const struct DTYPE * __single'. |
385 | * |
386 | * Otherwise, the argument will be converted to `struct DTYPE * __single' |
387 | */ |
388 | #define __STC_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE) \ |
389 | __STC_GENERIC_CV_CNV_CLAUSE(, STAG, STYPE, __STC_TY_TY_CNV_F(STYPE, DTYPE)), \ |
390 | __STC_GENERIC_CV_CNV_CLAUSE(const, STAG, STYPE, __STC_CTY_CTY_CNV_F(STYPE, DTYPE)) |
391 | |
392 | |
393 | /** |
394 | * __STC_BYTES_TO_OBJ_CNV_CLAUSE(TYPE) |
395 | * |
396 | * Matches a BYte array, and attempts to convert to `TYPE' |
397 | * |
398 | * Notes on `__indexable' vs. `__bidi_indexable': |
399 | * |
400 | * When bounds-checks are enabled, the match block treats the `__indexable' and the `__bidi_indexable' |
401 | * pointers the same way (but still has to distinguish between the pointer sizes). |
402 | * |
403 | * The conversion preserves the `const' qualifier. |
404 | */ |
405 | #define __STC_BYTES_TO_OBJ_CNV_CLAUSE(TYPE) \ |
406 | __STC_GENERIC_CV_CNV_CLAUSE( , , char, __STC_BY_TO_OBJ_CNV(TYPE)), \ |
407 | __STC_GENERIC_CV_CNV_CLAUSE( , , uint8_t, __STC_BY_TO_OBJ_CNV(TYPE)), \ |
408 | __STC_GENERIC_CV_CNV_CLAUSE( , , void, __STC_BY_TO_OBJ_CNV(TYPE)), \ |
409 | __STC_GENERIC_CV_CNV_CLAUSE(const, , char, __STC_CBY_TO_COBJ_CNV(TYPE)), \ |
410 | __STC_GENERIC_CV_CNV_CLAUSE(const, , uint8_t, __STC_CBY_TO_COBJ_CNV(TYPE)), \ |
411 | __STC_GENERIC_CV_CNV_CLAUSE(const, , void, __STC_CBY_TO_COBJ_CNV(TYPE)) |
412 | |
413 | /** |
414 | * __STC_OBJ_TO_BYTES_CNV_CLAUSE(TAG, TYPE) |
415 | * |
416 | * Matches a `TAG TYPE *' variable, and converts it to a BYte array. |
417 | * |
418 | * The conversion preserves the `const' qualifier. |
419 | */ |
420 | #define __STC_OBJ_TO_BYTES_CNV_CLAUSE(TAG, TYPE) \ |
421 | __STC_GENERIC_CV_CNV_CLAUSE( , TAG, TYPE, __STC_OBJ_TO_BY_CNV(TYPE)), \ |
422 | __STC_GENERIC_CV_CNV_CLAUSE(const, TAG, TYPE, __STC_COBJ_TO_CBY_CNV(TYPE)) |
423 | |
424 | /** |
425 | * __STC_BYTES_TO_BYTES_CNV_CLAUSE() |
426 | * |
427 | * Matches a BYte array and returns a BYte array. |
428 | * |
429 | * The conversion preserves the `const' qualifier. |
430 | */ |
431 | #define __STC_BYTES_TO_BYTES_CNV_CLAUSE() \ |
432 | __STC_GENERIC_CV_CNV_CLAUSE( , , char, __STC_BY_TO_BY_CNV()), \ |
433 | __STC_GENERIC_CV_CNV_CLAUSE( , , uint8_t, __STC_BY_TO_BY_CNV()), \ |
434 | __STC_GENERIC_CV_CNV_CLAUSE( , , void, __STC_BY_TO_BY_CNV()), \ |
435 | __STC_GENERIC_CV_CNV_CLAUSE(const, , char, __STC_CBY_TO_CBY_CNV()), \ |
436 | __STC_GENERIC_CV_CNV_CLAUSE(const, , uint8_t, __STC_CBY_TO_CBY_CNV()), \ |
437 | __STC_GENERIC_CV_CNV_CLAUSE(const, , void, __STC_CBY_TO_CBY_CNV()) |
438 | |
439 | |
440 | /** |
441 | * __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE) |
442 | * |
443 | * Matches a `const STAG STYPE *' and converts it to `STAG STYPE * __single' |
444 | * |
445 | * The conversion REMOVES the `const' qualifier, if present. |
446 | * To preserve the `const' qualifier, use the `__STC_TYPE_TO_OBJ_CNV_CLAUSE' instead. |
447 | */ |
448 | #define __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE) \ |
449 | __STC_GENERIC_CV_CNV_CLAUSE(const, STAG, STYPE, __STC_CTY_TY_CNV_F(STYPE, DTYPE)) |
450 | |
451 | /** |
452 | * __STC_MATCH_MATCH_CID(TAG, TYPE) |
453 | * |
454 | * Matches a `const TAG TYPE *' and converts it to `TAG TYPE * __single' |
455 | * |
456 | * The conversion REMOVES the `const' qualifier, if present. |
457 | * To preserve the `const' qualifier, use the `__STC_IDENTITY_CNV_CLAUSE' instead. |
458 | */ |
459 | #define __STC_CONST_IDENTITY_CNV_CLAUSE(TAG, TYPE) \ |
460 | __STC_GENERIC_CV_CNV_CLAUSE(const, TAG, TYPE, __STC_CTY_ID_CNV_F(TYPE)) |
461 | |
462 | |
463 | /** |
464 | * __STC_IDENTITY_CNV_CLAUSE(TAG, TYPE) |
465 | * |
466 | * Matches a `[const] TAG TYPE *' and converts it to `[const] TAG TYPE * __single' |
467 | * |
468 | * The conversion preserves the `const' qualifier. |
469 | */ |
470 | #define __STC_IDENTITY_CNV_CLAUSE(TAG, TYPE) \ |
471 | __STC_GENERIC_CV_CNV_CLAUSE(const, TAG, TYPE, __STC_CTY_ID_CNV_F(TYPE)), \ |
472 | __STC_GENERIC_CV_CNV_CLAUSE(, TAG, TYPE, __STC_TY_ID_CNV_F(TYPE)) |
473 | |
474 | |
475 | |
476 | /************************************************************************************************* |
477 | * Generators for cast operations. |
478 | */ |
479 | |
480 | |
481 | #define __STC_ENABLE_STATIC_CAST(SRC_TAG, SRC_TYPENAME, DST_TYPENAME) \ |
482 | __STC_TYPE_TO_OBJ_CNV_CLAUSE(SRC_TAG, SRC_TYPENAME, DST_TYPENAME) |
483 | |
484 | |
485 | #define __STC_ENABLE_DECONST_CAST(SRC_TAG, SRC_TYPENAME, DST_TYPENAME) \ |
486 | __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(SRC_TAG, SRC_TYPENAME, DST_TYPENAME) |
487 | |
488 | |
489 | /************************************************************************************************* |
490 | * Porcelain macros to define sockaddr subtypes. |
491 | */ |
492 | |
493 | /* |
494 | * Building blocks for variadic macro overrides. |
495 | */ |
496 | #define __STC_COUNT_ARGS1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N |
497 | #define __STC_COUNT_ARGS(...) \ |
498 | __STC_COUNT_ARGS1(, ##__VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0) |
499 | #define __STC_DISPATCH1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__) |
500 | #define __STC_DISPATCH(base, ...) \ |
501 | __STC_DISPATCH1(base, __STC_COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__) |
502 | |
503 | #define __STC_DEFINE_STATIC_CAST(SRC_TAG, SRC_TYPENAME, DST_TAG, DST_TYPENAME) \ |
504 | __STC_DEFINE_OBJECT_CONVERTERS(SRC_TAG, SRC_TYPENAME, DST_TAG, DST_TYPENAME) |
505 | |
506 | /* |
507 | * Building blocks for sockaddr subtype definitions. |
508 | */ |
509 | #define __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, MIN_LEN, MAX_LEN) \ |
510 | __STC_DEFINE_SELF_CONVERTERS(TAG, TYPENAME); /* [0] */ \ |
511 | __STC_DEFINE_STATIC_CAST(TAG, TYPENAME, struct, sockaddr) \ |
512 | __STC_DEFINE_STATIC_CAST(TAG, TYPENAME, struct, sockaddr_storage) \ |
513 | __STC_DEFINE_BYTE_TO_OBJ_CNVS(TAG, TYPENAME, MIN_LEN, MAX_LEN) |
514 | |
515 | #define __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, MIN_LEN, MAX_LEN, TAG1, TYPENAME1) \ |
516 | __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, MIN_LEN, MAX_LEN) \ |
517 | __STC_DEFINE_STATIC_CAST(TAG, TYPENAME, TAG1, TYPENAME1) |
518 | |
519 | #define __STC_DEFINE_SUBTYPE_IMPL_8(TAG, TYPENAME, MIN_LEN, MAX_LEN, \ |
520 | TAG1, TYPENAME1, TAG2, TYPENAME2) \ |
521 | __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, MIN_LEN, MAX_LEN, TAG1, TYPENAME1) \ |
522 | __STC_DEFINE_STATIC_CAST(TAG, TYPENAME, TAG2, TYPENAME2) |
523 | |
524 | |
525 | /************************************************************************************************* |
526 | * Porcelain macros to define a socakddr subtype with variable size, |
527 | * e.g. `struct sockaddr_dl' or `struct sockaddr_un'. |
528 | */ |
529 | #define __STC_DEFINE_VARIABLE_SIZE_SUBTYPE_2(TAG, TYPENAME) \ |
530 | __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, sizeof(TAG TYPENAME), 255) |
531 | |
532 | #define __STC_DEFINE_VARIABLE_SIZE_SUBTYPE_4(TAG, TYPENAME, TAG1, TYPENAME1) \ |
533 | __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, sizeof(TAG TYPENAME), 255, TAG1, TYPENAME1) |
534 | |
535 | #define __STC_DEFINE_VARIABLE_SIZE_SUBTYPE_6(TAG, TYPENAME, TAG1, TYPENAME1, TAG2, TYPENAME2) \ |
536 | __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, sizeof(TAG TYPENAME), 255, \ |
537 | TAG1, TYPENAME1, TAG2, TYPENAME2) |
538 | |
539 | #define __SA_UTILS_DEFINE_VARIABLE_SIZE_SUBTYPE(...) \ |
540 | __STC_DISPATCH(__STC_DEFINE_VARIABLE_SIZE_SUBTYPE, ##__VA_ARGS__) |
541 | |
542 | |
543 | /************************************************************************************************* |
544 | * Porcelain macros to define a socakddr subtype with fixed size, |
545 | * e.g. `struct sockaddr_in' or `struct sockaddr_in6'. |
546 | */ |
547 | #define __STC_DEFINE_FIXED_SIZE_SUBTYPE_2(TAG, TYPENAME) \ |
548 | __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, sizeof(TAG TYPENAME), sizeof(TAG TYPENAME)) |
549 | |
550 | #define __STC_DEFINE_FIXED_SIZE_SUBTYPE_4(TAG, TYPENAME, TAG1, TYPENAME1) \ |
551 | __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, sizeof(TAG TYPENAME), sizeof(TAG TYPENAME), \ |
552 | TAG1, TYPENAME1) |
553 | |
554 | #define __STC_DEFINE_FIXED_SIZE_SUBTYPE_6(TAG, TYPENAME, TAG1, TYPENAME1, TAG2, TYPENAME2) \ |
555 | __STC_DEFINE_SUBTYPE_IMPL_8(TAG, TYPENAME, sizeof(TAG TYPENAME), sizeof(TAG TYPENAME), \ |
556 | TAG1, TYPENAME1, TAG2, TYPENAME2) |
557 | |
558 | #define __SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(...) \ |
559 | __STC_DISPATCH(__STC_DEFINE_FIXED_SIZE_SUBTYPE, ##__VA_ARGS__) |
560 | |
561 | |
562 | #endif /* XNU_KERNEL_PRIVATE */ |
563 | |
564 | #endif /* _NET_STRICT_TYPE_CNV_PRIVATE_H_ */ |
565 | |