Bug Summary

File:net/rtsock.c
Warning:line 526, column 23
Access to field 'so_options' results in a dereference of a null pointer (loaded from variable 'so0')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name rtsock.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/net/rtsock.c
1/* $OpenBSD: rtsock.c,v 1.373 2023/12/03 10:51:17 mvs Exp $ */
2/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1988, 1991, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)rtsock.c 8.6 (Berkeley) 2/11/95
62 */
63
64#include <sys/param.h>
65#include <sys/systm.h>
66#include <sys/proc.h>
67#include <sys/sysctl.h>
68#include <sys/mbuf.h>
69#include <sys/socket.h>
70#include <sys/socketvar.h>
71#include <sys/domain.h>
72#include <sys/pool.h>
73#include <sys/protosw.h>
74#include <sys/srp.h>
75
76#include <net/if.h>
77#include <net/if_dl.h>
78#include <net/if_var.h>
79#include <net/route.h>
80
81#include <netinet/in.h>
82
83#ifdef MPLS1
84#include <netmpls/mpls.h>
85#endif
86#ifdef IPSEC1
87#include <netinet/ip_ipsp.h>
88#include <net/if_enc.h>
89#endif
90#ifdef BFD
91#include <net/bfd.h>
92#endif
93
94#include <sys/stdarg.h>
95#include <sys/kernel.h>
96#include <sys/timeout.h>
97
98#define ROUTESNDQ8192 8192
99#define ROUTERCVQ8192 8192
100
101const struct sockaddr route_src = { 2, PF_ROUTE17, };
102
103struct walkarg {
104 int w_op, w_arg, w_tmemsize;
105 size_t w_given, w_needed;
106 caddr_t w_where, w_tmem;
107};
108
109void route_prinit(void);
110void rcb_ref(void *, void *);
111void rcb_unref(void *, void *);
112int route_output(struct mbuf *, struct socket *);
113int route_ctloutput(int, struct socket *, int, int, struct mbuf *);
114int route_attach(struct socket *, int, int);
115int route_detach(struct socket *);
116int route_disconnect(struct socket *);
117int route_shutdown(struct socket *);
118void route_rcvd(struct socket *);
119int route_send(struct socket *, struct mbuf *, struct mbuf *,
120 struct mbuf *);
121int route_sockaddr(struct socket *, struct mbuf *);
122int route_peeraddr(struct socket *, struct mbuf *);
123void route_input(struct mbuf *m0, struct socket *, sa_family_t);
124int route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
125int route_cleargateway(struct rtentry *, void *, unsigned int);
126void rtm_senddesync_timer(void *);
127void rtm_senddesync(struct socket *);
128int rtm_sendup(struct socket *, struct mbuf *);
129
130int rtm_getifa(struct rt_addrinfo *, unsigned int);
131int rtm_output(struct rt_msghdr *, struct rtentry **, struct rt_addrinfo *,
132 uint8_t, unsigned int);
133struct rt_msghdr *rtm_report(struct rtentry *, u_char, int, int);
134struct mbuf *rtm_msg1(int, struct rt_addrinfo *);
135int rtm_msg2(int, int, struct rt_addrinfo *, caddr_t,
136 struct walkarg *);
137int rtm_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
138int rtm_validate_proposal(struct rt_addrinfo *);
139void rtm_setmetrics(u_long, const struct rt_metrics *,
140 struct rt_kmetrics *);
141void rtm_getmetrics(const struct rtentry *,
142 struct rt_metrics *);
143
144int sysctl_iflist(int, struct walkarg *);
145int sysctl_ifnames(struct walkarg *);
146int sysctl_rtable_rtstat(void *, size_t *, void *);
147
148int rt_setsource(unsigned int, const struct sockaddr *);
149
150/*
151 * Locks used to protect struct members
152 * I immutable after creation
153 * s solock
154 */
155struct rtpcb {
156 struct socket *rop_socket; /* [I] */
157
158 SRPL_ENTRY(rtpcb)struct { struct srp se_next; } rop_list;
159 struct refcnt rop_refcnt;
160 struct timeout rop_timeout;
161 unsigned int rop_msgfilter; /* [s] */
162 unsigned int rop_flagfilter; /* [s] */
163 unsigned int rop_flags; /* [s] */
164 u_int rop_rtableid; /* [s] */
165 unsigned short rop_proto; /* [I] */
166 u_char rop_priority; /* [s] */
167};
168#define sotortpcb(so)((struct rtpcb *)(so)->so_pcb) ((struct rtpcb *)(so)->so_pcb)
169
170struct rtptable {
171 SRPL_HEAD(, rtpcb)struct srpl rtp_list;
172 struct srpl_rc rtp_rc;
173 struct rwlock rtp_lk;
174 unsigned int rtp_count;
175};
176
177struct pool rtpcb_pool;
178struct rtptable rtptable;
179
180/*
181 * These flags and timeout are used for indicating to userland (via a
182 * RTM_DESYNC msg) when the route socket has overflowed and messages
183 * have been lost.
184 */
185#define ROUTECB_FLAG_DESYNC0x1 0x1 /* Route socket out of memory */
186#define ROUTECB_FLAG_FLUSH0x2 0x2 /* Wait until socket is empty before
187 queueing more packets */
188
189#define ROUTE_DESYNC_RESEND_TIMEOUT200 200 /* In ms */
190
191void
192route_prinit(void)
193{
194 srpl_rc_init(&rtptable.rtp_rc, rcb_ref, rcb_unref, NULL((void *)0));
195 rw_init(&rtptable.rtp_lk, "rtsock")_rw_init_flags(&rtptable.rtp_lk, "rtsock", 0, ((void *)0)
)
;
196 SRPL_INIT(&rtptable.rtp_list)srp_init(&(&rtptable.rtp_list)->sl_head);
197 pool_init(&rtpcb_pool, sizeof(struct rtpcb), 0,
198 IPL_SOFTNET0x2, PR_WAITOK0x0001, "rtpcb", NULL((void *)0));
199}
200
201void
202rcb_ref(void *null, void *v)
203{
204 struct rtpcb *rop = v;
205
206 refcnt_take(&rop->rop_refcnt);
207}
208
209void
210rcb_unref(void *null, void *v)
211{
212 struct rtpcb *rop = v;
213
214 refcnt_rele_wake(&rop->rop_refcnt);
215}
216
217int
218route_attach(struct socket *so, int proto, int wait)
219{
220 struct rtpcb *rop;
221 int error;
222
223 error = soreserve(so, ROUTESNDQ8192, ROUTERCVQ8192);
224 if (error)
225 return (error);
226 /*
227 * use the rawcb but allocate a rtpcb, this
228 * code does not care about the additional fields
229 * and works directly on the raw socket.
230 */
231 rop = pool_get(&rtpcb_pool, (wait == M_WAIT0x0001 ? PR_WAITOK0x0001 : PR_NOWAIT0x0002) |
232 PR_ZERO0x0008);
233 if (rop == NULL((void *)0))
234 return (ENOBUFS55);
235 so->so_pcb = rop;
236 /* Init the timeout structure */
237 timeout_set_flags(&rop->rop_timeout, rtm_senddesync_timer, so,
238 KCLOCK_NONE(-1), TIMEOUT_PROC0x01 | TIMEOUT_MPSAFE0x10);
239 refcnt_init(&rop->rop_refcnt);
240
241 rop->rop_socket = so;
242 rop->rop_proto = proto;
243
244 rop->rop_rtableid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_rtableid;
245
246 soisconnected(so);
247 so->so_options |= SO_USELOOPBACK0x0040;
248
249 rw_enter(&rtptable.rtp_lk, RW_WRITE0x0001UL);
250 SRPL_INSERT_HEAD_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop,do { void *head; srp_init(&(rop)->rop_list.se_next); head
= srp_get_locked(&(&rtptable.rtp_list)->sl_head);
if (head != ((void *)0)) { (&rtptable.rtp_rc)->srpl_ref
(&(&rtptable.rtp_rc)->srpl_gc.srp_gc_cookie, head)
; srp_update_locked(&(&rtptable.rtp_rc)->srpl_gc, &
(rop)->rop_list.se_next, head); } (&rtptable.rtp_rc)->
srpl_ref(&(&rtptable.rtp_rc)->srpl_gc.srp_gc_cookie
, rop); srp_update_locked(&(&rtptable.rtp_rc)->srpl_gc
, &(&rtptable.rtp_list)->sl_head, (rop)); } while (
0)
251 rop_list)do { void *head; srp_init(&(rop)->rop_list.se_next); head
= srp_get_locked(&(&rtptable.rtp_list)->sl_head);
if (head != ((void *)0)) { (&rtptable.rtp_rc)->srpl_ref
(&(&rtptable.rtp_rc)->srpl_gc.srp_gc_cookie, head)
; srp_update_locked(&(&rtptable.rtp_rc)->srpl_gc, &
(rop)->rop_list.se_next, head); } (&rtptable.rtp_rc)->
srpl_ref(&(&rtptable.rtp_rc)->srpl_gc.srp_gc_cookie
, rop); srp_update_locked(&(&rtptable.rtp_rc)->srpl_gc
, &(&rtptable.rtp_list)->sl_head, (rop)); } while (
0)
;
252 rtptable.rtp_count++;
253 rw_exit(&rtptable.rtp_lk);
254
255 return (0);
256}
257
258int
259route_detach(struct socket *so)
260{
261 struct rtpcb *rop;
262
263 soassertlocked(so);
264
265 rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
266 if (rop == NULL((void *)0))
267 return (EINVAL22);
268
269 rw_enter(&rtptable.rtp_lk, RW_WRITE0x0001UL);
270
271 rtptable.rtp_count--;
272 SRPL_REMOVE_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop, rtpcb,do { struct srp *ref; struct rtpcb *c, *n; ref = &(&rtptable
.rtp_list)->sl_head; while ((c = srp_get_locked(ref)) != (
rop)) ref = &c->rop_list.se_next; n = srp_get_locked(&
(c)->rop_list.se_next); if (n != ((void *)0)) (&rtptable
.rtp_rc)->srpl_ref(&(&rtptable.rtp_rc)->srpl_gc
.srp_gc_cookie, n); srp_update_locked(&(&rtptable.rtp_rc
)->srpl_gc, ref, n); srp_update_locked(&(&rtptable
.rtp_rc)->srpl_gc, &c->rop_list.se_next, ((void *)0
)); } while (0)
273 rop_list)do { struct srp *ref; struct rtpcb *c, *n; ref = &(&rtptable
.rtp_list)->sl_head; while ((c = srp_get_locked(ref)) != (
rop)) ref = &c->rop_list.se_next; n = srp_get_locked(&
(c)->rop_list.se_next); if (n != ((void *)0)) (&rtptable
.rtp_rc)->srpl_ref(&(&rtptable.rtp_rc)->srpl_gc
.srp_gc_cookie, n); srp_update_locked(&(&rtptable.rtp_rc
)->srpl_gc, ref, n); srp_update_locked(&(&rtptable
.rtp_rc)->srpl_gc, &c->rop_list.se_next, ((void *)0
)); } while (0)
;
274 rw_exit(&rtptable.rtp_lk);
275
276 sounlock(so);
277
278 /* wait for all references to drop */
279 refcnt_finalize(&rop->rop_refcnt, "rtsockrefs");
280 timeout_del_barrier(&rop->rop_timeout);
281
282 solock(so);
283
284 so->so_pcb = NULL((void *)0);
285 KASSERT((so->so_state & SS_NOFDREF) == 0)(((so->so_state & 0x001) == 0) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/rtsock.c", 285, "(so->so_state & SS_NOFDREF) == 0"
))
;
286 pool_put(&rtpcb_pool, rop);
287
288 return (0);
289}
290
291int
292route_disconnect(struct socket *so)
293{
294 soisdisconnected(so);
295 return (0);
296}
297
298int
299route_shutdown(struct socket *so)
300{
301 socantsendmore(so);
302 return (0);
303}
304
305void
306route_rcvd(struct socket *so)
307{
308 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
309
310 soassertlocked(so);
311
312 /*
313 * If we are in a FLUSH state, check if the buffer is
314 * empty so that we can clear the flag.
315 */
316 if (((rop->rop_flags & ROUTECB_FLAG_FLUSH0x2) != 0) &&
317 ((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) ==
318 rop->rop_socket->so_rcv.sb_hiwat)))
319 rop->rop_flags &= ~ROUTECB_FLAG_FLUSH0x2;
320}
321
322int
323route_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
324 struct mbuf *control)
325{
326 int error;
327
328 soassertlocked(so);
329
330 if (control && control->m_lenm_hdr.mh_len) {
331 error = EOPNOTSUPP45;
332 goto out;
333 }
334
335 if (nam) {
336 error = EISCONN56;
337 goto out;
338 }
339
340 error = route_output(m, so);
341 m = NULL((void *)0);
342
343out:
344 m_freem(control);
345 m_freem(m);
346
347 return (error);
348}
349
350int
351route_sockaddr(struct socket *so, struct mbuf *nam)
352{
353 return (EINVAL22);
354}
355
356int
357route_peeraddr(struct socket *so, struct mbuf *nam)
358{
359 /* minimal support, just implement a fake peer address */
360 bcopy(&route_src, mtod(nam, caddr_t)((caddr_t)((nam)->m_hdr.mh_data)), route_src.sa_len);
361 nam->m_lenm_hdr.mh_len = route_src.sa_len;
362 return (0);
363}
364
365int
366route_ctloutput(int op, struct socket *so, int level, int optname,
367 struct mbuf *m)
368{
369 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
370 int error = 0;
371 unsigned int tid, prio;
372
373 if (level != AF_ROUTE17)
374 return (EINVAL22);
375
376 switch (op) {
377 case PRCO_SETOPT1:
378 switch (optname) {
379 case ROUTE_MSGFILTER1:
380 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int))
381 error = EINVAL22;
382 else
383 rop->rop_msgfilter = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
384 break;
385 case ROUTE_TABLEFILTER2:
386 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int)) {
387 error = EINVAL22;
388 break;
389 }
390 tid = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
391 if (tid != RTABLE_ANY0xffffffff && !rtable_exists(tid))
392 error = ENOENT2;
393 else
394 rop->rop_rtableid = tid;
395 break;
396 case ROUTE_PRIOFILTER3:
397 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int)) {
398 error = EINVAL22;
399 break;
400 }
401 prio = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
402 if (prio > RTP_MAX63)
403 error = EINVAL22;
404 else
405 rop->rop_priority = prio;
406 break;
407 case ROUTE_FLAGFILTER4:
408 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int))
409 error = EINVAL22;
410 else
411 rop->rop_flagfilter = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
412 break;
413 default:
414 error = ENOPROTOOPT42;
415 break;
416 }
417 break;
418 case PRCO_GETOPT0:
419 switch (optname) {
420 case ROUTE_MSGFILTER1:
421 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
422 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_msgfilter;
423 break;
424 case ROUTE_TABLEFILTER2:
425 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
426 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_rtableid;
427 break;
428 case ROUTE_PRIOFILTER3:
429 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
430 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_priority;
431 break;
432 case ROUTE_FLAGFILTER4:
433 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
434 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_flagfilter;
435 break;
436 default:
437 error = ENOPROTOOPT42;
438 break;
439 }
440 }
441 return (error);
442}
443
444void
445rtm_senddesync_timer(void *xso)
446{
447 struct socket *so = xso;
448
449 solock(so);
450 rtm_senddesync(so);
451 sounlock(so);
452}
453
454void
455rtm_senddesync(struct socket *so)
456{
457 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
458 struct mbuf *desync_mbuf;
459
460 soassertlocked(so);
461
462 /*
463 * Dying socket is disconnected by upper layer and there is
464 * no reason to send packet. Also we shouldn't reschedule
465 * timeout(9), otherwise timeout_del_barrier(9) can't help us.
466 */
467 if ((so->so_state & SS_ISCONNECTED0x002) == 0 ||
468 (so->so_rcv.sb_state & SS_CANTRCVMORE0x020))
469 return;
470
471 /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */
472 if ((rop->rop_flags & ROUTECB_FLAG_DESYNC0x1) == 0)
473 return;
474
475 /*
476 * If we fail to alloc memory or if sbappendaddr()
477 * fails, re-add timeout and try again.
478 */
479 desync_mbuf = rtm_msg1(RTM_DESYNC0x10, NULL((void *)0));
480 if (desync_mbuf != NULL((void *)0)) {
481 if (sbappendaddr(so, &so->so_rcv, &route_src,
482 desync_mbuf, NULL((void *)0)) != 0) {
483 rop->rop_flags &= ~ROUTECB_FLAG_DESYNC0x1;
484 sorwakeup(rop->rop_socket);
485 return;
486 }
487 m_freem(desync_mbuf);
488 }
489 /* Re-add timeout to try sending msg again */
490 timeout_add_msec(&rop->rop_timeout, ROUTE_DESYNC_RESEND_TIMEOUT200);
491}
492
493void
494route_input(struct mbuf *m0, struct socket *so0, sa_family_t sa_family)
495{
496 struct socket *so;
497 struct rtpcb *rop;
498 struct rt_msghdr *rtm;
499 struct mbuf *m = m0;
500 struct srp_ref sr;
501
502 /* ensure that we can access the rtm_type via mtod() */
503 if (m->m_lenm_hdr.mh_len < offsetof(struct rt_msghdr, rtm_type)__builtin_offsetof(struct rt_msghdr, rtm_type) + 1) {
5
Assuming the condition is false
6
Taking false branch
504 m_freem(m);
505 return;
506 }
507
508 SRPL_FOREACH(rop, &sr, &rtptable.rtp_list, rop_list)for ((rop) = srp_enter((&sr), &(&rtptable.rtp_list
)->sl_head); (rop) != ((void *)0); (rop) = srp_follow((&
sr), &(rop)->rop_list.se_next))
{
7
Assuming 'rop' is not equal to null
509 /*
510 * If route socket is bound to an address family only send
511 * messages that match the address family. Address family
512 * agnostic messages are always sent.
513 */
514 if (sa_family != AF_UNSPEC0 && rop->rop_proto != AF_UNSPEC0 &&
8
Assuming 'sa_family' is equal to AF_UNSPEC
515 rop->rop_proto != sa_family)
516 continue;
517
518
519 so = rop->rop_socket;
520 solock(so);
521
522 /*
523 * Check to see if we don't want our own messages and
524 * if we can receive anything.
525 */
526 if ((so0 == so && !(so0->so_options & SO_USELOOPBACK0x0040)) ||
9
Assuming 'so0' is equal to 'so'
10
Access to field 'so_options' results in a dereference of a null pointer (loaded from variable 'so0')
527 !(so->so_state & SS_ISCONNECTED0x002) ||
528 (so->so_rcv.sb_state & SS_CANTRCVMORE0x020))
529 goto next;
530
531 /* filter messages that the process does not want */
532 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
533 /* but RTM_DESYNC can't be filtered */
534 if (rtm->rtm_type != RTM_DESYNC0x10) {
535 if (rop->rop_msgfilter != 0 &&
536 !(rop->rop_msgfilter & (1U << rtm->rtm_type)))
537 goto next;
538 if (ISSET(rop->rop_flagfilter, rtm->rtm_flags)((rop->rop_flagfilter) & (rtm->rtm_flags)))
539 goto next;
540 }
541 switch (rtm->rtm_type) {
542 case RTM_IFANNOUNCE0xf:
543 case RTM_DESYNC0x10:
544 /* no tableid */
545 break;
546 case RTM_RESOLVE0xb:
547 case RTM_NEWADDR0xc:
548 case RTM_DELADDR0xd:
549 case RTM_IFINFO0xe:
550 case RTM_80211INFO0x15:
551 case RTM_BFD0x12:
552 /* check against rdomain id */
553 if (rop->rop_rtableid != RTABLE_ANY0xffffffff &&
554 rtable_l2(rop->rop_rtableid) != rtm->rtm_tableid)
555 goto next;
556 break;
557 default:
558 if (rop->rop_priority != 0 &&
559 rop->rop_priority < rtm->rtm_priority)
560 goto next;
561 /* check against rtable id */
562 if (rop->rop_rtableid != RTABLE_ANY0xffffffff &&
563 rop->rop_rtableid != rtm->rtm_tableid)
564 goto next;
565 break;
566 }
567
568 /*
569 * Check to see if the flush flag is set. If so, don't queue
570 * any more messages until the flag is cleared.
571 */
572 if ((rop->rop_flags & ROUTECB_FLAG_FLUSH0x2) != 0)
573 goto next;
574
575 rtm_sendup(so, m);
576next:
577 sounlock(so);
578 }
579 SRPL_LEAVE(&sr)srp_leave((&sr));
580
581 m_freem(m);
582}
583
584int
585rtm_sendup(struct socket *so, struct mbuf *m0)
586{
587 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
588 struct mbuf *m;
589
590 soassertlocked(so);
591
592 m = m_copym(m0, 0, M_COPYALL1000000000, M_NOWAIT0x0002);
593 if (m == NULL((void *)0))
594 return (ENOMEM12);
595
596 if (sbspace(so, &so->so_rcv) < (2 * MSIZE256) ||
597 sbappendaddr(so, &so->so_rcv, &route_src, m, NULL((void *)0)) == 0) {
598 /* Flag socket as desync'ed and flush required */
599 rop->rop_flags |= ROUTECB_FLAG_DESYNC0x1 | ROUTECB_FLAG_FLUSH0x2;
600 rtm_senddesync(so);
601 m_freem(m);
602 return (ENOBUFS55);
603 }
604
605 sorwakeup(so);
606 return (0);
607}
608
609struct rt_msghdr *
610rtm_report(struct rtentry *rt, u_char type, int seq, int tableid)
611{
612 struct rt_msghdr *rtm;
613 struct rt_addrinfo info;
614 struct sockaddr_rtlabel sa_rl;
615 struct sockaddr_in6 sa_mask;
616#ifdef BFD
617 struct sockaddr_bfd sa_bfd;
618#endif
619 struct ifnet *ifp = NULL((void *)0);
620 int len;
621
622 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
623 info.rti_info[RTAX_DST0] = rt_key(rt)((rt)->rt_dest);
624 info.rti_info[RTAX_GATEWAY1] = rt->rt_gateway;
625 info.rti_info[RTAX_NETMASK2] = rt_plen2mask(rt, &sa_mask);
626 info.rti_info[RTAX_LABEL10] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
627#ifdef BFD
628 if (rt->rt_flags & RTF_BFD0x1000000) {
629 KERNEL_LOCK()_kernel_lock();
630 info.rti_info[RTAX_BFD11] = bfd2sa(rt, &sa_bfd);
631 KERNEL_UNLOCK()_kernel_unlock();
632 }
633#endif
634#ifdef MPLS1
635 if (rt->rt_flags & RTF_MPLS0x100000) {
636 struct sockaddr_mpls sa_mpls;
637
638 bzero(&sa_mpls, sizeof(sa_mpls))__builtin_bzero((&sa_mpls), (sizeof(sa_mpls)));
639 sa_mpls.smpls_family = AF_MPLS33;
640 sa_mpls.smpls_len = sizeof(sa_mpls);
641 sa_mpls.smpls_label = ((struct rt_mpls *)
642 rt->rt_llinfo)->mpls_label;
643 info.rti_info[RTAX_SRC8] = (struct sockaddr *)&sa_mpls;
644 info.rti_mpls = ((struct rt_mpls *)
645 rt->rt_llinfo)->mpls_operation;
646 }
647#endif
648 ifp = if_get(rt->rt_ifidx);
649 if (ifp != NULL((void *)0)) {
650 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
651 info.rti_info[RTAX_IFA5] = rtable_getsource(tableid,
652 info.rti_info[RTAX_DST0]->sa_family);
653 if (info.rti_info[RTAX_IFA5] == NULL((void *)0))
654 info.rti_info[RTAX_IFA5] = rt->rt_ifa->ifa_addr;
655 if (ifp->if_flags & IFF_POINTOPOINT0x10)
656 info.rti_info[RTAX_BRD7] = rt->rt_ifa->ifa_dstaddr;
657 }
658 if_put(ifp);
659 /* RTAX_GENMASK, RTAX_AUTHOR, RTAX_SRCMASK ignored */
660
661 /* build new route message */
662 len = rtm_msg2(type, RTM_VERSION5, &info, NULL((void *)0), NULL((void *)0));
663 rtm = malloc(len, M_RTABLE5, M_WAITOK0x0001 | M_ZERO0x0008);
664
665 rtm_msg2(type, RTM_VERSION5, &info, (caddr_t)rtm, NULL((void *)0));
666 rtm->rtm_type = type;
667 rtm->rtm_index = rt->rt_ifidx;
668 rtm->rtm_tableid = tableid;
669 rtm->rtm_priority = rt->rt_priority & RTP_MASK0x7f;
670 rtm->rtm_flags = rt->rt_flags;
671 rtm->rtm_pid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_pid;
672 rtm->rtm_seq = seq;
673 rtm_getmetrics(rt, &rtm->rtm_rmx);
674 rtm->rtm_addrs = info.rti_addrs;
675#ifdef MPLS1
676 rtm->rtm_mpls = info.rti_mpls;
677#endif
678 return rtm;
679}
680
681int
682route_output(struct mbuf *m, struct socket *so)
683{
684 struct rt_msghdr *rtm = NULL((void *)0);
685 struct rtentry *rt = NULL((void *)0);
686 struct rt_addrinfo info;
687 struct ifnet *ifp;
688 int len, seq, useloopback, error = 0;
689 u_int tableid;
690 u_int8_t prio;
691 u_char vers, type;
692
693 if (m == NULL((void *)0) || ((m->m_lenm_hdr.mh_len < sizeof(int32_t)) &&
694 (m = m_pullup(m, sizeof(int32_t))) == NULL((void *)0)))
695 return (ENOBUFS55);
696 if ((m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) == 0)
697 panic("route_output");
698
699 useloopback = so->so_options & SO_USELOOPBACK0x0040;
700
701 /*
702 * The socket can't be closed concurrently because the file
703 * descriptor reference is still held.
704 */
705
706 sounlock(so);
707
708 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
709 if (len < offsetof(struct rt_msghdr, rtm_hdrlen)__builtin_offsetof(struct rt_msghdr, rtm_hdrlen) +
710 sizeof(rtm->rtm_hdrlen) ||
711 len != mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data))->rtm_msglen) {
712 error = EINVAL22;
713 goto fail;
714 }
715 vers = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data))->rtm_version;
716 switch (vers) {
717 case RTM_VERSION5:
718 if (len < sizeof(struct rt_msghdr)) {
719 error = EINVAL22;
720 goto fail;
721 }
722 if (len > RTM_MAXSIZE2048) {
723 error = EMSGSIZE40;
724 goto fail;
725 }
726 rtm = malloc(len, M_RTABLE5, M_WAITOK0x0001);
727 m_copydata(m, 0, len, rtm);
728 break;
729 default:
730 error = EPROTONOSUPPORT43;
731 goto fail;
732 }
733
734 /* Verify that the caller is sending an appropriate message early */
735 switch (rtm->rtm_type) {
736 case RTM_ADD0x1:
737 case RTM_DELETE0x2:
738 case RTM_GET0x4:
739 case RTM_CHANGE0x3:
740 case RTM_PROPOSAL0x13:
741 case RTM_SOURCE0x16:
742 break;
743 default:
744 error = EOPNOTSUPP45;
745 goto fail;
746 }
747 /*
748 * Verify that the header length is valid.
749 * All messages from userland start with a struct rt_msghdr.
750 */
751 if (rtm->rtm_hdrlen == 0) /* old client */
752 rtm->rtm_hdrlen = sizeof(struct rt_msghdr);
753 if (rtm->rtm_hdrlen < sizeof(struct rt_msghdr) ||
754 len < rtm->rtm_hdrlen) {
755 error = EINVAL22;
756 goto fail;
757 }
758
759 rtm->rtm_pid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_pid;
760
761 /*
762 * Verify that the caller has the appropriate privilege; RTM_GET
763 * is the only operation the non-superuser is allowed.
764 */
765 if (rtm->rtm_type != RTM_GET0x4 && suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
) != 0) {
766 error = EACCES13;
767 goto fail;
768 }
769 tableid = rtm->rtm_tableid;
770 if (!rtable_exists(tableid)) {
771 if (rtm->rtm_type == RTM_ADD0x1) {
772 if ((error = rtable_add(tableid)) != 0)
773 goto fail;
774 } else {
775 error = EINVAL22;
776 goto fail;
777 }
778 }
779
780 /* Do not let userland play with kernel-only flags. */
781 if ((rtm->rtm_flags & (RTF_LOCAL0x200000|RTF_BROADCAST0x400000)) != 0) {
782 error = EINVAL22;
783 goto fail;
784 }
785
786 /* make sure that kernel-only bits are not set */
787 rtm->rtm_priority &= RTP_MASK0x7f;
788 rtm->rtm_flags &= ~(RTF_DONE0x40|RTF_CLONED0x10000|RTF_CACHED0x20000);
789 rtm->rtm_fmask &= RTF_FMASK(0x400 | 0x8000 | 0x4000 | 0x2000 | 0x1000 | 0x8 | 0x800 | 0x100000
| 0x1000000)
;
790
791 if (rtm->rtm_priority != 0) {
792 if (rtm->rtm_priority > RTP_MAX63 ||
793 rtm->rtm_priority == RTP_LOCAL1) {
794 error = EINVAL22;
795 goto fail;
796 }
797 prio = rtm->rtm_priority;
798 } else if (rtm->rtm_type != RTM_ADD0x1)
799 prio = RTP_ANY64;
800 else if (rtm->rtm_flags & RTF_STATIC0x800)
801 prio = 0;
802 else
803 prio = RTP_DEFAULT56;
804
805 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
806 info.rti_addrs = rtm->rtm_addrs;
807 if ((error = rtm_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm,
808 len + (caddr_t)rtm, &info)) != 0)
809 goto fail;
810
811 info.rti_flags = rtm->rtm_flags;
812
813 if (rtm->rtm_type != RTM_SOURCE0x16 &&
814 rtm->rtm_type != RTM_PROPOSAL0x13 &&
815 (info.rti_info[RTAX_DST0] == NULL((void *)0) ||
816 info.rti_info[RTAX_DST0]->sa_family >= AF_MAX36 ||
817 (info.rti_info[RTAX_GATEWAY1] != NULL((void *)0) &&
818 info.rti_info[RTAX_GATEWAY1]->sa_family >= AF_MAX36) ||
819 info.rti_info[RTAX_GENMASK3] != NULL((void *)0))) {
820 error = EINVAL22;
821 goto fail;
822 }
823#ifdef MPLS1
824 info.rti_mpls = rtm->rtm_mpls;
825#endif
826
827 if (info.rti_info[RTAX_GATEWAY1] != NULL((void *)0) &&
828 info.rti_info[RTAX_GATEWAY1]->sa_family == AF_LINK18 &&
829 (info.rti_flags & RTF_CLONING0x100) == 0) {
830 info.rti_flags |= RTF_LLINFO0x400;
831 }
832
833 /*
834 * Validate RTM_PROPOSAL and pass it along or error out.
835 */
836 if (rtm->rtm_type == RTM_PROPOSAL0x13) {
837 if (rtm_validate_proposal(&info) == -1) {
838 error = EINVAL22;
839 goto fail;
840 }
841 /*
842 * If this is a solicitation proposal forward request to
843 * all interfaces. Most handlers will ignore it but at least
844 * umb(4) will send a response to this event.
845 */
846 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT62) {
847 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
848 TAILQ_FOREACH(ifp, &ifnetlist, if_list)for((ifp) = ((&ifnetlist)->tqh_first); (ifp) != ((void
*)0); (ifp) = ((ifp)->if_list.tqe_next))
{
849 ifp->if_rtrequest(ifp, RTM_PROPOSAL0x13, NULL((void *)0));
850 }
851 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
852 }
853 } else if (rtm->rtm_type == RTM_SOURCE0x16) {
854 if (info.rti_info[RTAX_IFA5] == NULL((void *)0)) {
855 error = EINVAL22;
856 goto fail;
857 }
858 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
859 error = rt_setsource(tableid, info.rti_info[RTAX_IFA5]);
860 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
861 if (error)
862 goto fail;
863 } else {
864 error = rtm_output(rtm, &rt, &info, prio, tableid);
865 if (!error) {
866 type = rtm->rtm_type;
867 seq = rtm->rtm_seq;
868 free(rtm, M_RTABLE5, len);
869 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
870 rtm = rtm_report(rt, type, seq, tableid);
871 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
872 len = rtm->rtm_msglen;
873 }
874 }
875
876 rtfree(rt);
877 if (error) {
878 rtm->rtm_errno = error;
879 } else {
880 rtm->rtm_flags |= RTF_DONE0x40;
881 }
882
883 /*
884 * Check to see if we don't want our own messages.
885 */
886 if (!useloopback) {
887 if (rtptable.rtp_count == 0) {
888 /* no other listener and no loopback of messages */
889 goto fail;
890 }
891 }
892 if (m_copyback(m, 0, len, rtm, M_NOWAIT0x0002)) {
893 m_freem(m);
894 m = NULL((void *)0);
895 } else if (m->m_pkthdrM_dat.MH.MH_pkthdr.len > len)
896 m_adj(m, len - m->m_pkthdrM_dat.MH.MH_pkthdr.len);
897 free(rtm, M_RTABLE5, len);
898 if (m)
899 route_input(m, so, info.rti_info[RTAX_DST0] ?
900 info.rti_info[RTAX_DST0]->sa_family : AF_UNSPEC0);
901 solock(so);
902
903 return (error);
904fail:
905 free(rtm, M_RTABLE5, len);
906 m_freem(m);
907 solock(so);
908
909 return (error);
910}
911
912int
913rtm_output(struct rt_msghdr *rtm, struct rtentry **prt,
914 struct rt_addrinfo *info, uint8_t prio, unsigned int tableid)
915{
916 struct rtentry *rt = *prt;
917 struct ifnet *ifp = NULL((void *)0);
918 int plen, newgate = 0, error = 0;
919
920 switch (rtm->rtm_type) {
921 case RTM_ADD0x1:
922 if (info->rti_info[RTAX_GATEWAY1] == NULL((void *)0)) {
923 error = EINVAL22;
924 break;
925 }
926
927 rt = rtable_match(tableid, info->rti_info[RTAX_DST0], NULL((void *)0));
928 if ((error = route_arp_conflict(rt, info))) {
929 rtfree(rt);
930 rt = NULL((void *)0);
931 break;
932 }
933
934 /*
935 * We cannot go through a delete/create/insert cycle for
936 * cached route because this can lead to races in the
937 * receive path. Instead we update the L2 cache.
938 */
939 if ((rt != NULL((void *)0)) && ISSET(rt->rt_flags, RTF_CACHED)((rt->rt_flags) & (0x20000))) {
940 ifp = if_get(rt->rt_ifidx);
941 if (ifp == NULL((void *)0)) {
942 rtfree(rt);
943 rt = NULL((void *)0);
944 error = ESRCH3;
945 break;
946 }
947
948 goto change;
949 }
950
951 rtfree(rt);
952 rt = NULL((void *)0);
953
954 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
955 if ((error = rtm_getifa(info, tableid)) != 0) {
956 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
957 break;
958 }
959 error = rtrequest(RTM_ADD0x1, info, prio, &rt, tableid);
960 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
961 if (error == 0)
962 rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
963 &rt->rt_rmx);
964 break;
965 case RTM_DELETE0x2:
966 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
967 info->rti_info[RTAX_NETMASK2], info->rti_info[RTAX_GATEWAY1],
968 prio);
969 if (rt == NULL((void *)0)) {
970 error = ESRCH3;
971 break;
972 }
973
974 /*
975 * If we got multipath routes, we require users to specify
976 * a matching gateway.
977 */
978 if (ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000)) &&
979 info->rti_info[RTAX_GATEWAY1] == NULL((void *)0)) {
980 error = ESRCH3;
981 break;
982 }
983
984 ifp = if_get(rt->rt_ifidx);
985 if (ifp == NULL((void *)0)) {
986 rtfree(rt);
987 rt = NULL((void *)0);
988 error = ESRCH3;
989 break;
990 }
991
992 /*
993 * Invalidate the cache of automagically created and
994 * referenced L2 entries to make sure that ``rt_gwroute''
995 * pointer stays valid for other CPUs.
996 */
997 if ((ISSET(rt->rt_flags, RTF_CACHED)((rt->rt_flags) & (0x20000)))) {
998 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
999 ifp->if_rtrequest(ifp, RTM_INVALIDATE0x11, rt);
1000 /* Reset the MTU of the gateway route. */
1001 rtable_walk(tableid, rt_key(rt)((rt)->rt_dest)->sa_family, NULL((void *)0),
1002 route_cleargateway, rt);
1003 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1004 break;
1005 }
1006
1007 /*
1008 * Make sure that local routes are only modified by the
1009 * kernel.
1010 */
1011 if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)((rt->rt_flags) & (0x200000|0x400000))) {
1012 error = EINVAL22;
1013 break;
1014 }
1015
1016 rtfree(rt);
1017 rt = NULL((void *)0);
1018
1019 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1020 error = rtrequest_delete(info, prio, ifp, &rt, tableid);
1021 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1022 break;
1023 case RTM_CHANGE0x3:
1024 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
1025 info->rti_info[RTAX_NETMASK2], info->rti_info[RTAX_GATEWAY1],
1026 prio);
1027 /*
1028 * If we got multipath routes, we require users to specify
1029 * a matching gateway.
1030 */
1031 if ((rt != NULL((void *)0)) && ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000)) &&
1032 (info->rti_info[RTAX_GATEWAY1] == NULL((void *)0))) {
1033 rtfree(rt);
1034 rt = NULL((void *)0);
1035 }
1036
1037 /*
1038 * If RTAX_GATEWAY is the argument we're trying to
1039 * change, try to find a compatible route.
1040 */
1041 if ((rt == NULL((void *)0)) && (info->rti_info[RTAX_GATEWAY1] != NULL((void *)0))) {
1042 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
1043 info->rti_info[RTAX_NETMASK2], NULL((void *)0), prio);
1044 /* Ensure we don't pick a multipath one. */
1045 if ((rt != NULL((void *)0)) && ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000))) {
1046 rtfree(rt);
1047 rt = NULL((void *)0);
1048 }
1049 }
1050
1051 if (rt == NULL((void *)0)) {
1052 error = ESRCH3;
1053 break;
1054 }
1055
1056 /*
1057 * Make sure that local routes are only modified by the
1058 * kernel.
1059 */
1060 if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)((rt->rt_flags) & (0x200000|0x400000))) {
1061 error = EINVAL22;
1062 break;
1063 }
1064
1065 ifp = if_get(rt->rt_ifidx);
1066 if (ifp == NULL((void *)0)) {
1067 rtfree(rt);
1068 rt = NULL((void *)0);
1069 error = ESRCH3;
1070 break;
1071 }
1072
1073 /*
1074 * RTM_CHANGE needs a perfect match.
1075 */
1076 plen = rtable_satoplen(info->rti_info[RTAX_DST0]->sa_family,
1077 info->rti_info[RTAX_NETMASK2]);
1078 if (rt_plen(rt)((rt)->rt_plen) != plen) {
1079 error = ESRCH3;
1080 break;
1081 }
1082
1083 if (info->rti_info[RTAX_GATEWAY1] != NULL((void *)0))
1084 if (rt->rt_gateway == NULL((void *)0) ||
1085 bcmp(rt->rt_gateway,
1086 info->rti_info[RTAX_GATEWAY1],
1087 info->rti_info[RTAX_GATEWAY1]->sa_len)) {
1088 newgate = 1;
1089 }
1090 /*
1091 * Check reachable gateway before changing the route.
1092 * New gateway could require new ifaddr, ifp;
1093 * flags may also be different; ifp may be specified
1094 * by ll sockaddr when protocol address is ambiguous.
1095 */
1096 if (newgate || info->rti_info[RTAX_IFP4] != NULL((void *)0) ||
1097 info->rti_info[RTAX_IFA5] != NULL((void *)0)) {
1098 struct ifaddr *ifa = NULL((void *)0);
1099
1100 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1101 if ((error = rtm_getifa(info, tableid)) != 0) {
1102 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1103 break;
1104 }
1105 ifa = info->rti_ifa;
1106 if (rt->rt_ifa != ifa) {
1107 ifp->if_rtrequest(ifp, RTM_DELETE0x2, rt);
1108 ifafree(rt->rt_ifa);
1109
1110 rt->rt_ifa = ifaref(ifa);
1111 rt->rt_ifidx = ifa->ifa_ifp->if_index;
1112 /* recheck link state after ifp change */
1113 rt_if_linkstate_change(rt, ifa->ifa_ifp,
1114 tableid);
1115 }
1116 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1117 }
1118change:
1119 if (info->rti_info[RTAX_GATEWAY1] != NULL((void *)0)) {
1120 /* When updating the gateway, make sure it is valid. */
1121 if (!newgate && rt->rt_gateway->sa_family !=
1122 info->rti_info[RTAX_GATEWAY1]->sa_family) {
1123 error = EINVAL22;
1124 break;
1125 }
1126
1127 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1128 error = rt_setgate(rt,
1129 info->rti_info[RTAX_GATEWAY1], tableid);
1130 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1131 if (error)
1132 break;
1133 }
1134#ifdef MPLS1
1135 if (rtm->rtm_flags & RTF_MPLS0x100000) {
1136 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1137 error = rt_mpls_set(rt,
1138 info->rti_info[RTAX_SRC8], info->rti_mpls);
1139 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1140 if (error)
1141 break;
1142 } else if (newgate || (rtm->rtm_fmask & RTF_MPLS0x100000)) {
1143 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1144 /* if gateway changed remove MPLS information */
1145 rt_mpls_clear(rt);
1146 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1147 }
1148#endif
1149
1150#ifdef BFD
1151 if (ISSET(rtm->rtm_flags, RTF_BFD)((rtm->rtm_flags) & (0x1000000))) {
1152 KERNEL_LOCK()_kernel_lock();
1153 error = bfdset(rt);
1154 KERNEL_UNLOCK()_kernel_unlock();
1155 if (error)
1156 break;
1157 } else if (!ISSET(rtm->rtm_flags, RTF_BFD)((rtm->rtm_flags) & (0x1000000)) &&
1158 ISSET(rtm->rtm_fmask, RTF_BFD)((rtm->rtm_fmask) & (0x1000000))) {
1159 KERNEL_LOCK()_kernel_lock();
1160 bfdclear(rt);
1161 KERNEL_UNLOCK()_kernel_unlock();
1162 }
1163#endif
1164
1165 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1166 /* Hack to allow some flags to be toggled */
1167 if (rtm->rtm_fmask) {
1168 /* MPLS flag it is set by rt_mpls_set() */
1169 rtm->rtm_fmask &= ~RTF_MPLS0x100000;
1170 rtm->rtm_flags &= ~RTF_MPLS0x100000;
1171 rt->rt_flags =
1172 (rt->rt_flags & ~rtm->rtm_fmask) |
1173 (rtm->rtm_flags & rtm->rtm_fmask);
1174 }
1175 rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
1176
1177 ifp->if_rtrequest(ifp, RTM_ADD0x1, rt);
1178
1179 if (info->rti_info[RTAX_LABEL10] != NULL((void *)0)) {
1180 const char *rtlabel = ((const struct sockaddr_rtlabel *)
1181 info->rti_info[RTAX_LABEL10])->sr_label;
1182 rtlabel_unref(rt->rt_labelid);
1183 rt->rt_labelid = rtlabel_name2id(rtlabel);
1184 }
1185 if_group_routechange(info->rti_info[RTAX_DST0],
1186 info->rti_info[RTAX_NETMASK2]);
1187 rt->rt_locksrt_rmx.rmx_locks &= ~(rtm->rtm_inits);
1188 rt->rt_locksrt_rmx.rmx_locks |= (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
1189 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1190 break;
1191 case RTM_GET0x4:
1192 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
1193 info->rti_info[RTAX_NETMASK2], info->rti_info[RTAX_GATEWAY1],
1194 prio);
1195 if (rt == NULL((void *)0))
1196 error = ESRCH3;
1197 break;
1198 }
1199
1200 if_put(ifp);
1201 *prt = rt;
1202 return (error);
1203}
1204
1205struct ifaddr *
1206ifa_ifwithroute(int flags, const struct sockaddr *dst,
1207 const struct sockaddr *gateway, unsigned int rtableid)
1208{
1209 struct ifaddr *ifa;
1210
1211 if ((flags & RTF_GATEWAY0x2) == 0) {
1212 /*
1213 * If we are adding a route to an interface,
1214 * and the interface is a pt to pt link
1215 * we should search for the destination
1216 * as our clue to the interface. Otherwise
1217 * we can use the local address.
1218 */
1219 ifa = NULL((void *)0);
1220 if (flags & RTF_HOST0x4)
1221 ifa = ifa_ifwithdstaddr(dst, rtableid);
1222 if (ifa == NULL((void *)0))
1223 ifa = ifa_ifwithaddr(gateway, rtableid);
1224 } else {
1225 /*
1226 * If we are adding a route to a remote net
1227 * or host, the gateway may still be on the
1228 * other end of a pt to pt link.
1229 */
1230 ifa = ifa_ifwithdstaddr(gateway, rtableid);
1231 }
1232 if (ifa == NULL((void *)0)) {
1233 if (gateway->sa_family == AF_LINK18) {
1234 const struct sockaddr_dl *sdl;
1235 struct ifnet *ifp;
1236
1237 sdl = satosdl_const(gateway);
1238 ifp = if_get(sdl->sdl_index);
1239 if (ifp != NULL((void *)0))
1240 ifa = ifaof_ifpforaddr(dst, ifp);
1241 if_put(ifp);
1242 } else {
1243 struct rtentry *rt;
1244
1245 rt = rtalloc(gateway, RT_RESOLVE1, rtable_l2(rtableid));
1246 if (rt != NULL((void *)0))
1247 ifa = rt->rt_ifa;
1248 rtfree(rt);
1249 }
1250 }
1251 if (ifa == NULL((void *)0))
1252 return (NULL((void *)0));
1253 if (ifa->ifa_addr->sa_family != dst->sa_family) {
1254 struct ifaddr *oifa = ifa;
1255 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
1256 if (ifa == NULL((void *)0))
1257 ifa = oifa;
1258 }
1259 return (ifa);
1260}
1261
1262int
1263rtm_getifa(struct rt_addrinfo *info, unsigned int rtid)
1264{
1265 struct ifnet *ifp = NULL((void *)0);
1266
1267 /*
1268 * The "returned" `ifa' is guaranteed to be alive only if
1269 * the NET_LOCK() is held.
1270 */
1271 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
1272
1273 /*
1274 * ifp may be specified by sockaddr_dl when protocol address
1275 * is ambiguous
1276 */
1277 if (info->rti_info[RTAX_IFP4] != NULL((void *)0)) {
1278 const struct sockaddr_dl *sdl;
1279
1280 sdl = satosdl_const(info->rti_info[RTAX_IFP4]);
1281 ifp = if_get(sdl->sdl_index);
1282 }
1283
1284#ifdef IPSEC1
1285 /*
1286 * If the destination is a PF_KEY address, we'll look
1287 * for the existence of a encap interface number or address
1288 * in the options list of the gateway. By default, we'll return
1289 * enc0.
1290 */
1291 if (info->rti_info[RTAX_DST0] &&
1292 info->rti_info[RTAX_DST0]->sa_family == PF_KEY30)
1293 info->rti_ifa = enc_getifa(rtid, 0);
1294#endif
1295
1296 if (info->rti_ifa == NULL((void *)0) && info->rti_info[RTAX_IFA5] != NULL((void *)0))
1297 info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA5], rtid);
1298
1299 if (info->rti_ifa == NULL((void *)0)) {
1300 const struct sockaddr *sa;
1301
1302 if ((sa = info->rti_info[RTAX_IFA5]) == NULL((void *)0))
1303 if ((sa = info->rti_info[RTAX_GATEWAY1]) == NULL((void *)0))
1304 sa = info->rti_info[RTAX_DST0];
1305
1306 if (sa != NULL((void *)0) && ifp != NULL((void *)0))
1307 info->rti_ifa = ifaof_ifpforaddr(sa, ifp);
1308 else if (info->rti_info[RTAX_DST0] != NULL((void *)0) &&
1309 info->rti_info[RTAX_GATEWAY1] != NULL((void *)0))
1310 info->rti_ifa = ifa_ifwithroute(info->rti_flags,
1311 info->rti_info[RTAX_DST0],
1312 info->rti_info[RTAX_GATEWAY1],
1313 rtid);
1314 else if (sa != NULL((void *)0))
1315 info->rti_ifa = ifa_ifwithroute(info->rti_flags,
1316 sa, sa, rtid);
1317 }
1318
1319 if_put(ifp);
1320
1321 if (info->rti_ifa == NULL((void *)0))
1322 return (ENETUNREACH51);
1323
1324 return (0);
1325}
1326
1327int
1328route_cleargateway(struct rtentry *rt, void *arg, unsigned int rtableid)
1329{
1330 struct rtentry *nhrt = arg;
1331
1332 if (ISSET(rt->rt_flags, RTF_GATEWAY)((rt->rt_flags) & (0x2)) && rt->rt_gwrouteRT_gw._nh == nhrt &&
1333 !ISSET(rt->rt_locks, RTV_MTU)((rt->rt_rmx.rmx_locks) & (0x1)))
1334 rt->rt_mturt_rmx.rmx_mtu = 0;
1335
1336 return (0);
1337}
1338
1339/*
1340 * Check if the user request to insert an ARP entry does not conflict
1341 * with existing ones.
1342 *
1343 * Only two entries are allowed for a given IP address: a private one
1344 * (priv) and a public one (pub).
1345 */
1346int
1347route_arp_conflict(struct rtentry *rt, struct rt_addrinfo *info)
1348{
1349 int proxy = (info->rti_flags & RTF_ANNOUNCE0x4000);
1350
1351 if ((info->rti_flags & RTF_LLINFO0x400) == 0 ||
1352 (info->rti_info[RTAX_DST0]->sa_family != AF_INET2))
1353 return (0);
1354
1355 if (rt == NULL((void *)0) || !ISSET(rt->rt_flags, RTF_LLINFO)((rt->rt_flags) & (0x400)))
1356 return (0);
1357
1358 /* If the entry is cached, it can be updated. */
1359 if (ISSET(rt->rt_flags, RTF_CACHED)((rt->rt_flags) & (0x20000)))
1360 return (0);
1361
1362 /*
1363 * Same destination, not cached and both "priv" or "pub" conflict.
1364 * If a second entry exists, it always conflict.
1365 */
1366 if ((ISSET(rt->rt_flags, RTF_ANNOUNCE)((rt->rt_flags) & (0x4000)) == proxy) ||
1367 ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000)))
1368 return (EEXIST17);
1369
1370 /* No conflict but an entry exist so we need to force mpath. */
1371 info->rti_flags |= RTF_MPATH0x40000;
1372 return (0);
1373}
1374
1375void
1376rtm_setmetrics(u_long which, const struct rt_metrics *in,
1377 struct rt_kmetrics *out)
1378{
1379 int64_t expire;
1380
1381 if (which & RTV_MTU0x1)
1382 out->rmx_mtu = in->rmx_mtu;
1383 if (which & RTV_EXPIRE0x4) {
1384 expire = in->rmx_expire;
1385 if (expire != 0) {
1386 expire -= gettime();
1387 expire += getuptime();
1388 }
1389
1390 out->rmx_expire = expire;
1391 }
1392}
1393
1394void
1395rtm_getmetrics(const struct rtentry *rt, struct rt_metrics *out)
1396{
1397 const struct rt_kmetrics *in = &rt->rt_rmx;
1398 int64_t expire;
1399
1400 expire = in->rmx_expire;
1401 if (expire == 0)
1402 expire = rt_timer_get_expire(rt);
1403 if (expire != 0) {
1404 expire -= getuptime();
1405 expire += gettime();
1406 }
1407
1408 bzero(out, sizeof(*out))__builtin_bzero((out), (sizeof(*out)));
1409 out->rmx_locks = in->rmx_locks;
1410 out->rmx_mtu = in->rmx_mtu;
1411 out->rmx_expire = expire;
1412 out->rmx_pksent = in->rmx_pksent;
1413}
1414
1415#define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof
(long))
\
1416 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1417#define ADVANCE(x, n)(x += (((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1)
| (sizeof(long) - 1))) : sizeof(long)))
(x += ROUNDUP((n)->sa_len)(((n)->sa_len) > 0 ? (1 + ((((n)->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
)
1418
1419int
1420rtm_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
1421{
1422 int i;
1423
1424 /*
1425 * Parse address bits, split address storage in chunks, and
1426 * set info pointers. Use sa_len for traversing the memory
1427 * and check that we stay within in the limit.
1428 */
1429 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info))__builtin_bzero((rtinfo->rti_info), (sizeof(rtinfo->rti_info
)))
;
1430 for (i = 0; i < sizeof(rtinfo->rti_addrs) * 8; i++) {
1431 struct sockaddr *sa;
1432
1433 if ((rtinfo->rti_addrs & (1U << i)) == 0)
1434 continue;
1435 if (i >= RTAX_MAX15 || cp + sizeof(socklen_t) > cplim)
1436 return (EINVAL22);
1437 sa = (struct sockaddr *)cp;
1438 if (cp + sa->sa_len > cplim)
1439 return (EINVAL22);
1440 rtinfo->rti_info[i] = sa;
1441 ADVANCE(cp, sa)(cp += (((sa)->sa_len) > 0 ? (1 + ((((sa)->sa_len) -
1) | (sizeof(long) - 1))) : sizeof(long)))
;
1442 }
1443 /*
1444 * Check that the address family is suitable for the route address
1445 * type. Check that each address has a size that fits its family
1446 * and its length is within the size. Strings within addresses must
1447 * be NUL terminated.
1448 */
1449 for (i = 0; i < RTAX_MAX15; i++) {
1450 const struct sockaddr *sa;
1451 size_t len, maxlen, size;
1452
1453 sa = rtinfo->rti_info[i];
1454 if (sa == NULL((void *)0))
1455 continue;
1456 maxlen = size = 0;
1457 switch (i) {
1458 case RTAX_DST0:
1459 case RTAX_GATEWAY1:
1460 case RTAX_SRC8:
1461 switch (sa->sa_family) {
1462 case AF_INET2:
1463 size = sizeof(struct sockaddr_in);
1464 break;
1465 case AF_LINK18:
1466 size = sizeof(struct sockaddr_dl);
1467 break;
1468#ifdef INET61
1469 case AF_INET624:
1470 size = sizeof(struct sockaddr_in6);
1471 break;
1472#endif
1473#ifdef MPLS1
1474 case AF_MPLS33:
1475 size = sizeof(struct sockaddr_mpls);
1476 break;
1477#endif
1478 }
1479 break;
1480 case RTAX_IFP4:
1481 if (sa->sa_family != AF_LINK18)
1482 return (EAFNOSUPPORT47);
1483 /*
1484 * XXX Should be sizeof(struct sockaddr_dl), but
1485 * route(8) has a bug and provides less memory.
1486 * arp(8) has another bug and uses sizeof pointer.
1487 */
1488 size = 4;
1489 break;
1490 case RTAX_IFA5:
1491 switch (sa->sa_family) {
1492 case AF_INET2:
1493 size = sizeof(struct sockaddr_in);
1494 break;
1495#ifdef INET61
1496 case AF_INET624:
1497 size = sizeof(struct sockaddr_in6);
1498 break;
1499#endif
1500 default:
1501 return (EAFNOSUPPORT47);
1502 }
1503 break;
1504 case RTAX_LABEL10:
1505 if (sa->sa_family != AF_UNSPEC0)
1506 return (EAFNOSUPPORT47);
1507 maxlen = RTLABEL_LEN32;
1508 size = sizeof(struct sockaddr_rtlabel);
1509 break;
1510#ifdef BFD
1511 case RTAX_BFD11:
1512 if (sa->sa_family != AF_UNSPEC0)
1513 return (EAFNOSUPPORT47);
1514 size = sizeof(struct sockaddr_bfd);
1515 break;
1516#endif
1517 case RTAX_DNS12:
1518 /* more validation in rtm_validate_proposal */
1519 if (sa->sa_len > sizeof(struct sockaddr_rtdns))
1520 return (EINVAL22);
1521 if (sa->sa_len < offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
1522 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns))
1523 return (EINVAL22);
1524 switch (sa->sa_family) {
1525 case AF_INET2:
1526#ifdef INET61
1527 case AF_INET624:
1528#endif
1529 break;
1530 default:
1531 return (EAFNOSUPPORT47);
1532 }
1533 break;
1534 case RTAX_STATIC13:
1535 switch (sa->sa_family) {
1536 case AF_INET2:
1537#ifdef INET61
1538 case AF_INET624:
1539#endif
1540 break;
1541 default:
1542 return (EAFNOSUPPORT47);
1543 }
1544 maxlen = RTSTATIC_LEN128;
1545 size = sizeof(struct sockaddr_rtstatic);
1546 break;
1547 case RTAX_SEARCH14:
1548 if (sa->sa_family != AF_UNSPEC0)
1549 return (EAFNOSUPPORT47);
1550 maxlen = RTSEARCH_LEN128;
1551 size = sizeof(struct sockaddr_rtsearch);
1552 break;
1553 }
1554 if (size) {
1555 /* memory for the full struct must be provided */
1556 if (sa->sa_len < size)
1557 return (EINVAL22);
1558 }
1559 if (maxlen) {
1560 /* this should not happen */
1561 if (2 + maxlen > size)
1562 return (EINVAL22);
1563 /* strings must be NUL terminated within the struct */
1564 len = strnlen(sa->sa_data, maxlen);
1565 if (len >= maxlen || 2 + len >= sa->sa_len)
1566 return (EINVAL22);
1567 break;
1568 }
1569 }
1570 return (0);
1571}
1572
1573struct mbuf *
1574rtm_msg1(int type, struct rt_addrinfo *rtinfo)
1575{
1576 struct rt_msghdr *rtm;
1577 struct mbuf *m;
1578 int i;
1579 const struct sockaddr *sa;
1580 int len, dlen, hlen;
1581
1582 switch (type) {
1583 case RTM_DELADDR0xd:
1584 case RTM_NEWADDR0xc:
1585 hlen = sizeof(struct ifa_msghdr);
1586 break;
1587 case RTM_IFINFO0xe:
1588 hlen = sizeof(struct if_msghdr);
1589 break;
1590 case RTM_IFANNOUNCE0xf:
1591 hlen = sizeof(struct if_announcemsghdr);
1592 break;
1593#ifdef BFD
1594 case RTM_BFD0x12:
1595 hlen = sizeof(struct bfd_msghdr);
1596 break;
1597#endif
1598 case RTM_80211INFO0x15:
1599 hlen = sizeof(struct if_ieee80211_msghdr);
1600 break;
1601 default:
1602 hlen = sizeof(struct rt_msghdr);
1603 break;
1604 }
1605 len = hlen;
1606 for (i = 0; i < RTAX_MAX15; i++) {
1607 if (rtinfo == NULL((void *)0) || (sa = rtinfo->rti_info[i]) == NULL((void *)0))
1608 continue;
1609 len += ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
1610 }
1611 if (len > MCLBYTES(1 << 11))
1612 panic("rtm_msg1");
1613 m = m_gethdr(M_DONTWAIT0x0002, MT_DATA1);
1614 if (m && len > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1615 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1616 if ((m->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0) {
1617 m_free(m);
1618 m = NULL((void *)0);
1619 }
1620 }
1621 if (m == NULL((void *)0))
1622 return (m);
1623 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = len;
1624 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = 0;
1625 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
1626 bzero(rtm, len)__builtin_bzero((rtm), (len));
1627 len = hlen;
1628 for (i = 0; i < RTAX_MAX15; i++) {
1629 if (rtinfo == NULL((void *)0) || (sa = rtinfo->rti_info[i]) == NULL((void *)0))
1630 continue;
1631 rtinfo->rti_addrs |= (1U << i);
1632 dlen = ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
1633 if (m_copyback(m, len, sa->sa_len, sa, M_NOWAIT0x0002)) {
1634 m_freem(m);
1635 return (NULL((void *)0));
1636 }
1637 len += dlen;
1638 }
1639 rtm->rtm_msglen = len;
1640 rtm->rtm_hdrlen = hlen;
1641 rtm->rtm_version = RTM_VERSION5;
1642 rtm->rtm_type = type;
1643 return (m);
1644}
1645
1646int
1647rtm_msg2(int type, int vers, struct rt_addrinfo *rtinfo, caddr_t cp,
1648 struct walkarg *w)
1649{
1650 int i;
1651 int len, dlen, hlen, second_time = 0;
1652 caddr_t cp0;
1653
1654 rtinfo->rti_addrs = 0;
1655again:
1656 switch (type) {
1657 case RTM_DELADDR0xd:
1658 case RTM_NEWADDR0xc:
1659 len = sizeof(struct ifa_msghdr);
1660 break;
1661 case RTM_IFINFO0xe:
1662 len = sizeof(struct if_msghdr);
1663 break;
1664 default:
1665 len = sizeof(struct rt_msghdr);
1666 break;
1667 }
1668 hlen = len;
1669 if ((cp0 = cp) != NULL((void *)0))
1670 cp += len;
1671 for (i = 0; i < RTAX_MAX15; i++) {
1672 const struct sockaddr *sa;
1673
1674 if ((sa = rtinfo->rti_info[i]) == NULL((void *)0))
1675 continue;
1676 rtinfo->rti_addrs |= (1U << i);
1677 dlen = ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
1678 if (cp) {
1679 bcopy(sa, cp, sa->sa_len);
1680 bzero(cp + sa->sa_len, dlen - sa->sa_len)__builtin_bzero((cp + sa->sa_len), (dlen - sa->sa_len));
1681 cp += dlen;
1682 }
1683 len += dlen;
1684 }
1685 /* align message length to the next natural boundary */
1686 len = ALIGN(len)(((unsigned long)(len) + (sizeof(long) - 1)) &~(sizeof(long
) - 1))
;
1687 if (cp == 0 && w != NULL((void *)0) && !second_time) {
1688 w->w_needed += len;
1689 if (w->w_needed <= w->w_given && w->w_where) {
1690 if (w->w_tmemsize < len) {
1691 free(w->w_tmem, M_RTABLE5, w->w_tmemsize);
1692 w->w_tmem = malloc(len, M_RTABLE5,
1693 M_NOWAIT0x0002 | M_ZERO0x0008);
1694 if (w->w_tmem)
1695 w->w_tmemsize = len;
1696 }
1697 if (w->w_tmem) {
1698 cp = w->w_tmem;
1699 second_time = 1;
1700 goto again;
1701 } else
1702 w->w_where = 0;
1703 }
1704 }
1705 if (cp && w) /* clear the message header */
1706 bzero(cp0, hlen)__builtin_bzero((cp0), (hlen));
1707
1708 if (cp) {
1709 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
1710
1711 rtm->rtm_version = RTM_VERSION5;
1712 rtm->rtm_type = type;
1713 rtm->rtm_msglen = len;
1714 rtm->rtm_hdrlen = hlen;
1715 }
1716 return (len);
1717}
1718
1719void
1720rtm_send(struct rtentry *rt, int cmd, int error, unsigned int rtableid)
1721{
1722 struct rt_addrinfo info;
1723 struct ifnet *ifp;
1724 struct sockaddr_rtlabel sa_rl;
1725 struct sockaddr_in6 sa_mask;
1726
1727 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1728 info.rti_info[RTAX_DST0] = rt_key(rt)((rt)->rt_dest);
1729 info.rti_info[RTAX_GATEWAY1] = rt->rt_gateway;
1730 if (!ISSET(rt->rt_flags, RTF_HOST)((rt->rt_flags) & (0x4)))
1731 info.rti_info[RTAX_NETMASK2] = rt_plen2mask(rt, &sa_mask);
1732 info.rti_info[RTAX_LABEL10] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
1733 ifp = if_get(rt->rt_ifidx);
1734 if (ifp != NULL((void *)0)) {
1735 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1736 info.rti_info[RTAX_IFA5] = rtable_getsource(rtableid,
1737 info.rti_info[RTAX_DST0]->sa_family);
1738 if (info.rti_info[RTAX_IFA5] == NULL((void *)0))
1739 info.rti_info[RTAX_IFA5] = rt->rt_ifa->ifa_addr;
1740 }
1741
1742 rtm_miss(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, error,
1743 rtableid);
1744 if_put(ifp);
1745}
1746
1747/*
1748 * This routine is called to generate a message from the routing
1749 * socket indicating that a redirect has occurred, a routing lookup
1750 * has failed, or that a protocol has detected timeouts to a particular
1751 * destination.
1752 */
1753void
1754rtm_miss(int type, struct rt_addrinfo *rtinfo, int flags, uint8_t prio,
1755 u_int ifidx, int error, u_int tableid)
1756{
1757 struct rt_msghdr *rtm;
1758 struct mbuf *m;
1759 const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST0];
1760
1761 if (rtptable.rtp_count == 0)
1762 return;
1763 m = rtm_msg1(type, rtinfo);
1764 if (m == NULL((void *)0))
1765 return;
1766 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
1767 rtm->rtm_flags = RTF_DONE0x40 | flags;
1768 rtm->rtm_priority = prio;
1769 rtm->rtm_errno = error;
1770 rtm->rtm_tableid = tableid;
1771 rtm->rtm_addrs = rtinfo->rti_addrs;
1772 rtm->rtm_index = ifidx;
1773 route_input(m, NULL((void *)0), sa ? sa->sa_family : AF_UNSPEC0);
1774}
1775
1776/*
1777 * This routine is called to generate a message from the routing
1778 * socket indicating that the status of a network interface has changed.
1779 */
1780void
1781rtm_ifchg(struct ifnet *ifp)
1782{
1783 struct rt_addrinfo info;
1784 struct if_msghdr *ifm;
1785 struct mbuf *m;
1786
1787 if (rtptable.rtp_count == 0)
1788 return;
1789 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1790 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1791 m = rtm_msg1(RTM_IFINFO0xe, &info);
1792 if (m == NULL((void *)0))
1793 return;
1794 ifm = mtod(m, struct if_msghdr *)((struct if_msghdr *)((m)->m_hdr.mh_data));
1795 ifm->ifm_index = ifp->if_index;
1796 ifm->ifm_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1797 ifm->ifm_flags = ifp->if_flags;
1798 ifm->ifm_xflags = ifp->if_xflags;
1799 if_getdata(ifp, &ifm->ifm_data);
1800 ifm->ifm_addrs = info.rti_addrs;
1801 route_input(m, NULL((void *)0), AF_UNSPEC0);
1802}
1803
1804/*
1805 * This is called to generate messages from the routing socket
1806 * indicating a network interface has had addresses associated with it.
1807 * if we ever reverse the logic and replace messages TO the routing
1808 * socket indicate a request to configure interfaces, then it will
1809 * be unnecessary as the routing socket will automatically generate
1810 * copies of it.
1811 */
1812void
1813rtm_addr(int cmd, struct ifaddr *ifa)
1814{
1815 struct ifnet *ifp = ifa->ifa_ifp;
1816 struct mbuf *m;
1817 struct rt_addrinfo info;
1818 struct ifa_msghdr *ifam;
1819
1820 if (rtptable.rtp_count == 0)
1821 return;
1822
1823 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1824 info.rti_info[RTAX_IFA5] = ifa->ifa_addr;
1825 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1826 info.rti_info[RTAX_NETMASK2] = ifa->ifa_netmask;
1827 info.rti_info[RTAX_BRD7] = ifa->ifa_dstaddr;
1828 if ((m = rtm_msg1(cmd, &info)) == NULL((void *)0))
1829 return;
1830 ifam = mtod(m, struct ifa_msghdr *)((struct ifa_msghdr *)((m)->m_hdr.mh_data));
1831 ifam->ifam_index = ifp->if_index;
1832 ifam->ifam_metric = ifa->ifa_metric;
1833 ifam->ifam_flags = ifa->ifa_flags;
1834 ifam->ifam_addrs = info.rti_addrs;
1835 ifam->ifam_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1836
1837 route_input(m, NULL((void *)0),
1838 ifa->ifa_addr ? ifa->ifa_addr->sa_family : AF_UNSPEC0);
1839}
1840
1841/*
1842 * This is called to generate routing socket messages indicating
1843 * network interface arrival and departure.
1844 */
1845void
1846rtm_ifannounce(struct ifnet *ifp, int what)
1847{
1848 struct if_announcemsghdr *ifan;
1849 struct mbuf *m;
1850
1851 if (rtptable.rtp_count == 0)
1852 return;
1853 m = rtm_msg1(RTM_IFANNOUNCE0xf, NULL((void *)0));
1854 if (m == NULL((void *)0))
1855 return;
1856 ifan = mtod(m, struct if_announcemsghdr *)((struct if_announcemsghdr *)((m)->m_hdr.mh_data));
1857 ifan->ifan_index = ifp->if_index;
1858 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
1859 ifan->ifan_what = what;
1860 route_input(m, NULL((void *)0), AF_UNSPEC0);
1861}
1862
1863#ifdef BFD
1864/*
1865 * This is used to generate routing socket messages indicating
1866 * the state of a BFD session.
1867 */
1868void
1869rtm_bfd(struct bfd_config *bfd)
1870{
1871 struct bfd_msghdr *bfdm;
1872 struct sockaddr_bfd sa_bfd;
1873 struct mbuf *m;
1874 struct rt_addrinfo info;
1875
1876 if (rtptable.rtp_count == 0)
1877 return;
1878 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1879 info.rti_info[RTAX_DST0] = rt_key(bfd->bc_rt)((bfd->bc_rt)->rt_dest);
1880 info.rti_info[RTAX_IFA5] = bfd->bc_rt->rt_ifa->ifa_addr;
1881
1882 m = rtm_msg1(RTM_BFD0x12, &info);
1883 if (m == NULL((void *)0))
1884 return;
1885 bfdm = mtod(m, struct bfd_msghdr *)((struct bfd_msghdr *)((m)->m_hdr.mh_data));
1886 bfdm->bm_addrs = info.rti_addrs;
1887
1888 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/rtsock.c"
, 1888, "_kernel_lock_held()"))
;
1889 bfd2sa(bfd->bc_rt, &sa_bfd);
1890 memcpy(&bfdm->bm_sa, &sa_bfd, sizeof(sa_bfd))__builtin_memcpy((&bfdm->bm_sa), (&sa_bfd), (sizeof
(sa_bfd)))
;
1891
1892 route_input(m, NULL((void *)0), info.rti_info[RTAX_DST0]->sa_family);
1893}
1894#endif /* BFD */
1895
1896/*
1897 * This is used to generate routing socket messages indicating
1898 * the state of an ieee80211 interface.
1899 */
1900void
1901rtm_80211info(struct ifnet *ifp, struct if_ieee80211_data *ifie)
1902{
1903 struct if_ieee80211_msghdr *ifim;
1904 struct mbuf *m;
1905
1906 if (rtptable.rtp_count == 0)
1907 return;
1908 m = rtm_msg1(RTM_80211INFO0x15, NULL((void *)0));
1909 if (m == NULL((void *)0))
1910 return;
1911 ifim = mtod(m, struct if_ieee80211_msghdr *)((struct if_ieee80211_msghdr *)((m)->m_hdr.mh_data));
1912 ifim->ifim_index = ifp->if_index;
1913 ifim->ifim_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1914
1915 memcpy(&ifim->ifim_ifie, ifie, sizeof(ifim->ifim_ifie))__builtin_memcpy((&ifim->ifim_ifie), (ifie), (sizeof(ifim
->ifim_ifie)))
;
1916 route_input(m, NULL((void *)0), AF_UNSPEC0);
1917}
1918
1919/*
1920 * This is used to generate routing socket messages indicating
1921 * the address selection proposal from an interface.
1922 */
1923void
1924rtm_proposal(struct ifnet *ifp, struct rt_addrinfo *rtinfo, int flags,
1925 uint8_t prio)
1926{
1927 struct rt_msghdr *rtm;
1928 struct mbuf *m;
1929
1930 m = rtm_msg1(RTM_PROPOSAL0x13, rtinfo);
1931 if (m == NULL((void *)0))
1
Assuming 'm' is not equal to NULL
2
Taking false branch
1932 return;
1933 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
1934 rtm->rtm_flags = RTF_DONE0x40 | flags;
1935 rtm->rtm_priority = prio;
1936 rtm->rtm_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1937 rtm->rtm_index = ifp->if_index;
1938 rtm->rtm_addrs = rtinfo->rti_addrs;
1939
1940 route_input(m, NULL((void *)0), rtinfo->rti_info[RTAX_DNS12]->sa_family);
3
Passing null pointer value via 2nd parameter 'so0'
4
Calling 'route_input'
1941}
1942
1943/*
1944 * This is used in dumping the kernel table via sysctl().
1945 */
1946int
1947sysctl_dumpentry(struct rtentry *rt, void *v, unsigned int id)
1948{
1949 struct walkarg *w = v;
1950 int error = 0, size;
1951 struct rt_addrinfo info;
1952 struct ifnet *ifp;
1953#ifdef BFD
1954 struct sockaddr_bfd sa_bfd;
1955#endif
1956 struct sockaddr_rtlabel sa_rl;
1957 struct sockaddr_in6 sa_mask;
1958
1959 if (w->w_op == NET_RT_FLAGS2 && !(rt->rt_flags & w->w_arg))
1960 return 0;
1961 if (w->w_op == NET_RT_DUMP1 && w->w_arg) {
1962 u_int8_t prio = w->w_arg & RTP_MASK0x7f;
1963 if (w->w_arg < 0) {
1964 prio = (-w->w_arg) & RTP_MASK0x7f;
1965 /* Show all routes that are not this priority */
1966 if (prio == (rt->rt_priority & RTP_MASK0x7f))
1967 return 0;
1968 } else {
1969 if (prio != (rt->rt_priority & RTP_MASK0x7f) &&
1970 prio != RTP_ANY64)
1971 return 0;
1972 }
1973 }
1974 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
1975 info.rti_info[RTAX_DST0] = rt_key(rt)((rt)->rt_dest);
1976 info.rti_info[RTAX_GATEWAY1] = rt->rt_gateway;
1977 info.rti_info[RTAX_NETMASK2] = rt_plen2mask(rt, &sa_mask);
1978 ifp = if_get(rt->rt_ifidx);
1979 if (ifp != NULL((void *)0)) {
1980 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1981 info.rti_info[RTAX_IFA5] =
1982 rtable_getsource(id, info.rti_info[RTAX_DST0]->sa_family);
1983 if (info.rti_info[RTAX_IFA5] == NULL((void *)0))
1984 info.rti_info[RTAX_IFA5] = rt->rt_ifa->ifa_addr;
1985 if (ifp->if_flags & IFF_POINTOPOINT0x10)
1986 info.rti_info[RTAX_BRD7] = rt->rt_ifa->ifa_dstaddr;
1987 }
1988 if_put(ifp);
1989 info.rti_info[RTAX_LABEL10] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
1990#ifdef BFD
1991 if (rt->rt_flags & RTF_BFD0x1000000) {
1992 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/rtsock.c"
, 1992, "_kernel_lock_held()"))
;
1993 info.rti_info[RTAX_BFD11] = bfd2sa(rt, &sa_bfd);
1994 }
1995#endif
1996#ifdef MPLS1
1997 if (rt->rt_flags & RTF_MPLS0x100000) {
1998 struct sockaddr_mpls sa_mpls;
1999
2000 bzero(&sa_mpls, sizeof(sa_mpls))__builtin_bzero((&sa_mpls), (sizeof(sa_mpls)));
2001 sa_mpls.smpls_family = AF_MPLS33;
2002 sa_mpls.smpls_len = sizeof(sa_mpls);
2003 sa_mpls.smpls_label = ((struct rt_mpls *)
2004 rt->rt_llinfo)->mpls_label;
2005 info.rti_info[RTAX_SRC8] = (struct sockaddr *)&sa_mpls;
2006 info.rti_mpls = ((struct rt_mpls *)
2007 rt->rt_llinfo)->mpls_operation;
2008 }
2009#endif
2010
2011 size = rtm_msg2(RTM_GET0x4, RTM_VERSION5, &info, NULL((void *)0), w);
2012 if (w->w_where && w->w_tmem && w->w_needed <= w->w_given) {
2013 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
2014
2015 rtm->rtm_pid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_pid;
2016 rtm->rtm_flags = RTF_DONE0x40 | rt->rt_flags;
2017 rtm->rtm_priority = rt->rt_priority & RTP_MASK0x7f;
2018 rtm_getmetrics(rt, &rtm->rtm_rmx);
2019 /* Do not account the routing table's reference. */
2020 rtm->rtm_rmx.rmx_refcnt = refcnt_read(&rt->rt_refcnt) - 1;
2021 rtm->rtm_index = rt->rt_ifidx;
2022 rtm->rtm_addrs = info.rti_addrs;
2023 rtm->rtm_tableid = id;
2024#ifdef MPLS1
2025 rtm->rtm_mpls = info.rti_mpls;
2026#endif
2027 if ((error = copyout(rtm, w->w_where, size)) != 0)
2028 w->w_where = NULL((void *)0);
2029 else
2030 w->w_where += size;
2031 }
2032 return (error);
2033}
2034
2035int
2036sysctl_iflist(int af, struct walkarg *w)
2037{
2038 struct ifnet *ifp;
2039 struct ifaddr *ifa;
2040 struct rt_addrinfo info;
2041 int len, error = 0;
2042
2043 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
2044 TAILQ_FOREACH(ifp, &ifnetlist, if_list)for((ifp) = ((&ifnetlist)->tqh_first); (ifp) != ((void
*)0); (ifp) = ((ifp)->if_list.tqe_next))
{
2045 if (w->w_arg && w->w_arg != ifp->if_index)
2046 continue;
2047 /* Copy the link-layer address first */
2048 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
2049 len = rtm_msg2(RTM_IFINFO0xe, RTM_VERSION5, &info, 0, w);
2050 if (w->w_where && w->w_tmem && w->w_needed <= w->w_given) {
2051 struct if_msghdr *ifm;
2052
2053 ifm = (struct if_msghdr *)w->w_tmem;
2054 ifm->ifm_index = ifp->if_index;
2055 ifm->ifm_tableid = ifp->if_rdomainif_data.ifi_rdomain;
2056 ifm->ifm_flags = ifp->if_flags;
2057 if_getdata(ifp, &ifm->ifm_data);
2058 ifm->ifm_addrs = info.rti_addrs;
2059 error = copyout(ifm, w->w_where, len);
2060 if (error)
2061 return (error);
2062 w->w_where += len;
2063 }
2064 info.rti_info[RTAX_IFP4] = NULL((void *)0);
2065 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)for((ifa) = ((&ifp->if_addrlist)->tqh_first); (ifa)
!= ((void *)0); (ifa) = ((ifa)->ifa_list.tqe_next))
{
2066 KASSERT(ifa->ifa_addr->sa_family != AF_LINK)((ifa->ifa_addr->sa_family != 18) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/net/rtsock.c", 2066, "ifa->ifa_addr->sa_family != AF_LINK"
))
;
2067 if (af && af != ifa->ifa_addr->sa_family)
2068 continue;
2069 info.rti_info[RTAX_IFA5] = ifa->ifa_addr;
2070 info.rti_info[RTAX_NETMASK2] = ifa->ifa_netmask;
2071 info.rti_info[RTAX_BRD7] = ifa->ifa_dstaddr;
2072 len = rtm_msg2(RTM_NEWADDR0xc, RTM_VERSION5, &info, 0, w);
2073 if (w->w_where && w->w_tmem &&
2074 w->w_needed <= w->w_given) {
2075 struct ifa_msghdr *ifam;
2076
2077 ifam = (struct ifa_msghdr *)w->w_tmem;
2078 ifam->ifam_index = ifa->ifa_ifp->if_index;
2079 ifam->ifam_flags = ifa->ifa_flags;
2080 ifam->ifam_metric = ifa->ifa_metric;
2081 ifam->ifam_addrs = info.rti_addrs;
2082 error = copyout(w->w_tmem, w->w_where, len);
2083 if (error)
2084 return (error);
2085 w->w_where += len;
2086 }
2087 }
2088 info.rti_info[RTAX_IFA5] = info.rti_info[RTAX_NETMASK2] =
2089 info.rti_info[RTAX_BRD7] = NULL((void *)0);
2090 }
2091 return (0);
2092}
2093
2094int
2095sysctl_ifnames(struct walkarg *w)
2096{
2097 struct if_nameindex_msg ifn;
2098 struct ifnet *ifp;
2099 int error = 0;
2100
2101 /* XXX ignore tableid for now */
2102 TAILQ_FOREACH(ifp, &ifnetlist, if_list)for((ifp) = ((&ifnetlist)->tqh_first); (ifp) != ((void
*)0); (ifp) = ((ifp)->if_list.tqe_next))
{
2103 if (w->w_arg && w->w_arg != ifp->if_index)
2104 continue;
2105 w->w_needed += sizeof(ifn);
2106 if (w->w_where && w->w_needed <= w->w_given) {
2107
2108 memset(&ifn, 0, sizeof(ifn))__builtin_memset((&ifn), (0), (sizeof(ifn)));
2109 ifn.if_index = ifp->if_index;
2110 strlcpy(ifn.if_name, ifp->if_xname,
2111 sizeof(ifn.if_name));
2112 error = copyout(&ifn, w->w_where, sizeof(ifn));
2113 if (error)
2114 return (error);
2115 w->w_where += sizeof(ifn);
2116 }
2117 }
2118
2119 return (0);
2120}
2121
2122int
2123sysctl_source(int af, u_int tableid, struct walkarg *w)
2124{
2125 struct sockaddr *sa;
2126 int size, error = 0;
2127
2128 sa = rtable_getsource(tableid, af);
2129 if (sa) {
2130 switch (sa->sa_family) {
2131 case AF_INET2:
2132 size = sizeof(struct sockaddr_in);
2133 break;
2134#ifdef INET61
2135 case AF_INET624:
2136 size = sizeof(struct sockaddr_in6);
2137 break;
2138#endif
2139 default:
2140 return (0);
2141 }
2142 w->w_needed += size;
2143 if (w->w_where && w->w_needed <= w->w_given) {
2144 if ((error = copyout(sa, w->w_where, size)))
2145 return (error);
2146 w->w_where += size;
2147 }
2148 }
2149 return (0);
2150}
2151
2152int
2153sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new,
2154 size_t newlen)
2155{
2156 int i, error = EINVAL22;
2157 u_char af;
2158 struct walkarg w;
2159 struct rt_tableinfo tableinfo;
2160 u_int tableid = 0;
2161
2162 if (new)
2163 return (EPERM1);
2164 if (namelen < 3 || namelen > 4)
2165 return (EINVAL22);
2166 af = name[0];
2167 bzero(&w, sizeof(w))__builtin_bzero((&w), (sizeof(w)));
2168 w.w_where = where;
2169 w.w_given = *given;
2170 w.w_op = name[1];
2171 w.w_arg = name[2];
2172
2173 if (namelen == 4) {
2174 tableid = name[3];
2175 if (!rtable_exists(tableid))
2176 return (ENOENT2);
2177 } else
2178 tableid = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
->p_p->ps_rtableid;
2179
2180 switch (w.w_op) {
2181 case NET_RT_DUMP1:
2182 case NET_RT_FLAGS2:
2183 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
2184 for (i = 1; i <= AF_MAX36; i++) {
2185 if (af != 0 && af != i)
2186 continue;
2187
2188 error = rtable_walk(tableid, i, NULL((void *)0), sysctl_dumpentry,
2189 &w);
2190 if (error == EAFNOSUPPORT47)
2191 error = 0;
2192 if (error)
2193 break;
2194 }
2195 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
2196 break;
2197
2198 case NET_RT_IFLIST3:
2199 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
2200 error = sysctl_iflist(af, &w);
2201 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
2202 break;
2203
2204 case NET_RT_STATS4:
2205 return (sysctl_rtable_rtstat(where, given, new));
2206 case NET_RT_TABLE5:
2207 tableid = w.w_arg;
2208 if (!rtable_exists(tableid))
2209 return (ENOENT2);
2210 memset(&tableinfo, 0, sizeof tableinfo)__builtin_memset((&tableinfo), (0), (sizeof tableinfo));
2211 tableinfo.rti_tableid = tableid;
2212 tableinfo.rti_domainid = rtable_l2(tableid);
2213 error = sysctl_rdstruct(where, given, new,
2214 &tableinfo, sizeof(tableinfo));
2215 return (error);
2216 case NET_RT_IFNAMES6:
2217 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
2218 error = sysctl_ifnames(&w);
2219 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
2220 break;
2221 case NET_RT_SOURCE7:
2222 tableid = w.w_arg;
2223 if (!rtable_exists(tableid))
2224 return (ENOENT2);
2225 NET_LOCK_SHARED()do { rw_enter_read(&netlock); } while (0);
2226 for (i = 1; i <= AF_MAX36; i++) {
2227 if (af != 0 && af != i)
2228 continue;
2229
2230 error = sysctl_source(i, tableid, &w);
2231 if (error == EAFNOSUPPORT47)
2232 error = 0;
2233 if (error)
2234 break;
2235 }
2236 NET_UNLOCK_SHARED()do { rw_exit_read(&netlock); } while (0);
2237 break;
2238 }
2239 free(w.w_tmem, M_RTABLE5, w.w_tmemsize);
2240 if (where) {
2241 *given = w.w_where - (caddr_t)where;
2242 if (w.w_needed > w.w_given)
2243 return (ENOMEM12);
2244 } else if (w.w_needed == 0) {
2245 *given = 0;
2246 } else {
2247 *given = roundup(w.w_needed + MAX(w.w_needed / 10, 1024),((((w.w_needed + (((w.w_needed / 10)>(1024))?(w.w_needed /
10):(1024)))+(((1 << 12))-1))/((1 << 12)))*((1 <<
12)))
2248 PAGE_SIZE)((((w.w_needed + (((w.w_needed / 10)>(1024))?(w.w_needed /
10):(1024)))+(((1 << 12))-1))/((1 << 12)))*((1 <<
12)))
;
2249 }
2250 return (error);
2251}
2252
2253int
2254sysctl_rtable_rtstat(void *oldp, size_t *oldlenp, void *newp)
2255{
2256 extern struct cpumem *rtcounters;
2257 uint64_t counters[rts_ncounters];
2258 struct rtstat rtstat;
2259 uint32_t *words = (uint32_t *)&rtstat;
2260 int i;
2261
2262 CTASSERT(sizeof(rtstat) == (nitems(counters) * sizeof(uint32_t)))extern char _ctassert[(sizeof(rtstat) == ((sizeof((counters))
/ sizeof((counters)[0])) * sizeof(uint32_t))) ? 1 : -1 ] __attribute__
((__unused__))
;
2263 memset(&rtstat, 0, sizeof rtstat)__builtin_memset((&rtstat), (0), (sizeof rtstat));
2264 counters_read(rtcounters, counters, nitems(counters)(sizeof((counters)) / sizeof((counters)[0])), NULL((void *)0));
2265
2266 for (i = 0; i < nitems(counters)(sizeof((counters)) / sizeof((counters)[0])); i++)
2267 words[i] = (uint32_t)counters[i];
2268
2269 return (sysctl_rdstruct(oldp, oldlenp, newp, &rtstat, sizeof(rtstat)));
2270}
2271
2272int
2273rtm_validate_proposal(struct rt_addrinfo *info)
2274{
2275 if (info->rti_addrs & ~(RTA_NETMASK0x4 | RTA_IFA0x20 | RTA_DNS0x1000 | RTA_STATIC0x2000 |
2276 RTA_SEARCH0x4000)) {
2277 return -1;
2278 }
2279
2280 if (ISSET(info->rti_addrs, RTA_NETMASK)((info->rti_addrs) & (0x4))) {
2281 const struct sockaddr *sa = info->rti_info[RTAX_NETMASK2];
2282 if (sa == NULL((void *)0))
2283 return -1;
2284 switch (sa->sa_family) {
2285 case AF_INET2:
2286 if (sa->sa_len != sizeof(struct sockaddr_in))
2287 return -1;
2288 break;
2289 case AF_INET624:
2290 if (sa->sa_len != sizeof(struct sockaddr_in6))
2291 return -1;
2292 break;
2293 default:
2294 return -1;
2295 }
2296 }
2297
2298 if (ISSET(info->rti_addrs, RTA_IFA)((info->rti_addrs) & (0x20))) {
2299 const struct sockaddr *sa = info->rti_info[RTAX_IFA5];
2300 if (sa == NULL((void *)0))
2301 return -1;
2302 switch (sa->sa_family) {
2303 case AF_INET2:
2304 if (sa->sa_len != sizeof(struct sockaddr_in))
2305 return -1;
2306 break;
2307 case AF_INET624:
2308 if (sa->sa_len != sizeof(struct sockaddr_in6))
2309 return -1;
2310 break;
2311 default:
2312 return -1;
2313 }
2314 }
2315
2316 if (ISSET(info->rti_addrs, RTA_DNS)((info->rti_addrs) & (0x1000))) {
2317 const struct sockaddr_rtdns *rtdns =
2318 (const struct sockaddr_rtdns *)info->rti_info[RTAX_DNS12];
2319 if (rtdns == NULL((void *)0))
2320 return -1;
2321 if (rtdns->sr_len > sizeof(*rtdns))
2322 return -1;
2323 if (rtdns->sr_len < offsetof(struct sockaddr_rtdns, sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns))
2324 return -1;
2325 switch (rtdns->sr_family) {
2326 case AF_INET2:
2327 if ((rtdns->sr_len - offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
2328 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns)) % sizeof(struct in_addr) != 0)
2329 return -1;
2330 break;
2331#ifdef INET61
2332 case AF_INET624:
2333 if ((rtdns->sr_len - offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
2334 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns)) % sizeof(struct in6_addr) != 0)
2335 return -1;
2336 break;
2337#endif
2338 default:
2339 return -1;
2340 }
2341 }
2342
2343 if (ISSET(info->rti_addrs, RTA_STATIC)((info->rti_addrs) & (0x2000))) {
2344 const struct sockaddr_rtstatic *rtstatic = (const struct
2345 sockaddr_rtstatic *)info->rti_info[RTAX_STATIC13];
2346 if (rtstatic == NULL((void *)0))
2347 return -1;
2348 if (rtstatic->sr_len > sizeof(*rtstatic))
2349 return -1;
2350 if (rtstatic->sr_len <=
2351 offsetof(struct sockaddr_rtstatic, sr_static)__builtin_offsetof(struct sockaddr_rtstatic, sr_static))
2352 return -1;
2353 }
2354
2355 if (ISSET(info->rti_addrs, RTA_SEARCH)((info->rti_addrs) & (0x4000))) {
2356 const struct sockaddr_rtsearch *rtsearch = (const struct
2357 sockaddr_rtsearch *)info->rti_info[RTAX_SEARCH14];
2358 if (rtsearch == NULL((void *)0))
2359 return -1;
2360 if (rtsearch->sr_len > sizeof(*rtsearch))
2361 return -1;
2362 if (rtsearch->sr_len <=
2363 offsetof(struct sockaddr_rtsearch, sr_search)__builtin_offsetof(struct sockaddr_rtsearch, sr_search))
2364 return -1;
2365 }
2366
2367 return 0;
2368}
2369
2370int
2371rt_setsource(unsigned int rtableid, const struct sockaddr *src)
2372{
2373 struct ifaddr *ifa;
2374 /*
2375 * If source address is 0.0.0.0 or ::
2376 * use automatic source selection
2377 */
2378 switch(src->sa_family) {
2379 case AF_INET2:
2380 if(satosin_const(src)->sin_addr.s_addr == INADDR_ANY((u_int32_t) (__uint32_t)(__builtin_constant_p((u_int32_t)(0x00000000
)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000000)) &
0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000000)) &
0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000000)) &
0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000000)
) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000000
))))
) {
2381 rtable_setsource(rtableid, AF_INET2, NULL((void *)0));
2382 return (0);
2383 }
2384 break;
2385#ifdef INET61
2386 case AF_INET624:
2387 if (IN6_IS_ADDR_UNSPECIFIED(&satosin6_const(src)->sin6_addr)((*(const u_int32_t *)(const void *)(&(&satosin6_const
(src)->sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6_const
(src)->sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6_const
(src)->sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6_const
(src)->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
) {
2388 rtable_setsource(rtableid, AF_INET624, NULL((void *)0));
2389 return (0);
2390 }
2391 break;
2392#endif
2393 default:
2394 return (EAFNOSUPPORT47);
2395 }
2396
2397 /*
2398 * Check if source address is assigned to an interface in the
2399 * same rdomain
2400 */
2401 if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL((void *)0))
2402 return (EINVAL22);
2403
2404 return rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr);
2405}
2406
2407/*
2408 * Definitions of protocols supported in the ROUTE domain.
2409 */
2410
2411const struct pr_usrreqs route_usrreqs = {
2412 .pru_attach = route_attach,
2413 .pru_detach = route_detach,
2414 .pru_disconnect = route_disconnect,
2415 .pru_shutdown = route_shutdown,
2416 .pru_rcvd = route_rcvd,
2417 .pru_send = route_send,
2418 .pru_sockaddr = route_sockaddr,
2419 .pru_peeraddr = route_peeraddr,
2420};
2421
2422const struct protosw routesw[] = {
2423{
2424 .pr_type = SOCK_RAW3,
2425 .pr_domain = &routedomain,
2426 .pr_flags = PR_ATOMIC0x0001|PR_ADDR0x0002|PR_WANTRCVD0x0008,
2427 .pr_ctloutput = route_ctloutput,
2428 .pr_usrreqs = &route_usrreqs,
2429 .pr_init = route_prinit,
2430 .pr_sysctl = sysctl_rtable
2431}
2432};
2433
2434const struct domain routedomain = {
2435 .dom_family = PF_ROUTE17,
2436 .dom_name = "route",
2437 .dom_init = route_init,
2438 .dom_protosw = routesw,
2439 .dom_protoswNPROTOSW = &routesw[nitems(routesw)(sizeof((routesw)) / sizeof((routesw)[0]))]
2440};