1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021-2022 Alexander V. Chernikov
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 #include "opt_inet.h"
30 #include "opt_inet6.h"
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/malloc.h>
35 #include <sys/socket.h>
36 #include <sys/jail.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/rmlock.h>
40
41 #include <net/if.h>
42 #include <net/if_var.h>
43 #include <net/vnet.h>
44 #include <net/route.h>
45 #include <net/route/route_ctl.h>
46 #include <net/route/route_var.h>
47 #include <net/route/nhop.h>
48 #include <netinet/in.h>
49 #include <netinet6/scope6_var.h>
50
51 #include <vm/uma.h>
52
53 /* Routing table UMA zone */
54 VNET_DEFINE_STATIC(uma_zone_t, rtzone);
55 #define V_rtzone VNET(rtzone)
56
57 void
vnet_rtzone_init(void)58 vnet_rtzone_init(void)
59 {
60
61 V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry),
62 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
63 }
64
65 #ifdef VIMAGE
66 void
vnet_rtzone_destroy(void)67 vnet_rtzone_destroy(void)
68 {
69
70 uma_zdestroy(V_rtzone);
71 }
72 #endif
73
74 /*
75 * Creates rtentry and based on @dst/@netmask data.
76 * Return 0 and fills in rtentry into @prt on success,
77 * Note: rtentry mask ptr will be set to @netmask , thus its pointer is required
78 * to be stable till the end of the operation (radix rt insertion/change/removal).
79 */
80 struct rtentry *
rt_alloc(struct rib_head * rnh,const struct sockaddr * dst,struct sockaddr * netmask)81 rt_alloc(struct rib_head *rnh, const struct sockaddr *dst,
82 struct sockaddr *netmask)
83 {
84 MPASS(dst->sa_len <= sizeof(((struct rtentry *)NULL)->rt_dstb));
85
86 struct rtentry *rt = uma_zalloc(V_rtzone, M_NOWAIT | M_ZERO);
87 if (rt == NULL)
88 return (NULL);
89 rt->rte_flags = RTF_UP | (netmask == NULL ? RTF_HOST : 0);
90
91 /* Fill in dst, ensuring it's masked if needed. */
92 if (netmask != NULL) {
93 rt_maskedcopy(dst, &rt->rt_dst, netmask);
94 } else
95 bcopy(dst, &rt->rt_dst, dst->sa_len);
96 rt_key(rt) = &rt->rt_dst;
97 /* Set netmask to the storage from info. It will be updated upon insertion */
98 rt_mask(rt) = netmask;
99
100 return (rt);
101 }
102
103 static void
destroy_rtentry(struct rtentry * rt)104 destroy_rtentry(struct rtentry *rt)
105 {
106 #ifdef VIMAGE
107 const struct weightened_nhop *wn;
108 struct nhop_object *nh = rt->rt_nhop;
109 uint32_t num_nhops;
110
111 /*
112 * At this moment rnh, nh_control may be already freed.
113 * nhop interface may have been migrated to a different vnet.
114 * Use vnet stored in the nexthop to delete the entry.
115 */
116 if (NH_IS_NHGRP(nh)) {
117 wn = nhgrp_get_nhops((struct nhgrp_object *)nh, &num_nhops);
118 nh = wn[0].nh;
119 }
120 CURVNET_SET(nhop_get_vnet(nh));
121 #endif
122
123 /* Unreference nexthop */
124 nhop_free_any(rt->rt_nhop);
125
126 rt_free_immediate(rt);
127
128 CURVNET_RESTORE();
129 }
130
131 /*
132 * Epoch callback indicating rtentry is safe to destroy
133 */
134 static void
destroy_rtentry_epoch(epoch_context_t ctx)135 destroy_rtentry_epoch(epoch_context_t ctx)
136 {
137 struct rtentry *rt;
138
139 rt = __containerof(ctx, struct rtentry, rt_epoch_ctx);
140
141 destroy_rtentry(rt);
142 }
143
144 /*
145 * Schedule rtentry deletion
146 */
147 void
rt_free(struct rtentry * rt)148 rt_free(struct rtentry *rt)
149 {
150
151 KASSERT(rt != NULL, ("%s: NULL rt", __func__));
152
153 NET_EPOCH_CALL(destroy_rtentry_epoch, &rt->rt_epoch_ctx);
154 }
155
156 void
rt_free_immediate(struct rtentry * rt)157 rt_free_immediate(struct rtentry *rt)
158 {
159 uma_zfree(V_rtzone, rt);
160 }
161
162 bool
rt_is_host(const struct rtentry * rt)163 rt_is_host(const struct rtentry *rt)
164 {
165
166 return (rt->rte_flags & RTF_HOST);
167 }
168
169 sa_family_t
rt_get_family(const struct rtentry * rt)170 rt_get_family(const struct rtentry *rt)
171 {
172 const struct sockaddr *dst;
173
174 dst = (const struct sockaddr *)rt_key_const(rt);
175
176 return (dst->sa_family);
177 }
178
179 /*
180 * Returns pointer to nexthop or nexthop group
181 * associated with @rt
182 */
183 struct nhop_object *
rt_get_raw_nhop(const struct rtentry * rt)184 rt_get_raw_nhop(const struct rtentry *rt)
185 {
186
187 return (rt->rt_nhop);
188 }
189
190 void
rt_get_rnd(const struct rtentry * rt,struct route_nhop_data * rnd)191 rt_get_rnd(const struct rtentry *rt, struct route_nhop_data *rnd)
192 {
193 rnd->rnd_nhop = rt->rt_nhop;
194 rnd->rnd_weight = rt->rt_weight;
195 }
196
197 /*
198 * If the process in in jail w/o VNET, export only host routes for the
199 * addresses assigned to the jail.
200 * Otherwise, allow exporting the entire table.
201 */
202 bool
rt_is_exportable(const struct rtentry * rt,struct ucred * cred)203 rt_is_exportable(const struct rtentry *rt, struct ucred *cred)
204 {
205 if (!rt_is_host(rt)) {
206 /*
207 * Performance optimisation: only host routes are allowed
208 * in the jail w/o vnet.
209 */
210 if (jailed_without_vnet(cred))
211 return (false);
212 } else {
213 if (prison_if(cred, rt_key_const(rt)) != 0)
214 return (false);
215 }
216
217 return (true);
218 }
219
220 #ifdef INET
221 /*
222 * Stores IPv4 address and prefix length of @rt inside
223 * @paddr and @plen.
224 * @pscopeid is currently always set to 0.
225 */
226 void
rt_get_inet_prefix_plen(const struct rtentry * rt,struct in_addr * paddr,int * plen,uint32_t * pscopeid)227 rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr,
228 int *plen, uint32_t *pscopeid)
229 {
230 const struct sockaddr_in *dst;
231
232 dst = (const struct sockaddr_in *)rt_key_const(rt);
233 KASSERT((dst->sin_family == AF_INET),
234 ("rt family is %d, not inet", dst->sin_family));
235 *paddr = dst->sin_addr;
236 dst = (const struct sockaddr_in *)rt_mask_const(rt);
237 if (dst == NULL)
238 *plen = 32;
239 else
240 *plen = bitcount32(dst->sin_addr.s_addr);
241 *pscopeid = 0;
242 }
243
244 /*
245 * Stores IPv4 address and prefix mask of @rt inside
246 * @paddr and @pmask. Sets mask to INADDR_ANY for host routes.
247 * @pscopeid is currently always set to 0.
248 */
249 void
rt_get_inet_prefix_pmask(const struct rtentry * rt,struct in_addr * paddr,struct in_addr * pmask,uint32_t * pscopeid)250 rt_get_inet_prefix_pmask(const struct rtentry *rt, struct in_addr *paddr,
251 struct in_addr *pmask, uint32_t *pscopeid)
252 {
253 const struct sockaddr_in *dst;
254
255 dst = (const struct sockaddr_in *)rt_key_const(rt);
256 KASSERT((dst->sin_family == AF_INET),
257 ("rt family is %d, not inet", dst->sin_family));
258 *paddr = dst->sin_addr;
259 dst = (const struct sockaddr_in *)rt_mask_const(rt);
260 if (dst == NULL)
261 pmask->s_addr = INADDR_BROADCAST;
262 else
263 *pmask = dst->sin_addr;
264 *pscopeid = 0;
265 }
266 #endif
267
268 #ifdef INET6
269 static int
inet6_get_plen(const struct in6_addr * addr)270 inet6_get_plen(const struct in6_addr *addr)
271 {
272
273 return (bitcount32(addr->s6_addr32[0]) + bitcount32(addr->s6_addr32[1]) +
274 bitcount32(addr->s6_addr32[2]) + bitcount32(addr->s6_addr32[3]));
275 }
276
277 /*
278 * Stores IPv6 address and prefix length of @rt inside
279 * @paddr and @plen. Addresses are returned in de-embedded form.
280 * Scopeid is set to 0 for non-LL addresses.
281 */
282 void
rt_get_inet6_prefix_plen(const struct rtentry * rt,struct in6_addr * paddr,int * plen,uint32_t * pscopeid)283 rt_get_inet6_prefix_plen(const struct rtentry *rt, struct in6_addr *paddr,
284 int *plen, uint32_t *pscopeid)
285 {
286 const struct sockaddr_in6 *dst;
287
288 dst = (const struct sockaddr_in6 *)rt_key_const(rt);
289 KASSERT((dst->sin6_family == AF_INET6),
290 ("rt family is %d, not inet6", dst->sin6_family));
291 if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
292 in6_splitscope(&dst->sin6_addr, paddr, pscopeid);
293 else
294 *paddr = dst->sin6_addr;
295 dst = (const struct sockaddr_in6 *)rt_mask_const(rt);
296 if (dst == NULL)
297 *plen = 128;
298 else
299 *plen = inet6_get_plen(&dst->sin6_addr);
300 }
301
302 /*
303 * Stores IPv6 address and prefix mask of @rt inside
304 * @paddr and @pmask. Addresses are returned in de-embedded form.
305 * Scopeid is set to 0 for non-LL addresses.
306 */
307 void
rt_get_inet6_prefix_pmask(const struct rtentry * rt,struct in6_addr * paddr,struct in6_addr * pmask,uint32_t * pscopeid)308 rt_get_inet6_prefix_pmask(const struct rtentry *rt, struct in6_addr *paddr,
309 struct in6_addr *pmask, uint32_t *pscopeid)
310 {
311 const struct sockaddr_in6 *dst;
312
313 dst = (const struct sockaddr_in6 *)rt_key_const(rt);
314 KASSERT((dst->sin6_family == AF_INET6),
315 ("rt family is %d, not inet", dst->sin6_family));
316 if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
317 in6_splitscope(&dst->sin6_addr, paddr, pscopeid);
318 else
319 *paddr = dst->sin6_addr;
320 dst = (const struct sockaddr_in6 *)rt_mask_const(rt);
321 if (dst == NULL)
322 memset(pmask, 0xFF, sizeof(struct in6_addr));
323 else
324 *pmask = dst->sin6_addr;
325 }
326 #endif
327
328
329