xref: /xnu-10063.121.3/bsd/net/strict_type_cnv_private.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
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))
__STC_CBY_TO_CBY_CNV()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))
__STC_CBY_TO_CBY_CNV()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))
__STC_CBY_TO_CBY_CNV()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))
__STC_BY_TO_BY_CNV()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))
__STC_BY_TO_BY_CNV()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))
__STC_BY_TO_BY_CNV()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