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__ \
153static inline CV uint8_t* __indexable \
154CNV_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) \
160static inline CV TAG TYPE * __single \
161__attribute__((overloadable)) \
162CNV_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__ \
174static inline CV DTAG DTYPE * __single \
175__attribute__((overloadable)) \
176CNV_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__ \
187static inline DTAG DTYPE * __single \
188__attribute__((overloadable)) \
189CNV_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__ \
243static 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__ \
251static 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__ \
259static 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__
298static 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__
307static 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__
315static 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__
323static 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__
332static 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__
340static 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