xref: /xnu-11215.41.3/bsd/net/radix.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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 /*
86  * Radix search tree node layout.
87  */
88 
89 struct radix_node {
90 	struct  radix_mask *rn_mklist;  /* list of masks contained in subtree */
91 	struct  radix_node *rn_parent;  /* parent */
92 	short   rn_bit;                 /* bit offset; -1-index(netmask) */
93 	char    rn_bmask;               /* node: mask for bit test*/
94 	u_char  rn_flags;               /* enumerated next */
95 #define RNF_NORMAL      1               /* leaf contains normal route */
96 #define RNF_ROOT        2               /* leaf is root leaf for tree */
97 #define RNF_ACTIVE      4               /* This node is alive (for rtfree) */
98 #if __RN_INLINE_LENGTHS
99 	u_char  __rn_keylen;
100 	u_char  __rn_masklen;
101 	short   pad2;
102 #endif /* __RN_INLINE_LENGTHS */
103 	union {
104 		struct {                        /* leaf only data: */
105 			caddr_t rn_Key;         /* object of search */
106 			caddr_t rn_Mask;        /* netmask, if present */
107 			struct  radix_node *rn_Dupedkey;
108 		} rn_leaf;
109 		struct {                        /* node only data: */
110 			int     rn_Off;         /* where to start compare */
111 			struct  radix_node *rn_L;/* progeny */
112 			struct  radix_node *rn_R;/* progeny */
113 		} rn_node;
114 	}               rn_u;
115 #ifdef RN_DEBUG
116 	int rn_info;
117 	struct radix_node *rn_twin;
118 	struct radix_node *rn_ybro;
119 #endif
120 
121 #if __arm__ && (__BIGGEST_ALIGNMENT__ > 4)
122 /* For the newer ARMv7k ABI where 64-bit types are 64-bit aligned, but pointers
123  * are 32-bit:
124  * Aligned to 64-bit since this is cast to rtentry, which is 64-bit aligned.
125  */
126 } __attribute__ ((aligned(8)));
127 #else
128 };
129 #endif
130 
131 #define rn_dupedkey     rn_u.rn_leaf.rn_Dupedkey
132 #define rn_offset       rn_u.rn_node.rn_Off
133 #define rn_left         rn_u.rn_node.rn_L
134 #define rn_right        rn_u.rn_node.rn_R
135 
136 /*
137  * The `__rn_key' and `__rn_mask' fields are considered
138  * private in the BSD codebase, and should not be accessed directly.
139  * Outside of the BSD codebase these fields are exposed for the
140  * backwards compatibility.
141  */
142 #define __rn_key          rn_u.rn_leaf.rn_Key
143 #define __rn_mask         rn_u.rn_leaf.rn_Mask
144 
145 #if !defined(BSD_KERNEL_PRIVATE)
146 #define rn_key __rn_key
147 #define rn_mask __rn_mask
148 #endif /* !defined(BSD_KERNEL_PRIVATE) */
149 
150 typedef struct radix_node * __single radix_node_ref_t;
151 
152 #define rn_is_leaf(r) ((r)->rn_bit < 0)
153 
154 
155 /*
156  * Sets the routing key bytes and length.
157  */
158 static inline void
159 __attribute__((always_inline))
rn_set_key(struct radix_node * rn,void * key __sized_by (keylen),uint8_t keylen)160 rn_set_key(struct radix_node *rn, void *key __sized_by(keylen), uint8_t keylen)
161 {
162 #if __RN_INLINE_LENGTHS
163 	rn->__rn_keylen = keylen;
164 #else /* !__RN_INLINE_LENGTHS */
165 	(void)keylen;
166 #endif /* !__RN_INLINE_LENGTHS */
167 	rn->__rn_key = key;
168 }
169 
170 /*
171  * Returns the routing key length.
172  */
173 static inline uint8_t
174 __attribute__((always_inline)) __stateful_pure
rn_get_keylen(struct radix_node * rn)175 rn_get_keylen(struct radix_node *rn)
176 {
177 #if __RN_INLINE_LENGTHS
178 	return rn->__rn_keylen;
179 #else /* !__RN_INLINE_LENGTHS */
180 	if (rn->__rn_key != NULL) {
181 		return *((uint8_t *)rn->__rn_key);
182 	} else {
183 		return 0;
184 	}
185 #endif /* !__RN_INLINE_LENGTHS */
186 }
187 
188 /*
189  * Returns the pointer to the routing key associated with
190  * the radix tree node.
191  * If the `-fbounds-safety' feature is both available and enabled,
192  * the returned value is sized by the corresponding key len.
193  * Otherwise, the returned value is a plain C pointer.
194  */
195 static inline char * __header_indexable
196 __attribute__((always_inline)) __stateful_pure
rn_get_key(struct radix_node * rn)197 rn_get_key(struct radix_node *rn)
198 {
199 	return __unsafe_forge_bidi_indexable(char *, rn->rn_u.rn_leaf.rn_Key,
200 	           rn_get_keylen(rn));
201 }
202 
203 /*
204  * Sets the routing mask bytes and length.
205  */
206 static inline void
207 __attribute__((always_inline))
rn_set_mask(struct radix_node * rn,void * mask __sized_by (masklen),uint8_t masklen)208 rn_set_mask(struct radix_node *rn, void *mask __sized_by(masklen), uint8_t masklen)
209 {
210 #if __RN_INLINE_LENGTHS
211 	/*
212 	 * Unlike the keys, the masks are always sockaddrs.
213 	 * The first byte is the length of the addressable bytes,
214 	 * whereas the second is the address family.
215 	 *
216 	 * To avoid memory traps, we are taking into the consideration
217 	 * both the addressable length and the address family.
218 	 */
219 	uint8_t sa_len = *((uint8_t*)mask);
220 	uint8_t sa_family = *(((uint8_t*)mask) + 1);
221 	uint8_t allocation_size =
222 	    (sa_family == AF_INET)    ? 16     /* sizeof(struct sockaddr_in) */
223 	    : (sa_family == AF_INET6) ? 28     /* sizeof(struct sockaddr_in6) */
224 	    : masklen;
225 	/* Set the allocation size to be the max(sa_len, masklen, allocation_size) */
226 	allocation_size = allocation_size < sa_len ? sa_len : allocation_size;
227 	allocation_size = allocation_size < masklen ? masklen : allocation_size;
228 	rn->__rn_masklen = allocation_size;
229 #else /* !__RN_INLINE_LENGTHS */
230 	(void)masklen;
231 #endif /* !__RN_INLINE_LENGTHS */
232 	rn->__rn_mask = mask;
233 }
234 
235 /*
236  * Returns the routing mask length.
237  */
238 static inline uint8_t
239 __attribute__((always_inline)) __stateful_pure
rn_get_masklen(struct radix_node * rn)240 rn_get_masklen(struct radix_node *rn)
241 {
242 #if __RN_INLINE_LENGTHS
243 	return rn->__rn_masklen;
244 #else /* !__RN_INLINE_LENGTHS */
245 	if (rn->__rn_mask != NULL) {
246 		return *((uint8_t *)rn->__rn_mask);
247 	} else {
248 		return 0;
249 	}
250 #endif /* !__RN_INLINE_LENGTHS */
251 }
252 
253 /*
254  * Returns the pointer to the routing mask associated with
255  * the radix tree node.
256  * If the `-fbounds-safety' feature is both available and enabled,
257  * the returned value is sized by the corresponding mask len.
258  * Otherwise, the returned value is a plain C pointer.
259  */
260 static inline char * __header_indexable
261 __attribute__((always_inline)) __stateful_pure
rn_get_mask(struct radix_node * rn)262 rn_get_mask(struct radix_node *rn)
263 {
264 	return __unsafe_forge_bidi_indexable(char *, rn->rn_u.rn_leaf.rn_Mask,
265 	           rn_get_masklen(rn));
266 }
267 
268 /*
269  * Annotations to tree concerning potential routes applying to subtrees.
270  */
271 struct radix_mask {
272 	short   rm_bit;                 /* bit offset; -1-index(netmask) */
273 	char    rm_unused;              /* cf. rn_bmask */
274 	u_char  rm_flags;               /* cf. rn_flags */
275 #if __RN_INLINE_LENGTHS
276 	u_char  __rm_masklen;
277 	u_char  pad[3];
278 #endif /* __RN_INNLINE_LENGTHS */
279 	struct  radix_mask *rm_mklist;  /* more masks to try */
280 	union   {
281 		caddr_t __rm_mask;              /* the mask, see note below. */
282 		struct  radix_node *rm_leaf;    /* for normal routes */
283 	};
284 	int     rm_refs;                /* # of references to this struct */
285 };
286 
287 typedef struct radix_mask * __single radix_mask_ref_t;
288 
289 /*
290  * The `__rm_mask' field is considered private in the BSD
291  * codebase, and should not be accessed directly.
292  * Outside of the BSD codebase it is exposed for the
293  * backwards compatibility.
294  */
295 #if !defined(BSD_KERNEL_PRIVATE)
296 #define rm_mask __rm_mask
297 #endif /* !defined(BSD_KERNEL_PRIVATE) */
298 
299 static inline void
rm_set_mask(struct radix_mask * rm,void * mask __sized_by (masklen),uint8_t masklen)300 rm_set_mask(struct radix_mask *rm, void *mask __sized_by(masklen), uint8_t masklen)
301 {
302 #if __RN_INLINE_LENGTHS
303 	rm->__rm_masklen = masklen;
304 #else /* !__RN_INLINE_LENGTHS */
305 	(void)masklen;
306 #endif /* !__RN_INLINE_LENGTHS */
307 	rm->__rm_mask = mask;
308 }
309 
310 
311 /*
312  * Returns the routing mask length.
313  */
314 static inline uint8_t
315 __attribute__((always_inline)) __stateful_pure
rm_get_masklen(struct radix_mask * rm)316 rm_get_masklen(struct radix_mask *rm)
317 {
318 #if __RN_INLINE_LENGTHS
319 	return rm->__rm_masklen;
320 #else /* !__RN_INLINE_LENGTHS */
321 	if (rn->__rn_mask != NULL) {
322 		return *((uint8_t *)rm->__rm_mask);
323 	} else {
324 		return 0;
325 	}
326 #endif /* !__RN_INLINE_LENGTHS */
327 }
328 
329 /*
330  * Returns the pointer to the routing mask associated with
331  * the radix tree mask node.
332  * If the `-fbounds-safety' feature is both available and enabled,
333  * the returned value is sized by the corresponding mask len.
334  * Otherwise, the returned value is a plain C pointer.
335  */
336 static inline char * __header_indexable
337 __attribute__((always_inline)) __stateful_pure
rm_get_mask(struct radix_mask * rm)338 rm_get_mask(struct radix_mask *rm)
339 {
340 	return __unsafe_forge_bidi_indexable(char *, rm->__rm_mask,
341 	           rm_get_masklen(rm));
342 }
343 
344 #define MKGet(m) {\
345 	if (rn_mkfreelist) {\
346 	        m = rn_mkfreelist; \
347 	        rn_mkfreelist = (m)->rm_mklist; \
348 	} else { \
349 	        m = kalloc_type(struct radix_mask, Z_WAITOK_ZERO_NOFAIL); \
350 	} \
351 }
352 
353 #define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
354 
355 typedef int walktree_f_t(struct radix_node *, void *);
356 typedef int rn_matchf_t(struct radix_node *, void *);
357 
358 #if KERNEL_PRIVATE
359 KALLOC_TYPE_DECLARE(radix_node_head_zone);
360 #endif
361 
362 struct radix_node_head {
363 	struct  radix_node *rnh_treetop;
364 	int     rnh_addrsize;           /* permit, but not require fixed keys */
365 	int     rnh_pktsize;            /* permit, but not require fixed keys */
366 	struct  radix_node *(*rnh_addaddr)      /* add based on sockaddr */
367 	(void *v, void *mask,
368 	    struct radix_node_head *head, struct radix_node nodes[]);
369 	struct  radix_node *(*rnh_addpkt)       /* add based on packet hdr */
370 	(void *v, void *mask,
371 	    struct radix_node_head *head, struct radix_node nodes[]);
372 	struct  radix_node *(*rnh_deladdr)      /* remove based on sockaddr */
373 	(void *v, void *mask, struct radix_node_head *head);
374 	struct  radix_node *(*rnh_delpkt)       /* remove based on packet hdr */
375 	(void *v, void *mask, struct radix_node_head *head);
376 	struct  radix_node *(*rnh_matchaddr)    /* locate based on sockaddr */
377 	(void *v, struct radix_node_head *head);
378 	/* locate based on sockaddr and rn_matchf_t() */
379 	struct  radix_node *(*rnh_matchaddr_args)
380 	(void *v, struct radix_node_head *head,
381 	    rn_matchf_t *f, void *w);
382 	struct  radix_node *(*rnh_lookup)       /* locate based on sockaddr */
383 	(void *v, void *mask, struct radix_node_head *head);
384 	/* locate based on sockaddr, mask and rn_matchf_t() */
385 	struct  radix_node *(*rnh_lookup_args)
386 	(void *v, void *mask, struct radix_node_head *head,
387 	    rn_matchf_t *f, void *);
388 	struct  radix_node *(*rnh_matchpkt)     /* locate based on packet hdr */
389 	(void *v, struct radix_node_head *head);
390 	int     (*rnh_walktree)                 /* traverse tree */
391 	(struct radix_node_head *head, walktree_f_t *f, void *w);
392 	int     (*rnh_walktree_from)            /* traverse tree below a */
393 	(struct radix_node_head *head, void *a, void *m,
394 	walktree_f_t *f, void *w);
395 	void    (*rnh_close)    /* do something when the last ref drops */
396 	(struct radix_node *rn, struct radix_node_head *head);
397 	struct  radix_node rnh_nodes[3];        /* empty tree for common case */
398 	int     rnh_cnt;                        /* tree dimension */
399 };
400 
401 typedef struct radix_node_head * __single radix_node_head_ref_t;
402 
403 #ifndef KERNEL
404 #define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
405 #define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
406 #define Bzero(p, n) bzero((char *)(p), (int)(n));
407 #else
408 #define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
409 #define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
410 #define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
411 #endif /*KERNEL*/
412 
413 void     rn_init(void);
414 int      rn_inithead(void **, int);
415 int      rn_refines(void *, void *);
416 struct radix_node *rn_addmask(void *, int, int);
417 struct radix_node *rn_addroute(void *, void *, struct radix_node_head *,
418     struct radix_node [2]);
419 struct radix_node *rn_delete(void *, void *, struct radix_node_head *);
420 struct radix_node *rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head);
421 struct radix_node *rn_lookup_args(void *v_arg, void *m_arg, struct radix_node_head *head,
422     rn_matchf_t *, void *);
423 struct radix_node *rn_match(void *, struct radix_node_head *);
424 struct radix_node *rn_match_args(void *, struct radix_node_head *, rn_matchf_t *, void *);
425 
426 #endif /* PRIVATE */
427 #endif /* _RADIX_H_ */
428