]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/rtsock.c
xnu-3789.60.24.tar.gz
[apple/xnu.git] / bsd / net / rtsock.c
CommitLineData
1c79356b 1/*
d190cdc3 2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
39236c6e 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
39236c6e 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
39236c6e 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
39236c6e 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1988, 1991, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)rtsock.c 8.5 (Berkeley) 11/2/94
61 */
62
1c79356b
A
63#include <sys/param.h>
64#include <sys/systm.h>
39236c6e 65#include <sys/kauth.h>
1c79356b
A
66#include <sys/kernel.h>
67#include <sys/sysctl.h>
68#include <sys/proc.h>
69#include <sys/malloc.h>
70#include <sys/mbuf.h>
71#include <sys/socket.h>
72#include <sys/socketvar.h>
73#include <sys/domain.h>
74#include <sys/protosw.h>
9bccf70c 75#include <sys/syslog.h>
6d2010ae 76#include <sys/mcache.h>
fe8ab488 77#include <kern/locks.h>
1c79356b
A
78
79#include <net/if.h>
80#include <net/route.h>
d1ecb069 81#include <net/dlil.h>
1c79356b 82#include <net/raw_cb.h>
9bccf70c 83#include <netinet/in.h>
d1ecb069
A
84#include <netinet/in_var.h>
85#include <netinet/in_arp.h>
86#include <netinet6/nd6.h>
1c79356b 87
91447636 88extern struct rtstat rtstat;
39236c6e
A
89extern struct domain routedomain_s;
90static struct domain *routedomain = NULL;
91447636 91
1c79356b
A
92MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
93
39236c6e
A
94static struct sockaddr route_dst = { 2, PF_ROUTE, { 0, } };
95static struct sockaddr route_src = { 2, PF_ROUTE, { 0, } };
96static struct sockaddr sa_zero = { sizeof (sa_zero), AF_INET, { 0, } };
97
98struct route_cb {
99 u_int32_t ip_count; /* attached w/ AF_INET */
100 u_int32_t ip6_count; /* attached w/ AF_INET6 */
101 u_int32_t any_count; /* total attached */
102};
103
104static struct route_cb route_cb;
1c79356b 105
1c79356b
A
106struct walkarg {
107 int w_tmemsize;
108 int w_op, w_arg;
109 caddr_t w_tmem;
110 struct sysctl_req *w_req;
111};
112
39236c6e
A
113static void route_dinit(struct domain *);
114static int rts_abort(struct socket *);
115static int rts_attach(struct socket *, int, struct proc *);
116static int rts_bind(struct socket *, struct sockaddr *, struct proc *);
117static int rts_connect(struct socket *, struct sockaddr *, struct proc *);
118static int rts_detach(struct socket *);
119static int rts_disconnect(struct socket *);
120static int rts_peeraddr(struct socket *, struct sockaddr **);
121static int rts_send(struct socket *, int, struct mbuf *, struct sockaddr *,
122 struct mbuf *, struct proc *);
123static int rts_shutdown(struct socket *);
124static int rts_sockaddr(struct socket *, struct sockaddr **);
125
126static int route_output(struct mbuf *, struct socket *);
3e170ce0 127static int rt_setmetrics(u_int32_t, struct rt_metrics *, struct rtentry *);
39236c6e
A
128static void rt_getmetrics(struct rtentry *, struct rt_metrics *);
129static void rt_setif(struct rtentry *, struct sockaddr *, struct sockaddr *,
130 struct sockaddr *, unsigned int);
131static int rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
b0d623f7 132static struct mbuf *rt_msg1(int, struct rt_addrinfo *);
39236c6e 133static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *,
813fb2f6 134 kauth_cred_t *, uint32_t);
39236c6e
A
135static int sysctl_dumpentry(struct radix_node *rn, void *vw);
136static int sysctl_dumpentry_ext(struct radix_node *rn, void *vw);
137static int sysctl_iflist(int af, struct walkarg *w);
138static int sysctl_iflist2(int af, struct walkarg *w);
139static int sysctl_rtstat(struct sysctl_req *);
140static int sysctl_rttrash(struct sysctl_req *);
141static int sysctl_rtsock SYSCTL_HANDLER_ARGS;
142
143SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD | CTLFLAG_LOCKED,
144 sysctl_rtsock, "");
145
146SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "routing");
147
148#define ROUNDUP32(a) \
149 ((a) > 0 ? (1 + (((a) - 1) | (sizeof (uint32_t) - 1))) : \
150 sizeof (uint32_t))
151
152#define ADVANCE32(x, n) \
153 (x += ROUNDUP32((n)->sa_len))
d1ecb069 154
1c79356b
A
155/*
156 * It really doesn't make any sense at all for this code to share much
157 * with raw_usrreq.c, since its functionality is so restricted. XXX
158 */
159static int
160rts_abort(struct socket *so)
161{
39236c6e 162 return (raw_usrreqs.pru_abort(so));
1c79356b
A
163}
164
165/* pru_accept is EOPNOTSUPP */
166
167static int
39236c6e 168rts_attach(struct socket *so, int proto, struct proc *p)
1c79356b 169{
39236c6e 170#pragma unused(p)
1c79356b 171 struct rawcb *rp;
91447636 172 int error;
1c79356b 173
39236c6e
A
174 VERIFY(so->so_pcb == NULL);
175
176 MALLOC(rp, struct rawcb *, sizeof (*rp), M_PCB, M_WAITOK | M_ZERO);
177 if (rp == NULL)
178 return (ENOBUFS);
1c79356b 179
1c79356b 180 so->so_pcb = (caddr_t)rp;
39236c6e
A
181 /* don't use raw_usrreqs.pru_attach, it checks for SS_PRIV */
182 error = raw_attach(so, proto);
1c79356b
A
183 rp = sotorawcb(so);
184 if (error) {
1c79356b 185 FREE(rp, M_PCB);
2d21ac55 186 so->so_pcb = NULL;
91447636 187 so->so_flags |= SOF_PCBCLEARING;
39236c6e 188 return (error);
1c79356b 189 }
37839358 190
39236c6e 191 switch (rp->rcb_proto.sp_protocol) {
1c79356b 192 case AF_INET:
39236c6e 193 atomic_add_32(&route_cb.ip_count, 1);
1c79356b
A
194 break;
195 case AF_INET6:
39236c6e 196 atomic_add_32(&route_cb.ip6_count, 1);
1c79356b 197 break;
1c79356b
A
198 }
199 rp->rcb_faddr = &route_src;
39236c6e
A
200 atomic_add_32(&route_cb.any_count, 1);
201 /* the socket is already locked when we enter rts_attach */
1c79356b
A
202 soisconnected(so);
203 so->so_options |= SO_USELOOPBACK;
39236c6e 204 return (0);
1c79356b
A
205}
206
207static int
208rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
209{
39236c6e 210 return (raw_usrreqs.pru_bind(so, nam, p)); /* xxx just EINVAL */
1c79356b
A
211}
212
213static int
214rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
215{
39236c6e 216 return (raw_usrreqs.pru_connect(so, nam, p)); /* XXX just EINVAL */
1c79356b
A
217}
218
219/* pru_connect2 is EOPNOTSUPP */
220/* pru_control is EOPNOTSUPP */
221
222static int
223rts_detach(struct socket *so)
224{
225 struct rawcb *rp = sotorawcb(so);
1c79356b 226
39236c6e
A
227 VERIFY(rp != NULL);
228
229 switch (rp->rcb_proto.sp_protocol) {
230 case AF_INET:
231 atomic_add_32(&route_cb.ip_count, -1);
232 break;
233 case AF_INET6:
234 atomic_add_32(&route_cb.ip6_count, -1);
235 break;
1c79356b 236 }
39236c6e
A
237 atomic_add_32(&route_cb.any_count, -1);
238 return (raw_usrreqs.pru_detach(so));
1c79356b
A
239}
240
241static int
242rts_disconnect(struct socket *so)
243{
39236c6e 244 return (raw_usrreqs.pru_disconnect(so));
1c79356b
A
245}
246
247/* pru_listen is EOPNOTSUPP */
248
249static int
250rts_peeraddr(struct socket *so, struct sockaddr **nam)
251{
39236c6e 252 return (raw_usrreqs.pru_peeraddr(so, nam));
1c79356b
A
253}
254
255/* pru_rcvd is EOPNOTSUPP */
256/* pru_rcvoob is EOPNOTSUPP */
257
258static int
259rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
39236c6e 260 struct mbuf *control, struct proc *p)
1c79356b 261{
39236c6e 262 return (raw_usrreqs.pru_send(so, flags, m, nam, control, p));
1c79356b
A
263}
264
265/* pru_sense is null */
266
267static int
268rts_shutdown(struct socket *so)
269{
39236c6e 270 return (raw_usrreqs.pru_shutdown(so));
1c79356b
A
271}
272
273static int
274rts_sockaddr(struct socket *so, struct sockaddr **nam)
275{
39236c6e 276 return (raw_usrreqs.pru_sockaddr(so, nam));
1c79356b
A
277}
278
279static struct pr_usrreqs route_usrreqs = {
39236c6e
A
280 .pru_abort = rts_abort,
281 .pru_attach = rts_attach,
282 .pru_bind = rts_bind,
283 .pru_connect = rts_connect,
284 .pru_detach = rts_detach,
285 .pru_disconnect = rts_disconnect,
286 .pru_peeraddr = rts_peeraddr,
287 .pru_send = rts_send,
288 .pru_shutdown = rts_shutdown,
289 .pru_sockaddr = rts_sockaddr,
290 .pru_sosend = sosend,
291 .pru_soreceive = soreceive,
1c79356b
A
292};
293
294/*ARGSUSED*/
295static int
2d21ac55 296route_output(struct mbuf *m, struct socket *so)
1c79356b 297{
2d21ac55
A
298 struct rt_msghdr *rtm = NULL;
299 struct rtentry *rt = NULL;
300 struct rtentry *saved_nrt = NULL;
1c79356b
A
301 struct radix_node_head *rnh;
302 struct rt_addrinfo info;
303 int len, error = 0;
6d2010ae 304 sa_family_t dst_sa_family = 0;
2d21ac55 305 struct ifnet *ifp = NULL;
c910b4d9 306 struct sockaddr_in dst_in, gate_in;
55e303ae 307 int sendonlytoself = 0;
c910b4d9 308 unsigned int ifscope = IFSCOPE_NONE;
39236c6e 309 struct rawcb *rp = NULL;
813fb2f6 310 uint32_t rtm_hint_flags = 0;
39236c6e
A
311#define senderr(e) { error = (e); goto flush; }
312 if (m == NULL || ((m->m_len < sizeof (intptr_t)) &&
313 (m = m_pullup(m, sizeof (intptr_t))) == NULL))
1c79356b 314 return (ENOBUFS);
39236c6e 315 VERIFY(m->m_flags & M_PKTHDR);
91447636 316
39236c6e
A
317 /*
318 * Unlock the socket (but keep a reference) it won't be
319 * accessed until raw_input appends to it.
320 */
91447636 321 socket_unlock(so, 0);
b0d623f7 322 lck_mtx_lock(rnh_lock);
91447636 323
1c79356b 324 len = m->m_pkthdr.len;
39236c6e 325 if (len < sizeof (*rtm) ||
1c79356b 326 len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
6d2010ae 327 info.rti_info[RTAX_DST] = NULL;
1c79356b
A
328 senderr(EINVAL);
329 }
330 R_Malloc(rtm, struct rt_msghdr *, len);
c910b4d9 331 if (rtm == NULL) {
6d2010ae 332 info.rti_info[RTAX_DST] = NULL;
1c79356b
A
333 senderr(ENOBUFS);
334 }
335 m_copydata(m, 0, len, (caddr_t)rtm);
336 if (rtm->rtm_version != RTM_VERSION) {
6d2010ae 337 info.rti_info[RTAX_DST] = NULL;
1c79356b
A
338 senderr(EPROTONOSUPPORT);
339 }
c910b4d9 340
55e303ae
A
341 /*
342 * Silent version of RTM_GET for Reachabiltiy APIs. We may change
343 * all RTM_GETs to be silent in the future, so this is private for now.
344 */
345 if (rtm->rtm_type == RTM_GET_SILENT) {
39236c6e 346 if (!(so->so_options & SO_USELOOPBACK))
55e303ae
A
347 senderr(EINVAL);
348 sendonlytoself = 1;
349 rtm->rtm_type = RTM_GET;
350 }
c910b4d9 351
55e303ae
A
352 /*
353 * Perform permission checking, only privileged sockets
354 * may perform operations other than RTM_GET
355 */
39236c6e 356 if (rtm->rtm_type != RTM_GET && !(so->so_state & SS_PRIV)) {
6d2010ae 357 info.rti_info[RTAX_DST] = NULL;
55e303ae
A
358 senderr(EPERM);
359 }
91447636
A
360
361 rtm->rtm_pid = proc_selfpid();
1c79356b
A
362 info.rti_addrs = rtm->rtm_addrs;
363 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
6d2010ae 364 info.rti_info[RTAX_DST] = NULL;
1c79356b
A
365 senderr(EINVAL);
366 }
39236c6e
A
367 if (info.rti_info[RTAX_DST] == NULL ||
368 info.rti_info[RTAX_DST]->sa_family >= AF_MAX ||
369 (info.rti_info[RTAX_GATEWAY] != NULL &&
370 info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
1c79356b 371 senderr(EINVAL);
c910b4d9 372
39236c6e
A
373 if (info.rti_info[RTAX_DST]->sa_family == AF_INET &&
374 info.rti_info[RTAX_DST]->sa_len != sizeof (dst_in)) {
c910b4d9 375 /* At minimum, we need up to sin_addr */
39236c6e
A
376 if (info.rti_info[RTAX_DST]->sa_len <
377 offsetof(struct sockaddr_in, sin_zero))
c910b4d9
A
378 senderr(EINVAL);
379 bzero(&dst_in, sizeof (dst_in));
380 dst_in.sin_len = sizeof (dst_in);
381 dst_in.sin_family = AF_INET;
6d2010ae
A
382 dst_in.sin_port = SIN(info.rti_info[RTAX_DST])->sin_port;
383 dst_in.sin_addr = SIN(info.rti_info[RTAX_DST])->sin_addr;
384 info.rti_info[RTAX_DST] = (struct sockaddr *)&dst_in;
385 dst_sa_family = info.rti_info[RTAX_DST]->sa_family;
c910b4d9
A
386 }
387
6d2010ae 388 if (info.rti_info[RTAX_GATEWAY] != NULL &&
39236c6e
A
389 info.rti_info[RTAX_GATEWAY]->sa_family == AF_INET &&
390 info.rti_info[RTAX_GATEWAY]->sa_len != sizeof (gate_in)) {
c910b4d9 391 /* At minimum, we need up to sin_addr */
39236c6e
A
392 if (info.rti_info[RTAX_GATEWAY]->sa_len <
393 offsetof(struct sockaddr_in, sin_zero))
c910b4d9
A
394 senderr(EINVAL);
395 bzero(&gate_in, sizeof (gate_in));
396 gate_in.sin_len = sizeof (gate_in);
397 gate_in.sin_family = AF_INET;
6d2010ae
A
398 gate_in.sin_port = SIN(info.rti_info[RTAX_GATEWAY])->sin_port;
399 gate_in.sin_addr = SIN(info.rti_info[RTAX_GATEWAY])->sin_addr;
400 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gate_in;
c910b4d9
A
401 }
402
6d2010ae 403 if (info.rti_info[RTAX_GENMASK]) {
1c79356b 404 struct radix_node *t;
6d2010ae 405 t = rn_addmask((caddr_t)info.rti_info[RTAX_GENMASK], 0, 1);
39236c6e
A
406 if (t != NULL && Bcmp(info.rti_info[RTAX_GENMASK],
407 t->rn_key, *(u_char *)info.rti_info[RTAX_GENMASK]) == 0)
408 info.rti_info[RTAX_GENMASK] =
409 (struct sockaddr *)(t->rn_key);
1c79356b
A
410 else
411 senderr(ENOBUFS);
412 }
c910b4d9
A
413
414 /*
415 * If RTF_IFSCOPE flag is set, then rtm_index specifies the scope.
416 */
417 if (rtm->rtm_flags & RTF_IFSCOPE) {
39236c6e
A
418 if (info.rti_info[RTAX_DST]->sa_family != AF_INET &&
419 info.rti_info[RTAX_DST]->sa_family != AF_INET6)
c910b4d9
A
420 senderr(EINVAL);
421 ifscope = rtm->rtm_index;
422 }
00867663
A
423 /*
424 * Block changes on INTCOPROC interfaces.
425 */
426 if (ifscope) {
427 unsigned int intcoproc_scope = 0;
428 ifnet_head_lock_shared();
429 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
430 if (IFNET_IS_INTCOPROC(ifp)) {
431 intcoproc_scope = ifp->if_index;
432 break;
433 }
434 }
435 ifnet_head_done();
436 if (intcoproc_scope == ifscope && current_proc()->p_pid != 0)
437 senderr(EINVAL);
438 }
c910b4d9 439
316670eb
A
440 /*
441 * RTF_PROXY can only be set internally from within the kernel.
442 */
443 if (rtm->rtm_flags & RTF_PROXY)
444 senderr(EINVAL);
445
6d2010ae
A
446 /*
447 * For AF_INET, always zero out the embedded scope ID. If this is
448 * a scoped request, it must be done explicitly by setting RTF_IFSCOPE
449 * flag and the corresponding rtm_index value. This is to prevent
450 * false interpretation of the scope ID because it's using the sin_zero
451 * field, which might not be properly cleared by the requestor.
452 */
453 if (info.rti_info[RTAX_DST]->sa_family == AF_INET)
454 sin_set_ifscope(info.rti_info[RTAX_DST], IFSCOPE_NONE);
39236c6e
A
455 if (info.rti_info[RTAX_GATEWAY] != NULL &&
456 info.rti_info[RTAX_GATEWAY]->sa_family == AF_INET)
6d2010ae
A
457 sin_set_ifscope(info.rti_info[RTAX_GATEWAY], IFSCOPE_NONE);
458
1c79356b 459 switch (rtm->rtm_type) {
39236c6e
A
460 case RTM_ADD:
461 if (info.rti_info[RTAX_GATEWAY] == NULL)
462 senderr(EINVAL);
c910b4d9 463
39236c6e
A
464 error = rtrequest_scoped_locked(RTM_ADD,
465 info.rti_info[RTAX_DST], info.rti_info[RTAX_GATEWAY],
466 info.rti_info[RTAX_NETMASK], rtm->rtm_flags, &saved_nrt,
467 ifscope);
468 if (error == 0 && saved_nrt != NULL) {
469 RT_LOCK(saved_nrt);
470 /*
471 * If the route request specified an interface with
472 * IFA and/or IFP, we set the requested interface on
473 * the route with rt_setif. It would be much better
474 * to do this inside rtrequest, but that would
475 * require passing the desired interface, in some
476 * form, to rtrequest. Since rtrequest is called in
477 * so many places (roughly 40 in our source), adding
478 * a parameter is to much for us to swallow; this is
479 * something for the FreeBSD developers to tackle.
480 * Instead, we let rtrequest compute whatever
481 * interface it wants, then come in behind it and
482 * stick in the interface that we really want. This
483 * works reasonably well except when rtrequest can't
484 * figure out what interface to use (with
485 * ifa_withroute) and returns ENETUNREACH. Ideally
486 * it shouldn't matter if rtrequest can't figure out
487 * the interface if we're going to explicitly set it
488 * ourselves anyway. But practically we can't
489 * recover here because rtrequest will not do any of
490 * the work necessary to add the route if it can't
491 * find an interface. As long as there is a default
492 * route that leads to some interface, rtrequest will
493 * find an interface, so this problem should be
494 * rarely encountered.
495 * dwiggins@bbn.com
496 */
497 rt_setif(saved_nrt,
498 info.rti_info[RTAX_IFP], info.rti_info[RTAX_IFA],
499 info.rti_info[RTAX_GATEWAY], ifscope);
3e170ce0 500 (void)rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, saved_nrt);
39236c6e
A
501 saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
502 saved_nrt->rt_rmx.rmx_locks |=
503 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
504 saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
505 RT_REMREF_LOCKED(saved_nrt);
506 RT_UNLOCK(saved_nrt);
507 }
508 break;
509
510 case RTM_DELETE:
511 error = rtrequest_scoped_locked(RTM_DELETE,
512 info.rti_info[RTAX_DST], info.rti_info[RTAX_GATEWAY],
513 info.rti_info[RTAX_NETMASK], rtm->rtm_flags, &saved_nrt,
514 ifscope);
515 if (error == 0) {
516 rt = saved_nrt;
517 RT_LOCK(rt);
518 goto report;
519 }
520 break;
521
522 case RTM_GET:
523 case RTM_CHANGE:
524 case RTM_LOCK:
525 rnh = rt_tables[info.rti_info[RTAX_DST]->sa_family];
526 if (rnh == NULL)
527 senderr(EAFNOSUPPORT);
528 /*
529 * Lookup the best match based on the key-mask pair;
530 * callee adds a reference and checks for root node.
531 */
532 rt = rt_lookup(TRUE, info.rti_info[RTAX_DST],
533 info.rti_info[RTAX_NETMASK], rnh, ifscope);
534 if (rt == NULL)
535 senderr(ESRCH);
536 RT_LOCK(rt);
91447636 537
813fb2f6
A
538 if (rt->rt_ifp == lo_ifp)
539 rtm_hint_flags |= RTMF_HIDE_LLADDR;
540
39236c6e
A
541 /*
542 * Holding rnh_lock here prevents the possibility of
543 * ifa from changing (e.g. in_ifinit), so it is safe
544 * to access its ifa_addr (down below) without locking.
545 */
546 switch (rtm->rtm_type) {
547 case RTM_GET: {
813fb2f6 548 kauth_cred_t cred;
39236c6e
A
549 struct ifaddr *ifa2;
550report:
813fb2f6 551 cred = kauth_cred_proc_ref(current_proc());
39236c6e
A
552 ifa2 = NULL;
553 RT_LOCK_ASSERT_HELD(rt);
554 info.rti_info[RTAX_DST] = rt_key(rt);
555 dst_sa_family = info.rti_info[RTAX_DST]->sa_family;
556 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
557 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
558 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
559 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
560 ifp = rt->rt_ifp;
561 if (ifp != NULL) {
562 ifnet_lock_shared(ifp);
563 ifa2 = ifp->if_lladdr;
564 info.rti_info[RTAX_IFP] =
565 ifa2->ifa_addr;
566 IFA_ADDREF(ifa2);
567 ifnet_lock_done(ifp);
568 info.rti_info[RTAX_IFA] =
569 rt->rt_ifa->ifa_addr;
570 rtm->rtm_index = ifp->if_index;
571 } else {
572 info.rti_info[RTAX_IFP] = NULL;
573 info.rti_info[RTAX_IFA] = NULL;
574 }
575 } else if ((ifp = rt->rt_ifp) != NULL) {
576 rtm->rtm_index = ifp->if_index;
1c79356b 577 }
39236c6e
A
578 if (ifa2 != NULL)
579 IFA_LOCK(ifa2);
813fb2f6
A
580
581 len = rt_msg2(rtm->rtm_type, &info, NULL, NULL, &cred, rtm_hint_flags);
582
39236c6e
A
583 if (ifa2 != NULL)
584 IFA_UNLOCK(ifa2);
585 if (len > rtm->rtm_msglen) {
586 struct rt_msghdr *new_rtm;
587 R_Malloc(new_rtm, struct rt_msghdr *, len);
588 if (new_rtm == NULL) {
589 RT_UNLOCK(rt);
590 if (ifa2 != NULL)
591 IFA_REMREF(ifa2);
592 senderr(ENOBUFS);
593 }
594 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
595 R_Free(rtm); rtm = new_rtm;
596 }
597 if (ifa2 != NULL)
598 IFA_LOCK(ifa2);
813fb2f6 599
39236c6e 600 (void) rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
813fb2f6
A
601 NULL, &cred, rtm_hint_flags);
602
39236c6e
A
603 if (ifa2 != NULL)
604 IFA_UNLOCK(ifa2);
605 rtm->rtm_flags = rt->rt_flags;
606 rt_getmetrics(rt, &rtm->rtm_rmx);
607 rtm->rtm_addrs = info.rti_addrs;
608 if (ifa2 != NULL)
609 IFA_REMREF(ifa2);
1c79356b 610 break;
39236c6e 611 }
1c79356b
A
612
613 case RTM_CHANGE:
39236c6e
A
614 if (info.rti_info[RTAX_GATEWAY] != NULL &&
615 (error = rt_setgate(rt, rt_key(rt),
616 info.rti_info[RTAX_GATEWAY]))) {
617 int tmp = error;
618 RT_UNLOCK(rt);
619 senderr(tmp);
620 }
c910b4d9 621 /*
39236c6e
A
622 * If they tried to change things but didn't specify
623 * the required gateway, then just use the old one.
624 * This can happen if the user tries to change the
625 * flags on the default route without changing the
626 * default gateway. Changing flags still doesn't work.
c910b4d9 627 */
39236c6e
A
628 if ((rt->rt_flags & RTF_GATEWAY) &&
629 info.rti_info[RTAX_GATEWAY] == NULL)
630 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
c910b4d9 631
6d2010ae 632 /*
39236c6e
A
633 * On Darwin, we call rt_setif which contains the
634 * equivalent to the code found at this very spot
635 * in BSD.
6d2010ae 636 */
39236c6e
A
637 rt_setif(rt,
638 info.rti_info[RTAX_IFP], info.rti_info[RTAX_IFA],
639 info.rti_info[RTAX_GATEWAY], ifscope);
640
3e170ce0
A
641 if ((error = rt_setmetrics(rtm->rtm_inits,
642 &rtm->rtm_rmx, rt))) {
643 int tmp = error;
644 RT_UNLOCK(rt);
645 senderr(tmp);
646 }
39236c6e
A
647 if (info.rti_info[RTAX_GENMASK])
648 rt->rt_genmask = info.rti_info[RTAX_GENMASK];
649 /* FALLTHRU */
650 case RTM_LOCK:
651 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
652 rt->rt_rmx.rmx_locks |=
653 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
1c79356b 654 break;
39236c6e
A
655 }
656 RT_UNLOCK(rt);
657 break;
658
659 default:
660 senderr(EOPNOTSUPP);
1c79356b 661 }
1c79356b 662flush:
39236c6e 663 if (rtm != NULL) {
1c79356b
A
664 if (error)
665 rtm->rtm_errno = error;
666 else
667 rtm->rtm_flags |= RTF_DONE;
668 }
b0d623f7
A
669 if (rt != NULL) {
670 RT_LOCK_ASSERT_NOTHELD(rt);
91447636 671 rtfree_locked(rt);
b0d623f7
A
672 }
673 lck_mtx_unlock(rnh_lock);
39236c6e
A
674
675 /* relock the socket now */
676 socket_lock(so, 0);
1c79356b
A
677 /*
678 * Check to see if we don't want our own messages.
679 */
39236c6e 680 if (!(so->so_options & SO_USELOOPBACK)) {
1c79356b 681 if (route_cb.any_count <= 1) {
39236c6e 682 if (rtm != NULL)
91447636 683 R_Free(rtm);
1c79356b
A
684 m_freem(m);
685 return (error);
686 }
687 /* There is another listener, so construct message */
688 rp = sotorawcb(so);
689 }
39236c6e 690 if (rtm != NULL) {
1c79356b 691 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
9bccf70c
A
692 if (m->m_pkthdr.len < rtm->rtm_msglen) {
693 m_freem(m);
694 m = NULL;
39236c6e 695 } else if (m->m_pkthdr.len > rtm->rtm_msglen) {
9bccf70c 696 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
39236c6e 697 }
91447636 698 R_Free(rtm);
1c79356b 699 }
39236c6e 700 if (sendonlytoself && m != NULL) {
91447636 701 error = 0;
39236c6e
A
702 if (sbappendaddr(&so->so_rcv, &route_src, m,
703 NULL, &error) != 0) {
55e303ae
A
704 sorwakeup(so);
705 }
91447636 706 if (error)
39236c6e 707 return (error);
55e303ae 708 } else {
39236c6e
A
709 struct sockproto route_proto = { PF_ROUTE, 0 };
710 if (rp != NULL)
55e303ae 711 rp->rcb_proto.sp_family = 0; /* Avoid us */
6d2010ae
A
712 if (dst_sa_family != 0)
713 route_proto.sp_protocol = dst_sa_family;
39236c6e 714 if (m != NULL) {
91447636 715 socket_unlock(so, 0);
55e303ae 716 raw_input(m, &route_proto, &route_src, &route_dst);
91447636
A
717 socket_lock(so, 0);
718 }
39236c6e 719 if (rp != NULL)
55e303ae 720 rp->rcb_proto.sp_family = PF_ROUTE;
55e303ae 721 }
1c79356b
A
722 return (error);
723}
724
6d2010ae
A
725void
726rt_setexpire(struct rtentry *rt, uint64_t expiry)
727{
728 /* set both rt_expire and rmx_expire */
729 rt->rt_expire = expiry;
730 if (expiry) {
731 rt->rt_rmx.rmx_expire = expiry + rt->base_calendartime -
732 rt->base_uptime;
39236c6e 733 } else {
6d2010ae 734 rt->rt_rmx.rmx_expire = 0;
39236c6e 735 }
6d2010ae
A
736}
737
3e170ce0 738static int
6d2010ae 739rt_setmetrics(u_int32_t which, struct rt_metrics *in, struct rtentry *out)
1c79356b 740{
3e170ce0
A
741 if (!(which & RTV_REFRESH_HOST)) {
742 struct timeval caltime;
743 getmicrotime(&caltime);
39236c6e 744#define metric(f, e) if (which & (f)) out->rt_rmx.e = in->e;
3e170ce0
A
745 metric(RTV_RPIPE, rmx_recvpipe);
746 metric(RTV_SPIPE, rmx_sendpipe);
747 metric(RTV_SSTHRESH, rmx_ssthresh);
748 metric(RTV_RTT, rmx_rtt);
749 metric(RTV_RTTVAR, rmx_rttvar);
750 metric(RTV_HOPCOUNT, rmx_hopcount);
751 metric(RTV_MTU, rmx_mtu);
752 metric(RTV_EXPIRE, rmx_expire);
1c79356b 753#undef metric
3e170ce0
A
754 if (out->rt_rmx.rmx_expire > 0) {
755 /* account for system time change */
756 getmicrotime(&caltime);
757 out->base_calendartime +=
758 NET_CALCULATE_CLOCKSKEW(caltime,
759 out->base_calendartime,
760 net_uptime(), out->base_uptime);
761 rt_setexpire(out,
762 out->rt_rmx.rmx_expire -
763 out->base_calendartime +
764 out->base_uptime);
765 } else {
766 rt_setexpire(out, 0);
767 }
39236c6e 768
3e170ce0
A
769 VERIFY(out->rt_expire == 0 || out->rt_rmx.rmx_expire != 0);
770 VERIFY(out->rt_expire != 0 || out->rt_rmx.rmx_expire == 0);
6d2010ae 771 } else {
3e170ce0
A
772 /* Only RTV_REFRESH_HOST must be set */
773 if ((which & ~RTV_REFRESH_HOST) ||
774 (out->rt_flags & RTF_STATIC) ||
775 !(out->rt_flags & RTF_LLINFO)) {
776 return (EINVAL);
777 }
39236c6e 778
3e170ce0
A
779 if (out->rt_llinfo_refresh == NULL) {
780 return (ENOTSUP);
781 }
782
783 out->rt_llinfo_refresh(out);
784 }
785 return (0);
6d2010ae
A
786}
787
788static void
789rt_getmetrics(struct rtentry *in, struct rt_metrics *out)
790{
39236c6e 791 struct timeval caltime;
6d2010ae
A
792
793 VERIFY(in->rt_expire == 0 || in->rt_rmx.rmx_expire != 0);
794 VERIFY(in->rt_expire != 0 || in->rt_rmx.rmx_expire == 0);
39236c6e
A
795
796 *out = in->rt_rmx;
797
798 if (in->rt_expire != 0) {
6d2010ae 799 /* account for system time change */
39236c6e 800 getmicrotime(&caltime);
6d2010ae
A
801
802 in->base_calendartime +=
39236c6e
A
803 NET_CALCULATE_CLOCKSKEW(caltime,
804 in->base_calendartime, net_uptime(), in->base_uptime);
805
6d2010ae
A
806 out->rmx_expire = in->base_calendartime +
807 in->rt_expire - in->base_uptime;
39236c6e 808 } else {
6d2010ae 809 out->rmx_expire = 0;
39236c6e 810 }
1c79356b
A
811}
812
813/*
39236c6e
A
814 * Set route's interface given info.rti_info[RTAX_IFP],
815 * info.rti_info[RTAX_IFA], and gateway.
1c79356b
A
816 */
817static void
c910b4d9
A
818rt_setif(struct rtentry *rt, struct sockaddr *Ifpaddr, struct sockaddr *Ifaaddr,
819 struct sockaddr *Gate, unsigned int ifscope)
1c79356b 820{
6d2010ae
A
821 struct ifaddr *ifa = NULL;
822 struct ifnet *ifp = NULL;
39236c6e 823 void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *);
1c79356b 824
b0d623f7
A
825 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
826
827 RT_LOCK_ASSERT_HELD(rt);
91447636 828
b0d623f7
A
829 /* Don't update a defunct route */
830 if (rt->rt_flags & RTF_CONDEMNED)
831 return;
832
833 /* Add an extra ref for ourselves */
834 RT_ADDREF_LOCKED(rt);
2d21ac55 835
6d2010ae
A
836 /* Become a regular mutex, just in case */
837 RT_CONVERT_LOCK(rt);
838
c910b4d9
A
839 /*
840 * New gateway could require new ifaddr, ifp; flags may also
841 * be different; ifp may be specified by ll sockaddr when
842 * protocol address is ambiguous.
843 */
844 if (Ifpaddr && (ifa = ifa_ifwithnet_scoped(Ifpaddr, ifscope)) &&
91447636 845 (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate)) {
6d2010ae 846 IFA_REMREF(ifa);
c910b4d9
A
847 ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate, ifp);
848 } else {
39236c6e 849 if (ifa != NULL) {
6d2010ae 850 IFA_REMREF(ifa);
39236c6e 851 ifa = NULL;
91447636 852 }
39236c6e 853 if (Ifpaddr && (ifp = if_withname(Ifpaddr))) {
91447636
A
854 if (Gate) {
855 ifa = ifaof_ifpforaddr(Gate, ifp);
c910b4d9 856 } else {
91447636
A
857 ifnet_lock_shared(ifp);
858 ifa = TAILQ_FIRST(&ifp->if_addrhead);
b0d623f7 859 if (ifa != NULL)
6d2010ae 860 IFA_ADDREF(ifa);
91447636
A
861 ifnet_lock_done(ifp);
862 }
c910b4d9
A
863 } else if (Ifaaddr &&
864 (ifa = ifa_ifwithaddr_scoped(Ifaaddr, ifscope))) {
91447636 865 ifp = ifa->ifa_ifp;
b0d623f7
A
866 } else if (Gate != NULL) {
867 /*
868 * Safe to drop rt_lock and use rt_key, since holding
869 * rnh_lock here prevents another thread from calling
870 * rt_setgate() on this route. We cannot hold the
871 * lock across ifa_ifwithroute since the lookup done
872 * by that routine may point to the same route.
873 */
874 RT_UNLOCK(rt);
875 if ((ifa = ifa_ifwithroute_scoped_locked(rt->rt_flags,
876 rt_key(rt), Gate, ifscope)) != NULL)
877 ifp = ifa->ifa_ifp;
878 RT_LOCK(rt);
879 /* Don't update a defunct route */
880 if (rt->rt_flags & RTF_CONDEMNED) {
881 if (ifa != NULL)
6d2010ae 882 IFA_REMREF(ifa);
b0d623f7
A
883 /* Release extra ref */
884 RT_REMREF_LOCKED(rt);
885 return;
886 }
91447636
A
887 }
888 }
39236c6e
A
889
890 /* trigger route cache reevaluation */
891 if (rt_key(rt)->sa_family == AF_INET)
892 routegenid_inet_update();
893#if INET6
894 else if (rt_key(rt)->sa_family == AF_INET6)
895 routegenid_inet6_update();
896#endif /* INET6 */
897
898 if (ifa != NULL) {
91447636 899 struct ifaddr *oifa = rt->rt_ifa;
1c79356b 900 if (oifa != ifa) {
6d2010ae
A
901 if (oifa != NULL) {
902 IFA_LOCK_SPIN(oifa);
903 ifa_rtrequest = oifa->ifa_rtrequest;
904 IFA_UNLOCK(oifa);
905 if (ifa_rtrequest != NULL)
906 ifa_rtrequest(RTM_DELETE, rt, Gate);
907 }
9bccf70c 908 rtsetifa(rt, ifa);
6d2010ae
A
909
910 if (rt->rt_ifp != ifp) {
911 /*
912 * Purge any link-layer info caching.
913 */
914 if (rt->rt_llinfo_purge != NULL)
915 rt->rt_llinfo_purge(rt);
916
917 /*
918 * Adjust route ref count for the interfaces.
919 */
920 if (rt->rt_if_ref_fn != NULL) {
921 rt->rt_if_ref_fn(ifp, 1);
922 rt->rt_if_ref_fn(rt->rt_ifp, -1);
923 }
d1ecb069 924 }
c910b4d9
A
925 rt->rt_ifp = ifp;
926 /*
927 * If this is the (non-scoped) default route, record
928 * the interface index used for the primary ifscope.
929 */
6d2010ae
A
930 if (rt_primary_default(rt, rt_key(rt))) {
931 set_primary_ifscope(rt_key(rt)->sa_family,
932 rt->rt_ifp->if_index);
933 }
39236c6e
A
934 /*
935 * If rmx_mtu is not locked, update it
936 * to the MTU used by the new interface.
937 */
938 if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
939 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
940
6d2010ae
A
941 if (rt->rt_ifa != NULL) {
942 IFA_LOCK_SPIN(rt->rt_ifa);
943 ifa_rtrequest = rt->rt_ifa->ifa_rtrequest;
944 IFA_UNLOCK(rt->rt_ifa);
945 if (ifa_rtrequest != NULL)
946 ifa_rtrequest(RTM_ADD, rt, Gate);
947 }
948 IFA_REMREF(ifa);
b0d623f7
A
949 /* Release extra ref */
950 RT_REMREF_LOCKED(rt);
951 return;
91447636 952 }
6d2010ae 953 IFA_REMREF(ifa);
39236c6e 954 ifa = NULL;
1c79356b 955 }
b0d623f7 956
1c79356b 957 /* XXX: to reset gateway to correct value, at RTM_CHANGE */
6d2010ae
A
958 if (rt->rt_ifa != NULL) {
959 IFA_LOCK_SPIN(rt->rt_ifa);
960 ifa_rtrequest = rt->rt_ifa->ifa_rtrequest;
961 IFA_UNLOCK(rt->rt_ifa);
962 if (ifa_rtrequest != NULL)
963 ifa_rtrequest(RTM_ADD, rt, Gate);
964 }
1c79356b 965
39236c6e
A
966 /*
967 * Workaround for local address routes pointing to the loopback
968 * interface added by configd, until <rdar://problem/12970142>.
969 */
970 if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
971 (rt->rt_flags & RTF_HOST) && rt->rt_ifa->ifa_ifp == rt->rt_ifp) {
972 ifa = ifa_ifwithaddr(rt_key(rt));
973 if (ifa != NULL) {
974 if (ifa != rt->rt_ifa)
975 rtsetifa(rt, ifa);
976 IFA_REMREF(ifa);
977 }
978 }
979
b0d623f7
A
980 /* Release extra ref */
981 RT_REMREF_LOCKED(rt);
982}
1c79356b 983
1c79356b
A
984/*
985 * Extract the addresses of the passed sockaddrs.
986 * Do a little sanity checking so as to avoid bad memory references.
987 * This data is derived straight from userland.
988 */
989static int
2d21ac55 990rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
1c79356b 991{
91447636
A
992 struct sockaddr *sa;
993 int i;
1c79356b 994
39236c6e 995 bzero(rtinfo->rti_info, sizeof (rtinfo->rti_info));
1c79356b
A
996 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
997 if ((rtinfo->rti_addrs & (1 << i)) == 0)
998 continue;
999 sa = (struct sockaddr *)cp;
1000 /*
1001 * It won't fit.
1002 */
39236c6e 1003 if ((cp + sa->sa_len) > cplim)
1c79356b 1004 return (EINVAL);
1c79356b
A
1005 /*
1006 * there are no more.. quit now
1007 * If there are more bits, they are in error.
39236c6e 1008 * I've seen this. route(1) can evidently generate these.
1c79356b
A
1009 * This causes kernel to core dump.
1010 * for compatibility, If we see this, point to a safe address.
1011 */
1012 if (sa->sa_len == 0) {
1013 rtinfo->rti_info[i] = &sa_zero;
1014 return (0); /* should be EINVAL but for compat */
1015 }
1c79356b
A
1016 /* accept it */
1017 rtinfo->rti_info[i] = sa;
b0d623f7 1018 ADVANCE32(cp, sa);
1c79356b
A
1019 }
1020 return (0);
1021}
1022
1023static struct mbuf *
b0d623f7 1024rt_msg1(int type, struct rt_addrinfo *rtinfo)
1c79356b 1025{
91447636
A
1026 struct rt_msghdr *rtm;
1027 struct mbuf *m;
1028 int i;
3e170ce0 1029 int len, dlen, off;
1c79356b 1030
1c79356b
A
1031 switch (type) {
1032
1033 case RTM_DELADDR:
1034 case RTM_NEWADDR:
39236c6e 1035 len = sizeof (struct ifa_msghdr);
1c79356b
A
1036 break;
1037
1038 case RTM_DELMADDR:
1039 case RTM_NEWMADDR:
39236c6e 1040 len = sizeof (struct ifma_msghdr);
1c79356b
A
1041 break;
1042
1043 case RTM_IFINFO:
39236c6e 1044 len = sizeof (struct if_msghdr);
1c79356b
A
1045 break;
1046
1047 default:
39236c6e 1048 len = sizeof (struct rt_msghdr);
1c79356b 1049 }
9bccf70c
A
1050 m = m_gethdr(M_DONTWAIT, MT_DATA);
1051 if (m && len > MHLEN) {
1052 MCLGET(m, M_DONTWAIT);
39236c6e 1053 if (!(m->m_flags & M_EXT)) {
9bccf70c
A
1054 m_free(m);
1055 m = NULL;
1056 }
1057 }
39236c6e
A
1058 if (m == NULL)
1059 return (NULL);
1c79356b 1060 m->m_pkthdr.len = m->m_len = len;
39236c6e 1061 m->m_pkthdr.rcvif = NULL;
1c79356b
A
1062 rtm = mtod(m, struct rt_msghdr *);
1063 bzero((caddr_t)rtm, len);
3e170ce0 1064 off = len;
1c79356b 1065 for (i = 0; i < RTAX_MAX; i++) {
b0d623f7 1066 struct sockaddr *sa, *hint;
39236c6e
A
1067 uint8_t ssbuf[SOCK_MAXADDRLEN + 1];
1068
1069 /*
1070 * Make sure to accomodate the largest possible size of sa_len.
1071 */
1072 _CASSERT(sizeof (ssbuf) == (SOCK_MAXADDRLEN + 1));
b0d623f7 1073
1c79356b
A
1074 if ((sa = rtinfo->rti_info[i]) == NULL)
1075 continue;
b0d623f7
A
1076
1077 switch (i) {
1078 case RTAX_DST:
1079 case RTAX_NETMASK:
1080 if ((hint = rtinfo->rti_info[RTAX_DST]) == NULL)
1081 hint = rtinfo->rti_info[RTAX_IFA];
1082
1083 /* Scrub away any trace of embedded interface scope */
39236c6e 1084 sa = rtm_scrub(type, i, hint, sa, &ssbuf,
813fb2f6 1085 sizeof (ssbuf), NULL, 0);
b0d623f7
A
1086 break;
1087
1088 default:
1089 break;
1090 }
1091
1c79356b 1092 rtinfo->rti_addrs |= (1 << i);
3e170ce0
A
1093 dlen = sa->sa_len;
1094 m_copyback(m, off, dlen, (caddr_t)sa);
1095 len = off + dlen;
1096 off += ROUNDUP32(dlen);
1c79356b
A
1097 }
1098 if (m->m_pkthdr.len != len) {
1099 m_freem(m);
1100 return (NULL);
1101 }
1102 rtm->rtm_msglen = len;
1103 rtm->rtm_version = RTM_VERSION;
1104 rtm->rtm_type = type;
1105 return (m);
1106}
1107
1108static int
39236c6e 1109rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w,
813fb2f6 1110 kauth_cred_t* credp, uint32_t rtm_hint_flags)
1c79356b 1111{
91447636 1112 int i;
3e170ce0 1113 int len, dlen, rlen, second_time = 0;
1c79356b
A
1114 caddr_t cp0;
1115
1116 rtinfo->rti_addrs = 0;
1117again:
1118 switch (type) {
1119
1120 case RTM_DELADDR:
1121 case RTM_NEWADDR:
39236c6e 1122 len = sizeof (struct ifa_msghdr);
1c79356b
A
1123 break;
1124
91447636
A
1125 case RTM_DELMADDR:
1126 case RTM_NEWMADDR:
39236c6e 1127 len = sizeof (struct ifma_msghdr);
91447636
A
1128 break;
1129
1c79356b 1130 case RTM_IFINFO:
39236c6e 1131 len = sizeof (struct if_msghdr);
1c79356b
A
1132 break;
1133
91447636 1134 case RTM_IFINFO2:
39236c6e 1135 len = sizeof (struct if_msghdr2);
91447636
A
1136 break;
1137
1138 case RTM_NEWMADDR2:
39236c6e 1139 len = sizeof (struct ifma_msghdr2);
91447636
A
1140 break;
1141
6d2010ae
A
1142 case RTM_GET_EXT:
1143 len = sizeof (struct rt_msghdr_ext);
1144 break;
1145
91447636 1146 case RTM_GET2:
39236c6e 1147 len = sizeof (struct rt_msghdr2);
91447636
A
1148 break;
1149
1c79356b 1150 default:
39236c6e 1151 len = sizeof (struct rt_msghdr);
1c79356b
A
1152 }
1153 cp0 = cp;
1154 if (cp0)
1155 cp += len;
1156 for (i = 0; i < RTAX_MAX; i++) {
b0d623f7 1157 struct sockaddr *sa, *hint;
39236c6e 1158 uint8_t ssbuf[SOCK_MAXADDRLEN + 1];
1c79356b 1159
39236c6e
A
1160 /*
1161 * Make sure to accomodate the largest possible size of sa_len.
1162 */
1163 _CASSERT(sizeof (ssbuf) == (SOCK_MAXADDRLEN + 1));
1164
1165 if ((sa = rtinfo->rti_info[i]) == NULL)
1c79356b 1166 continue;
b0d623f7
A
1167
1168 switch (i) {
1169 case RTAX_DST:
1170 case RTAX_NETMASK:
1171 if ((hint = rtinfo->rti_info[RTAX_DST]) == NULL)
1172 hint = rtinfo->rti_info[RTAX_IFA];
1173
1174 /* Scrub away any trace of embedded interface scope */
39236c6e 1175 sa = rtm_scrub(type, i, hint, sa, &ssbuf,
813fb2f6 1176 sizeof (ssbuf), NULL, rtm_hint_flags);
39236c6e 1177 break;
d190cdc3 1178 case RTAX_GATEWAY:
39236c6e
A
1179 case RTAX_IFP:
1180 sa = rtm_scrub(type, i, NULL, sa, &ssbuf,
813fb2f6 1181 sizeof (ssbuf), credp, rtm_hint_flags);
b0d623f7
A
1182 break;
1183
1184 default:
1185 break;
1186 }
1187
1c79356b 1188 rtinfo->rti_addrs |= (1 << i);
3e170ce0
A
1189 dlen = sa->sa_len;
1190 rlen = ROUNDUP32(dlen);
1c79356b 1191 if (cp) {
3e170ce0
A
1192 bcopy((caddr_t)sa, cp, (size_t)dlen);
1193 if (dlen != rlen)
1194 bzero(cp + dlen, rlen - dlen);
1195 cp += rlen;
1c79356b 1196 }
3e170ce0 1197 len += rlen;
1c79356b 1198 }
39236c6e 1199 if (cp == NULL && w != NULL && !second_time) {
91447636 1200 struct walkarg *rw = w;
1c79356b 1201
39236c6e 1202 if (rw->w_req != NULL) {
1c79356b 1203 if (rw->w_tmemsize < len) {
39236c6e 1204 if (rw->w_tmem != NULL)
1c79356b 1205 FREE(rw->w_tmem, M_RTABLE);
316670eb 1206 rw->w_tmem = _MALLOC(len, M_RTABLE, M_WAITOK);
39236c6e 1207 if (rw->w_tmem != NULL)
1c79356b
A
1208 rw->w_tmemsize = len;
1209 }
39236c6e 1210 if (rw->w_tmem != NULL) {
1c79356b
A
1211 cp = rw->w_tmem;
1212 second_time = 1;
1213 goto again;
1214 }
1215 }
1216 }
1217 if (cp) {
316670eb 1218 struct rt_msghdr *rtm = (struct rt_msghdr *)(void *)cp0;
1c79356b
A
1219
1220 rtm->rtm_version = RTM_VERSION;
1221 rtm->rtm_type = type;
1222 rtm->rtm_msglen = len;
1223 }
1224 return (len);
1225}
1226
1227/*
1228 * This routine is called to generate a message from the routing
91447636 1229 * socket indicating that a redirect has occurred, a routing lookup
1c79356b
A
1230 * has failed, or that a protocol has detected timeouts to a particular
1231 * destination.
1232 */
1233void
2d21ac55 1234rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
1c79356b 1235{
91447636
A
1236 struct rt_msghdr *rtm;
1237 struct mbuf *m;
1c79356b 1238 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
39236c6e 1239 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b
A
1240
1241 if (route_cb.any_count == 0)
1242 return;
1243 m = rt_msg1(type, rtinfo);
39236c6e 1244 if (m == NULL)
1c79356b
A
1245 return;
1246 rtm = mtod(m, struct rt_msghdr *);
1247 rtm->rtm_flags = RTF_DONE | flags;
1248 rtm->rtm_errno = error;
1249 rtm->rtm_addrs = rtinfo->rti_addrs;
6d2010ae 1250 route_proto.sp_family = sa ? sa->sa_family : 0;
1c79356b
A
1251 raw_input(m, &route_proto, &route_src, &route_dst);
1252}
1253
1254/*
1255 * This routine is called to generate a message from the routing
1256 * socket indicating that the status of a network interface has changed.
1257 */
1258void
39236c6e 1259rt_ifmsg(struct ifnet *ifp)
1c79356b 1260{
91447636 1261 struct if_msghdr *ifm;
1c79356b
A
1262 struct mbuf *m;
1263 struct rt_addrinfo info;
39236c6e 1264 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b
A
1265
1266 if (route_cb.any_count == 0)
1267 return;
39236c6e 1268 bzero((caddr_t)&info, sizeof (info));
1c79356b 1269 m = rt_msg1(RTM_IFINFO, &info);
39236c6e 1270 if (m == NULL)
1c79356b
A
1271 return;
1272 ifm = mtod(m, struct if_msghdr *);
1273 ifm->ifm_index = ifp->if_index;
1274 ifm->ifm_flags = (u_short)ifp->if_flags;
2d21ac55 1275 if_data_internal_to_if_data(ifp, &ifp->if_data, &ifm->ifm_data);
1c79356b 1276 ifm->ifm_addrs = 0;
1c79356b
A
1277 raw_input(m, &route_proto, &route_src, &route_dst);
1278}
1279
1280/*
1281 * This is called to generate messages from the routing socket
1282 * indicating a network interface has had addresses associated with it.
1283 * if we ever reverse the logic and replace messages TO the routing
1284 * socket indicate a request to configure interfaces, then it will
1285 * be unnecessary as the routing socket will automatically generate
1286 * copies of it.
91447636
A
1287 *
1288 * Since this is coming from the interface, it is expected that the
6d2010ae 1289 * interface will be locked. Caller must hold rnh_lock and rt_lock.
1c79356b
A
1290 */
1291void
2d21ac55 1292rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1c79356b
A
1293{
1294 struct rt_addrinfo info;
1295 struct sockaddr *sa = 0;
1296 int pass;
1297 struct mbuf *m = 0;
1298 struct ifnet *ifp = ifa->ifa_ifp;
39236c6e 1299 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b 1300
6d2010ae 1301 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1302 RT_LOCK_ASSERT_HELD(rt);
1303
1c79356b
A
1304 if (route_cb.any_count == 0)
1305 return;
6d2010ae
A
1306
1307 /* Become a regular mutex, just in case */
1308 RT_CONVERT_LOCK(rt);
1c79356b 1309 for (pass = 1; pass < 3; pass++) {
39236c6e 1310 bzero((caddr_t)&info, sizeof (info));
1c79356b
A
1311 if ((cmd == RTM_ADD && pass == 1) ||
1312 (cmd == RTM_DELETE && pass == 2)) {
91447636 1313 struct ifa_msghdr *ifam;
1c79356b
A
1314 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
1315
6d2010ae 1316 /* Lock ifp for if_lladdr */
b0d623f7 1317 ifnet_lock_shared(ifp);
6d2010ae
A
1318 IFA_LOCK(ifa);
1319 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
1320 /*
1321 * Holding ifnet lock here prevents the link address
1322 * from changing contents, so no need to hold its
1323 * lock. The link address is always present; it's
1324 * never freed.
1325 */
1326 info.rti_info[RTAX_IFP] = ifp->if_lladdr->ifa_addr;
1327 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1328 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
b0d623f7 1329 if ((m = rt_msg1(ncmd, &info)) == NULL) {
6d2010ae 1330 IFA_UNLOCK(ifa);
b0d623f7 1331 ifnet_lock_done(ifp);
1c79356b 1332 continue;
b0d623f7 1333 }
6d2010ae 1334 IFA_UNLOCK(ifa);
b0d623f7 1335 ifnet_lock_done(ifp);
1c79356b
A
1336 ifam = mtod(m, struct ifa_msghdr *);
1337 ifam->ifam_index = ifp->if_index;
6d2010ae 1338 IFA_LOCK_SPIN(ifa);
1c79356b
A
1339 ifam->ifam_metric = ifa->ifa_metric;
1340 ifam->ifam_flags = ifa->ifa_flags;
6d2010ae 1341 IFA_UNLOCK(ifa);
1c79356b
A
1342 ifam->ifam_addrs = info.rti_addrs;
1343 }
1344 if ((cmd == RTM_ADD && pass == 2) ||
1345 (cmd == RTM_DELETE && pass == 1)) {
91447636 1346 struct rt_msghdr *rtm;
1c79356b 1347
39236c6e 1348 if (rt == NULL)
1c79356b 1349 continue;
6d2010ae
A
1350 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1351 info.rti_info[RTAX_DST] = sa = rt_key(rt);
1352 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1c79356b
A
1353 if ((m = rt_msg1(cmd, &info)) == NULL)
1354 continue;
1355 rtm = mtod(m, struct rt_msghdr *);
1356 rtm->rtm_index = ifp->if_index;
1357 rtm->rtm_flags |= rt->rt_flags;
1358 rtm->rtm_errno = error;
1359 rtm->rtm_addrs = info.rti_addrs;
1360 }
1361 route_proto.sp_protocol = sa ? sa->sa_family : 0;
1362 raw_input(m, &route_proto, &route_src, &route_dst);
1363 }
1364}
1365
1366/*
1367 * This is the analogue to the rt_newaddrmsg which performs the same
1368 * function but for multicast group memberhips. This is easier since
1369 * there is no route state to worry about.
1370 */
1371void
2d21ac55 1372rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1c79356b
A
1373{
1374 struct rt_addrinfo info;
1375 struct mbuf *m = 0;
1376 struct ifnet *ifp = ifma->ifma_ifp;
1377 struct ifma_msghdr *ifmam;
39236c6e 1378 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b
A
1379
1380 if (route_cb.any_count == 0)
1381 return;
1382
6d2010ae
A
1383 /* Lock ifp for if_lladdr */
1384 ifnet_lock_shared(ifp);
39236c6e 1385 bzero((caddr_t)&info, sizeof (info));
6d2010ae
A
1386 IFMA_LOCK(ifma);
1387 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
39236c6e
A
1388 /* lladdr doesn't need lock */
1389 info.rti_info[RTAX_IFP] = ifp->if_lladdr->ifa_addr;
6d2010ae 1390
1c79356b
A
1391 /*
1392 * If a link-layer address is present, present it as a ``gateway''
1393 * (similarly to how ARP entries, e.g., are presented).
1394 */
39236c6e
A
1395 info.rti_info[RTAX_GATEWAY] = (ifma->ifma_ll != NULL) ?
1396 ifma->ifma_ll->ifma_addr : NULL;
b0d623f7 1397 if ((m = rt_msg1(cmd, &info)) == NULL) {
6d2010ae
A
1398 IFMA_UNLOCK(ifma);
1399 ifnet_lock_done(ifp);
1c79356b 1400 return;
b0d623f7 1401 }
1c79356b 1402 ifmam = mtod(m, struct ifma_msghdr *);
6d2010ae 1403 ifmam->ifmam_index = ifp->if_index;
1c79356b
A
1404 ifmam->ifmam_addrs = info.rti_addrs;
1405 route_proto.sp_protocol = ifma->ifma_addr->sa_family;
6d2010ae
A
1406 IFMA_UNLOCK(ifma);
1407 ifnet_lock_done(ifp);
1c79356b
A
1408 raw_input(m, &route_proto, &route_src, &route_dst);
1409}
1410
39236c6e
A
1411const char *
1412rtm2str(int cmd)
1413{
1414 const char *c = "RTM_?";
1415
1416 switch (cmd) {
1417 case RTM_ADD:
1418 c = "RTM_ADD";
1419 break;
1420 case RTM_DELETE:
1421 c = "RTM_DELETE";
1422 break;
1423 case RTM_CHANGE:
1424 c = "RTM_CHANGE";
1425 break;
1426 case RTM_GET:
1427 c = "RTM_GET";
1428 break;
1429 case RTM_LOSING:
1430 c = "RTM_LOSING";
1431 break;
1432 case RTM_REDIRECT:
1433 c = "RTM_REDIRECT";
1434 break;
1435 case RTM_MISS:
1436 c = "RTM_MISS";
1437 break;
1438 case RTM_LOCK:
1439 c = "RTM_LOCK";
1440 break;
1441 case RTM_OLDADD:
1442 c = "RTM_OLDADD";
1443 break;
1444 case RTM_OLDDEL:
1445 c = "RTM_OLDDEL";
1446 break;
1447 case RTM_RESOLVE:
1448 c = "RTM_RESOLVE";
1449 break;
1450 case RTM_NEWADDR:
1451 c = "RTM_NEWADDR";
1452 break;
1453 case RTM_DELADDR:
1454 c = "RTM_DELADDR";
1455 break;
1456 case RTM_IFINFO:
1457 c = "RTM_IFINFO";
1458 break;
1459 case RTM_NEWMADDR:
1460 c = "RTM_NEWMADDR";
1461 break;
1462 case RTM_DELMADDR:
1463 c = "RTM_DELMADDR";
1464 break;
1465 case RTM_GET_SILENT:
1466 c = "RTM_GET_SILENT";
1467 break;
1468 case RTM_IFINFO2:
1469 c = "RTM_IFINFO2";
1470 break;
1471 case RTM_NEWMADDR2:
1472 c = "RTM_NEWMADDR2";
1473 break;
1474 case RTM_GET2:
1475 c = "RTM_GET2";
1476 break;
1477 case RTM_GET_EXT:
1478 c = "RTM_GET_EXT";
1479 break;
1480 }
1481
1482 return (c);
1483}
1484
1c79356b
A
1485/*
1486 * This is used in dumping the kernel table via sysctl().
1487 */
39236c6e 1488static int
2d21ac55 1489sysctl_dumpentry(struct radix_node *rn, void *vw)
1c79356b 1490{
91447636
A
1491 struct walkarg *w = vw;
1492 struct rtentry *rt = (struct rtentry *)rn;
1c79356b
A
1493 int error = 0, size;
1494 struct rt_addrinfo info;
39236c6e 1495 kauth_cred_t cred;
813fb2f6 1496 uint32_t rtm_hint_flags = 0;
39236c6e
A
1497
1498 cred = kauth_cred_proc_ref(current_proc());
1c79356b 1499
b0d623f7 1500 RT_LOCK(rt);
39236c6e
A
1501 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1502 goto done;
1503 bzero((caddr_t)&info, sizeof (info));
6d2010ae
A
1504 info.rti_info[RTAX_DST] = rt_key(rt);
1505 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1506 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1507 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
1508
813fb2f6
A
1509 if (rt->rt_ifp == lo_ifp)
1510 rtm_hint_flags |= RTMF_HIDE_LLADDR;
1511
91447636 1512 if (w->w_op != NET_RT_DUMP2) {
813fb2f6 1513 size = rt_msg2(RTM_GET, &info, NULL, w, &cred, rtm_hint_flags);
39236c6e 1514 if (w->w_req != NULL && w->w_tmem != NULL) {
316670eb
A
1515 struct rt_msghdr *rtm =
1516 (struct rt_msghdr *)(void *)w->w_tmem;
91447636
A
1517
1518 rtm->rtm_flags = rt->rt_flags;
1519 rtm->rtm_use = rt->rt_use;
6d2010ae 1520 rt_getmetrics(rt, &rtm->rtm_rmx);
91447636
A
1521 rtm->rtm_index = rt->rt_ifp->if_index;
1522 rtm->rtm_pid = 0;
6d2010ae
A
1523 rtm->rtm_seq = 0;
1524 rtm->rtm_errno = 0;
91447636
A
1525 rtm->rtm_addrs = info.rti_addrs;
1526 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
91447636
A
1527 }
1528 } else {
813fb2f6 1529 size = rt_msg2(RTM_GET2, &info, NULL, w, &cred, rtm_hint_flags);
39236c6e 1530 if (w->w_req != NULL && w->w_tmem != NULL) {
316670eb
A
1531 struct rt_msghdr2 *rtm =
1532 (struct rt_msghdr2 *)(void *)w->w_tmem;
6d2010ae
A
1533
1534 rtm->rtm_flags = rt->rt_flags;
1535 rtm->rtm_use = rt->rt_use;
1536 rt_getmetrics(rt, &rtm->rtm_rmx);
1537 rtm->rtm_index = rt->rt_ifp->if_index;
1538 rtm->rtm_refcnt = rt->rt_refcnt;
91447636
A
1539 if (rt->rt_parent)
1540 rtm->rtm_parentflags = rt->rt_parent->rt_flags;
1541 else
1542 rtm->rtm_parentflags = 0;
6d2010ae
A
1543 rtm->rtm_reserved = 0;
1544 rtm->rtm_addrs = info.rti_addrs;
1545 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
91447636 1546 }
1c79356b 1547 }
39236c6e
A
1548
1549done:
b0d623f7 1550 RT_UNLOCK(rt);
39236c6e 1551 kauth_cred_unref(&cred);
1c79356b
A
1552 return (error);
1553}
1554
6d2010ae
A
1555/*
1556 * This is used for dumping extended information from route entries.
1557 */
39236c6e 1558static int
6d2010ae
A
1559sysctl_dumpentry_ext(struct radix_node *rn, void *vw)
1560{
1561 struct walkarg *w = vw;
1562 struct rtentry *rt = (struct rtentry *)rn;
1563 int error = 0, size;
1564 struct rt_addrinfo info;
39236c6e 1565 kauth_cred_t cred;
813fb2f6 1566 uint32_t rtm_hint_flags = 0;
39236c6e
A
1567
1568 cred = kauth_cred_proc_ref(current_proc());
6d2010ae
A
1569
1570 RT_LOCK(rt);
39236c6e
A
1571 if (w->w_op == NET_RT_DUMPX_FLAGS && !(rt->rt_flags & w->w_arg))
1572 goto done;
6d2010ae
A
1573 bzero(&info, sizeof (info));
1574 info.rti_info[RTAX_DST] = rt_key(rt);
1575 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1576 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1577 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
39236c6e 1578
813fb2f6
A
1579 if (rt->rt_ifp == lo_ifp)
1580 rtm_hint_flags |= RTMF_HIDE_LLADDR;
1581
1582 size = rt_msg2(RTM_GET_EXT, &info, NULL, w, &cred, rtm_hint_flags);
39236c6e 1583 if (w->w_req != NULL && w->w_tmem != NULL) {
316670eb
A
1584 struct rt_msghdr_ext *ertm =
1585 (struct rt_msghdr_ext *)(void *)w->w_tmem;
6d2010ae
A
1586
1587 ertm->rtm_flags = rt->rt_flags;
1588 ertm->rtm_use = rt->rt_use;
1589 rt_getmetrics(rt, &ertm->rtm_rmx);
1590 ertm->rtm_index = rt->rt_ifp->if_index;
1591 ertm->rtm_pid = 0;
1592 ertm->rtm_seq = 0;
1593 ertm->rtm_errno = 0;
1594 ertm->rtm_addrs = info.rti_addrs;
316670eb 1595 if (rt->rt_llinfo_get_ri == NULL) {
6d2010ae 1596 bzero(&ertm->rtm_ri, sizeof (ertm->rtm_ri));
316670eb
A
1597 ertm->rtm_ri.ri_rssi = IFNET_RSSI_UNKNOWN;
1598 ertm->rtm_ri.ri_lqm = IFNET_LQM_THRESH_OFF;
1599 ertm->rtm_ri.ri_npm = IFNET_NPM_THRESH_UNKNOWN;
39236c6e 1600 } else {
6d2010ae 1601 rt->rt_llinfo_get_ri(rt, &ertm->rtm_ri);
39236c6e 1602 }
6d2010ae 1603 error = SYSCTL_OUT(w->w_req, (caddr_t)ertm, size);
6d2010ae 1604 }
39236c6e
A
1605
1606done:
6d2010ae 1607 RT_UNLOCK(rt);
39236c6e 1608 kauth_cred_unref(&cred);
6d2010ae
A
1609 return (error);
1610}
1611
1612/*
1613 * rdar://9307819
39236c6e
A
1614 * To avoid to call copyout() while holding locks and to cause problems
1615 * in the paging path, sysctl_iflist() and sysctl_iflist2() contstruct
6d2010ae
A
1616 * the list in two passes. In the first pass we compute the total
1617 * length of the data we are going to copyout, then we release
39236c6e 1618 * all locks to allocate a temporary buffer that gets filled
6d2010ae
A
1619 * in the second pass.
1620 *
39236c6e
A
1621 * Note that we are verifying the assumption that _MALLOC returns a buffer
1622 * that is at least 32 bits aligned and that the messages and addresses are
6d2010ae
A
1623 * 32 bits aligned.
1624 */
39236c6e 1625static int
6d2010ae 1626sysctl_iflist(int af, struct walkarg *w)
1c79356b 1627{
91447636
A
1628 struct ifnet *ifp;
1629 struct ifaddr *ifa;
1c79356b
A
1630 struct rt_addrinfo info;
1631 int len, error = 0;
6d2010ae
A
1632 int pass = 0;
1633 int total_len = 0, current_len = 0;
1634 char *total_buffer = NULL, *cp = NULL;
39236c6e
A
1635 kauth_cred_t cred;
1636
1637 cred = kauth_cred_proc_ref(current_proc());
1638
1639 bzero((caddr_t)&info, sizeof (info));
1c79356b 1640
6d2010ae
A
1641 for (pass = 0; pass < 2; pass++) {
1642 ifnet_head_lock_shared();
39236c6e 1643
6d2010ae
A
1644 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1645 if (error)
91447636 1646 break;
6d2010ae 1647 if (w->w_arg && w->w_arg != ifp->if_index)
1c79356b 1648 continue;
6d2010ae
A
1649 ifnet_lock_shared(ifp);
1650 /*
39236c6e
A
1651 * Holding ifnet lock here prevents the link address
1652 * from changing contents, so no need to hold the ifa
1653 * lock. The link address is always present; it's
1654 * never freed.
6d2010ae
A
1655 */
1656 ifa = ifp->if_lladdr;
1657 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
813fb2f6 1658 len = rt_msg2(RTM_IFINFO, &info, NULL, NULL, &cred, RTMF_HIDE_LLADDR);
6d2010ae
A
1659 if (pass == 0) {
1660 total_len += len;
1661 } else {
1662 struct if_msghdr *ifm;
1663
1664 if (current_len + len > total_len) {
1665 ifnet_lock_done(ifp);
6d2010ae 1666 error = ENOBUFS;
91447636 1667 break;
6d2010ae
A
1668 }
1669 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
39236c6e 1670 len = rt_msg2(RTM_IFINFO, &info,
813fb2f6 1671 (caddr_t)cp, NULL, &cred, RTMF_HIDE_LLADDR);
6d2010ae 1672 info.rti_info[RTAX_IFP] = NULL;
39236c6e 1673
316670eb 1674 ifm = (struct if_msghdr *)(void *)cp;
6d2010ae
A
1675 ifm->ifm_index = ifp->if_index;
1676 ifm->ifm_flags = (u_short)ifp->if_flags;
1677 if_data_internal_to_if_data(ifp, &ifp->if_data,
39236c6e 1678 &ifm->ifm_data);
6d2010ae
A
1679 ifm->ifm_addrs = info.rti_addrs;
1680
1681 cp += len;
39236c6e 1682 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae 1683 current_len += len;
1c79356b 1684 }
39236c6e 1685 while ((ifa = ifa->ifa_link.tqe_next) != NULL) {
6d2010ae
A
1686 IFA_LOCK(ifa);
1687 if (af && af != ifa->ifa_addr->sa_family) {
1688 IFA_UNLOCK(ifa);
1689 continue;
1690 }
1691 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1692 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1693 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
39236c6e 1694 len = rt_msg2(RTM_NEWADDR, &info, NULL, NULL,
813fb2f6 1695 &cred, RTMF_HIDE_LLADDR);
6d2010ae
A
1696 if (pass == 0) {
1697 total_len += len;
1698 } else {
1699 struct ifa_msghdr *ifam;
1700
1701 if (current_len + len > total_len) {
1702 IFA_UNLOCK(ifa);
6d2010ae
A
1703 error = ENOBUFS;
1704 break;
1705 }
39236c6e 1706 len = rt_msg2(RTM_NEWADDR, &info,
813fb2f6 1707 (caddr_t)cp, NULL, &cred, RTMF_HIDE_LLADDR);
39236c6e 1708
316670eb 1709 ifam = (struct ifa_msghdr *)(void *)cp;
39236c6e
A
1710 ifam->ifam_index =
1711 ifa->ifa_ifp->if_index;
6d2010ae
A
1712 ifam->ifam_flags = ifa->ifa_flags;
1713 ifam->ifam_metric = ifa->ifa_metric;
1714 ifam->ifam_addrs = info.rti_addrs;
1715
1716 cp += len;
39236c6e
A
1717 VERIFY(IS_P2ALIGNED(cp,
1718 sizeof (u_int32_t)));
6d2010ae
A
1719 current_len += len;
1720 }
1721 IFA_UNLOCK(ifa);
1722 }
1723 ifnet_lock_done(ifp);
39236c6e
A
1724 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1725 info.rti_info[RTAX_BRD] = NULL;
6d2010ae 1726 }
39236c6e 1727
6d2010ae 1728 ifnet_head_done();
39236c6e
A
1729
1730 if (error != 0) {
1731 if (error == ENOBUFS)
1732 printf("%s: current_len (%d) + len (%d) > "
1733 "total_len (%d)\n", __func__, current_len,
1734 len, total_len);
6d2010ae 1735 break;
39236c6e
A
1736 }
1737
6d2010ae
A
1738 if (pass == 0) {
1739 /* Better to return zero length buffer than ENOBUFS */
1740 if (total_len == 0)
1741 total_len = 1;
1742 total_len += total_len >> 3;
39236c6e
A
1743 total_buffer = _MALLOC(total_len, M_RTABLE,
1744 M_ZERO | M_WAITOK);
6d2010ae 1745 if (total_buffer == NULL) {
39236c6e
A
1746 printf("%s: _MALLOC(%d) failed\n", __func__,
1747 total_len);
6d2010ae
A
1748 error = ENOBUFS;
1749 break;
1750 }
1751 cp = total_buffer;
39236c6e 1752 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae
A
1753 } else {
1754 error = SYSCTL_OUT(w->w_req, total_buffer, current_len);
1755 if (error)
1756 break;
1c79356b 1757 }
1c79356b 1758 }
39236c6e 1759
6d2010ae
A
1760 if (total_buffer != NULL)
1761 _FREE(total_buffer, M_RTABLE);
39236c6e
A
1762
1763 kauth_cred_unref(&cred);
1764 return (error);
1c79356b
A
1765}
1766
39236c6e 1767static int
6d2010ae 1768sysctl_iflist2(int af, struct walkarg *w)
91447636
A
1769{
1770 struct ifnet *ifp;
1771 struct ifaddr *ifa;
1772 struct rt_addrinfo info;
1773 int len, error = 0;
6d2010ae
A
1774 int pass = 0;
1775 int total_len = 0, current_len = 0;
1776 char *total_buffer = NULL, *cp = NULL;
39236c6e 1777 kauth_cred_t cred;
6d2010ae 1778
39236c6e
A
1779 cred = kauth_cred_proc_ref(current_proc());
1780
1781 bzero((caddr_t)&info, sizeof (info));
6d2010ae
A
1782
1783 for (pass = 0; pass < 2; pass++) {
39236c6e
A
1784 struct ifmultiaddr *ifma;
1785
6d2010ae 1786 ifnet_head_lock_shared();
39236c6e 1787
6d2010ae
A
1788 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1789 if (error)
91447636 1790 break;
6d2010ae 1791 if (w->w_arg && w->w_arg != ifp->if_index)
91447636 1792 continue;
6d2010ae
A
1793 ifnet_lock_shared(ifp);
1794 /*
39236c6e
A
1795 * Holding ifnet lock here prevents the link address
1796 * from changing contents, so no need to hold the ifa
1797 * lock. The link address is always present; it's
1798 * never freed.
6d2010ae
A
1799 */
1800 ifa = ifp->if_lladdr;
1801 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
813fb2f6 1802 len = rt_msg2(RTM_IFINFO2, &info, NULL, NULL, &cred, RTMF_HIDE_LLADDR);
6d2010ae
A
1803 if (pass == 0) {
1804 total_len += len;
1805 } else {
1806 struct if_msghdr2 *ifm;
1807
1808 if (current_len + len > total_len) {
1809 ifnet_lock_done(ifp);
6d2010ae 1810 error = ENOBUFS;
91447636 1811 break;
6d2010ae
A
1812 }
1813 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
39236c6e 1814 len = rt_msg2(RTM_IFINFO2, &info,
813fb2f6 1815 (caddr_t)cp, NULL, &cred, RTMF_HIDE_LLADDR);
6d2010ae 1816 info.rti_info[RTAX_IFP] = NULL;
39236c6e 1817
316670eb 1818 ifm = (struct if_msghdr2 *)(void *)cp;
6d2010ae
A
1819 ifm->ifm_addrs = info.rti_addrs;
1820 ifm->ifm_flags = (u_short)ifp->if_flags;
1821 ifm->ifm_index = ifp->if_index;
316670eb
A
1822 ifm->ifm_snd_len = IFCQ_LEN(&ifp->if_snd);
1823 ifm->ifm_snd_maxlen = IFCQ_MAXLEN(&ifp->if_snd);
1824 ifm->ifm_snd_drops =
1825 ifp->if_snd.ifcq_dropcnt.packets;
6d2010ae 1826 ifm->ifm_timer = ifp->if_timer;
39236c6e
A
1827 if_data_internal_to_if_data64(ifp,
1828 &ifp->if_data, &ifm->ifm_data);
6d2010ae
A
1829
1830 cp += len;
39236c6e 1831 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae 1832 current_len += len;
91447636 1833 }
39236c6e 1834 while ((ifa = ifa->ifa_link.tqe_next) != NULL) {
6d2010ae
A
1835 IFA_LOCK(ifa);
1836 if (af && af != ifa->ifa_addr->sa_family) {
1837 IFA_UNLOCK(ifa);
91447636 1838 continue;
6d2010ae
A
1839 }
1840 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1841 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1842 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
39236c6e 1843 len = rt_msg2(RTM_NEWADDR, &info, NULL, NULL,
813fb2f6 1844 &cred, RTMF_HIDE_LLADDR);
6d2010ae
A
1845 if (pass == 0) {
1846 total_len += len;
1847 } else {
1848 struct ifa_msghdr *ifam;
39236c6e 1849
6d2010ae
A
1850 if (current_len + len > total_len) {
1851 IFA_UNLOCK(ifa);
6d2010ae 1852 error = ENOBUFS;
91447636 1853 break;
6d2010ae 1854 }
39236c6e 1855 len = rt_msg2(RTM_NEWADDR, &info,
813fb2f6 1856 (caddr_t)cp, NULL, &cred, RTMF_HIDE_LLADDR);
6d2010ae 1857
316670eb 1858 ifam = (struct ifa_msghdr *)(void *)cp;
39236c6e
A
1859 ifam->ifam_index =
1860 ifa->ifa_ifp->if_index;
6d2010ae
A
1861 ifam->ifam_flags = ifa->ifa_flags;
1862 ifam->ifam_metric = ifa->ifa_metric;
1863 ifam->ifam_addrs = info.rti_addrs;
1864
1865 cp += len;
39236c6e
A
1866 VERIFY(IS_P2ALIGNED(cp,
1867 sizeof (u_int32_t)));
6d2010ae
A
1868 current_len += len;
1869 }
1870 IFA_UNLOCK(ifa);
1871 }
1872 if (error) {
1873 ifnet_lock_done(ifp);
1874 break;
1875 }
39236c6e
A
1876
1877 for (ifma = LIST_FIRST(&ifp->if_multiaddrs);
1878 ifma != NULL; ifma = LIST_NEXT(ifma, ifma_link)) {
1879 struct ifaddr *ifa0;
1880
1881 IFMA_LOCK(ifma);
1882 if (af && af != ifma->ifma_addr->sa_family) {
1883 IFMA_UNLOCK(ifma);
1884 continue;
1885 }
1886 bzero((caddr_t)&info, sizeof (info));
1887 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
1888 /*
1889 * Holding ifnet lock here prevents the link
1890 * address from changing contents, so no need
1891 * to hold the ifa0 lock. The link address is
1892 * always present; it's never freed.
1893 */
1894 ifa0 = ifp->if_lladdr;
1895 info.rti_info[RTAX_IFP] = ifa0->ifa_addr;
1896 if (ifma->ifma_ll != NULL)
1897 info.rti_info[RTAX_GATEWAY] =
1898 ifma->ifma_ll->ifma_addr;
1899 len = rt_msg2(RTM_NEWMADDR2, &info, NULL, NULL,
813fb2f6 1900 &cred, RTMF_HIDE_LLADDR);
39236c6e
A
1901 if (pass == 0) {
1902 total_len += len;
1903 } else {
1904 struct ifma_msghdr2 *ifmam;
1905
1906 if (current_len + len > total_len) {
6d2010ae 1907 IFMA_UNLOCK(ifma);
39236c6e
A
1908 error = ENOBUFS;
1909 break;
6d2010ae 1910 }
39236c6e 1911 len = rt_msg2(RTM_NEWMADDR2, &info,
813fb2f6 1912 (caddr_t)cp, NULL, &cred, RTMF_HIDE_LLADDR);
39236c6e
A
1913
1914 ifmam =
1915 (struct ifma_msghdr2 *)(void *)cp;
1916 ifmam->ifmam_addrs = info.rti_addrs;
1917 ifmam->ifmam_flags = 0;
1918 ifmam->ifmam_index =
1919 ifma->ifma_ifp->if_index;
1920 ifmam->ifmam_refcount =
1921 ifma->ifma_reqcnt;
1922
1923 cp += len;
1924 VERIFY(IS_P2ALIGNED(cp,
1925 sizeof (u_int32_t)));
1926 current_len += len;
91447636 1927 }
39236c6e 1928 IFMA_UNLOCK(ifma);
91447636 1929 }
6d2010ae 1930 ifnet_lock_done(ifp);
39236c6e
A
1931 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1932 info.rti_info[RTAX_BRD] = NULL;
6d2010ae
A
1933 }
1934 ifnet_head_done();
39236c6e
A
1935
1936 if (error) {
1937 if (error == ENOBUFS)
1938 printf("%s: current_len (%d) + len (%d) > "
1939 "total_len (%d)\n", __func__, current_len,
1940 len, total_len);
6d2010ae 1941 break;
39236c6e
A
1942 }
1943
6d2010ae
A
1944 if (pass == 0) {
1945 /* Better to return zero length buffer than ENOBUFS */
1946 if (total_len == 0)
1947 total_len = 1;
1948 total_len += total_len >> 3;
39236c6e
A
1949 total_buffer = _MALLOC(total_len, M_RTABLE,
1950 M_ZERO | M_WAITOK);
6d2010ae 1951 if (total_buffer == NULL) {
39236c6e
A
1952 printf("%s: _MALLOC(%d) failed\n", __func__,
1953 total_len);
6d2010ae
A
1954 error = ENOBUFS;
1955 break;
1956 }
1957 cp = total_buffer;
39236c6e 1958 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae
A
1959 } else {
1960 error = SYSCTL_OUT(w->w_req, total_buffer, current_len);
1961 if (error)
1962 break;
91447636 1963 }
91447636 1964 }
39236c6e 1965
6d2010ae
A
1966 if (total_buffer != NULL)
1967 _FREE(total_buffer, M_RTABLE);
39236c6e
A
1968
1969 kauth_cred_unref(&cred);
1970 return (error);
91447636
A
1971}
1972
1973
1974static int
1975sysctl_rtstat(struct sysctl_req *req)
1976{
39236c6e 1977 return (SYSCTL_OUT(req, &rtstat, sizeof (struct rtstat)));
91447636
A
1978}
1979
1980static int
1981sysctl_rttrash(struct sysctl_req *req)
1982{
39236c6e 1983 return (SYSCTL_OUT(req, &rttrash, sizeof (rttrash)));
d1ecb069 1984}
91447636 1985
1c79356b
A
1986static int
1987sysctl_rtsock SYSCTL_HANDLER_ARGS
1988{
c910b4d9 1989#pragma unused(oidp)
1c79356b
A
1990 int *name = (int *)arg1;
1991 u_int namelen = arg2;
91447636
A
1992 struct radix_node_head *rnh;
1993 int i, error = EINVAL;
1c79356b
A
1994 u_char af;
1995 struct walkarg w;
1996
1997 name ++;
1998 namelen--;
1999 if (req->newptr)
2000 return (EPERM);
2001 if (namelen != 3)
2002 return (EINVAL);
2003 af = name[0];
39236c6e 2004 Bzero(&w, sizeof (w));
1c79356b
A
2005 w.w_op = name[1];
2006 w.w_arg = name[2];
2007 w.w_req = req;
2008
1c79356b
A
2009 switch (w.w_op) {
2010
2011 case NET_RT_DUMP:
91447636 2012 case NET_RT_DUMP2:
1c79356b 2013 case NET_RT_FLAGS:
b0d623f7 2014 lck_mtx_lock(rnh_lock);
1c79356b
A
2015 for (i = 1; i <= AF_MAX; i++)
2016 if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
2017 (error = rnh->rnh_walktree(rnh,
6d2010ae
A
2018 sysctl_dumpentry, &w)))
2019 break;
2020 lck_mtx_unlock(rnh_lock);
2021 break;
2022 case NET_RT_DUMPX:
2023 case NET_RT_DUMPX_FLAGS:
2024 lck_mtx_lock(rnh_lock);
2025 for (i = 1; i <= AF_MAX; i++)
2026 if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
2027 (error = rnh->rnh_walktree(rnh,
2028 sysctl_dumpentry_ext, &w)))
1c79356b 2029 break;
b0d623f7 2030 lck_mtx_unlock(rnh_lock);
1c79356b 2031 break;
1c79356b
A
2032 case NET_RT_IFLIST:
2033 error = sysctl_iflist(af, &w);
91447636
A
2034 break;
2035 case NET_RT_IFLIST2:
2036 error = sysctl_iflist2(af, &w);
2037 break;
2038 case NET_RT_STAT:
2039 error = sysctl_rtstat(req);
2040 break;
2041 case NET_RT_TRASH:
2042 error = sysctl_rttrash(req);
2043 break;
1c79356b 2044 }
39236c6e 2045 if (w.w_tmem != NULL)
1c79356b
A
2046 FREE(w.w_tmem, M_RTABLE);
2047 return (error);
2048}
2049
1c79356b
A
2050/*
2051 * Definitions of protocols supported in the ROUTE domain.
2052 */
1c79356b 2053static struct protosw routesw[] = {
39236c6e
A
2054{
2055 .pr_type = SOCK_RAW,
2056 .pr_protocol = 0,
2057 .pr_flags = PR_ATOMIC|PR_ADDR,
2058 .pr_output = route_output,
2059 .pr_ctlinput = raw_ctlinput,
2060 .pr_init = raw_init,
2061 .pr_usrreqs = &route_usrreqs,
1c79356b
A
2062}
2063};
2064
39236c6e 2065static int route_proto_count = (sizeof (routesw) / sizeof (struct protosw));
1c79356b 2066
39236c6e
A
2067struct domain routedomain_s = {
2068 .dom_family = PF_ROUTE,
2069 .dom_name = "route",
2070 .dom_init = route_dinit,
2071};
2072
2073static void
2074route_dinit(struct domain *dp)
2075{
2076 struct protosw *pr;
2077 int i;
1c79356b 2078
39236c6e
A
2079 VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
2080 VERIFY(routedomain == NULL);
2081
2082 routedomain = dp;
2083
2084 for (i = 0, pr = &routesw[0]; i < route_proto_count; i++, pr++)
2085 net_add_proto(pr, dp, 1);
2086
2087 route_init();
2088}