xref: /xnu-12377.41.6/bsd/net/radix.h (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 /*
2  * Copyright (c) 2000-2024 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 /*
29  * Copyright (c) 1988, 1989, 1993
30  *	The Regents of the University of California.  All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  * 2. Redistributions in binary form must reproduce the above copyright
38  *    notice, this list of conditions and the following disclaimer in the
39  *    documentation and/or other materials provided with the distribution.
40  * 3. All advertising materials mentioning features or use of this software
41  *    must display the following acknowledgement:
42  *	This product includes software developed by the University of
43  *	California, Berkeley and its contributors.
44  * 4. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  *	@(#)radix.h	8.2 (Berkeley) 10/31/94
61  * $FreeBSD: src/sys/net/radix.h,v 1.16.2.1 2000/05/03 19:17:11 wollman Exp $
62  */
63 
64 #ifndef _RADIX_H_
65 #define _RADIX_H_
66 
67 #include <sys/appleapiopts.h>
68 #include <sys/cdefs.h>
69 #include <sys/socket.h>
70 #include <stdint.h>
71 
72 #if KERNEL_PRIVATE
73 #include <kern/kalloc.h>
74 #endif /* KERNEL_PRIVATE */
75 
76 #ifdef PRIVATE
77 
78 #ifdef MALLOC_DECLARE
79 MALLOC_DECLARE(M_RTABLE);
80 #endif
81 
82 
83 #define __RN_INLINE_LENGTHS (__BIGGEST_ALIGNMENT__ > 4)
84 
85 #if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
86 /*
87  * For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
88  * are 32-bit:
89  * Aligned to 64-bit since this is cast to rtentry, which is 64-bit aligned.
90  */
91 #define __RN_NODE_ALIGNMENT_ATTR__ __attribute__((aligned(8)))
92 #else /* __arm__ && (__BIGGEST_ALIGNMENT__ > 4) */
93 #define __RN_NODE_ALIGNMENT_ATTR__
94 #endif /* __arm__ && (__BIGGEST_ALIGNMENT__ > 4) */
95 
96 /*
97  * Radix search tree node layout.
98  */
99 
100 struct radix_node {
101 	struct  radix_mask *rn_mklist;  /* list of masks contained in subtree */
102 	struct  radix_node *rn_parent;  /* parent */
103 	short   rn_bit;                 /* bit offset; -1-index(netmask) */
104 	char    rn_bmask;               /* node: mask for bit test*/
105 	u_char  rn_flags;               /* enumerated next */
106 #define RNF_NORMAL      1               /* leaf contains normal route */
107 #define RNF_ROOT        2               /* leaf is root leaf for tree */
108 #define RNF_ACTIVE      4               /* This node is alive (for rtfree) */
109 #if __RN_INLINE_LENGTHS
110 	u_char  __rn_keylen;
111 	u_char  __rn_masklen;
112 	short   pad2;
113 #endif /* __RN_INLINE_LENGTHS */
114 	union {
115 		struct {                        /* leaf only data: */
116 			caddr_t rn_Key;         /* object of search */
117 			caddr_t rn_Mask;        /* netmask, if present */
118 			struct  radix_node *rn_Dupedkey;
119 		} rn_leaf;
120 		struct {                        /* node only data: */
121 			int     rn_Off;         /* where to start compare */
122 			struct  radix_node *rn_L;/* progeny */
123 			struct  radix_node *rn_R;/* progeny */
124 		} rn_node;
125 	}               rn_u;
126 #ifdef RN_DEBUG
127 	int rn_info;
128 	struct radix_node *rn_twin;
129 	struct radix_node *rn_ybro;
130 #endif
131 } __RN_NODE_ALIGNMENT_ATTR__;
132 
133 #define rn_dupedkey     rn_u.rn_leaf.rn_Dupedkey
134 #define rn_offset       rn_u.rn_node.rn_Off
135 #define rn_left         rn_u.rn_node.rn_L
136 #define rn_right        rn_u.rn_node.rn_R
137 
138 /*
139  * The `__rn_key' and `__rn_mask' fields are considered
140  * private in the BSD codebase, and should not be accessed directly.
141  * Outside of the BSD codebase these fields are exposed for the
142  * backwards compatibility.
143  */
144 #define __rn_key          rn_u.rn_leaf.rn_Key
145 #define __rn_mask         rn_u.rn_leaf.rn_Mask
146 
147 #if !defined(BSD_KERNEL_PRIVATE)
148 #define rn_key __rn_key
149 #define rn_mask __rn_mask
150 #endif /* !defined(BSD_KERNEL_PRIVATE) */
151 
152 typedef struct radix_node * __single radix_node_ref_t;
153 
154 #define rn_is_leaf(r) ((r)->rn_bit < 0)
155 
156 
157 /*
158  * Sets the routing key bytes and length.
159  */
160 static inline void
161 __attribute__((always_inline))
162 __attribute__((overloadable))
rn_set_key(struct radix_node * rn,void * key __sized_by (keylen),uint8_t keylen)163 rn_set_key(struct radix_node *rn, void *key __sized_by(keylen), uint8_t keylen)
164 {
165 #if __RN_INLINE_LENGTHS
166 	rn->__rn_keylen = keylen;
167 #else /* !__RN_INLINE_LENGTHS */
168 	(void)keylen;
169 #endif /* !__RN_INLINE_LENGTHS */
170 	rn->__rn_key = key;
171 }
172 
173 static inline void
174 __attribute__((always_inline))
175 __attribute__((overloadable))
rn_set_key(struct radix_node * rn,const void * key __sized_by (keylen),uint8_t keylen)176 rn_set_key(struct radix_node *rn, const void *key __sized_by(keylen), uint8_t keylen)
177 {
178 #if __RN_INLINE_LENGTHS
179 	rn->__rn_keylen = keylen;
180 #else /* !__RN_INLINE_LENGTHS */
181 	(void)keylen;
182 #endif /* !__RN_INLINE_LENGTHS */
183 	rn->__rn_key = __DECONST(void *, key);
184 }
185 
186 /*
187  * Returns the routing key length.
188  */
189 static inline uint8_t
190 __attribute__((always_inline)) __stateful_pure
rn_get_keylen(struct radix_node * rn)191 rn_get_keylen(struct radix_node *rn)
192 {
193 #if __RN_INLINE_LENGTHS
194 	return rn->__rn_keylen;
195 #else /* !__RN_INLINE_LENGTHS */
196 	if (rn->__rn_key != NULL) {
197 		return *((uint8_t *)rn->__rn_key);
198 	} else {
199 		return 0;
200 	}
201 #endif /* !__RN_INLINE_LENGTHS */
202 }
203 
204 /*
205  * Returns the pointer to the routing key associated with
206  * the radix tree node.
207  * If the `-fbounds-safety' feature is both available and enabled,
208  * the returned value is sized by the corresponding key len.
209  * Otherwise, the returned value is a plain C pointer.
210  */
211 static inline char * __header_indexable
212 __attribute__((always_inline)) __stateful_pure
213 __attribute__((overloadable))
rn_get_key(struct radix_node * rn)214 rn_get_key(struct radix_node *rn)
215 {
216 	return __unsafe_forge_bidi_indexable(char *, rn->rn_u.rn_leaf.rn_Key,
217 	           rn_get_keylen(rn));
218 }
219 
220 static inline char * __header_indexable
221 __attribute__((always_inline)) __stateful_pure
222 __attribute__((overloadable))
rn_get_key(struct radix_node * rn,uint8_t * plen)223 rn_get_key(struct radix_node *rn, uint8_t *plen)
224 {
225 	uint8_t keylen = rn_get_keylen(rn);
226 	caddr_t key = __unsafe_forge_bidi_indexable(char *, rn->rn_u.rn_leaf.rn_Key, keylen);
227 	*plen = keylen;
228 	return key;
229 }
230 
231 /*
232  * Sets the routing mask bytes and length.
233  */
234 static inline void
235 __attribute__((always_inline))
rn_set_mask(struct radix_node * rn,void * mask __sized_by (masklen),uint8_t masklen)236 rn_set_mask(struct radix_node *rn, void *mask __sized_by(masklen), uint8_t masklen)
237 {
238 #if __RN_INLINE_LENGTHS
239 	/*
240 	 * The first byte is the length of the addressable bytes,
241 	 * whereas the second is the address family.
242 	 *
243 	 * To avoid memory traps, we are taking into the consideration
244 	 * both the addressable length and the address family.
245 	 */
246 	uint8_t sa_len = *((uint8_t*)mask);
247 	uint8_t sa_family = *(((uint8_t*)mask) + 1);
248 	uint8_t allocation_size =
249 	    (sa_family == AF_INET)    ? 16     /* sizeof(struct sockaddr_in) */
250 	    : (sa_family == AF_INET6) ? 28     /* sizeof(struct sockaddr_in6) */
251 	    : masklen;
252 	/* Set the allocation size to be the max(sa_len, masklen, allocation_size) */
253 	allocation_size = allocation_size < sa_len ? sa_len : allocation_size;
254 	allocation_size = allocation_size < masklen ? masklen : allocation_size;
255 	rn->__rn_masklen = allocation_size;
256 #else /* !__RN_INLINE_LENGTHS */
257 	(void)masklen;
258 #endif /* !__RN_INLINE_LENGTHS */
259 	rn->__rn_mask = mask;
260 }
261 
262 /*
263  * Returns the routing mask length.
264  */
265 static inline uint8_t
266 __attribute__((always_inline)) __stateful_pure
rn_get_masklen(struct radix_node * rn)267 rn_get_masklen(struct radix_node *rn)
268 {
269 #if __RN_INLINE_LENGTHS
270 	return rn->__rn_masklen;
271 #else /* !__RN_INLINE_LENGTHS */
272 	if (rn->__rn_mask != NULL) {
273 		return *((uint8_t *)rn->__rn_mask);
274 	} else {
275 		return 0;
276 	}
277 #endif /* !__RN_INLINE_LENGTHS */
278 }
279 
280 /*
281  * Returns the pointer to the routing mask associated with
282  * the radix tree node.
283  * If the `-fbounds-safety' feature is both available and enabled,
284  * the returned value is sized by the corresponding mask len.
285  * Otherwise, the returned value is a plain C pointer.
286  */
287 static inline char * __header_indexable
288 __attribute__((always_inline)) __stateful_pure
rn_get_mask(struct radix_node * rn)289 rn_get_mask(struct radix_node *rn)
290 {
291 	return __unsafe_forge_bidi_indexable(char *, rn->rn_u.rn_leaf.rn_Mask,
292 	           rn_get_masklen(rn));
293 }
294 
295 /*
296  * Annotations to tree concerning potential routes applying to subtrees.
297  */
298 struct radix_mask {
299 	short   rm_bit;                 /* bit offset; -1-index(netmask) */
300 	char    rm_unused;              /* cf. rn_bmask */
301 	u_char  rm_flags;               /* cf. rn_flags */
302 #if __RN_INLINE_LENGTHS
303 	u_char  __rm_masklen;
304 	u_char  pad[3];
305 #endif /* __RN_INNLINE_LENGTHS */
306 	struct  radix_mask *rm_mklist;  /* more masks to try */
307 	union   {
308 		caddr_t __rm_mask;              /* the mask, see note below. */
309 		struct  radix_node *rm_leaf;    /* for normal routes */
310 	};
311 	int     rm_refs;                /* # of references to this struct */
312 };
313 
314 typedef struct radix_mask * __single radix_mask_ref_t;
315 
316 /*
317  * The `__rm_mask' field is considered private in the BSD
318  * codebase, and should not be accessed directly.
319  * Outside of the BSD codebase it is exposed for the
320  * backwards compatibility.
321  */
322 #if !defined(BSD_KERNEL_PRIVATE)
323 #define rm_mask __rm_mask
324 #endif /* !defined(BSD_KERNEL_PRIVATE) */
325 
326 static inline void
rm_set_mask(struct radix_mask * rm,void * mask __sized_by (masklen),uint8_t masklen)327 rm_set_mask(struct radix_mask *rm, void *mask __sized_by(masklen), uint8_t masklen)
328 {
329 #if __RN_INLINE_LENGTHS
330 	rm->__rm_masklen = masklen;
331 #else /* !__RN_INLINE_LENGTHS */
332 	(void)masklen;
333 #endif /* !__RN_INLINE_LENGTHS */
334 	rm->__rm_mask = mask;
335 }
336 
337 
338 /*
339  * Returns the routing mask length.
340  */
341 static inline uint8_t
342 __attribute__((always_inline)) __stateful_pure
rm_get_masklen(struct radix_mask * rm)343 rm_get_masklen(struct radix_mask *rm)
344 {
345 #if __RN_INLINE_LENGTHS
346 	return rm->__rm_masklen;
347 #else /* !__RN_INLINE_LENGTHS */
348 	if (rn->__rn_mask != NULL) {
349 		return *((uint8_t *)rm->__rm_mask);
350 	} else {
351 		return 0;
352 	}
353 #endif /* !__RN_INLINE_LENGTHS */
354 }
355 
356 /*
357  * Returns the pointer to the routing mask associated with
358  * the radix tree mask node.
359  * If the `-fbounds-safety' feature is both available and enabled,
360  * the returned value is sized by the corresponding mask len.
361  * Otherwise, the returned value is a plain C pointer.
362  */
363 static inline char * __header_indexable
364 __attribute__((always_inline)) __stateful_pure
rm_get_mask(struct radix_mask * rm)365 rm_get_mask(struct radix_mask *rm)
366 {
367 	return __unsafe_forge_bidi_indexable(char *, rm->__rm_mask,
368 	           rm_get_masklen(rm));
369 }
370 
371 #define MKGet(m) {\
372 	if (rn_mkfreelist) {\
373 	        m = rn_mkfreelist; \
374 	        rn_mkfreelist = (m)->rm_mklist; \
375 	} else { \
376 	        m = kalloc_type(struct radix_mask, Z_WAITOK_ZERO_NOFAIL); \
377 	} \
378 }
379 
380 #define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
381 
382 typedef int walktree_f_t(struct radix_node *, void *);
383 typedef int rn_matchf_t(struct radix_node *, void *);
384 
385 #if KERNEL_PRIVATE
386 KALLOC_TYPE_DECLARE(radix_node_head_zone);
387 #endif
388 
389 struct radix_node_head {
390 	struct  radix_node *rnh_treetop;
391 	int     rnh_addrsize;           /* permit, but not require fixed keys */
392 	int     rnh_pktsize;            /* permit, but not require fixed keys */
393 	struct  radix_node *(*rnh_addaddr)      /* add based on sockaddr */
394 	(void *v, void *mask,
395 	    struct radix_node_head *head, struct radix_node nodes[]);
396 	struct  radix_node *(*rnh_addpkt)       /* add based on packet hdr */
397 	(void *v, void *mask,
398 	    struct radix_node_head *head, struct radix_node nodes[]);
399 	struct  radix_node *(*rnh_deladdr)      /* remove based on sockaddr */
400 	(void *v, void *mask, struct radix_node_head *head);
401 	struct  radix_node *(*rnh_delpkt)       /* remove based on packet hdr */
402 	(void *v, void *mask, struct radix_node_head *head);
403 	struct  radix_node *(*rnh_matchaddr)    /* locate based on sockaddr */
404 	(void *v, struct radix_node_head *head);
405 	/* locate based on sockaddr and rn_matchf_t() */
406 	struct  radix_node *(*rnh_matchaddr_args)
407 	(void *v, struct radix_node_head *head,
408 	    rn_matchf_t *f, void *w);
409 	struct  radix_node *(*rnh_lookup)       /* locate based on sockaddr */
410 	(void *v, void *mask, struct radix_node_head *head);
411 	/* locate based on sockaddr, mask and rn_matchf_t() */
412 	struct  radix_node *(*rnh_lookup_args)
413 	(void *v, void *mask, struct radix_node_head *head,
414 	    rn_matchf_t *f, void *);
415 	struct  radix_node *(*rnh_matchpkt)     /* locate based on packet hdr */
416 	(void *v, struct radix_node_head *head);
417 	int     (*rnh_walktree)                 /* traverse tree */
418 	(struct radix_node_head *head, walktree_f_t *f, void *w);
419 	int     (*rnh_walktree_from)            /* traverse tree below a */
420 	(struct radix_node_head *head, void *a, void *m,
421 	walktree_f_t *f, void *w);
422 	void    (*rnh_close)    /* do something when the last ref drops */
423 	(struct radix_node *rn, struct radix_node_head *head);
424 	struct  radix_node rnh_nodes[3];        /* empty tree for common case */
425 	int     rnh_cnt;                        /* tree dimension */
426 };
427 
428 typedef struct radix_node_head * __single radix_node_head_ref_t;
429 
430 #ifndef KERNEL
431 #define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
432 #define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
433 #define Bzero(p, n) bzero((char *)(p), (int)(n));
434 #else
435 #define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
436 #define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
437 #define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
438 #endif /*KERNEL*/
439 
440 void     rn_init(void);
441 int      rn_inithead(void **, int);
442 int      rn_refines(void *, void *);
443 struct radix_node *rn_addmask(void *, int, int);
444 struct radix_node *rn_addroute(void *, void *, struct radix_node_head *,
445     struct radix_node [2]);
446 struct radix_node *rn_delete(void *, void *, struct radix_node_head *);
447 struct radix_node *rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head);
448 struct radix_node *rn_lookup_args(void *v_arg, void *m_arg, struct radix_node_head *head,
449     rn_matchf_t *, void *);
450 struct radix_node *rn_match(void *, struct radix_node_head *);
451 struct radix_node *rn_match_args(void *, struct radix_node_head *, rn_matchf_t *, void *);
452 
453 #endif /* PRIVATE */
454 #endif /* _RADIX_H_ */
455