Bug Summary

File:net/rtsock.c
Warning:line 531, 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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name rtsock.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -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 -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/lib/clang/13.0.0 -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/swsmu -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/powerplay -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/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 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 -D CONFIG_DRM_AMD_DC_DCN3_0 -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 -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 /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/net/rtsock.c
1/* $OpenBSD: rtsock.c,v 1.323 2021/12/16 09:33:56 claudio 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_given, w_needed, w_tmemsize;
105 caddr_t w_where, w_tmem;
106};
107
108void route_prinit(void);
109void rcb_ref(void *, void *);
110void rcb_unref(void *, void *);
111int route_output(struct mbuf *, struct socket *, struct sockaddr *,
112 struct mbuf *);
113int route_ctloutput(int, struct socket *, int, int, struct mbuf *);
114int route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
115 struct mbuf *, struct proc *);
116void route_input(struct mbuf *m0, struct socket *, sa_family_t);
117int route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
118int route_cleargateway(struct rtentry *, void *, unsigned int);
119void rtm_senddesync_timer(void *);
120void rtm_senddesync(struct socket *);
121int rtm_sendup(struct socket *, struct mbuf *);
122
123int rtm_getifa(struct rt_addrinfo *, unsigned int);
124int rtm_output(struct rt_msghdr *, struct rtentry **, struct rt_addrinfo *,
125 uint8_t, unsigned int);
126struct rt_msghdr *rtm_report(struct rtentry *, u_char, int, int);
127struct mbuf *rtm_msg1(int, struct rt_addrinfo *);
128int rtm_msg2(int, int, struct rt_addrinfo *, caddr_t,
129 struct walkarg *);
130int rtm_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
131int rtm_validate_proposal(struct rt_addrinfo *);
132void rtm_setmetrics(u_long, const struct rt_metrics *,
133 struct rt_kmetrics *);
134void rtm_getmetrics(const struct rt_kmetrics *,
135 struct rt_metrics *);
136
137int sysctl_iflist(int, struct walkarg *);
138int sysctl_ifnames(struct walkarg *);
139int sysctl_rtable_rtstat(void *, size_t *, void *);
140
141int rt_setsource(unsigned int, struct sockaddr *);
142
143/*
144 * Locks used to protect struct members
145 * I immutable after creation
146 * s solock
147 */
148struct rtpcb {
149 struct socket *rop_socket; /* [I] */
150
151 SRPL_ENTRY(rtpcb)struct { struct srp se_next; } rop_list;
152 struct refcnt rop_refcnt;
153 struct timeout rop_timeout;
154 unsigned int rop_msgfilter; /* [s] */
155 unsigned int rop_flagfilter; /* [s] */
156 unsigned int rop_flags; /* [s] */
157 u_int rop_rtableid; /* [s] */
158 unsigned short rop_proto; /* [I] */
159 u_char rop_priority; /* [s] */
160};
161#define sotortpcb(so)((struct rtpcb *)(so)->so_pcb) ((struct rtpcb *)(so)->so_pcb)
162
163struct rtptable {
164 SRPL_HEAD(, rtpcb)struct srpl rtp_list;
165 struct srpl_rc rtp_rc;
166 struct rwlock rtp_lk;
167 unsigned int rtp_count;
168};
169
170struct pool rtpcb_pool;
171struct rtptable rtptable;
172
173/*
174 * These flags and timeout are used for indicating to userland (via a
175 * RTM_DESYNC msg) when the route socket has overflowed and messages
176 * have been lost.
177 */
178#define ROUTECB_FLAG_DESYNC0x1 0x1 /* Route socket out of memory */
179#define ROUTECB_FLAG_FLUSH0x2 0x2 /* Wait until socket is empty before
180 queueing more packets */
181
182#define ROUTE_DESYNC_RESEND_TIMEOUT200 200 /* In ms */
183
184void
185route_prinit(void)
186{
187 srpl_rc_init(&rtptable.rtp_rc, rcb_ref, rcb_unref, NULL((void *)0));
188 rw_init(&rtptable.rtp_lk, "rtsock")_rw_init_flags(&rtptable.rtp_lk, "rtsock", 0, ((void *)0)
)
;
189 SRPL_INIT(&rtptable.rtp_list)srp_init(&(&rtptable.rtp_list)->sl_head);
190 pool_init(&rtpcb_pool, sizeof(struct rtpcb), 0,
191 IPL_SOFTNET0x5, PR_WAITOK0x0001, "rtpcb", NULL((void *)0));
192}
193
194void
195rcb_ref(void *null, void *v)
196{
197 struct rtpcb *rop = v;
198
199 refcnt_take(&rop->rop_refcnt);
200}
201
202void
203rcb_unref(void *null, void *v)
204{
205 struct rtpcb *rop = v;
206
207 refcnt_rele_wake(&rop->rop_refcnt);
208}
209
210int
211route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
212 struct mbuf *control, struct proc *p)
213{
214 struct rtpcb *rop;
215 int error = 0;
216
217 if (req == PRU_CONTROL11)
218 return (EOPNOTSUPP45);
219
220 soassertlocked(so);
221
222 if (control && control->m_lenm_hdr.mh_len) {
223 error = EOPNOTSUPP45;
224 goto release;
225 }
226
227 rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
228 if (rop == NULL((void *)0)) {
229 error = EINVAL22;
230 goto release;
231 }
232
233 switch (req) {
234 /* no connect, bind, accept. Socket is connected from the start */
235 case PRU_CONNECT4:
236 case PRU_BIND2:
237 case PRU_CONNECT217:
238 case PRU_LISTEN3:
239 case PRU_ACCEPT5:
240 error = EOPNOTSUPP45;
241 break;
242
243 case PRU_DISCONNECT6:
244 case PRU_ABORT10:
245 soisdisconnected(so);
246 break;
247 case PRU_SHUTDOWN7:
248 socantsendmore(so);
249 break;
250 case PRU_SENSE12:
251 /* stat: don't bother with a blocksize. */
252 break;
253
254 /* minimal support, just implement a fake peer address */
255 case PRU_SOCKADDR15:
256 error = EINVAL22;
257 break;
258 case PRU_PEERADDR16:
259 bcopy(&route_src, mtod(nam, caddr_t)((caddr_t)((nam)->m_hdr.mh_data)), route_src.sa_len);
260 nam->m_lenm_hdr.mh_len = route_src.sa_len;
261 break;
262
263 case PRU_RCVD8:
264 /*
265 * If we are in a FLUSH state, check if the buffer is
266 * empty so that we can clear the flag.
267 */
268 if (((rop->rop_flags & ROUTECB_FLAG_FLUSH0x2) != 0) &&
269 ((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) ==
270 rop->rop_socket->so_rcv.sb_hiwat)))
271 rop->rop_flags &= ~ROUTECB_FLAG_FLUSH0x2;
272 break;
273
274 case PRU_RCVOOB13:
275 case PRU_SENDOOB14:
276 error = EOPNOTSUPP45;
277 break;
278 case PRU_SEND9:
279 if (nam) {
280 error = EISCONN56;
281 break;
282 }
283 error = (*so->so_proto->pr_output)(m, so, NULL((void *)0), NULL((void *)0));
284 m = NULL((void *)0);
285 break;
286 default:
287 panic("route_usrreq");
288 }
289
290 release:
291 if (req != PRU_RCVD8 && req != PRU_RCVOOB13 && req != PRU_SENSE12) {
292 m_freem(control);
293 m_freem(m);
294 }
295 return (error);
296}
297
298int
299route_attach(struct socket *so, int proto)
300{
301 struct rtpcb *rop;
302 int error;
303
304 error = soreserve(so, ROUTESNDQ8192, ROUTERCVQ8192);
305 if (error)
306 return (error);
307 /*
308 * use the rawcb but allocate a rtpcb, this
309 * code does not care about the additional fields
310 * and works directly on the raw socket.
311 */
312 rop = pool_get(&rtpcb_pool, PR_WAITOK0x0001|PR_ZERO0x0008);
313 so->so_pcb = rop;
314 /* Init the timeout structure */
315 timeout_set_proc(&rop->rop_timeout, rtm_senddesync_timer, so);
316 refcnt_init(&rop->rop_refcnt);
317
318 rop->rop_socket = so;
319 rop->rop_proto = proto;
320
321 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;
322
323 soisconnected(so);
324 so->so_options |= SO_USELOOPBACK0x0040;
325
326 rw_enter(&rtptable.rtp_lk, RW_WRITE0x0001UL);
327 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)
328 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)
;
329 rtptable.rtp_count++;
330 rw_exit(&rtptable.rtp_lk);
331
332 return (0);
333}
334
335int
336route_detach(struct socket *so)
337{
338 struct rtpcb *rop;
339
340 soassertlocked(so);
341
342 rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
343 if (rop == NULL((void *)0))
344 return (EINVAL22);
345
346 rw_enter(&rtptable.rtp_lk, RW_WRITE0x0001UL);
347
348 rtptable.rtp_count--;
349 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)
350 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)
;
351 rw_exit(&rtptable.rtp_lk);
352
353 sounlock(so, SL_LOCKED0x42);
354
355 /* wait for all references to drop */
356 refcnt_finalize(&rop->rop_refcnt, "rtsockrefs");
357 timeout_del_barrier(&rop->rop_timeout);
358
359 solock(so);
360
361 so->so_pcb = NULL((void *)0);
362 KASSERT((so->so_state & SS_NOFDREF) == 0)(((so->so_state & 0x001) == 0) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/rtsock.c", 362, "(so->so_state & SS_NOFDREF) == 0"
))
;
363 pool_put(&rtpcb_pool, rop);
364
365 return (0);
366}
367
368int
369route_ctloutput(int op, struct socket *so, int level, int optname,
370 struct mbuf *m)
371{
372 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
373 int error = 0;
374 unsigned int tid, prio;
375
376 if (level != AF_ROUTE17)
377 return (EINVAL22);
378
379 switch (op) {
380 case PRCO_SETOPT1:
381 switch (optname) {
382 case ROUTE_MSGFILTER1:
383 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int))
384 error = EINVAL22;
385 else
386 rop->rop_msgfilter = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
387 break;
388 case ROUTE_TABLEFILTER2:
389 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int)) {
390 error = EINVAL22;
391 break;
392 }
393 tid = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
394 if (tid != RTABLE_ANY0xffffffff && !rtable_exists(tid))
395 error = ENOENT2;
396 else
397 rop->rop_rtableid = tid;
398 break;
399 case ROUTE_PRIOFILTER3:
400 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int)) {
401 error = EINVAL22;
402 break;
403 }
404 prio = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
405 if (prio > RTP_MAX63)
406 error = EINVAL22;
407 else
408 rop->rop_priority = prio;
409 break;
410 case ROUTE_FLAGFILTER4:
411 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof(unsigned int))
412 error = EINVAL22;
413 else
414 rop->rop_flagfilter = *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data));
415 break;
416 default:
417 error = ENOPROTOOPT42;
418 break;
419 }
420 break;
421 case PRCO_GETOPT0:
422 switch (optname) {
423 case ROUTE_MSGFILTER1:
424 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
425 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_msgfilter;
426 break;
427 case ROUTE_TABLEFILTER2:
428 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
429 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_rtableid;
430 break;
431 case ROUTE_PRIOFILTER3:
432 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
433 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_priority;
434 break;
435 case ROUTE_FLAGFILTER4:
436 m->m_lenm_hdr.mh_len = sizeof(unsigned int);
437 *mtod(m, unsigned int *)((unsigned int *)((m)->m_hdr.mh_data)) = rop->rop_flagfilter;
438 break;
439 default:
440 error = ENOPROTOOPT42;
441 break;
442 }
443 }
444 return (error);
445}
446
447void
448rtm_senddesync_timer(void *xso)
449{
450 struct socket *so = xso;
451 int s;
452
453 s = solock(so);
454 rtm_senddesync(so);
455 sounlock(so, s);
456}
457
458void
459rtm_senddesync(struct socket *so)
460{
461 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
462 struct mbuf *desync_mbuf;
463
464 soassertlocked(so);
465
466 /*
467 * Dying socket is disconnected by upper layer and there is
468 * no reason to send packet. Also we shouldn't reschedule
469 * timeout(9), otherwise timeout_del_barrier(9) can't help us.
470 */
471 if ((so->so_state & SS_ISCONNECTED0x002) == 0 ||
472 (so->so_state & SS_CANTRCVMORE0x020))
473 return;
474
475 /* If we are in a DESYNC state, try to send a RTM_DESYNC packet */
476 if ((rop->rop_flags & ROUTECB_FLAG_DESYNC0x1) == 0)
477 return;
478
479 /*
480 * If we fail to alloc memory or if sbappendaddr()
481 * fails, re-add timeout and try again.
482 */
483 desync_mbuf = rtm_msg1(RTM_DESYNC0x10, NULL((void *)0));
484 if (desync_mbuf != NULL((void *)0)) {
485 if (sbappendaddr(so, &so->so_rcv, &route_src,
486 desync_mbuf, NULL((void *)0)) != 0) {
487 rop->rop_flags &= ~ROUTECB_FLAG_DESYNC0x1;
488 sorwakeup(rop->rop_socket);
489 return;
490 }
491 m_freem(desync_mbuf);
492 }
493 /* Re-add timeout to try sending msg again */
494 timeout_add_msec(&rop->rop_timeout, ROUTE_DESYNC_RESEND_TIMEOUT200);
495}
496
497void
498route_input(struct mbuf *m0, struct socket *so0, sa_family_t sa_family)
499{
500 struct socket *so;
501 struct rtpcb *rop;
502 struct rt_msghdr *rtm;
503 struct mbuf *m = m0;
504 struct srp_ref sr;
505 int s;
506
507 /* ensure that we can access the rtm_type via mtod() */
508 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
509 m_freem(m);
510 return;
511 }
512
513 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
8
Loop condition is true. Entering loop body
514 /*
515 * If route socket is bound to an address family only send
516 * messages that match the address family. Address family
517 * agnostic messages are always sent.
518 */
519 if (sa_family != AF_UNSPEC0 && rop->rop_proto != AF_UNSPEC0 &&
9
Assuming 'sa_family' is equal to AF_UNSPEC
520 rop->rop_proto != sa_family)
521 continue;
522
523
524 so = rop->rop_socket;
525 s = solock(so);
526
527 /*
528 * Check to see if we don't want our own messages and
529 * if we can receive anything.
530 */
531 if ((so0 == so && !(so0->so_options & SO_USELOOPBACK0x0040)) ||
10
Assuming 'so0' is equal to 'so'
11
Access to field 'so_options' results in a dereference of a null pointer (loaded from variable 'so0')
532 !(so->so_state & SS_ISCONNECTED0x002) ||
533 (so->so_state & SS_CANTRCVMORE0x020))
534 goto next;
535
536 /* filter messages that the process does not want */
537 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
538 /* but RTM_DESYNC can't be filtered */
539 if (rtm->rtm_type != RTM_DESYNC0x10) {
540 if (rop->rop_msgfilter != 0 &&
541 !(rop->rop_msgfilter & (1 << rtm->rtm_type)))
542 goto next;
543 if (ISSET(rop->rop_flagfilter, rtm->rtm_flags)((rop->rop_flagfilter) & (rtm->rtm_flags)))
544 goto next;
545 }
546 switch (rtm->rtm_type) {
547 case RTM_IFANNOUNCE0xf:
548 case RTM_DESYNC0x10:
549 /* no tableid */
550 break;
551 case RTM_RESOLVE0xb:
552 case RTM_NEWADDR0xc:
553 case RTM_DELADDR0xd:
554 case RTM_IFINFO0xe:
555 case RTM_80211INFO0x15:
556 case RTM_BFD0x12:
557 /* check against rdomain id */
558 if (rop->rop_rtableid != RTABLE_ANY0xffffffff &&
559 rtable_l2(rop->rop_rtableid) != rtm->rtm_tableid)
560 goto next;
561 break;
562 default:
563 if (rop->rop_priority != 0 &&
564 rop->rop_priority < rtm->rtm_priority)
565 goto next;
566 /* check against rtable id */
567 if (rop->rop_rtableid != RTABLE_ANY0xffffffff &&
568 rop->rop_rtableid != rtm->rtm_tableid)
569 goto next;
570 break;
571 }
572
573 /*
574 * Check to see if the flush flag is set. If so, don't queue
575 * any more messages until the flag is cleared.
576 */
577 if ((rop->rop_flags & ROUTECB_FLAG_FLUSH0x2) != 0)
578 goto next;
579
580 rtm_sendup(so, m);
581next:
582 sounlock(so, s);
583 }
584 SRPL_LEAVE(&sr)srp_leave((&sr));
585
586 m_freem(m);
587}
588
589int
590rtm_sendup(struct socket *so, struct mbuf *m0)
591{
592 struct rtpcb *rop = sotortpcb(so)((struct rtpcb *)(so)->so_pcb);
593 struct mbuf *m;
594
595 soassertlocked(so);
596
597 m = m_copym(m0, 0, M_COPYALL1000000000, M_NOWAIT0x0002);
598 if (m == NULL((void *)0))
599 return (ENOMEM12);
600
601 if (sbspace(so, &so->so_rcv) < (2 * MSIZE256) ||
602 sbappendaddr(so, &so->so_rcv, &route_src, m, NULL((void *)0)) == 0) {
603 /* Flag socket as desync'ed and flush required */
604 rop->rop_flags |= ROUTECB_FLAG_DESYNC0x1 | ROUTECB_FLAG_FLUSH0x2;
605 rtm_senddesync(so);
606 m_freem(m);
607 return (ENOBUFS55);
608 }
609
610 sorwakeup(so);
611 return (0);
612}
613
614struct rt_msghdr *
615rtm_report(struct rtentry *rt, u_char type, int seq, int tableid)
616{
617 struct rt_msghdr *rtm;
618 struct rt_addrinfo info;
619 struct sockaddr_rtlabel sa_rl;
620 struct sockaddr_in6 sa_mask;
621#ifdef BFD
622 struct sockaddr_bfd sa_bfd;
623#endif
624 struct ifnet *ifp = NULL((void *)0);
625 int len;
626
627 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
628 info.rti_info[RTAX_DST0] = rt_key(rt)((rt)->rt_dest);
629 info.rti_info[RTAX_GATEWAY1] = rt->rt_gateway;
630 info.rti_info[RTAX_NETMASK2] = rt_plen2mask(rt, &sa_mask);
631 info.rti_info[RTAX_LABEL10] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
632#ifdef BFD
633 if (rt->rt_flags & RTF_BFD0x1000000) {
634 KERNEL_LOCK()_kernel_lock();
635 info.rti_info[RTAX_BFD11] = bfd2sa(rt, &sa_bfd);
636 KERNEL_UNLOCK()_kernel_unlock();
637 }
638#endif
639#ifdef MPLS1
640 if (rt->rt_flags & RTF_MPLS0x100000) {
641 struct sockaddr_mpls sa_mpls;
642
643 bzero(&sa_mpls, sizeof(sa_mpls))__builtin_bzero((&sa_mpls), (sizeof(sa_mpls)));
644 sa_mpls.smpls_family = AF_MPLS33;
645 sa_mpls.smpls_len = sizeof(sa_mpls);
646 sa_mpls.smpls_label = ((struct rt_mpls *)
647 rt->rt_llinfo)->mpls_label;
648 info.rti_info[RTAX_SRC8] = (struct sockaddr *)&sa_mpls;
649 info.rti_mpls = ((struct rt_mpls *)
650 rt->rt_llinfo)->mpls_operation;
651 }
652#endif
653 ifp = if_get(rt->rt_ifidx);
654 if (ifp != NULL((void *)0)) {
655 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
656 info.rti_info[RTAX_IFA5] =
657 rtable_getsource(tableid, info.rti_info[RTAX_DST0]->sa_family);
658 if (info.rti_info[RTAX_IFA5] == NULL((void *)0))
659 info.rti_info[RTAX_IFA5] = rt->rt_ifa->ifa_addr;
660 if (ifp->if_flags & IFF_POINTOPOINT0x10)
661 info.rti_info[RTAX_BRD7] = rt->rt_ifa->ifa_dstaddr;
662 }
663 if_put(ifp);
664 /* RTAX_GENMASK, RTAX_AUTHOR, RTAX_SRCMASK ignored */
665
666 /* build new route message */
667 len = rtm_msg2(type, RTM_VERSION5, &info, NULL((void *)0), NULL((void *)0));
668 rtm = malloc(len, M_RTABLE5, M_WAITOK0x0001 | M_ZERO0x0008);
669
670 rtm_msg2(type, RTM_VERSION5, &info, (caddr_t)rtm, NULL((void *)0));
671 rtm->rtm_type = type;
672 rtm->rtm_index = rt->rt_ifidx;
673 rtm->rtm_tableid = tableid;
674 rtm->rtm_priority = rt->rt_priority & RTP_MASK0x7f;
675 rtm->rtm_flags = rt->rt_flags;
676 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;
677 rtm->rtm_seq = seq;
678 rtm_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
679 rtm->rtm_addrs = info.rti_addrs;
680#ifdef MPLS1
681 rtm->rtm_mpls = info.rti_mpls;
682#endif
683 return rtm;
684}
685
686int
687route_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr,
688 struct mbuf *control)
689{
690 struct rt_msghdr *rtm = NULL((void *)0);
691 struct rtentry *rt = NULL((void *)0);
692 struct rt_addrinfo info;
693 struct ifnet *ifp;
694 int len, seq, useloopback, error = 0;
695 u_int tableid;
696 u_int8_t prio;
697 u_char vers, type;
698
699 if (m == NULL((void *)0) || ((m->m_lenm_hdr.mh_len < sizeof(int32_t)) &&
700 (m = m_pullup(m, sizeof(int32_t))) == 0))
701 return (ENOBUFS55);
702 if ((m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) == 0)
703 panic("route_output");
704
705 useloopback = so->so_options & SO_USELOOPBACK0x0040;
706
707 /*
708 * The socket can't be closed concurrently because the file
709 * descriptor reference is still held.
710 */
711
712 sounlock(so, SL_LOCKED0x42);
713
714 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
715 if (len < offsetof(struct rt_msghdr, rtm_hdrlen)__builtin_offsetof(struct rt_msghdr, rtm_hdrlen) + 1 ||
716 len != mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data))->rtm_msglen) {
717 error = EINVAL22;
718 goto fail;
719 }
720 vers = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data))->rtm_version;
721 switch (vers) {
722 case RTM_VERSION5:
723 if (len < sizeof(struct rt_msghdr)) {
724 error = EINVAL22;
725 goto fail;
726 }
727 if (len > RTM_MAXSIZE2048) {
728 error = EMSGSIZE40;
729 goto fail;
730 }
731 rtm = malloc(len, M_RTABLE5, M_WAITOK0x0001);
732 m_copydata(m, 0, len, rtm);
733 break;
734 default:
735 error = EPROTONOSUPPORT43;
736 goto fail;
737 }
738
739 /* Verify that the caller is sending an appropriate message early */
740 switch (rtm->rtm_type) {
741 case RTM_ADD0x1:
742 case RTM_DELETE0x2:
743 case RTM_GET0x4:
744 case RTM_CHANGE0x3:
745 case RTM_PROPOSAL0x13:
746 case RTM_SOURCE0x16:
747 break;
748 default:
749 error = EOPNOTSUPP45;
750 goto fail;
751 }
752 /*
753 * Verify that the header length is valid.
754 * All messages from userland start with a struct rt_msghdr.
755 */
756 if (rtm->rtm_hdrlen == 0) /* old client */
757 rtm->rtm_hdrlen = sizeof(struct rt_msghdr);
758 if (rtm->rtm_hdrlen < sizeof(struct rt_msghdr) ||
759 len < rtm->rtm_hdrlen) {
760 error = EINVAL22;
761 goto fail;
762 }
763
764 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;
765
766 /*
767 * Verify that the caller has the appropriate privilege; RTM_GET
768 * is the only operation the non-superuser is allowed.
769 */
770 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) {
771 error = EACCES13;
772 goto fail;
773 }
774 tableid = rtm->rtm_tableid;
775 if (!rtable_exists(tableid)) {
776 if (rtm->rtm_type == RTM_ADD0x1) {
777 if ((error = rtable_add(tableid)) != 0)
778 goto fail;
779 } else {
780 error = EINVAL22;
781 goto fail;
782 }
783 }
784
785 /* Do not let userland play with kernel-only flags. */
786 if ((rtm->rtm_flags & (RTF_LOCAL0x200000|RTF_BROADCAST0x400000)) != 0) {
787 error = EINVAL22;
788 goto fail;
789 }
790
791 /* make sure that kernel-only bits are not set */
792 rtm->rtm_priority &= RTP_MASK0x7f;
793 rtm->rtm_flags &= ~(RTF_DONE0x40|RTF_CLONED0x10000|RTF_CACHED0x20000);
794 rtm->rtm_fmask &= RTF_FMASK(0x400 | 0x8000 | 0x4000 | 0x2000 | 0x1000 | 0x8 | 0x800 | 0x100000
| 0x1000000)
;
795
796 if (rtm->rtm_priority != 0) {
797 if (rtm->rtm_priority > RTP_MAX63 ||
798 rtm->rtm_priority == RTP_LOCAL1) {
799 error = EINVAL22;
800 goto fail;
801 }
802 prio = rtm->rtm_priority;
803 } else if (rtm->rtm_type != RTM_ADD0x1)
804 prio = RTP_ANY64;
805 else if (rtm->rtm_flags & RTF_STATIC0x800)
806 prio = 0;
807 else
808 prio = RTP_DEFAULT56;
809
810 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
811 info.rti_addrs = rtm->rtm_addrs;
812 if ((error = rtm_xaddrs(rtm->rtm_hdrlen + (caddr_t)rtm,
813 len + (caddr_t)rtm, &info)) != 0)
814 goto fail;
815
816 info.rti_flags = rtm->rtm_flags;
817
818 if (rtm->rtm_type != RTM_SOURCE0x16 &&
819 rtm->rtm_type != RTM_PROPOSAL0x13 &&
820 (info.rti_info[RTAX_DST0] == NULL((void *)0) ||
821 info.rti_info[RTAX_DST0]->sa_family >= AF_MAX36 ||
822 (info.rti_info[RTAX_GATEWAY1] != NULL((void *)0) &&
823 info.rti_info[RTAX_GATEWAY1]->sa_family >= AF_MAX36) ||
824 info.rti_info[RTAX_GENMASK3] != NULL((void *)0))) {
825 error = EINVAL22;
826 goto fail;
827 }
828#ifdef MPLS1
829 info.rti_mpls = rtm->rtm_mpls;
830#endif
831
832 if (info.rti_info[RTAX_GATEWAY1] != NULL((void *)0) &&
833 info.rti_info[RTAX_GATEWAY1]->sa_family == AF_LINK18 &&
834 (info.rti_flags & RTF_CLONING0x100) == 0) {
835 info.rti_flags |= RTF_LLINFO0x400;
836 }
837
838 /*
839 * Validate RTM_PROPOSAL and pass it along or error out.
840 */
841 if (rtm->rtm_type == RTM_PROPOSAL0x13) {
842 if (rtm_validate_proposal(&info) == -1) {
843 error = EINVAL22;
844 goto fail;
845 }
846 /*
847 * If this is a solicitation proposal forward request to
848 * all interfaces. Most handlers will ignore it but at least
849 * umb(4) will send a response to this event.
850 */
851 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT62) {
852 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
853 TAILQ_FOREACH(ifp, &ifnet, if_list)for((ifp) = ((&ifnet)->tqh_first); (ifp) != ((void *)0
); (ifp) = ((ifp)->if_list.tqe_next))
{
854 ifp->if_rtrequest(ifp, RTM_PROPOSAL0x13, NULL((void *)0));
855 }
856 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
857 }
858 } else if (rtm->rtm_type == RTM_SOURCE0x16) {
859 if (info.rti_info[RTAX_IFA5] == NULL((void *)0)) {
860 error = EINVAL22;
861 goto fail;
862 }
863 if ((error =
864 rt_setsource(tableid, info.rti_info[RTAX_IFA5])) != 0)
865 goto fail;
866 } else {
867 error = rtm_output(rtm, &rt, &info, prio, tableid);
868 if (!error) {
869 type = rtm->rtm_type;
870 seq = rtm->rtm_seq;
871 free(rtm, M_RTABLE5, len);
872 rtm = rtm_report(rt, type, seq, tableid);
873 len = rtm->rtm_msglen;
874 }
875 }
876
877 rtfree(rt);
878 if (error) {
879 rtm->rtm_errno = error;
880 } else {
881 rtm->rtm_flags |= RTF_DONE0x40;
882 }
883
884 /*
885 * Check to see if we don't want our own messages.
886 */
887 if (!useloopback) {
888 if (rtptable.rtp_count == 0) {
889 /* no other listener and no loopback of messages */
890 goto fail;
891 }
892 }
893 if (m_copyback(m, 0, len, rtm, M_NOWAIT0x0002)) {
894 m_freem(m);
895 m = NULL((void *)0);
896 } else if (m->m_pkthdrM_dat.MH.MH_pkthdr.len > len)
897 m_adj(m, len - m->m_pkthdrM_dat.MH.MH_pkthdr.len);
898 free(rtm, M_RTABLE5, len);
899 if (m)
900 route_input(m, so, info.rti_info[RTAX_DST0] ?
901 info.rti_info[RTAX_DST0]->sa_family : AF_UNSPEC0);
902 solock(so);
903
904 return (error);
905fail:
906 free(rtm, M_RTABLE5, len);
907 m_freem(m);
908 solock(so);
909
910 return (error);
911}
912
913int
914rtm_output(struct rt_msghdr *rtm, struct rtentry **prt,
915 struct rt_addrinfo *info, uint8_t prio, unsigned int tableid)
916{
917 struct rtentry *rt = *prt;
918 struct ifnet *ifp = NULL((void *)0);
919 int plen, newgate = 0, error = 0;
920
921 switch (rtm->rtm_type) {
922 case RTM_ADD0x1:
923 if (info->rti_info[RTAX_GATEWAY1] == NULL((void *)0)) {
924 error = EINVAL22;
925 break;
926 }
927
928 rt = rtable_match(tableid, info->rti_info[RTAX_DST0], NULL((void *)0));
929 if ((error = route_arp_conflict(rt, info))) {
930 rtfree(rt);
931 rt = NULL((void *)0);
932 break;
933 }
934
935 /*
936 * We cannot go through a delete/create/insert cycle for
937 * cached route because this can lead to races in the
938 * receive path. Instead we update the L2 cache.
939 */
940 if ((rt != NULL((void *)0)) && ISSET(rt->rt_flags, RTF_CACHED)((rt->rt_flags) & (0x20000))) {
941 ifp = if_get(rt->rt_ifidx);
942 if (ifp == NULL((void *)0)) {
943 rtfree(rt);
944 rt = NULL((void *)0);
945 error = ESRCH3;
946 break;
947 }
948
949 goto change;
950 }
951
952 rtfree(rt);
953 rt = NULL((void *)0);
954
955 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
956 if ((error = rtm_getifa(info, tableid)) != 0) {
957 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
958 break;
959 }
960 error = rtrequest(RTM_ADD0x1, info, prio, &rt, tableid);
961 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
962 if (error == 0)
963 rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
964 &rt->rt_rmx);
965 break;
966 case RTM_DELETE0x2:
967 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
968 info->rti_info[RTAX_NETMASK2], info->rti_info[RTAX_GATEWAY1],
969 prio);
970 if (rt == NULL((void *)0)) {
971 error = ESRCH3;
972 break;
973 }
974
975 /*
976 * If we got multipath routes, we require users to specify
977 * a matching gateway.
978 */
979 if (ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000)) &&
980 info->rti_info[RTAX_GATEWAY1] == NULL((void *)0)) {
981 error = ESRCH3;
982 break;
983 }
984
985 ifp = if_get(rt->rt_ifidx);
986 if (ifp == NULL((void *)0)) {
987 rtfree(rt);
988 rt = NULL((void *)0);
989 error = ESRCH3;
990 break;
991 }
992
993 /*
994 * Invalidate the cache of automagically created and
995 * referenced L2 entries to make sure that ``rt_gwroute''
996 * pointer stays valid for other CPUs.
997 */
998 if ((ISSET(rt->rt_flags, RTF_CACHED)((rt->rt_flags) & (0x20000)))) {
999 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1000 ifp->if_rtrequest(ifp, RTM_INVALIDATE0x11, rt);
1001 /* Reset the MTU of the gateway route. */
1002 rtable_walk(tableid, rt_key(rt)((rt)->rt_dest)->sa_family, NULL((void *)0),
1003 route_cleargateway, rt);
1004 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1005 break;
1006 }
1007
1008 /*
1009 * Make sure that local routes are only modified by the
1010 * kernel.
1011 */
1012 if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)((rt->rt_flags) & (0x200000|0x400000))) {
1013 error = EINVAL22;
1014 break;
1015 }
1016
1017 rtfree(rt);
1018 rt = NULL((void *)0);
1019
1020 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1021 error = rtrequest_delete(info, prio, ifp, &rt, tableid);
1022 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1023 break;
1024 case RTM_CHANGE0x3:
1025 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
1026 info->rti_info[RTAX_NETMASK2], info->rti_info[RTAX_GATEWAY1],
1027 prio);
1028 /*
1029 * If we got multipath routes, we require users to specify
1030 * a matching gateway.
1031 */
1032 if ((rt != NULL((void *)0)) && ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000)) &&
1033 (info->rti_info[RTAX_GATEWAY1] == NULL((void *)0))) {
1034 rtfree(rt);
1035 rt = NULL((void *)0);
1036 }
1037
1038 /*
1039 * If RTAX_GATEWAY is the argument we're trying to
1040 * change, try to find a compatible route.
1041 */
1042 if ((rt == NULL((void *)0)) && (info->rti_info[RTAX_GATEWAY1] != NULL((void *)0))) {
1043 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
1044 info->rti_info[RTAX_NETMASK2], NULL((void *)0), prio);
1045 /* Ensure we don't pick a multipath one. */
1046 if ((rt != NULL((void *)0)) && ISSET(rt->rt_flags, RTF_MPATH)((rt->rt_flags) & (0x40000))) {
1047 rtfree(rt);
1048 rt = NULL((void *)0);
1049 }
1050 }
1051
1052 if (rt == NULL((void *)0)) {
1053 error = ESRCH3;
1054 break;
1055 }
1056
1057 /*
1058 * Make sure that local routes are only modified by the
1059 * kernel.
1060 */
1061 if (ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)((rt->rt_flags) & (0x200000|0x400000))) {
1062 error = EINVAL22;
1063 break;
1064 }
1065
1066 ifp = if_get(rt->rt_ifidx);
1067 if (ifp == NULL((void *)0)) {
1068 rtfree(rt);
1069 rt = NULL((void *)0);
1070 error = ESRCH3;
1071 break;
1072 }
1073
1074 /*
1075 * RTM_CHANGE needs a perfect match.
1076 */
1077 plen = rtable_satoplen(info->rti_info[RTAX_DST0]->sa_family,
1078 info->rti_info[RTAX_NETMASK2]);
1079 if (rt_plen(rt)((rt)->rt_plen) != plen) {
1080 error = ESRCH3;
1081 break;
1082 }
1083
1084 if (info->rti_info[RTAX_GATEWAY1] != NULL((void *)0))
1085 if (rt->rt_gateway == NULL((void *)0) ||
1086 bcmp(rt->rt_gateway,
1087 info->rti_info[RTAX_GATEWAY1],
1088 info->rti_info[RTAX_GATEWAY1]->sa_len)) {
1089 newgate = 1;
1090 }
1091 /*
1092 * Check reachable gateway before changing the route.
1093 * New gateway could require new ifaddr, ifp;
1094 * flags may also be different; ifp may be specified
1095 * by ll sockaddr when protocol address is ambiguous.
1096 */
1097 if (newgate || info->rti_info[RTAX_IFP4] != NULL((void *)0) ||
1098 info->rti_info[RTAX_IFA5] != NULL((void *)0)) {
1099 struct ifaddr *ifa = NULL((void *)0);
1100
1101 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1102 if ((error = rtm_getifa(info, tableid)) != 0) {
1103 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1104 break;
1105 }
1106 ifa = info->rti_ifa;
1107 if (rt->rt_ifa != ifa) {
1108 ifp->if_rtrequest(ifp, RTM_DELETE0x2, rt);
1109 ifafree(rt->rt_ifa);
1110
1111 ifa->ifa_refcnt++;
1112 rt->rt_ifa = ifa;
1113 rt->rt_ifidx = ifa->ifa_ifp->if_index;
1114 /* recheck link state after ifp change */
1115 rt_if_linkstate_change(rt, ifa->ifa_ifp,
1116 tableid);
1117 }
1118 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1119 }
1120change:
1121 if (info->rti_info[RTAX_GATEWAY1] != NULL((void *)0)) {
1122 /* When updating the gateway, make sure it is valid. */
1123 if (!newgate && rt->rt_gateway->sa_family !=
1124 info->rti_info[RTAX_GATEWAY1]->sa_family) {
1125 error = EINVAL22;
1126 break;
1127 }
1128
1129 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1130 error = rt_setgate(rt,
1131 info->rti_info[RTAX_GATEWAY1], tableid);
1132 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1133 if (error)
1134 break;
1135 }
1136#ifdef MPLS1
1137 if (rtm->rtm_flags & RTF_MPLS0x100000) {
1138 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1139 error = rt_mpls_set(rt,
1140 info->rti_info[RTAX_SRC8], info->rti_mpls);
1141 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1142 if (error)
1143 break;
1144 } else if (newgate || (rtm->rtm_fmask & RTF_MPLS0x100000)) {
1145 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1146 /* if gateway changed remove MPLS information */
1147 rt_mpls_clear(rt);
1148 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1149 }
1150#endif
1151
1152#ifdef BFD
1153 if (ISSET(rtm->rtm_flags, RTF_BFD)((rtm->rtm_flags) & (0x1000000))) {
1154 KERNEL_LOCK()_kernel_lock();
1155 error = bfdset(rt);
1156 KERNEL_UNLOCK()_kernel_unlock();
1157 if (error)
1158 break;
1159 } else if (!ISSET(rtm->rtm_flags, RTF_BFD)((rtm->rtm_flags) & (0x1000000)) &&
1160 ISSET(rtm->rtm_fmask, RTF_BFD)((rtm->rtm_fmask) & (0x1000000))) {
1161 KERNEL_LOCK()_kernel_lock();
1162 bfdclear(rt);
1163 KERNEL_UNLOCK()_kernel_unlock();
1164 }
1165#endif
1166
1167 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
1168 /* Hack to allow some flags to be toggled */
1169 if (rtm->rtm_fmask) {
1170 /* MPLS flag it is set by rt_mpls_set() */
1171 rtm->rtm_fmask &= ~RTF_MPLS0x100000;
1172 rtm->rtm_flags &= ~RTF_MPLS0x100000;
1173 rt->rt_flags =
1174 (rt->rt_flags & ~rtm->rtm_fmask) |
1175 (rtm->rtm_flags & rtm->rtm_fmask);
1176 }
1177 rtm_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
1178
1179 ifp->if_rtrequest(ifp, RTM_ADD0x1, rt);
1180
1181 if (info->rti_info[RTAX_LABEL10] != NULL((void *)0)) {
1182 char *rtlabel = ((struct sockaddr_rtlabel *)
1183 info->rti_info[RTAX_LABEL10])->sr_label;
1184 rtlabel_unref(rt->rt_labelid);
1185 rt->rt_labelid = rtlabel_name2id(rtlabel);
1186 }
1187 if_group_routechange(info->rti_info[RTAX_DST0],
1188 info->rti_info[RTAX_NETMASK2]);
1189 rt->rt_locksrt_rmx.rmx_locks &= ~(rtm->rtm_inits);
1190 rt->rt_locksrt_rmx.rmx_locks |= (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
1191 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
1192 break;
1193 case RTM_GET0x4:
1194 rt = rtable_lookup(tableid, info->rti_info[RTAX_DST0],
1195 info->rti_info[RTAX_NETMASK2], info->rti_info[RTAX_GATEWAY1],
1196 prio);
1197 if (rt == NULL((void *)0))
1198 error = ESRCH3;
1199 break;
1200 }
1201
1202 if_put(ifp);
1203 *prt = rt;
1204 return (error);
1205}
1206
1207struct ifaddr *
1208ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway,
1209 unsigned int rtableid)
1210{
1211 struct ifaddr *ifa;
1212
1213 if ((flags & RTF_GATEWAY0x2) == 0) {
1214 /*
1215 * If we are adding a route to an interface,
1216 * and the interface is a pt to pt link
1217 * we should search for the destination
1218 * as our clue to the interface. Otherwise
1219 * we can use the local address.
1220 */
1221 ifa = NULL((void *)0);
1222 if (flags & RTF_HOST0x4)
1223 ifa = ifa_ifwithdstaddr(dst, rtableid);
1224 if (ifa == NULL((void *)0))
1225 ifa = ifa_ifwithaddr(gateway, rtableid);
1226 } else {
1227 /*
1228 * If we are adding a route to a remote net
1229 * or host, the gateway may still be on the
1230 * other end of a pt to pt link.
1231 */
1232 ifa = ifa_ifwithdstaddr(gateway, rtableid);
1233 }
1234 if (ifa == NULL((void *)0)) {
1235 if (gateway->sa_family == AF_LINK18) {
1236 struct sockaddr_dl *sdl = satosdl(gateway);
1237 struct ifnet *ifp = if_get(sdl->sdl_index);
1238
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 struct sockaddr_dl *sdl;
1279
1280 sdl = satosdl(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 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 rt_kmetrics *in, struct rt_metrics *out)
1396{
1397 int64_t expire;
1398
1399 expire = in->rmx_expire;
1400 if (expire != 0) {
1401 expire -= getuptime();
1402 expire += gettime();
1403 }
1404
1405 bzero(out, sizeof(*out))__builtin_bzero((out), (sizeof(*out)));
1406 out->rmx_locks = in->rmx_locks;
1407 out->rmx_mtu = in->rmx_mtu;
1408 out->rmx_expire = expire;
1409 out->rmx_pksent = in->rmx_pksent;
1410}
1411
1412#define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof
(long))
\
1413 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1414#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))
)
1415
1416int
1417rtm_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
1418{
1419 struct sockaddr *sa;
1420 int i;
1421
1422 /*
1423 * Parse address bits, split address storage in chunks, and
1424 * set info pointers. Use sa_len for traversing the memory
1425 * and check that we stay within in the limit.
1426 */
1427 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info))__builtin_bzero((rtinfo->rti_info), (sizeof(rtinfo->rti_info
)))
;
1428 for (i = 0; i < sizeof(rtinfo->rti_addrs) * 8; i++) {
1429 if ((rtinfo->rti_addrs & (1 << i)) == 0)
1430 continue;
1431 if (i >= RTAX_MAX15 || cp + sizeof(socklen_t) > cplim)
1432 return (EINVAL22);
1433 sa = (struct sockaddr *)cp;
1434 if (cp + sa->sa_len > cplim)
1435 return (EINVAL22);
1436 rtinfo->rti_info[i] = sa;
1437 ADVANCE(cp, sa)(cp += (((sa)->sa_len) > 0 ? (1 + ((((sa)->sa_len) -
1) | (sizeof(long) - 1))) : sizeof(long)))
;
1438 }
1439 /*
1440 * Check that the address family is suitable for the route address
1441 * type. Check that each address has a size that fits its family
1442 * and its length is within the size. Strings within addresses must
1443 * be NUL terminated.
1444 */
1445 for (i = 0; i < RTAX_MAX15; i++) {
1446 size_t len, maxlen, size;
1447
1448 sa = rtinfo->rti_info[i];
1449 if (sa == NULL((void *)0))
1450 continue;
1451 maxlen = size = 0;
1452 switch (i) {
1453 case RTAX_DST0:
1454 case RTAX_GATEWAY1:
1455 case RTAX_SRC8:
1456 switch (sa->sa_family) {
1457 case AF_INET2:
1458 size = sizeof(struct sockaddr_in);
1459 break;
1460 case AF_LINK18:
1461 size = sizeof(struct sockaddr_dl);
1462 break;
1463#ifdef INET61
1464 case AF_INET624:
1465 size = sizeof(struct sockaddr_in6);
1466 break;
1467#endif
1468#ifdef MPLS1
1469 case AF_MPLS33:
1470 size = sizeof(struct sockaddr_mpls);
1471 break;
1472#endif
1473 }
1474 break;
1475 case RTAX_IFP4:
1476 if (sa->sa_family != AF_LINK18)
1477 return (EAFNOSUPPORT47);
1478 /*
1479 * XXX Should be sizeof(struct sockaddr_dl), but
1480 * route(8) has a bug and provides less memory.
1481 * arp(8) has another bug and uses sizeof pointer.
1482 */
1483 size = 4;
1484 break;
1485 case RTAX_IFA5:
1486 switch (sa->sa_family) {
1487 case AF_INET2:
1488 size = sizeof(struct sockaddr_in);
1489 break;
1490#ifdef INET61
1491 case AF_INET624:
1492 size = sizeof(struct sockaddr_in6);
1493 break;
1494#endif
1495 default:
1496 return (EAFNOSUPPORT47);
1497 }
1498 break;
1499 case RTAX_LABEL10:
1500 sa->sa_family = AF_UNSPEC0;
1501 maxlen = RTLABEL_LEN32;
1502 size = sizeof(struct sockaddr_rtlabel);
1503 break;
1504#ifdef BFD
1505 case RTAX_BFD11:
1506 sa->sa_family = AF_UNSPEC0;
1507 size = sizeof(struct sockaddr_bfd);
1508 break;
1509#endif
1510 case RTAX_DNS12:
1511 /* more validation in rtm_validate_proposal */
1512 if (sa->sa_len > sizeof(struct sockaddr_rtdns))
1513 return (EINVAL22);
1514 if (sa->sa_len < offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
1515 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns))
1516 return (EINVAL22);
1517 switch (sa->sa_family) {
1518 case AF_INET2:
1519#ifdef INET61
1520 case AF_INET624:
1521#endif
1522 break;
1523 default:
1524 return (EAFNOSUPPORT47);
1525 }
1526 break;
1527 case RTAX_STATIC13:
1528 sa->sa_family = AF_UNSPEC0;
1529 maxlen = RTSTATIC_LEN128;
1530 size = sizeof(struct sockaddr_rtstatic);
1531 break;
1532 case RTAX_SEARCH14:
1533 sa->sa_family = AF_UNSPEC0;
1534 maxlen = RTSEARCH_LEN128;
1535 size = sizeof(struct sockaddr_rtsearch);
1536 break;
1537 }
1538 if (size) {
1539 /* memory for the full struct must be provided */
1540 if (sa->sa_len < size)
1541 return (EINVAL22);
1542 }
1543 if (maxlen) {
1544 /* this should not happen */
1545 if (2 + maxlen > size)
1546 return (EINVAL22);
1547 /* strings must be NUL terminated within the struct */
1548 len = strnlen(sa->sa_data, maxlen);
1549 if (len >= maxlen || 2 + len >= sa->sa_len)
1550 return (EINVAL22);
1551 break;
1552 }
1553 }
1554 return (0);
1555}
1556
1557struct mbuf *
1558rtm_msg1(int type, struct rt_addrinfo *rtinfo)
1559{
1560 struct rt_msghdr *rtm;
1561 struct mbuf *m;
1562 int i;
1563 struct sockaddr *sa;
1564 int len, dlen, hlen;
1565
1566 switch (type) {
1567 case RTM_DELADDR0xd:
1568 case RTM_NEWADDR0xc:
1569 len = sizeof(struct ifa_msghdr);
1570 break;
1571 case RTM_IFINFO0xe:
1572 len = sizeof(struct if_msghdr);
1573 break;
1574 case RTM_IFANNOUNCE0xf:
1575 len = sizeof(struct if_announcemsghdr);
1576 break;
1577#ifdef BFD
1578 case RTM_BFD0x12:
1579 len = sizeof(struct bfd_msghdr);
1580 break;
1581#endif
1582 case RTM_80211INFO0x15:
1583 len = sizeof(struct if_ieee80211_msghdr);
1584 break;
1585 default:
1586 len = sizeof(struct rt_msghdr);
1587 break;
1588 }
1589 if (len > MCLBYTES(1 << 11))
1590 panic("rtm_msg1");
1591 m = m_gethdr(M_DONTWAIT0x0002, MT_DATA1);
1592 if (m && len > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1593 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
1594 if ((m->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0) {
1595 m_free(m);
1596 m = NULL((void *)0);
1597 }
1598 }
1599 if (m == NULL((void *)0))
1600 return (m);
1601 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = hlen = len;
1602 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = 0;
1603 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
1604 bzero(rtm, len)__builtin_bzero((rtm), (len));
1605 for (i = 0; i < RTAX_MAX15; i++) {
1606 if (rtinfo == NULL((void *)0) || (sa = rtinfo->rti_info[i]) == NULL((void *)0))
1607 continue;
1608 rtinfo->rti_addrs |= (1 << i);
1609 dlen = ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
1610 if (m_copyback(m, len, dlen, sa, M_NOWAIT0x0002)) {
1611 m_freem(m);
1612 return (NULL((void *)0));
1613 }
1614 len += dlen;
1615 }
1616 rtm->rtm_msglen = len;
1617 rtm->rtm_hdrlen = hlen;
1618 rtm->rtm_version = RTM_VERSION5;
1619 rtm->rtm_type = type;
1620 return (m);
1621}
1622
1623int
1624rtm_msg2(int type, int vers, struct rt_addrinfo *rtinfo, caddr_t cp,
1625 struct walkarg *w)
1626{
1627 int i;
1628 int len, dlen, hlen, second_time = 0;
1629 caddr_t cp0;
1630
1631 rtinfo->rti_addrs = 0;
1632again:
1633 switch (type) {
1634 case RTM_DELADDR0xd:
1635 case RTM_NEWADDR0xc:
1636 len = sizeof(struct ifa_msghdr);
1637 break;
1638 case RTM_IFINFO0xe:
1639 len = sizeof(struct if_msghdr);
1640 break;
1641 default:
1642 len = sizeof(struct rt_msghdr);
1643 break;
1644 }
1645 hlen = len;
1646 if ((cp0 = cp) != NULL((void *)0))
1647 cp += len;
1648 for (i = 0; i < RTAX_MAX15; i++) {
1649 struct sockaddr *sa;
1650
1651 if ((sa = rtinfo->rti_info[i]) == NULL((void *)0))
1652 continue;
1653 rtinfo->rti_addrs |= (1 << i);
1654 dlen = ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
;
1655 if (cp) {
1656 bcopy(sa, cp, (size_t)dlen);
1657 cp += dlen;
1658 }
1659 len += dlen;
1660 }
1661 /* align message length to the next natural boundary */
1662 len = ALIGN(len)(((unsigned long)(len) + (sizeof(long) - 1)) &~(sizeof(long
) - 1))
;
1663 if (cp == 0 && w != NULL((void *)0) && !second_time) {
1664 w->w_needed += len;
1665 if (w->w_needed <= 0 && w->w_where) {
1666 if (w->w_tmemsize < len) {
1667 free(w->w_tmem, M_RTABLE5, w->w_tmemsize);
1668 w->w_tmem = malloc(len, M_RTABLE5,
1669 M_NOWAIT0x0002 | M_ZERO0x0008);
1670 if (w->w_tmem)
1671 w->w_tmemsize = len;
1672 }
1673 if (w->w_tmem) {
1674 cp = w->w_tmem;
1675 second_time = 1;
1676 goto again;
1677 } else
1678 w->w_where = 0;
1679 }
1680 }
1681 if (cp && w) /* clear the message header */
1682 bzero(cp0, hlen)__builtin_bzero((cp0), (hlen));
1683
1684 if (cp) {
1685 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
1686
1687 rtm->rtm_version = RTM_VERSION5;
1688 rtm->rtm_type = type;
1689 rtm->rtm_msglen = len;
1690 rtm->rtm_hdrlen = hlen;
1691 }
1692 return (len);
1693}
1694
1695void
1696rtm_send(struct rtentry *rt, int cmd, int error, unsigned int rtableid)
1697{
1698 struct rt_addrinfo info;
1699 struct ifnet *ifp;
1700 struct sockaddr_rtlabel sa_rl;
1701 struct sockaddr_in6 sa_mask;
1702
1703 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1704 info.rti_info[RTAX_DST0] = rt_key(rt)((rt)->rt_dest);
1705 info.rti_info[RTAX_GATEWAY1] = rt->rt_gateway;
1706 if (!ISSET(rt->rt_flags, RTF_HOST)((rt->rt_flags) & (0x4)))
1707 info.rti_info[RTAX_NETMASK2] = rt_plen2mask(rt, &sa_mask);
1708 info.rti_info[RTAX_LABEL10] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
1709 ifp = if_get(rt->rt_ifidx);
1710 if (ifp != NULL((void *)0)) {
1711 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1712 info.rti_info[RTAX_IFA5] =
1713 rtable_getsource(rtableid, info.rti_info[RTAX_DST0]->sa_family);
1714 if (info.rti_info[RTAX_IFA5] == NULL((void *)0))
1715 info.rti_info[RTAX_IFA5] = rt->rt_ifa->ifa_addr;
1716 }
1717
1718 rtm_miss(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, error,
1719 rtableid);
1720 if_put(ifp);
1721}
1722
1723/*
1724 * This routine is called to generate a message from the routing
1725 * socket indicating that a redirect has occurred, a routing lookup
1726 * has failed, or that a protocol has detected timeouts to a particular
1727 * destination.
1728 */
1729void
1730rtm_miss(int type, struct rt_addrinfo *rtinfo, int flags, uint8_t prio,
1731 u_int ifidx, int error, u_int tableid)
1732{
1733 struct rt_msghdr *rtm;
1734 struct mbuf *m;
1735 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST0];
1736
1737 if (rtptable.rtp_count == 0)
1738 return;
1739 m = rtm_msg1(type, rtinfo);
1740 if (m == NULL((void *)0))
1741 return;
1742 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
1743 rtm->rtm_flags = RTF_DONE0x40 | flags;
1744 rtm->rtm_priority = prio;
1745 rtm->rtm_errno = error;
1746 rtm->rtm_tableid = tableid;
1747 rtm->rtm_addrs = rtinfo->rti_addrs;
1748 rtm->rtm_index = ifidx;
1749 route_input(m, NULL((void *)0), sa ? sa->sa_family : AF_UNSPEC0);
1750}
1751
1752/*
1753 * This routine is called to generate a message from the routing
1754 * socket indicating that the status of a network interface has changed.
1755 */
1756void
1757rtm_ifchg(struct ifnet *ifp)
1758{
1759 struct rt_addrinfo info;
1760 struct if_msghdr *ifm;
1761 struct mbuf *m;
1762
1763 if (rtptable.rtp_count == 0)
1764 return;
1765 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1766 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1767 m = rtm_msg1(RTM_IFINFO0xe, &info);
1768 if (m == NULL((void *)0))
1769 return;
1770 ifm = mtod(m, struct if_msghdr *)((struct if_msghdr *)((m)->m_hdr.mh_data));
1771 ifm->ifm_index = ifp->if_index;
1772 ifm->ifm_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1773 ifm->ifm_flags = ifp->if_flags;
1774 ifm->ifm_xflags = ifp->if_xflags;
1775 if_getdata(ifp, &ifm->ifm_data);
1776 ifm->ifm_addrs = info.rti_addrs;
1777 route_input(m, NULL((void *)0), AF_UNSPEC0);
1778}
1779
1780/*
1781 * This is called to generate messages from the routing socket
1782 * indicating a network interface has had addresses associated with it.
1783 * if we ever reverse the logic and replace messages TO the routing
1784 * socket indicate a request to configure interfaces, then it will
1785 * be unnecessary as the routing socket will automatically generate
1786 * copies of it.
1787 */
1788void
1789rtm_addr(int cmd, struct ifaddr *ifa)
1790{
1791 struct ifnet *ifp = ifa->ifa_ifp;
1792 struct mbuf *m;
1793 struct rt_addrinfo info;
1794 struct ifa_msghdr *ifam;
1795
1796 if (rtptable.rtp_count == 0)
1797 return;
1798
1799 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1800 info.rti_info[RTAX_IFA5] = ifa->ifa_addr;
1801 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1802 info.rti_info[RTAX_NETMASK2] = ifa->ifa_netmask;
1803 info.rti_info[RTAX_BRD7] = ifa->ifa_dstaddr;
1804 if ((m = rtm_msg1(cmd, &info)) == NULL((void *)0))
1805 return;
1806 ifam = mtod(m, struct ifa_msghdr *)((struct ifa_msghdr *)((m)->m_hdr.mh_data));
1807 ifam->ifam_index = ifp->if_index;
1808 ifam->ifam_metric = ifa->ifa_metric;
1809 ifam->ifam_flags = ifa->ifa_flags;
1810 ifam->ifam_addrs = info.rti_addrs;
1811 ifam->ifam_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1812
1813 route_input(m, NULL((void *)0),
1814 ifa->ifa_addr ? ifa->ifa_addr->sa_family : AF_UNSPEC0);
1815}
1816
1817/*
1818 * This is called to generate routing socket messages indicating
1819 * network interface arrival and departure.
1820 */
1821void
1822rtm_ifannounce(struct ifnet *ifp, int what)
1823{
1824 struct if_announcemsghdr *ifan;
1825 struct mbuf *m;
1826
1827 if (rtptable.rtp_count == 0)
1828 return;
1829 m = rtm_msg1(RTM_IFANNOUNCE0xf, NULL((void *)0));
1830 if (m == NULL((void *)0))
1831 return;
1832 ifan = mtod(m, struct if_announcemsghdr *)((struct if_announcemsghdr *)((m)->m_hdr.mh_data));
1833 ifan->ifan_index = ifp->if_index;
1834 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
1835 ifan->ifan_what = what;
1836 route_input(m, NULL((void *)0), AF_UNSPEC0);
1837}
1838
1839#ifdef BFD
1840/*
1841 * This is used to generate routing socket messages indicating
1842 * the state of a BFD session.
1843 */
1844void
1845rtm_bfd(struct bfd_config *bfd)
1846{
1847 struct bfd_msghdr *bfdm;
1848 struct sockaddr_bfd sa_bfd;
1849 struct mbuf *m;
1850 struct rt_addrinfo info;
1851
1852 if (rtptable.rtp_count == 0)
1853 return;
1854 memset(&info, 0, sizeof(info))__builtin_memset((&info), (0), (sizeof(info)));
1855 info.rti_info[RTAX_DST0] = rt_key(bfd->bc_rt)((bfd->bc_rt)->rt_dest);
1856 info.rti_info[RTAX_IFA5] = bfd->bc_rt->rt_ifa->ifa_addr;
1857
1858 m = rtm_msg1(RTM_BFD0x12, &info);
1859 if (m == NULL((void *)0))
1860 return;
1861 bfdm = mtod(m, struct bfd_msghdr *)((struct bfd_msghdr *)((m)->m_hdr.mh_data));
1862 bfdm->bm_addrs = info.rti_addrs;
1863
1864 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/rtsock.c"
, 1864, "_kernel_lock_held()"))
;
1865 bfd2sa(bfd->bc_rt, &sa_bfd);
1866 memcpy(&bfdm->bm_sa, &sa_bfd, sizeof(sa_bfd))__builtin_memcpy((&bfdm->bm_sa), (&sa_bfd), (sizeof
(sa_bfd)))
;
1867
1868 route_input(m, NULL((void *)0), info.rti_info[RTAX_DST0]->sa_family);
1869}
1870#endif /* BFD */
1871
1872/*
1873 * This is used to generate routing socket messages indicating
1874 * the state of an ieee80211 interface.
1875 */
1876void
1877rtm_80211info(struct ifnet *ifp, struct if_ieee80211_data *ifie)
1878{
1879 struct if_ieee80211_msghdr *ifim;
1880 struct mbuf *m;
1881
1882 if (rtptable.rtp_count == 0)
1883 return;
1884 m = rtm_msg1(RTM_80211INFO0x15, NULL((void *)0));
1885 if (m == NULL((void *)0))
1886 return;
1887 ifim = mtod(m, struct if_ieee80211_msghdr *)((struct if_ieee80211_msghdr *)((m)->m_hdr.mh_data));
1888 ifim->ifim_index = ifp->if_index;
1889 ifim->ifim_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1890
1891 memcpy(&ifim->ifim_ifie, ifie, sizeof(ifim->ifim_ifie))__builtin_memcpy((&ifim->ifim_ifie), (ifie), (sizeof(ifim
->ifim_ifie)))
;
1892 route_input(m, NULL((void *)0), AF_UNSPEC0);
1893}
1894
1895/*
1896 * This is used to generate routing socket messages indicating
1897 * the address selection proposal from an interface.
1898 */
1899void
1900rtm_proposal(struct ifnet *ifp, struct rt_addrinfo *rtinfo, int flags,
1901 uint8_t prio)
1902{
1903 struct rt_msghdr *rtm;
1904 struct mbuf *m;
1905
1906 m = rtm_msg1(RTM_PROPOSAL0x13, rtinfo);
1907 if (m == NULL((void *)0))
1
Assuming 'm' is not equal to NULL
2
Taking false branch
1908 return;
1909 rtm = mtod(m, struct rt_msghdr *)((struct rt_msghdr *)((m)->m_hdr.mh_data));
1910 rtm->rtm_flags = RTF_DONE0x40 | flags;
1911 rtm->rtm_priority = prio;
1912 rtm->rtm_tableid = ifp->if_rdomainif_data.ifi_rdomain;
1913 rtm->rtm_index = ifp->if_index;
1914 rtm->rtm_addrs = rtinfo->rti_addrs;
1915
1916 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'
1917}
1918
1919/*
1920 * This is used in dumping the kernel table via sysctl().
1921 */
1922int
1923sysctl_dumpentry(struct rtentry *rt, void *v, unsigned int id)
1924{
1925 struct walkarg *w = v;
1926 int error = 0, size;
1927 struct rt_addrinfo info;
1928 struct ifnet *ifp;
1929#ifdef BFD
1930 struct sockaddr_bfd sa_bfd;
1931#endif
1932 struct sockaddr_rtlabel sa_rl;
1933 struct sockaddr_in6 sa_mask;
1934
1935 if (w->w_op == NET_RT_FLAGS2 && !(rt->rt_flags & w->w_arg))
1936 return 0;
1937 if (w->w_op == NET_RT_DUMP1 && w->w_arg) {
1938 u_int8_t prio = w->w_arg & RTP_MASK0x7f;
1939 if (w->w_arg < 0) {
1940 prio = (-w->w_arg) & RTP_MASK0x7f;
1941 /* Show all routes that are not this priority */
1942 if (prio == (rt->rt_priority & RTP_MASK0x7f))
1943 return 0;
1944 } else {
1945 if (prio != (rt->rt_priority & RTP_MASK0x7f) &&
1946 prio != RTP_ANY64)
1947 return 0;
1948 }
1949 }
1950 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
1951 info.rti_info[RTAX_DST0] = rt_key(rt)((rt)->rt_dest);
1952 info.rti_info[RTAX_GATEWAY1] = rt->rt_gateway;
1953 info.rti_info[RTAX_NETMASK2] = rt_plen2mask(rt, &sa_mask);
1954 ifp = if_get(rt->rt_ifidx);
1955 if (ifp != NULL((void *)0)) {
1956 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
1957 info.rti_info[RTAX_IFA5] =
1958 rtable_getsource(id, info.rti_info[RTAX_DST0]->sa_family);
1959 if (info.rti_info[RTAX_IFA5] == NULL((void *)0))
1960 info.rti_info[RTAX_IFA5] = rt->rt_ifa->ifa_addr;
1961 if (ifp->if_flags & IFF_POINTOPOINT0x10)
1962 info.rti_info[RTAX_BRD7] = rt->rt_ifa->ifa_dstaddr;
1963 }
1964 if_put(ifp);
1965 info.rti_info[RTAX_LABEL10] = rtlabel_id2sa(rt->rt_labelid, &sa_rl);
1966#ifdef BFD
1967 if (rt->rt_flags & RTF_BFD0x1000000) {
1968 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/rtsock.c"
, 1968, "_kernel_lock_held()"))
;
1969 info.rti_info[RTAX_BFD11] = bfd2sa(rt, &sa_bfd);
1970 }
1971#endif
1972#ifdef MPLS1
1973 if (rt->rt_flags & RTF_MPLS0x100000) {
1974 struct sockaddr_mpls sa_mpls;
1975
1976 bzero(&sa_mpls, sizeof(sa_mpls))__builtin_bzero((&sa_mpls), (sizeof(sa_mpls)));
1977 sa_mpls.smpls_family = AF_MPLS33;
1978 sa_mpls.smpls_len = sizeof(sa_mpls);
1979 sa_mpls.smpls_label = ((struct rt_mpls *)
1980 rt->rt_llinfo)->mpls_label;
1981 info.rti_info[RTAX_SRC8] = (struct sockaddr *)&sa_mpls;
1982 info.rti_mpls = ((struct rt_mpls *)
1983 rt->rt_llinfo)->mpls_operation;
1984 }
1985#endif
1986
1987 size = rtm_msg2(RTM_GET0x4, RTM_VERSION5, &info, NULL((void *)0), w);
1988 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
1989 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
1990
1991 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;
1992 rtm->rtm_flags = rt->rt_flags;
1993 rtm->rtm_priority = rt->rt_priority & RTP_MASK0x7f;
1994 rtm_getmetrics(&rt->rt_rmx, &rtm->rtm_rmx);
1995 /* Do not account the routing table's reference. */
1996 rtm->rtm_rmx.rmx_refcnt = rt->rt_refcnt - 1;
1997 rtm->rtm_index = rt->rt_ifidx;
1998 rtm->rtm_addrs = info.rti_addrs;
1999 rtm->rtm_tableid = id;
2000#ifdef MPLS1
2001 rtm->rtm_mpls = info.rti_mpls;
2002#endif
2003 if ((error = copyout(rtm, w->w_where, size)) != 0)
2004 w->w_where = NULL((void *)0);
2005 else
2006 w->w_where += size;
2007 }
2008 return (error);
2009}
2010
2011int
2012sysctl_iflist(int af, struct walkarg *w)
2013{
2014 struct ifnet *ifp;
2015 struct ifaddr *ifa;
2016 struct rt_addrinfo info;
2017 int len, error = 0;
2018
2019 bzero(&info, sizeof(info))__builtin_bzero((&info), (sizeof(info)));
2020 TAILQ_FOREACH(ifp, &ifnet, if_list)for((ifp) = ((&ifnet)->tqh_first); (ifp) != ((void *)0
); (ifp) = ((ifp)->if_list.tqe_next))
{
2021 if (w->w_arg && w->w_arg != ifp->if_index)
2022 continue;
2023 /* Copy the link-layer address first */
2024 info.rti_info[RTAX_IFP4] = sdltosa(ifp->if_sadl);
2025 len = rtm_msg2(RTM_IFINFO0xe, RTM_VERSION5, &info, 0, w);
2026 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
2027 struct if_msghdr *ifm;
2028
2029 ifm = (struct if_msghdr *)w->w_tmem;
2030 ifm->ifm_index = ifp->if_index;
2031 ifm->ifm_tableid = ifp->if_rdomainif_data.ifi_rdomain;
2032 ifm->ifm_flags = ifp->if_flags;
2033 if_getdata(ifp, &ifm->ifm_data);
2034 ifm->ifm_addrs = info.rti_addrs;
2035 error = copyout(ifm, w->w_where, len);
2036 if (error)
2037 return (error);
2038 w->w_where += len;
2039 }
2040 info.rti_info[RTAX_IFP4] = NULL((void *)0);
2041 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)for((ifa) = ((&ifp->if_addrlist)->tqh_first); (ifa)
!= ((void *)0); (ifa) = ((ifa)->ifa_list.tqe_next))
{
2042 KASSERT(ifa->ifa_addr->sa_family != AF_LINK)((ifa->ifa_addr->sa_family != 18) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/net/rtsock.c", 2042, "ifa->ifa_addr->sa_family != AF_LINK"
))
;
2043 if (af && af != ifa->ifa_addr->sa_family)
2044 continue;
2045 info.rti_info[RTAX_IFA5] = ifa->ifa_addr;
2046 info.rti_info[RTAX_NETMASK2] = ifa->ifa_netmask;
2047 info.rti_info[RTAX_BRD7] = ifa->ifa_dstaddr;
2048 len = rtm_msg2(RTM_NEWADDR0xc, RTM_VERSION5, &info, 0, w);
2049 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
2050 struct ifa_msghdr *ifam;
2051
2052 ifam = (struct ifa_msghdr *)w->w_tmem;
2053 ifam->ifam_index = ifa->ifa_ifp->if_index;
2054 ifam->ifam_flags = ifa->ifa_flags;
2055 ifam->ifam_metric = ifa->ifa_metric;
2056 ifam->ifam_addrs = info.rti_addrs;
2057 error = copyout(w->w_tmem, w->w_where, len);
2058 if (error)
2059 return (error);
2060 w->w_where += len;
2061 }
2062 }
2063 info.rti_info[RTAX_IFA5] = info.rti_info[RTAX_NETMASK2] =
2064 info.rti_info[RTAX_BRD7] = NULL((void *)0);
2065 }
2066 return (0);
2067}
2068
2069int
2070sysctl_ifnames(struct walkarg *w)
2071{
2072 struct if_nameindex_msg ifn;
2073 struct ifnet *ifp;
2074 int error = 0;
2075
2076 /* XXX ignore tableid for now */
2077 TAILQ_FOREACH(ifp, &ifnet, if_list)for((ifp) = ((&ifnet)->tqh_first); (ifp) != ((void *)0
); (ifp) = ((ifp)->if_list.tqe_next))
{
2078 if (w->w_arg && w->w_arg != ifp->if_index)
2079 continue;
2080 w->w_needed += sizeof(ifn);
2081 if (w->w_where && w->w_needed <= 0) {
2082
2083 memset(&ifn, 0, sizeof(ifn))__builtin_memset((&ifn), (0), (sizeof(ifn)));
2084 ifn.if_index = ifp->if_index;
2085 strlcpy(ifn.if_name, ifp->if_xname,
2086 sizeof(ifn.if_name));
2087 error = copyout(&ifn, w->w_where, sizeof(ifn));
2088 if (error)
2089 return (error);
2090 w->w_where += sizeof(ifn);
2091 }
2092 }
2093
2094 return (0);
2095}
2096
2097int
2098sysctl_source(int af, u_int tableid, struct walkarg *w)
2099{
2100 struct sockaddr *sa;
2101 int size, error = 0;
2102
2103 sa = rtable_getsource(tableid, af);
2104 if (sa) {
2105 switch (sa->sa_family) {
2106 case AF_INET2:
2107 size = sizeof(struct sockaddr_in);
2108 break;
2109#ifdef INET61
2110 case AF_INET624:
2111 size = sizeof(struct sockaddr_in6);
2112 break;
2113#endif
2114 default:
2115 return (0);
2116 }
2117 w->w_needed += size;
2118 if (w->w_where && w->w_needed <= 0) {
2119 if ((error = copyout(sa, w->w_where, size)))
2120 return (error);
2121 w->w_where += size;
2122 }
2123 }
2124 return (0);
2125}
2126
2127int
2128sysctl_rtable(int *name, u_int namelen, void *where, size_t *given, void *new,
2129 size_t newlen)
2130{
2131 int i, error = EINVAL22;
2132 u_char af;
2133 struct walkarg w;
2134 struct rt_tableinfo tableinfo;
2135 u_int tableid = 0;
2136
2137 if (new)
2138 return (EPERM1);
2139 if (namelen < 3 || namelen > 4)
2140 return (EINVAL22);
2141 af = name[0];
2142 bzero(&w, sizeof(w))__builtin_bzero((&w), (sizeof(w)));
2143 w.w_where = where;
2144 w.w_given = *given;
2145 w.w_needed = 0 - w.w_given;
2146 w.w_op = name[1];
2147 w.w_arg = name[2];
2148
2149 if (namelen == 4) {
2150 tableid = name[3];
2151 if (!rtable_exists(tableid))
2152 return (ENOENT2);
2153 } else
2154 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;
2155
2156 switch (w.w_op) {
2157 case NET_RT_DUMP1:
2158 case NET_RT_FLAGS2:
2159 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2160 for (i = 1; i <= AF_MAX36; i++) {
2161 if (af != 0 && af != i)
2162 continue;
2163
2164 error = rtable_walk(tableid, i, NULL((void *)0), sysctl_dumpentry,
2165 &w);
2166 if (error == EAFNOSUPPORT47)
2167 error = 0;
2168 if (error)
2169 break;
2170 }
2171 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2172 break;
2173
2174 case NET_RT_IFLIST3:
2175 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2176 error = sysctl_iflist(af, &w);
2177 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2178 break;
2179
2180 case NET_RT_STATS4:
2181 return (sysctl_rtable_rtstat(where, given, new));
2182 case NET_RT_TABLE5:
2183 tableid = w.w_arg;
2184 if (!rtable_exists(tableid))
2185 return (ENOENT2);
2186 memset(&tableinfo, 0, sizeof tableinfo)__builtin_memset((&tableinfo), (0), (sizeof tableinfo));
2187 tableinfo.rti_tableid = tableid;
2188 tableinfo.rti_domainid = rtable_l2(tableid);
2189 error = sysctl_rdstruct(where, given, new,
2190 &tableinfo, sizeof(tableinfo));
2191 return (error);
2192 case NET_RT_IFNAMES6:
2193 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2194 error = sysctl_ifnames(&w);
2195 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2196 break;
2197 case NET_RT_SOURCE7:
2198 tableid = w.w_arg;
2199 if (!rtable_exists(tableid))
2200 return (ENOENT2);
2201 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
2202 for (i = 1; i <= AF_MAX36; i++) {
2203 if (af != 0 && af != i)
2204 continue;
2205
2206 error = sysctl_source(i, tableid, &w);
2207 if (error == EAFNOSUPPORT47)
2208 error = 0;
2209 if (error)
2210 break;
2211 }
2212 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
2213 break;
2214 }
2215 free(w.w_tmem, M_RTABLE5, w.w_tmemsize);
2216 w.w_needed += w.w_given;
2217 if (where) {
2218 *given = w.w_where - (caddr_t)where;
2219 if (*given < w.w_needed)
2220 return (ENOMEM12);
2221 } else
2222 *given = w.w_needed + w.w_needed / 10;
2223
2224 return (error);
2225}
2226
2227int
2228sysctl_rtable_rtstat(void *oldp, size_t *oldlenp, void *newp)
2229{
2230 extern struct cpumem *rtcounters;
2231 uint64_t counters[rts_ncounters];
2232 struct rtstat rtstat;
2233 uint32_t *words = (uint32_t *)&rtstat;
2234 int i;
2235
2236 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__))
;
2237 memset(&rtstat, 0, sizeof rtstat)__builtin_memset((&rtstat), (0), (sizeof rtstat));
2238 counters_read(rtcounters, counters, nitems(counters)(sizeof((counters)) / sizeof((counters)[0])));
2239
2240 for (i = 0; i < nitems(counters)(sizeof((counters)) / sizeof((counters)[0])); i++)
2241 words[i] = (uint32_t)counters[i];
2242
2243 return (sysctl_rdstruct(oldp, oldlenp, newp, &rtstat, sizeof(rtstat)));
2244}
2245
2246int
2247rtm_validate_proposal(struct rt_addrinfo *info)
2248{
2249 if (info->rti_addrs & ~(RTA_NETMASK0x4 | RTA_IFA0x20 | RTA_DNS0x1000 | RTA_STATIC0x2000 |
2250 RTA_SEARCH0x4000)) {
2251 return -1;
2252 }
2253
2254 if (ISSET(info->rti_addrs, RTA_NETMASK)((info->rti_addrs) & (0x4))) {
2255 struct sockaddr *sa = info->rti_info[RTAX_NETMASK2];
2256 if (sa == NULL((void *)0))
2257 return -1;
2258 switch (sa->sa_family) {
2259 case AF_INET2:
2260 if (sa->sa_len != sizeof(struct sockaddr_in))
2261 return -1;
2262 break;
2263 case AF_INET624:
2264 if (sa->sa_len != sizeof(struct sockaddr_in6))
2265 return -1;
2266 break;
2267 default:
2268 return -1;
2269 }
2270 }
2271
2272 if (ISSET(info->rti_addrs, RTA_IFA)((info->rti_addrs) & (0x20))) {
2273 struct sockaddr *sa = info->rti_info[RTAX_IFA5];
2274 if (sa == NULL((void *)0))
2275 return -1;
2276 switch (sa->sa_family) {
2277 case AF_INET2:
2278 if (sa->sa_len != sizeof(struct sockaddr_in))
2279 return -1;
2280 break;
2281 case AF_INET624:
2282 if (sa->sa_len != sizeof(struct sockaddr_in6))
2283 return -1;
2284 break;
2285 default:
2286 return -1;
2287 }
2288 }
2289
2290 if (ISSET(info->rti_addrs, RTA_DNS)((info->rti_addrs) & (0x1000))) {
2291 struct sockaddr_rtdns *rtdns =
2292 (struct sockaddr_rtdns *)info->rti_info[RTAX_DNS12];
2293 if (rtdns == NULL((void *)0))
2294 return -1;
2295 if (rtdns->sr_len > sizeof(*rtdns))
2296 return -1;
2297 if (rtdns->sr_len < offsetof(struct sockaddr_rtdns, sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns))
2298 return -1;
2299 switch (rtdns->sr_family) {
2300 case AF_INET2:
2301 if ((rtdns->sr_len - offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
2302 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns)) % sizeof(struct in_addr) != 0)
2303 return -1;
2304 break;
2305#ifdef INET61
2306 case AF_INET624:
2307 if ((rtdns->sr_len - offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
2308 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns)) % sizeof(struct in6_addr) != 0)
2309 return -1;
2310 break;
2311#endif
2312 default:
2313 return -1;
2314 }
2315 }
2316
2317 if (ISSET(info->rti_addrs, RTA_STATIC)((info->rti_addrs) & (0x2000))) {
2318 struct sockaddr_rtstatic *rtstatic =
2319 (struct sockaddr_rtstatic *)info->rti_info[RTAX_STATIC13];
2320 if (rtstatic == NULL((void *)0))
2321 return -1;
2322 if (rtstatic->sr_len > sizeof(*rtstatic))
2323 return -1;
2324 if (rtstatic->sr_len <=
2325 offsetof(struct sockaddr_rtstatic, sr_static)__builtin_offsetof(struct sockaddr_rtstatic, sr_static))
2326 return -1;
2327 }
2328
2329 if (ISSET(info->rti_addrs, RTA_SEARCH)((info->rti_addrs) & (0x4000))) {
2330 struct sockaddr_rtsearch *rtsearch =
2331 (struct sockaddr_rtsearch *)info->rti_info[RTAX_SEARCH14];
2332 if (rtsearch == NULL((void *)0))
2333 return -1;
2334 if (rtsearch->sr_len > sizeof(*rtsearch))
2335 return -1;
2336 if (rtsearch->sr_len <=
2337 offsetof(struct sockaddr_rtsearch, sr_search)__builtin_offsetof(struct sockaddr_rtsearch, sr_search))
2338 return -1;
2339 }
2340
2341 return 0;
2342}
2343
2344int
2345rt_setsource(unsigned int rtableid, struct sockaddr *src)
2346{
2347 struct ifaddr *ifa;
2348 int error;
2349 /*
2350 * If source address is 0.0.0.0 or ::
2351 * use automatic source selection
2352 */
2353 switch(src->sa_family) {
2354 case AF_INET2:
2355 if(satosin(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
))))
) {
2356 rtable_setsource(rtableid, AF_INET2, NULL((void *)0));
2357 return (0);
2358 }
2359 break;
2360#ifdef INET61
2361 case AF_INET624:
2362 if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)((*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[0]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[4]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[8]) == 0) &&
(*(const u_int32_t *)(const void *)(&(&satosin6(src)
->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))
) {
2363 rtable_setsource(rtableid, AF_INET624, NULL((void *)0));
2364 return (0);
2365 }
2366 break;
2367#endif
2368 default:
2369 return (EAFNOSUPPORT47);
2370 }
2371
2372 KERNEL_LOCK()_kernel_lock();
2373 /*
2374 * Check if source address is assigned to an interface in the
2375 * same rdomain
2376 */
2377 if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL((void *)0)) {
2378 KERNEL_UNLOCK()_kernel_unlock();
2379 return (EINVAL22);
2380 }
2381
2382 error = rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr);
2383 KERNEL_UNLOCK()_kernel_unlock();
2384
2385 return (error);
2386}
2387
2388/*
2389 * Definitions of protocols supported in the ROUTE domain.
2390 */
2391
2392const struct protosw routesw[] = {
2393{
2394 .pr_type = SOCK_RAW3,
2395 .pr_domain = &routedomain,
2396 .pr_flags = PR_ATOMIC0x01|PR_ADDR0x02|PR_WANTRCVD0x08,
2397 .pr_output = route_output,
2398 .pr_ctloutput = route_ctloutput,
2399 .pr_usrreq = route_usrreq,
2400 .pr_attach = route_attach,
2401 .pr_detach = route_detach,
2402 .pr_init = route_prinit,
2403 .pr_sysctl = sysctl_rtable
2404}
2405};
2406
2407const struct domain routedomain = {
2408 .dom_family = PF_ROUTE17,
2409 .dom_name = "route",
2410 .dom_init = route_init,
2411 .dom_protosw = routesw,
2412 .dom_protoswNPROTOSW = &routesw[nitems(routesw)(sizeof((routesw)) / sizeof((routesw)[0]))]
2413};