This is xnu-11215.1.10. See this file in:
/*
 * Copyright (c) 2023 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
#ifndef _NET_STRICT_TYPE_CNV_PRIVATE_H_
#define _NET_STRICT_TYPE_CNV_PRIVATE_H_

#ifdef XNU_KERNEL_PRIVATE

#include <sys/mcache.h>
#include <sys/socket.h>
#include <os/log.h>

/*
 * Only include this header file from <net/sockaddr_utils.h>
 */
#ifndef __NET_SOCKADDR_UTILS_H_INCLUDED
#error "do not include <net/strict_type_cnv_private.h> directly, use <net/sockaddr_utils.h> instead."
#endif



/*
 * Debug mode. If defined, disables certain optimizations,
 * and introduces a "conversion failed" upcall,
 * which can be set for testing.
 */
//#define __STC_DEBUG

/*
 * Attributes for the conversion functions.
 */
#if defined(__STC_DEBUG)
#define __STC_CONV_ATTRS__    __attribute__((__noinline__))
#else /* !defined(__STC_DEBUG) */
#define __STC_CONV_ATTRS__    __attribute__((always_inline))  __pure2
#endif /* defined(__STC_DEBUG)*/

#define __WCAST_ALIGN          "clang diagnostic ignored \"-Wcast-align\""
#define __WITH_SUPPRESSION(SUPPRESSION, ...) ({                                                   \
	_Pragma("clang diagnostic push");                                                             \
	_Pragma(SUPPRESSION);                                                                         \
	__VA_ARGS__                                                                                   \
	_Pragma("clang diagnostic pop");                                                              \
})
/*
 * Converts `const struct STYPE * VAL' to `struct DTYPE *'.
 */
#define __STC_DECONST_AND_CONVERT(STAG, STYPE, DTAG, DTYPE, VAL) ({                                \
    STAG STYPE *__single __sau_deconst_val;                                                        \
	__sau_deconst_val = __DECONST(STAG STYPE * __single, (VAL));                                   \
    __WITH_SUPPRESSION(__WCAST_ALIGN, (DTAG DTYPE * __single)(__sau_deconst_val));                 \
})

/*
 * Converts `struct STYPE * VAL' to `struct DTYPE *'.
 */
#define __STC_CONV_TO(STAG, STYPE, DTAG, DTYPE, VAL) ({                                           \
    __WITH_SUPPRESSION(__WCAST_ALIGN, (DTAG DTYPE * __single)((VAL)));                            \
})

/*
 * Converts `const struct STYPE * VAL' to `const struct DTYPE *'.
 */
#define __STC_CONV_CONST_TO_CONST(STYPE, DTYPE, VAL) ({                                           \
    __WITH_SUPPRESSION(__WCAST_ALIGN, (const struct DTYPE * __single)((VAL)));                    \
})

/*
 * Converts `[const] struct STYPE * VAL' to
 * `uint8_t* __bidi_indexable', bounded by MAX_LEN
 */
#define __STC_CONV_TO_BYTES_LEN(VAL, MAX_LEN) ({                                                  \
    __WITH_SUPPRESSION(__WCAST_ALIGN, __unsafe_forge_bidi_indexable(uint8_t*, (VAL), (MAX_LEN))); \
})


/*
 * Converts `uint8_t* __bidi_indexable' to `[const] struct DTYPE'.
 * Returns NULL if the conversion is not possible.
 */
#define __STC_CONV_FROM_BYTES_LEN(DTAG, DTYPE, VAL, LEN) ({                                       \
    __WITH_SUPPRESSION(__WCAST_ALIGN, __unsafe_forge_single(DTAG DTYPE *, (VAL)));                \
})


/*
 * Converter function names, used both to generate the inline stubs,
 * and in the generic dispatch expressions.
 */
#define __STC_OBJ_TO_BY_CNV(T)       __stc_convert_##T##_to_bytes
#define __STC_COBJ_TO_CBY_CNV(T)     __stc_convert_const_##T##_to_const_bytes
#define __STC_BY_TO_OBJ_CNV(T)       __stc_convert_bytes_to_##T
#define __STC_CBY_TO_COBJ_CNV(T)     __stc_convert_const_bytes_to_const_##T
#define __STC_CBY_TO_CBY_CNV()       __stc_convert_const_bytes_to_const_bytes
#define __STC_BY_TO_BY_CNV()         __stc_convert_bytes_to_bytes
#define __STC_TY_TY_CNV_F(F, T)      __stc_convert_##F##_to_##T
#define __STC_CTY_TY_CNV_F(F, T)     __stc_convert_const_##F##_to_##T
#define __STC_CTY_CTY_CNV_F(F, T)    __stc_convert_const_##F##_to_const_##T
#define __STC_TY_ID_CNV_F(F)         __stc_convert_##F##_identity
#define __STC_CTY_ID_CNV_F(F)        __stc_convert_const_##F##_identity
#define __STC_CTY_CID_CNV_F(F)       __stc_convert_##F##_const_identity


/*************************************************************************************************
 * Conversion building blocks, used below for converter definitions.
 */

#if __has_ptrcheck
#define __STC_ENFORCE_MIN_LEN(BTYPE, MIN_LEN, PTR) do {                                           \
    if ((PTR)) {                                                                                  \
	        BTYPE * __ensure_minimal_len __sized_by(MIN_LEN) = (PTR);                             \
	        (void)__ensure_minimal_len;                                                           \
	}                                                                                             \
} while(0)

#define __STC_CONVERT_INDEXABLE_PTR_TO(T, P)                                                      \
	__unsafe_forge_bidi_indexable(T,  (P), __ptr_upper_bound((P)) - (P));

#else /* !__has_ptrcheck */
#define __STC_ENFORCE_MIN_LEN(BTYPE, MIN_LEN, PTR) do {} while (0)

#define __STC_CONVERT_INDEXABLE_PTR_TO(T, P) ((T)(P))

#endif /* !__has_ptrcheck */


#define __STC_OBJ_TO_BYTES_CNV_IMPL(CV, TAG, TYPE, MAX_LEN, CNV_F)                                \
__STC_CONV_ATTRS__                                                                                \
static inline CV uint8_t* __header_indexable                                                      \
CNV_F(const TAG TYPE *ptr __single)                                                               \
{                                                                                                 \
    return __STC_CONV_TO_BYTES_LEN(__DECONST(TAG TYPE *__single, ptr), (MAX_LEN));                \
}

#define __STC_BYTES_TO_OBJ_CNV_IMPL(CV, TAG, TYPE, BTYPE, MIN_LEN, CNV_F)                         \
static inline CV TAG TYPE * __single                                                              \
__attribute__((overloadable))                                                                     \
CNV_F(CV BTYPE * data __header_indexable)                                                         \
{                                                                                                 \
	__STC_ENFORCE_MIN_LEN(CV BTYPE, MIN_LEN, data);                                               \
    return __STC_CONV_FROM_BYTES_LEN(CV TAG, TYPE, data, (MIN_LEN));                              \
}


/*
 * Converts `[CV] STAG STYPE *__single' to `[CV] DTAG DTYPE *__single', using CNV_F.
 */
#define __STC_OBJ_TO_OBJ_CNV_IMPL(CV, STAG, STYPE, DTAG, DTYPE, CNV_F)                            \
__STC_CONV_ATTRS__                                                                                \
static inline CV DTAG DTYPE * __single                                                            \
__attribute__((overloadable))                                                                     \
CNV_F(CV STAG STYPE *ptr __single)                                                                \
{                                                                                                 \
    return __STC_CONV_TO(CV STAG, STYPE, CV DTAG, DTYPE, ptr);                                    \
}


/*
 * Converts `const STAG STYPE *__single' to `DTAG DTYPE *__single', using CNV_F.
 */
#define __STC_COBJ_TO_OBJ_CNV_IMPL(STAG, STYPE, DTAG, DTYPE, CNV_F)                               \
__STC_CONV_ATTRS__                                                                                \
static inline DTAG DTYPE * __single                                                               \
__attribute__((overloadable))                                                                     \
CNV_F(const STAG STYPE *ptr __single)                                                             \
{                                                                                                 \
    return __STC_DECONST_AND_CONVERT(STAG, STYPE, DTAG, DTYPE, ptr);                              \
}


/*************************************************************************************************
 * Statically typed converters.
 */

/*
 * Conversions between different variants of pointers to sockaddr objects
 * that have the different types.
 *
 * Given tuple (STAG, STYPE, DTAG, DTYPE), defines the converters:
 * 0. "Forward":          STAG STYPE *__single -> DTAG DTYPE *__single
 * 1. "Reverse":          DTAG DTYPE *__single -> STAG STYPE *__single
 * 2. "Forward const":    const STAG STYPE *__single -> const DTAG DTYPE *__single
 * 3. "Reverse const":    const DTAG DTYPE *__single -> const STAG STYPE *__single
 * 4. "Forward deconst":  const STAG STYPE *__single -> DTAG DTYPE *__single
 * 5. "Reverse deconst":  const DTAG DTYPE *__single -> STAG STYPE *__single
 */
#define __STC_DEFINE_OBJECT_CONVERTERS(STAG, STYPE, DTAG, DTYPE)                                  \
/* [0] ("Forward")  */                                                                            \
__STC_OBJ_TO_OBJ_CNV_IMPL(, STAG, STYPE, DTAG, DTYPE,  __STC_TY_TY_CNV_F(STYPE, DTYPE))           \
                                                                                                  \
/* [1] ("Reverse") */                                                                             \
__STC_OBJ_TO_OBJ_CNV_IMPL(, DTAG, DTYPE, STAG, STYPE,  __STC_TY_TY_CNV_F(DTYPE, STYPE))           \
                                                                                                  \
/* [2] ("Forward const")  */                                                                      \
__STC_OBJ_TO_OBJ_CNV_IMPL(const, STAG, STYPE, DTAG, DTYPE, __STC_CTY_CTY_CNV_F(STYPE, DTYPE))     \
                                                                                                  \
/* [3] ("Reverse const")  */                                                                      \
__STC_OBJ_TO_OBJ_CNV_IMPL(const, DTAG, DTYPE, STAG, STYPE, __STC_CTY_CTY_CNV_F(DTYPE, STYPE))     \
                                                                                                  \
/* [4] ("Forward deconst")  */                                                                    \
__STC_COBJ_TO_OBJ_CNV_IMPL(STAG, STYPE, DTAG, DTYPE, __STC_CTY_TY_CNV_F(STYPE, DTYPE))            \
                                                                                                  \
/* [5] ("Reverse deconst")  */                                                                    \
__STC_COBJ_TO_OBJ_CNV_IMPL(DTAG, DTYPE, STAG, STYPE, __STC_CTY_TY_CNV_F(DTYPE, STYPE))


/*
 * Conversions between different variants of pointers to sockaddr objects
 * that have the same type.
 *
 * Given tuple (TAG, TYPE), defines the edge case converters:
 * 0. "Identity":          TAG TYPE *__single -> TAG TYPE *__single
 * 1. "Const identity":    const TAG TYPE *__single -> const TAG TYPE *__single
 * 2. "Deconst identity":  const TAG TYPE *__single -> TAG DTYPE *__single
 */
#define __STC_DEFINE_SELF_CONVERTERS(DTAG, DTYPE)                                                 \
/* [0] ("Identity")  */                                                                           \
__STC_CONV_ATTRS__                                                                                \
static inline DTAG DTYPE *__single                                                                \
__STC_TY_ID_CNV_F(DTYPE)(DTAG DTYPE *sin __single)                                                \
{                                                                                                 \
    return sin;                                                                                   \
}                                                                                                 \
                                                                                                  \
/* [1] ("Const identity")  */                                                                     \
__STC_CONV_ATTRS__                                                                                \
static inline const DTAG DTYPE *__single                                                          \
__STC_CTY_CID_CNV_F(DTYPE)(const DTAG DTYPE *sin __single)                                        \
{                                                                                                 \
    return sin;                                                                                   \
}                                                                                                 \
                                                                                                  \
/* [2] ("Deconst identity")  */                                                                   \
__STC_CONV_ATTRS__                                                                                \
static inline DTAG DTYPE *__single                                                                \
__STC_CTY_ID_CNV_F(DTYPE)(const DTAG DTYPE *sin __single)                                         \
{                                                                                                 \
    return __DECONST(DTAG DTYPE *__single, sin);                                                  \
}


/*
 * Conversions between byte arrays and pointers to sockaddr objects
 *
 * Given tuple (TAG, TYPE, MIN_LEN, MAX_LEN), defines
 * the edge case converters:
 * 0. "Type to bytes": TAG TYPE * __single -> uint8_t *__sized_by(MAX_LEN)
 * 1. "Const type to const bytes": const TAG TYPE * __single -> const uint8_t *__sized_by(MAX_LEN)
 * 2. "Bytes to type": uint8_t *__sized_by(MIN_LEN) -> TAG TYPE * __single
 * 3. "Const bytes to const type": const uint8_t *__sized_by(MIN_LEN) -> const TAG TYPE * __single
 *
 * NOTE: Type-to-bytes converters use MAX_LEN;
 *       bytes-to-type converters use MIN_LEN
 */
#define __STC_DEFINE_BYTE_TO_OBJ_CNVS(TAG, TYPE, MIN_LEN, MAX_LEN)                                \
/* [0] ("Type to bytes") */                                                                       \
__STC_OBJ_TO_BYTES_CNV_IMPL(, TAG, TYPE, MAX_LEN, __STC_OBJ_TO_BY_CNV(TYPE))                      \
                                                                                                  \
/* [1] ("Const type to const bytes") */                                                           \
__STC_OBJ_TO_BYTES_CNV_IMPL(, TAG, TYPE, MAX_LEN, __STC_COBJ_TO_CBY_CNV(TYPE))                    \
                                                                                                  \
/* [2] ("Bytes to type") */                                                                       \
__STC_BYTES_TO_OBJ_CNV_IMPL(, TAG, TYPE, void, MIN_LEN, __STC_BY_TO_OBJ_CNV(TYPE))                \
                                                                                                  \
/* [3] ("Const bytes to const type") */                                                           \
__STC_BYTES_TO_OBJ_CNV_IMPL(const, TAG, TYPE, void, MIN_LEN, __STC_CBY_TO_COBJ_CNV(TYPE))


/*
 * Edge condition between different variants of byte pointers to uint8_t.
 * These are used by the SOCKADDR_{COPY,ZERO,CMP} operations.
 */
__STC_CONV_ATTRS__
static inline const uint8_t * __header_indexable
__attribute__((overloadable))
__STC_CBY_TO_CBY_CNV()(const void * data __header_indexable)
{
	const uint8_t * __header_indexable cdata = data;
	return __STC_CONVERT_INDEXABLE_PTR_TO(const uint8_t*, cdata);
}

__STC_CONV_ATTRS__
static inline const uint8_t * __header_indexable
__attribute__((overloadable))
__STC_CBY_TO_CBY_CNV()(const char * data __header_indexable)
{
	return __STC_CONVERT_INDEXABLE_PTR_TO(const uint8_t*, data);
}

__STC_CONV_ATTRS__
static inline const uint8_t * __header_indexable
__attribute__((overloadable))
__STC_CBY_TO_CBY_CNV()(const uint8_t * data __header_indexable)
{
	return data;
}

__STC_CONV_ATTRS__
static inline uint8_t * __header_indexable
__attribute__((overloadable))
__STC_BY_TO_BY_CNV()(void * data __header_indexable)
{
	uint8_t * __header_indexable cdata = data;
	return __STC_CONVERT_INDEXABLE_PTR_TO(uint8_t*, cdata);
}

__STC_CONV_ATTRS__
static inline uint8_t * __header_indexable
__attribute__((overloadable))
__STC_BY_TO_BY_CNV()(uint8_t * data __header_indexable)
{
	return data;
}

__STC_CONV_ATTRS__
static inline uint8_t * __header_indexable
__attribute__((overloadable))
__STC_BY_TO_BY_CNV()(char * data __header_indexable)
{
	return __STC_CONVERT_INDEXABLE_PTR_TO(uint8_t*, data);
}



/*************************************************************************************************
 * Dispatch block definitions.
 *
 * The dispatch blocks below are meant to be composed into a single generic selection expression.
 * See the definition of `__SA_UTILS_CONV_TO_SOCKADDR` for an example.
 *
 * Each dispatch block defines several type expressions and the corresponding conversion macros.
 *
 * Wnen compiled with `-fbounds-safety', the dispatch block accepst sized and single pointers.
 * When compiled without `-fbounds-safety', each dispatch block accepts only a pointer to the type.
 */


/*
 * Basic building block for associating a CNV_F function with a pointer to CV TAG TYPE.
 * Depending on whehter `-fbounds-safety' is enabled, the match block is extended to sized pointers.
 */
#if __has_ptrcheck
#define __STC_GENERIC_CV_CNV_CLAUSE(CV, TAG, TYPE, CNV_F)                                        \
	CV TAG TYPE * __single:                         CNV_F,                                                    \
	CV TAG TYPE * __bidi_indexable:         CNV_F,                                                    \
	CV TAG TYPE * __indexable:                      CNV_F
#else /* !__has_ptrcheck */
#define __STC_GENERIC_CV_CNV_CLAUSE(CV, TAG, TYPE, CNV_F)                                        \
	CV TAG TYPE * :                                         CNV_F
#endif /* !__has_ptrcheck */


/**
 * __STC_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE)
 *
 * Matches its argument against `STYPE' (`STAG' indicates struct or union), and upon a type match,
 * converts the argument to `DTYPE'.
 *
 * If the argument type is `const STAG STYPE *', the argument will be converted
 * to `const struct DTYPE * __single'.
 *
 * Otherwise, the argument will be converted to `struct DTYPE * __single'
 */
#define __STC_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE)                                           \
	__STC_GENERIC_CV_CNV_CLAUSE(, STAG, STYPE, __STC_TY_TY_CNV_F(STYPE, DTYPE)),                 \
	__STC_GENERIC_CV_CNV_CLAUSE(const, STAG, STYPE, __STC_CTY_CTY_CNV_F(STYPE, DTYPE))


/**
 * __STC_BYTES_TO_OBJ_CNV_CLAUSE(TYPE)
 *
 * Matches a BYte array, and attempts to convert to `TYPE'
 *
 * Notes on `__indexable' vs. `__bidi_indexable':
 *
 * When bounds-checks are enabled, the match block treats the `__indexable' and the `__bidi_indexable'
 * pointers the same way (but still has to distinguish between the pointer sizes).
 *
 * The conversion preserves the `const' qualifier.
 */
#define __STC_BYTES_TO_OBJ_CNV_CLAUSE(TYPE)                                                        \
	__STC_GENERIC_CV_CNV_CLAUSE(     , , char,     __STC_BY_TO_OBJ_CNV(TYPE)),                   \
	__STC_GENERIC_CV_CNV_CLAUSE(     , , uint8_t,  __STC_BY_TO_OBJ_CNV(TYPE)),                   \
	__STC_GENERIC_CV_CNV_CLAUSE(     , , void,     __STC_BY_TO_OBJ_CNV(TYPE)),                   \
	__STC_GENERIC_CV_CNV_CLAUSE(const, , char,     __STC_CBY_TO_COBJ_CNV(TYPE)),                 \
	__STC_GENERIC_CV_CNV_CLAUSE(const, , uint8_t,  __STC_CBY_TO_COBJ_CNV(TYPE)),                 \
	__STC_GENERIC_CV_CNV_CLAUSE(const, , void,     __STC_CBY_TO_COBJ_CNV(TYPE))

/**
 *  __STC_OBJ_TO_BYTES_CNV_CLAUSE(TAG, TYPE)
 *
 * Matches a `TAG TYPE *' variable, and converts it to a BYte array.
 *
 * The conversion preserves the `const' qualifier.
 */
#define __STC_OBJ_TO_BYTES_CNV_CLAUSE(TAG, TYPE)                                                              \
	__STC_GENERIC_CV_CNV_CLAUSE(     , TAG, TYPE,  __STC_OBJ_TO_BY_CNV(TYPE)),                    \
	__STC_GENERIC_CV_CNV_CLAUSE(const, TAG, TYPE,  __STC_COBJ_TO_CBY_CNV(TYPE))

/**
 * __STC_BYTES_TO_BYTES_CNV_CLAUSE()
 *
 * Matches a BYte array and returns a BYte array.
 *
 * The conversion preserves the `const' qualifier.
 */
#define __STC_BYTES_TO_BYTES_CNV_CLAUSE()                                                           \
	__STC_GENERIC_CV_CNV_CLAUSE(     , , char,     __STC_BY_TO_BY_CNV()),                          \
	__STC_GENERIC_CV_CNV_CLAUSE(     , , uint8_t,  __STC_BY_TO_BY_CNV()),                          \
	__STC_GENERIC_CV_CNV_CLAUSE(     , , void,     __STC_BY_TO_BY_CNV()),                          \
	__STC_GENERIC_CV_CNV_CLAUSE(const, , char,     __STC_CBY_TO_CBY_CNV()),                        \
	__STC_GENERIC_CV_CNV_CLAUSE(const, , uint8_t,  __STC_CBY_TO_CBY_CNV()),                        \
	__STC_GENERIC_CV_CNV_CLAUSE(const, , void,     __STC_CBY_TO_CBY_CNV())


/**
 * __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE)
 *
 * Matches a `const STAG STYPE *' and converts it to `STAG STYPE * __single'
 *
 * The conversion REMOVES the `const' qualifier, if present.
 * To preserve the `const' qualifier, use the `__STC_TYPE_TO_OBJ_CNV_CLAUSE' instead.
 */
#define __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(STAG, STYPE, DTYPE)                                     \
	__STC_GENERIC_CV_CNV_CLAUSE(const, STAG, STYPE,   __STC_CTY_TY_CNV_F(STYPE, DTYPE))

/**
 * __STC_MATCH_MATCH_CID(TAG, TYPE)
 *
 * Matches a `const TAG TYPE *' and converts it to `TAG TYPE * __single'
 *
 * The conversion REMOVES the `const' qualifier, if present.
 * To preserve the `const' qualifier, use the `__STC_IDENTITY_CNV_CLAUSE' instead.
 */
#define __STC_CONST_IDENTITY_CNV_CLAUSE(TAG, TYPE)                                                 \
	__STC_GENERIC_CV_CNV_CLAUSE(const, TAG, TYPE, __STC_CTY_ID_CNV_F(TYPE))


/**
 * __STC_IDENTITY_CNV_CLAUSE(TAG, TYPE)
 *
 * Matches a `[const] TAG TYPE *' and converts it to `[const] TAG TYPE * __single'
 *
 * The conversion preserves the `const' qualifier.
 */
#define __STC_IDENTITY_CNV_CLAUSE(TAG, TYPE)                                                     \
	__STC_GENERIC_CV_CNV_CLAUSE(const, TAG, TYPE, __STC_CTY_ID_CNV_F(TYPE)),                     \
	__STC_GENERIC_CV_CNV_CLAUSE(,      TAG, TYPE, __STC_TY_ID_CNV_F(TYPE))



/*************************************************************************************************
 * Generators for cast operations.
 */


#define __STC_ENABLE_STATIC_CAST(SRC_TAG, SRC_TYPENAME, DST_TYPENAME)                             \
	__STC_TYPE_TO_OBJ_CNV_CLAUSE(SRC_TAG, SRC_TYPENAME, DST_TYPENAME)


#define __STC_ENABLE_DECONST_CAST(SRC_TAG, SRC_TYPENAME, DST_TYPENAME)                            \
	__STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(SRC_TAG, SRC_TYPENAME, DST_TYPENAME)


/*************************************************************************************************
 * Porcelain macros to define sockaddr subtypes.
 */

/*
 * Building blocks for variadic macro overrides.
 */
#define __STC_COUNT_ARGS1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N
#define __STC_COUNT_ARGS(...)                                                                     \
	__STC_COUNT_ARGS1(, ##__VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
#define __STC_DISPATCH1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
#define __STC_DISPATCH(base, ...)                                                                 \
	__STC_DISPATCH1(base, __STC_COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)

#define __STC_DEFINE_STATIC_CAST(SRC_TAG, SRC_TYPENAME, DST_TAG, DST_TYPENAME)                    \
__STC_DEFINE_OBJECT_CONVERTERS(SRC_TAG, SRC_TYPENAME, DST_TAG, DST_TYPENAME)

/*
 * Building blocks for sockaddr subtype definitions.
 */
#define __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, MIN_LEN, MAX_LEN)                              \
	__STC_DEFINE_SELF_CONVERTERS(TAG, TYPENAME);      /* [0] */                                   \
	__STC_DEFINE_STATIC_CAST(TAG, TYPENAME, struct, sockaddr)                                     \
	__STC_DEFINE_STATIC_CAST(TAG, TYPENAME, struct, sockaddr_storage)                             \
	__STC_DEFINE_BYTE_TO_OBJ_CNVS(TAG, TYPENAME, MIN_LEN, MAX_LEN)

#define __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, MIN_LEN, MAX_LEN, TAG1, TYPENAME1)             \
	__STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, MIN_LEN, MAX_LEN)                                  \
	__STC_DEFINE_STATIC_CAST(TAG, TYPENAME, TAG1, TYPENAME1)

#define __STC_DEFINE_SUBTYPE_IMPL_8(TAG, TYPENAME, MIN_LEN, MAX_LEN,                              \
	    TAG1, TYPENAME1, TAG2, TYPENAME2)                             \
	__STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, MIN_LEN, MAX_LEN, TAG1, TYPENAME1)                 \
	__STC_DEFINE_STATIC_CAST(TAG, TYPENAME, TAG2, TYPENAME2)


/*************************************************************************************************
 * Porcelain macros to define a socakddr subtype with variable size,
 * e.g. `struct sockaddr_dl' or `struct sockaddr_un'.
 */
#define __STC_DEFINE_VARIABLE_SIZE_SUBTYPE_2(TAG, TYPENAME)                                       \
    __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, sizeof(TAG TYPENAME), 255)

#define __STC_DEFINE_VARIABLE_SIZE_SUBTYPE_4(TAG, TYPENAME, TAG1, TYPENAME1)                      \
	__STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, sizeof(TAG TYPENAME), 255, TAG1, TYPENAME1)

#define __STC_DEFINE_VARIABLE_SIZE_SUBTYPE_6(TAG, TYPENAME, TAG1, TYPENAME1, TAG2, TYPENAME2)     \
	__STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, sizeof(TAG TYPENAME), 255,                         \
	                                                        TAG1, TYPENAME1, TAG2, TYPENAME2)

#define __SA_UTILS_DEFINE_VARIABLE_SIZE_SUBTYPE(...)                                              \
	__STC_DISPATCH(__STC_DEFINE_VARIABLE_SIZE_SUBTYPE, ##__VA_ARGS__)


/*************************************************************************************************
 * Porcelain macros to define a socakddr subtype with fixed size,
 * e.g. `struct sockaddr_in' or `struct sockaddr_in6'.
 */
#define __STC_DEFINE_FIXED_SIZE_SUBTYPE_2(TAG, TYPENAME)                                          \
    __STC_DEFINE_SUBTYPE_IMPL_4(TAG, TYPENAME, sizeof(TAG TYPENAME), sizeof(TAG TYPENAME))

#define __STC_DEFINE_FIXED_SIZE_SUBTYPE_4(TAG, TYPENAME, TAG1, TYPENAME1)                         \
    __STC_DEFINE_SUBTYPE_IMPL_6(TAG, TYPENAME, sizeof(TAG TYPENAME), sizeof(TAG TYPENAME),        \
	                                                        TAG1, TYPENAME1)

#define __STC_DEFINE_FIXED_SIZE_SUBTYPE_6(TAG, TYPENAME, TAG1, TYPENAME1, TAG2, TYPENAME2)        \
    __STC_DEFINE_SUBTYPE_IMPL_8(TAG, TYPENAME, sizeof(TAG TYPENAME), sizeof(TAG TYPENAME),        \
	                                                        TAG1, TYPENAME1, TAG2, TYPENAME2)

#define __SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(...)                                                 \
	__STC_DISPATCH(__STC_DEFINE_FIXED_SIZE_SUBTYPE, ##__VA_ARGS__)


#endif /* XNU_KERNEL_PRIVATE */

#endif /* _NET_STRICT_TYPE_CNV_PRIVATE_H_ */