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_SOCKADDR_UTILS_H_
29#define _NET_SOCKADDR_UTILS_H_
30
31#ifdef XNU_KERNEL_PRIVATE
32
33#include <sys/socket.h>
34
35/*
36 * Type conversion rules for socket address types
37 *
38 * 1. Context:
39 *
40 * XNU networking uses the "socket address" abstraction to represent
41 * the addresses for the different protocol families, e.g. IPv4, IPv6,
42 * UNIX domain sockets, ARP etc.
43 *
44 * Historically, the socket addresses were represented as a byte array,
45 * starting with a uint16_t "family" discriminator.
46 *
47 * This was changed with the advent of XOpen UNIX standard: the uint16_t
48 * "family" discriminator was split into 2 uint8_t fields: the length
49 * and the protocol family.
50 *
51 * Since the different protocols have different addressing semantics,
52 * the different addresses are represented by multiple structures.
53 * For example, the IPv6 addresses are represented by `struct sockaddr_in6',
54 * while the IPv4 addresses can be represented by `struct sockaddr_in' or by
55 * `struct sockaddr_inifscope', depending on whether the address is bound
56 * to a particular interface.
57 *
58 * The type `struct sockaddr' can be used interchangeably to represent any
59 * of the above addresses. Essentially, the C types that represent
60 * the different socket address families form a type hierarchy,
61 * with the `struct sockaddr' being the root type.
62 *
63 * There are some exceptions to the hierarchy. Sometimes the socket addresses
64 * are represented by a "container" type, e.g. `struct sockaddr_storage'
65 * or `union sockaddr_in_4_6'. Finally, some protocol families, such as
66 * the routing sockets, are represented by the plain `struct sockaddr'.
67 *
68 *
69 *
70 * +-------+ +-----------+
71 * +------------------+ Base | +. - - . - - . - - . |Containers |
72 * | struct sockaddr +----+--+ . +-----------+
73 * +-----------------------+ | +----------------------------+ |
74 * ^ . | union sockaddr_in_4_6 | .
75 * +------------------+ +----------------------------+ |
76 * | . +----------------------------+ .
77 * | | | struct sockaddr_storage | |
78 * | . +----------------------------+ .
79 * | +----------+ | +----------------------------+ |
80 * + . - - . - - . - + - .| Concrete | . | uint8_t * __bidi_indexable | .
81 * . +----------+ | +----------------------------+ |
82 * | +---------------------------+ | . .
83 * . | struct sockaddr_ctl | . +. - - . - - . - - . - - . - - . +
84 * | +---------------------------+ |
85 * . +---------------------------+ .
86 * | | struct sockaddr_dl | |
87 * . +---------------------------+ .
88 * | +---------------------------+ |
89 * . | struct sockaddr_in | .
90 * | +---------------------------+ |
91 * . +---------------------------+ .
92 * | | struct sockaddr_inarp | |
93 * . +---------------------------+ .
94 * | +---------------------------+ |
95 * . | struct sockaddr_inifscope | .
96 * | +---------------------------+ |
97 * . +---------------------------+ .
98 * | | struct sockaddr_in6 | |
99 * . +---------------------------+ .
100 * | +---------------------------+ |
101 * . | struct sockaddr_ndrv | .
102 * | +---------------------------+ |
103 * . +---------------------------+ .
104 * | | struct sockaddr_sys | |
105 * . +---------------------------+ .
106 * | +---------------------------+ |
107 * . | struct sockaddr_un | .
108 * | +---------------------------+ |
109 * . .
110 * + . - - . - - . - - . - - . - - .+
111 *
112 *
113 * 2. Challenges
114 *
115 * 2.1. Type safety challenges
116 *
117 * Since the pointer type `struct sockaddr *' can represent a pointer
118 * to any concrete derived type, or to a container type,
119 * the enforcement of bound checks can be tricky.
120 *
121 * In particular, one needs to safely support the following conversions:
122 *
123 * - From `struct sockaddr *' to any of the derived types, and vice versa.
124 * - From `uint8_t *' to any of the derived types, and vice versa.
125 * - From `union sockaddr_in_4_6 *' to either `struct sockaddr_in *'
126 * or to `struct sockaddr_in6 *', and vice versa.
127 * - From `struct sockaddr_in *' to `struct sockaddr_inifscope *',
128 * and vice versa.
129 *
130 * At the same time, the system needs to make accidental conversions between
131 * unrelated types difficult. Examples of such conversions include:
132 *
133 * - From `struct sockaddr_in *' to `struct sockaddr_un *' or vice versa.
134 * - From `struct sockaddr_sys *' to `struct sockaddr_ndrv *' or vice versa.
135 *
136 * 2.2. ABI constraints.
137 *
138 * The concrete types that are listed above are used both in the kernel space,
139 * the user space and by the drivers.
140 *
141 * 2.3. Pointer boundary challenges
142 *
143 * The transition between `__single' pointers, e.g. between
144 * `struct sockaddr * __single' to `struct sockaddr_in6 * __single'
145 * is currently assumed to be safe, as long as the concrete types
146 * have determined sizes.
147 *
148 * The challenge occurs whenever one needs to serialize or to deserialize
149 * the concrete socket address types into a byte arrays.
150 *
151 * 2.4. Runtime cost challenges
152 *
153 * The transition between the different socket address types
154 * should not incure a significant CPU or memory cost in runtime.
155 *
156 *
157 * 3. Implementation.
158 *
159 * This file implements a mechanism that:
160 * - Enforces the type safety by ensuring that only the valid
161 * type conversions can be made.
162 * - Ensures the ABI compatibility for the socket address types.
163 * - Implements the conversion between the socket address types
164 * and the container types (including byte arrays) in a way
165 * that allows enforcing the boundary checks.
166 * - Does not have a significant runtime impact.
167 *
168 * To achive that, the mechanism relies on the C generic dispatch
169 * mechanism, which allows converting variables to and from
170 * the desired types.
171 *
172 *
173 * 4. Usage.
174 *
175 * In order to use the sockaddr_utils, the implementation
176 * code needs to include this file *after* including the files
177 * which define the relevant sockaddr structures.
178 *
179 * For example:
180 *
181 * #include <netinet/in.h>
182 * #include <netinet/in_private.h>
183 * #include <net/sockaddr_utils.h>
184 *
185 *
186 * Doing so will redefine the canonical macros such as `SA(s)`
187 * and will allow for mostly seamless adoption.
188 *
189 * Once the adoption is mostly complete,
190 * this file can be included in the "private" versions
191 * of the header files, such as <netinet/in_private.h>
192 */
193
194#define __NET_SOCKADDR_UTILS_H_INCLUDED
195#include <net/strict_type_cnv_private.h>
196#undef __NET_SOCKADDR_UTILS_H_INCLUDED
197
198#include <net/if_dl.h>
199#include <sys/un.h>
200#include <net/ndrv.h>
201#include <netinet/in_private.h>
202#include <netinet/if_ether.h>
203#include <net/necp.h>
204
205/*
206 * Building blocks for the cast operations
207 */
208
209
210/*
211 * Generic static cast for sockaddr subtypes.
212 *
213 * Defines a static cast expression that, given the expression EXPR
214 * and the destination type DST_TYPENAME will:
215 * 0. If EXPR represents a byte array, attempt to convert EXPR
216 * to DST_TYPENAME.
217 * 1. If EXPR is compatible with `struct DST_TYPENAME *': return EXPR.
218 * 2. If EXPR is compatible with `struct sockaddr *', perform type conversion
219 * from `struct sockaddr *' to `struct DST_TYPENAME *'
220 * 3. If EXPR is compatible with `struct sockaddr_storage *',
221 * perform type conversion from `struct sockaddr_storage *'
222 * to `struct DST_TYPENAME *'.
223 * 4. If additional conversions are enabled, attempt to apply those
224 * to the EXPR, and if successful, return the result of conversion.
225 *
226 * NOTE: The static cast preserves the CV qualifiers.
227 */
228#define __SA_UTILS_STATIC_CAST(EXPR, DST_TYPENAME, ...) _Generic((EXPR), \
229 __STC_BYTES_TO_OBJ_CNV_CLAUSE(DST_TYPENAME), /* [0] */ \
230 __STC_IDENTITY_CNV_CLAUSE(struct, DST_TYPENAME), /* [1] */ \
231 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr, DST_TYPENAME), /* [2] */ \
232 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_storage, DST_TYPENAME), /* [3] */ \
233 ##__VA_ARGS__ /* [4] */ \
234)((EXPR))
235
236
237/*
238 * Generic const cast for sockaddr subtypes.
239 *
240 * Defines a const cast expression that, given the expression EXPR
241 * and the destination type DST_TYPENAME will:
242 * 0. If EXPR is compatible with `const struct DST_TYPENAME *':
243 * deconst EXPR and return the result.
244 * 1. If EXPR is compatible with `const struct sockaddr s*':
245 * convert EXPR to `const struct DST_TYPENAME *' and return deconsted result.
246 * 2. If EXPR is compatible with `const struct sockaddr_storage *':
247 * convert EXPR to `const struct DST_TYPENAME* ' and return deconsted result.
248 * 3. If additional conversions are enabled, attempt to apply those
249 * to the EXPR, and if successful, return the result of conversion.
250 *
251 * NOTE: The static cast preserves the CV qualifiers.
252 */
253#define __SA_UTILS_DECONST_CAST(EXPR, DST_TYPENAME, ...) _Generic((EXPR), \
254 __STC_CONST_IDENTITY_CNV_CLAUSE(struct, DST_TYPENAME), /* [0] */ \
255 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr, DST_TYPENAME), /* [1] */ \
256 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_storage, DST_TYPENAME), /* [2] */ \
257 ##__VA_ARGS__ /* [3] */ \
258)((EXPR))
259
260
261/*
262 * Strict replacement for struct sockaddr
263 */
264
265/* Register the base types: struct sockaddr and struct sockaddr_storage */
266__STC_DEFINE_SELF_CONVERTERS(struct, sockaddr);
267__STC_DEFINE_OBJECT_CONVERTERS(struct, sockaddr, struct, sockaddr_storage);
268__STC_DEFINE_OBJECT_CONVERTERS(struct, sockaddr, union, sockaddr_in_4_6);
269__STC_DEFINE_OBJECT_CONVERTERS(struct, sockaddr, union, necp_sockaddr_union);
270__STC_DEFINE_BYTE_TO_OBJ_CNVS(struct, sockaddr, sizeof(struct sockaddr), 255);
271
272__STC_DEFINE_SELF_CONVERTERS(struct, sockaddr_storage);
273__STC_DEFINE_BYTE_TO_OBJ_CNVS(struct, sockaddr_storage,
274 sizeof(struct sockaddr_storage), sizeof(struct sockaddr_storage));
275__STC_DEFINE_BYTE_TO_OBJ_CNVS(union, sockaddr_in_4_6,
276 sizeof(union sockaddr_in_4_6), sizeof(union sockaddr_in_4_6));
277__STC_DEFINE_BYTE_TO_OBJ_CNVS(union, necp_sockaddr_union,
278 sizeof(union necp_sockaddr_union), sizeof(union necp_sockaddr_union));
279
280
281/*************************************************************************************************
282 * Generic converter to bytes.
283 */
284#define __SA_UTILS_CONV_TO_BYTES(X) _Generic((X), \
285 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr), \
286 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_storage), \
287 __STC_OBJ_TO_BYTES_CNV_CLAUSE(union, sockaddr_in_4_6), \
288 __STC_OBJ_TO_BYTES_CNV_CLAUSE(union, necp_sockaddr_union), \
289 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_ctl), \
290 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_dl), \
291 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_in), \
292 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_in6), \
293 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_inarp), \
294 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_inifscope), \
295 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_ndrv), \
296 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_sys), \
297 __STC_OBJ_TO_BYTES_CNV_CLAUSE(struct, sockaddr_un), \
298 __STC_BYTES_TO_BYTES_CNV_CLAUSE() \
299 )((X))
300
301
302/*************************************************************************************************
303 * Converters to `struct sockaddr *'
304 */
305#define __SA_UTILS_CONV_TO_SOCKADDR(X) _Generic((X), \
306 __STC_BYTES_TO_OBJ_CNV_CLAUSE(sockaddr), \
307 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_storage, sockaddr), \
308 __STC_TYPE_TO_OBJ_CNV_CLAUSE(union, sockaddr_in_4_6, sockaddr), \
309 __STC_TYPE_TO_OBJ_CNV_CLAUSE(union, necp_sockaddr_union, sockaddr), \
310 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_ctl, sockaddr), \
311 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_dl, sockaddr), \
312 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_in, sockaddr), \
313 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_in6, sockaddr), \
314 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_inarp, sockaddr), \
315 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_inifscope, sockaddr), \
316 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_ndrv, sockaddr), \
317 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_sys, sockaddr), \
318 __STC_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_un, sockaddr), \
319 __STC_IDENTITY_CNV_CLAUSE(struct, sockaddr) \
320 )((X))
321
322#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR(X) _Generic((X), \
323 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_storage, sockaddr), \
324 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(union, sockaddr_in_4_6, sockaddr), \
325 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(union, necp_sockaddr_union, sockaddr), \
326 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_ctl, sockaddr), \
327 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_dl, sockaddr), \
328 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_in, sockaddr), \
329 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_in6, sockaddr), \
330 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_inarp, sockaddr), \
331 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_inifscope, sockaddr), \
332 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_ndrv, sockaddr), \
333 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_sys, sockaddr), \
334 __STC_CONST_TYPE_TO_OBJ_CNV_CLAUSE(struct, sockaddr_un, sockaddr), \
335 __STC_CONST_IDENTITY_CNV_CLAUSE(struct, sockaddr) \
336 )((X))
337
338
339#if defined(SA)
340#undef SA
341#endif /* defined(SA) */
342#define SA(s) __SA_UTILS_CONV_TO_SOCKADDR((s))
343#define __DECONST_SA(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR((s))
344
345#define SA_BYTES(s) __SA_UTILS_CONV_TO_BYTES(s)
346
347/*************************************************************************************************
348 * Replacements for `bcopy', `bcmp' and `bzero'.
349 */
350#define SOCKADDR_COPY(SRC, DST, LEN) do { \
351 const uint8_t* __sau_sbytes = __SA_UTILS_CONV_TO_BYTES((SRC)); \
352 uint8_t* __sau_dbytes = __SA_UTILS_CONV_TO_BYTES((DST)); \
353 bcopy(__sau_sbytes, __sau_dbytes, (LEN)); \
354} while(0)
355
356
357#define SOCKADDR_ZERO(SRC, LEN) do { \
358 uint8_t* __sau_src_bytes = __SA_UTILS_CONV_TO_BYTES((SRC)); \
359 bzero(__sau_src_bytes, (LEN)); \
360} while(0)
361
362
363#define SOCKADDR_CMP(LH, RH, LEN) ({ \
364 int __sac_rv = 0; \
365 const uint8_t* __sau_lhb = __SA_UTILS_CONV_TO_BYTES((LH)); \
366 const uint8_t* __sau_rhb = __SA_UTILS_CONV_TO_BYTES((RH)); \
367 __sac_rv = bcmp(__sau_lhb, __sau_rhb, (LEN)); \
368 __sac_rv; \
369})
370
371/*************************************************************************************************
372 * Strict replacement for `struct sockaddr_ctl *'
373 */
374__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_ctl)
375
376#define __SA_UTILS_CONV_TO_SOCKADDR_CTL(X) __SA_UTILS_STATIC_CAST(X, sockaddr_ctl)
377#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_CTL(X) __SA_UTILS_DECONST_CAST(X, sockaddr_ctl)
378
379#define SCTL(s) __SA_UTILS_CONV_TO_SOCKADDR_CTL((s))
380#define __DECONST_SCTL(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_CTL((s))
381
382
383/*************************************************************************************************
384 * Strict replacement for `struct sockaddr_dl *'
385 */
386__SA_UTILS_DEFINE_VARIABLE_SIZE_SUBTYPE(struct, sockaddr_dl)
387
388
389#define __SA_UTILS_CONV_TO_SOCKADDR_DL(X) __SA_UTILS_STATIC_CAST(X, sockaddr_dl)
390#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_DL(X) __SA_UTILS_DECONST_CAST (X, sockaddr_dl)
391
392#if defined(SDL)
393#undef SDL
394#endif /* defined(SDL) */
395#define SDL(s) __SA_UTILS_CONV_TO_SOCKADDR_DL((s))
396#define __DECONST_SDL(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_DL((s))
397
398
399/*************************************************************************************************
400 * Strict replacement for `struct sockaddr_in *'
401 */
402__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_in, \
403 union, sockaddr_in_4_6, \
404 union, necp_sockaddr_union)
405
406#define __SA_UTILS_CONV_TO_SOCKADDR_IN(X) \
407 __SA_UTILS_STATIC_CAST(X, sockaddr_in, \
408 __STC_ENABLE_STATIC_CAST(union, sockaddr_in_4_6, sockaddr_in), \
409 __STC_ENABLE_STATIC_CAST(union, necp_sockaddr_union, sockaddr_in))
410
411
412#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_IN(X) \
413 __SA_UTILS_DECONST_CAST (X, sockaddr_in, \
414 __STC_ENABLE_DECONST_CAST(union, sockaddr_in_4_6, sockaddr_in), \
415 __STC_ENABLE_DECONST_CAST(union, necp_sockaddr_union, sockaddr_in))
416
417#if defined(SIN)
418#undef SIN
419#endif /* defined(SIN) */
420#define SIN(s) __SA_UTILS_CONV_TO_SOCKADDR_IN((s))
421#define __DECONST_SIN(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_IN((s))
422
423#if defined(satosin)
424#undef satosin
425#endif /* defined(satosin) */
426#define satosin(sa) SIN(sa)
427
428#if defined(sintosa)
429#undef sintosa
430#endif /* defined(sintosa) */
431#define sintosa(sin) SA(sin)
432
433
434/*************************************************************************************************
435 * Strict replacement for `struct sockaddr_inarp *'
436 */
437__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_inarp)
438
439#define __SA_UTILS_CONV_TO_SOCKADDR_INARP(X) \
440 __SA_UTILS_STATIC_CAST(X, sockaddr_inarp)
441
442#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_INARP(X) \
443 __SA_UTILS_DECONST_CAST(X, sockaddr_inarp)
444
445#define SINARP(s) __SA_UTILS_CONV_TO_SOCKADDR_INARP((s))
446#define __DECONST_SINARP(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_INARP((s))
447
448
449/*************************************************************************************************
450 * Strict replacement for `struct sockaddr_inifscope *'
451 */
452__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_inifscope, \
453 union, sockaddr_in_4_6, \
454 union, necp_sockaddr_union)
455
456#define __SA_UTILS_CONV_TO_SOCKADDR_INIFSCOPE(X) \
457 __SA_UTILS_STATIC_CAST(X, sockaddr_inifscope, \
458 __STC_ENABLE_STATIC_CAST(union, sockaddr_in_4_6, sockaddr_inifscope), \
459 __STC_ENABLE_STATIC_CAST(union, necp_sockaddr_union, sockaddr_inifscope))
460
461#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_INIFSCOPE(X) \
462 __SA_UTILS_DECONST_CAST(X, sockaddr_inifscope, \
463 __STC_ENABLE_DECONST_CAST(union, sockaddr_in_4_6, sockaddr_inifscope), \
464 __STC_ENABLE_DECONST_CAST(union, necp_sockaddr_union, sockaddr_inifscope))
465
466#if defined(SINIFSCOPE)
467#undef SINIFSCOPE
468#endif /* defined(SINIFSCOPE) */
469#define SINIFSCOPE(s) __SA_UTILS_CONV_TO_SOCKADDR_INIFSCOPE((s))
470#define __DECONST_SINIFSCOPE(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_INIFSCOPE((s))
471
472
473/*************************************************************************************************
474 * Strict replacement for `struct sockaddr_in6 *'
475 */
476__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_in6, \
477 union, sockaddr_in_4_6, \
478 union, necp_sockaddr_union)
479
480#define __SA_UTILS_CONV_TO_SOCKADDR_IN6(X) \
481 __SA_UTILS_STATIC_CAST(X, sockaddr_in6, \
482 __STC_ENABLE_STATIC_CAST(union, sockaddr_in_4_6, sockaddr_in6), \
483 __STC_ENABLE_STATIC_CAST(union, necp_sockaddr_union, sockaddr_in6))
484
485#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_IN6(X) \
486 __SA_UTILS_DECONST_CAST(X, sockaddr_in6, \
487 __STC_ENABLE_DECONST_CAST(union, sockaddr_in_4_6, sockaddr_in6), \
488 __STC_ENABLE_DECONST_CAST(union, necp_sockaddr_union, sockaddr_in6))
489
490#if defined(SIN6)
491#undef SIN6
492#endif /* defined(SIN6) */
493#define SIN6(s) __SA_UTILS_CONV_TO_SOCKADDR_IN6((s))
494#define __DECONST_SIN6(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_IN6((s))
495
496#if defined(satosin6)
497#undef satosin6
498#endif /* defined(satosin6) */
499#define satosin6(sa) SIN6(sa)
500
501#if defined(sin6tosa)
502#undef sin6tosa
503#endif /* defined(sin6tosa) */
504#define sin6tosa(sin6) SA((sin6))
505
506#if defined(SIN6IFSCOPE)
507#undef SIN6IFSCOPE
508#endif /* defined(SIN6IFSCOPE) */
509#define SIN6IFSCOPE(s) SIN6(s)
510
511
512/*************************************************************************************************
513 * Strict replacement for `struct sockaddr_ndrv *'
514 */
515__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_ndrv)
516
517#define __SA_UTILS_CONV_TO_SOCKADDR_NDRV(X) \
518 __SA_UTILS_STATIC_CAST(X, sockaddr_ndrv)
519
520#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_NDRV(X) \
521 __SA_UTILS_DECONST_CAST(X, sockaddr_ndrv)
522
523#define SNDRV(s) __SA_UTILS_CONV_TO_SOCKADDR_NDRV((s))
524#define __DECONST_SNDRV(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_NDRV((s))
525
526
527/*************************************************************************************************
528 * Strict replacement for `struct sockaddr_sys *'
529 */
530__SA_UTILS_DEFINE_FIXED_SIZE_SUBTYPE(struct, sockaddr_sys)
531
532#define __SA_UTILS_CONV_TO_SOCKADDR_SYS(X) \
533 __SA_UTILS_STATIC_CAST(X, sockaddr_sys)
534
535#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_SYS(X) \
536 __SA_UTILS_DECONST_CAST(X, sockaddr_sys)
537
538#define SSYS(s) __SA_UTILS_CONV_TO_SOCKADDR_SYS((s))
539#define __DECONST_SSYS(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_SYS((s))
540
541
542/*************************************************************************************************
543 * Strict replacement for `struct sockaddr_un *'
544 */
545__SA_UTILS_DEFINE_VARIABLE_SIZE_SUBTYPE(struct, sockaddr_un)
546
547#define __SA_UTILS_CONV_TO_SOCKADDR_UN(X) \
548 __SA_UTILS_STATIC_CAST(X, sockaddr_un)
549
550#define __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_UN(X) \
551 __SA_UTILS_DECONST_CAST(X, sockaddr_un)
552
553#define SUN(s) __SA_UTILS_CONV_TO_SOCKADDR_UN((s))
554#define __DECONST_SUN(s) __SA_UTILS_DECONST_AND_CONV_TO_SOCKADDR_UN((s))
555
556
557#endif /* XNU_KERNEL_PRIVATE */
558
559#endif /* _NET_SOCKADDR_UTILS_H_ */
560