]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/rtsock.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / net / rtsock.c
CommitLineData
1c79356b 1/*
39236c6e 2 * Copyright (c) 2000-2013 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 *);
127static void rt_setmetrics(u_int32_t, struct rt_metrics *, struct rtentry *);
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
A
133static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *,
134 kauth_cred_t *);
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;
1c79356b 310
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 }
423
316670eb
A
424 /*
425 * RTF_PROXY can only be set internally from within the kernel.
426 */
427 if (rtm->rtm_flags & RTF_PROXY)
428 senderr(EINVAL);
429
6d2010ae
A
430 /*
431 * For AF_INET, always zero out the embedded scope ID. If this is
432 * a scoped request, it must be done explicitly by setting RTF_IFSCOPE
433 * flag and the corresponding rtm_index value. This is to prevent
434 * false interpretation of the scope ID because it's using the sin_zero
435 * field, which might not be properly cleared by the requestor.
436 */
437 if (info.rti_info[RTAX_DST]->sa_family == AF_INET)
438 sin_set_ifscope(info.rti_info[RTAX_DST], IFSCOPE_NONE);
39236c6e
A
439 if (info.rti_info[RTAX_GATEWAY] != NULL &&
440 info.rti_info[RTAX_GATEWAY]->sa_family == AF_INET)
6d2010ae
A
441 sin_set_ifscope(info.rti_info[RTAX_GATEWAY], IFSCOPE_NONE);
442
1c79356b 443 switch (rtm->rtm_type) {
39236c6e
A
444 case RTM_ADD:
445 if (info.rti_info[RTAX_GATEWAY] == NULL)
446 senderr(EINVAL);
c910b4d9 447
39236c6e
A
448 error = rtrequest_scoped_locked(RTM_ADD,
449 info.rti_info[RTAX_DST], info.rti_info[RTAX_GATEWAY],
450 info.rti_info[RTAX_NETMASK], rtm->rtm_flags, &saved_nrt,
451 ifscope);
452 if (error == 0 && saved_nrt != NULL) {
453 RT_LOCK(saved_nrt);
454 /*
455 * If the route request specified an interface with
456 * IFA and/or IFP, we set the requested interface on
457 * the route with rt_setif. It would be much better
458 * to do this inside rtrequest, but that would
459 * require passing the desired interface, in some
460 * form, to rtrequest. Since rtrequest is called in
461 * so many places (roughly 40 in our source), adding
462 * a parameter is to much for us to swallow; this is
463 * something for the FreeBSD developers to tackle.
464 * Instead, we let rtrequest compute whatever
465 * interface it wants, then come in behind it and
466 * stick in the interface that we really want. This
467 * works reasonably well except when rtrequest can't
468 * figure out what interface to use (with
469 * ifa_withroute) and returns ENETUNREACH. Ideally
470 * it shouldn't matter if rtrequest can't figure out
471 * the interface if we're going to explicitly set it
472 * ourselves anyway. But practically we can't
473 * recover here because rtrequest will not do any of
474 * the work necessary to add the route if it can't
475 * find an interface. As long as there is a default
476 * route that leads to some interface, rtrequest will
477 * find an interface, so this problem should be
478 * rarely encountered.
479 * dwiggins@bbn.com
480 */
481 rt_setif(saved_nrt,
482 info.rti_info[RTAX_IFP], info.rti_info[RTAX_IFA],
483 info.rti_info[RTAX_GATEWAY], ifscope);
484 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, saved_nrt);
485 saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
486 saved_nrt->rt_rmx.rmx_locks |=
487 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
488 saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
489 RT_REMREF_LOCKED(saved_nrt);
490 RT_UNLOCK(saved_nrt);
491 }
492 break;
493
494 case RTM_DELETE:
495 error = rtrequest_scoped_locked(RTM_DELETE,
496 info.rti_info[RTAX_DST], info.rti_info[RTAX_GATEWAY],
497 info.rti_info[RTAX_NETMASK], rtm->rtm_flags, &saved_nrt,
498 ifscope);
499 if (error == 0) {
500 rt = saved_nrt;
501 RT_LOCK(rt);
502 goto report;
503 }
504 break;
505
506 case RTM_GET:
507 case RTM_CHANGE:
508 case RTM_LOCK:
509 rnh = rt_tables[info.rti_info[RTAX_DST]->sa_family];
510 if (rnh == NULL)
511 senderr(EAFNOSUPPORT);
512 /*
513 * Lookup the best match based on the key-mask pair;
514 * callee adds a reference and checks for root node.
515 */
516 rt = rt_lookup(TRUE, info.rti_info[RTAX_DST],
517 info.rti_info[RTAX_NETMASK], rnh, ifscope);
518 if (rt == NULL)
519 senderr(ESRCH);
520 RT_LOCK(rt);
91447636 521
39236c6e
A
522 /*
523 * Holding rnh_lock here prevents the possibility of
524 * ifa from changing (e.g. in_ifinit), so it is safe
525 * to access its ifa_addr (down below) without locking.
526 */
527 switch (rtm->rtm_type) {
528 case RTM_GET: {
529 struct ifaddr *ifa2;
530report:
531 ifa2 = NULL;
532 RT_LOCK_ASSERT_HELD(rt);
533 info.rti_info[RTAX_DST] = rt_key(rt);
534 dst_sa_family = info.rti_info[RTAX_DST]->sa_family;
535 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
536 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
537 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
538 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
539 ifp = rt->rt_ifp;
540 if (ifp != NULL) {
541 ifnet_lock_shared(ifp);
542 ifa2 = ifp->if_lladdr;
543 info.rti_info[RTAX_IFP] =
544 ifa2->ifa_addr;
545 IFA_ADDREF(ifa2);
546 ifnet_lock_done(ifp);
547 info.rti_info[RTAX_IFA] =
548 rt->rt_ifa->ifa_addr;
549 rtm->rtm_index = ifp->if_index;
550 } else {
551 info.rti_info[RTAX_IFP] = NULL;
552 info.rti_info[RTAX_IFA] = NULL;
553 }
554 } else if ((ifp = rt->rt_ifp) != NULL) {
555 rtm->rtm_index = ifp->if_index;
1c79356b 556 }
39236c6e
A
557 if (ifa2 != NULL)
558 IFA_LOCK(ifa2);
559 len = rt_msg2(rtm->rtm_type, &info, NULL, NULL, NULL);
560 if (ifa2 != NULL)
561 IFA_UNLOCK(ifa2);
562 if (len > rtm->rtm_msglen) {
563 struct rt_msghdr *new_rtm;
564 R_Malloc(new_rtm, struct rt_msghdr *, len);
565 if (new_rtm == NULL) {
566 RT_UNLOCK(rt);
567 if (ifa2 != NULL)
568 IFA_REMREF(ifa2);
569 senderr(ENOBUFS);
570 }
571 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
572 R_Free(rtm); rtm = new_rtm;
573 }
574 if (ifa2 != NULL)
575 IFA_LOCK(ifa2);
576 (void) rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
577 NULL, NULL);
578 if (ifa2 != NULL)
579 IFA_UNLOCK(ifa2);
580 rtm->rtm_flags = rt->rt_flags;
581 rt_getmetrics(rt, &rtm->rtm_rmx);
582 rtm->rtm_addrs = info.rti_addrs;
583 if (ifa2 != NULL)
584 IFA_REMREF(ifa2);
1c79356b 585 break;
39236c6e 586 }
1c79356b
A
587
588 case RTM_CHANGE:
39236c6e
A
589 if (info.rti_info[RTAX_GATEWAY] != NULL &&
590 (error = rt_setgate(rt, rt_key(rt),
591 info.rti_info[RTAX_GATEWAY]))) {
592 int tmp = error;
593 RT_UNLOCK(rt);
594 senderr(tmp);
595 }
c910b4d9 596 /*
39236c6e
A
597 * If they tried to change things but didn't specify
598 * the required gateway, then just use the old one.
599 * This can happen if the user tries to change the
600 * flags on the default route without changing the
601 * default gateway. Changing flags still doesn't work.
c910b4d9 602 */
39236c6e
A
603 if ((rt->rt_flags & RTF_GATEWAY) &&
604 info.rti_info[RTAX_GATEWAY] == NULL)
605 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
c910b4d9 606
6d2010ae 607 /*
39236c6e
A
608 * On Darwin, we call rt_setif which contains the
609 * equivalent to the code found at this very spot
610 * in BSD.
6d2010ae 611 */
39236c6e
A
612 rt_setif(rt,
613 info.rti_info[RTAX_IFP], info.rti_info[RTAX_IFA],
614 info.rti_info[RTAX_GATEWAY], ifscope);
615
616 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, rt);
617 if (info.rti_info[RTAX_GENMASK])
618 rt->rt_genmask = info.rti_info[RTAX_GENMASK];
619 /* FALLTHRU */
620 case RTM_LOCK:
621 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
622 rt->rt_rmx.rmx_locks |=
623 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
1c79356b 624 break;
39236c6e
A
625 }
626 RT_UNLOCK(rt);
627 break;
628
629 default:
630 senderr(EOPNOTSUPP);
1c79356b 631 }
1c79356b 632flush:
39236c6e 633 if (rtm != NULL) {
1c79356b
A
634 if (error)
635 rtm->rtm_errno = error;
636 else
637 rtm->rtm_flags |= RTF_DONE;
638 }
b0d623f7
A
639 if (rt != NULL) {
640 RT_LOCK_ASSERT_NOTHELD(rt);
91447636 641 rtfree_locked(rt);
b0d623f7
A
642 }
643 lck_mtx_unlock(rnh_lock);
39236c6e
A
644
645 /* relock the socket now */
646 socket_lock(so, 0);
1c79356b
A
647 /*
648 * Check to see if we don't want our own messages.
649 */
39236c6e 650 if (!(so->so_options & SO_USELOOPBACK)) {
1c79356b 651 if (route_cb.any_count <= 1) {
39236c6e 652 if (rtm != NULL)
91447636 653 R_Free(rtm);
1c79356b
A
654 m_freem(m);
655 return (error);
656 }
657 /* There is another listener, so construct message */
658 rp = sotorawcb(so);
659 }
39236c6e 660 if (rtm != NULL) {
1c79356b 661 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
9bccf70c
A
662 if (m->m_pkthdr.len < rtm->rtm_msglen) {
663 m_freem(m);
664 m = NULL;
39236c6e 665 } else if (m->m_pkthdr.len > rtm->rtm_msglen) {
9bccf70c 666 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
39236c6e 667 }
91447636 668 R_Free(rtm);
1c79356b 669 }
39236c6e 670 if (sendonlytoself && m != NULL) {
91447636 671 error = 0;
39236c6e
A
672 if (sbappendaddr(&so->so_rcv, &route_src, m,
673 NULL, &error) != 0) {
55e303ae
A
674 sorwakeup(so);
675 }
91447636 676 if (error)
39236c6e 677 return (error);
55e303ae 678 } else {
39236c6e
A
679 struct sockproto route_proto = { PF_ROUTE, 0 };
680 if (rp != NULL)
55e303ae 681 rp->rcb_proto.sp_family = 0; /* Avoid us */
6d2010ae
A
682 if (dst_sa_family != 0)
683 route_proto.sp_protocol = dst_sa_family;
39236c6e 684 if (m != NULL) {
91447636 685 socket_unlock(so, 0);
55e303ae 686 raw_input(m, &route_proto, &route_src, &route_dst);
91447636
A
687 socket_lock(so, 0);
688 }
39236c6e 689 if (rp != NULL)
55e303ae 690 rp->rcb_proto.sp_family = PF_ROUTE;
55e303ae 691 }
1c79356b
A
692 return (error);
693}
694
6d2010ae
A
695void
696rt_setexpire(struct rtentry *rt, uint64_t expiry)
697{
698 /* set both rt_expire and rmx_expire */
699 rt->rt_expire = expiry;
700 if (expiry) {
701 rt->rt_rmx.rmx_expire = expiry + rt->base_calendartime -
702 rt->base_uptime;
39236c6e 703 } else {
6d2010ae 704 rt->rt_rmx.rmx_expire = 0;
39236c6e 705 }
6d2010ae
A
706}
707
1c79356b 708static void
6d2010ae 709rt_setmetrics(u_int32_t which, struct rt_metrics *in, struct rtentry *out)
1c79356b 710{
39236c6e
A
711 struct timeval caltime;
712
713 getmicrotime(&caltime);
6d2010ae 714
39236c6e 715#define metric(f, e) if (which & (f)) out->rt_rmx.e = in->e;
1c79356b
A
716 metric(RTV_RPIPE, rmx_recvpipe);
717 metric(RTV_SPIPE, rmx_sendpipe);
718 metric(RTV_SSTHRESH, rmx_ssthresh);
719 metric(RTV_RTT, rmx_rtt);
720 metric(RTV_RTTVAR, rmx_rttvar);
721 metric(RTV_HOPCOUNT, rmx_hopcount);
722 metric(RTV_MTU, rmx_mtu);
723 metric(RTV_EXPIRE, rmx_expire);
724#undef metric
39236c6e 725
6d2010ae
A
726 if (out->rt_rmx.rmx_expire > 0) {
727 /* account for system time change */
39236c6e 728 getmicrotime(&caltime);
6d2010ae 729 out->base_calendartime +=
39236c6e 730 NET_CALCULATE_CLOCKSKEW(caltime,
6d2010ae 731 out->base_calendartime,
39236c6e
A
732 net_uptime(), out->base_uptime);
733 rt_setexpire(out,
734 out->rt_rmx.rmx_expire -
735 out->base_calendartime +
6d2010ae
A
736 out->base_uptime);
737 } else {
738 rt_setexpire(out, 0);
739 }
39236c6e 740
6d2010ae
A
741 VERIFY(out->rt_expire == 0 || out->rt_rmx.rmx_expire != 0);
742 VERIFY(out->rt_expire != 0 || out->rt_rmx.rmx_expire == 0);
743}
744
745static void
746rt_getmetrics(struct rtentry *in, struct rt_metrics *out)
747{
39236c6e 748 struct timeval caltime;
6d2010ae
A
749
750 VERIFY(in->rt_expire == 0 || in->rt_rmx.rmx_expire != 0);
751 VERIFY(in->rt_expire != 0 || in->rt_rmx.rmx_expire == 0);
39236c6e
A
752
753 *out = in->rt_rmx;
754
755 if (in->rt_expire != 0) {
6d2010ae 756 /* account for system time change */
39236c6e 757 getmicrotime(&caltime);
6d2010ae
A
758
759 in->base_calendartime +=
39236c6e
A
760 NET_CALCULATE_CLOCKSKEW(caltime,
761 in->base_calendartime, net_uptime(), in->base_uptime);
762
6d2010ae
A
763 out->rmx_expire = in->base_calendartime +
764 in->rt_expire - in->base_uptime;
39236c6e 765 } else {
6d2010ae 766 out->rmx_expire = 0;
39236c6e 767 }
1c79356b
A
768}
769
770/*
39236c6e
A
771 * Set route's interface given info.rti_info[RTAX_IFP],
772 * info.rti_info[RTAX_IFA], and gateway.
1c79356b
A
773 */
774static void
c910b4d9
A
775rt_setif(struct rtentry *rt, struct sockaddr *Ifpaddr, struct sockaddr *Ifaaddr,
776 struct sockaddr *Gate, unsigned int ifscope)
1c79356b 777{
6d2010ae
A
778 struct ifaddr *ifa = NULL;
779 struct ifnet *ifp = NULL;
39236c6e 780 void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *);
1c79356b 781
b0d623f7
A
782 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
783
784 RT_LOCK_ASSERT_HELD(rt);
91447636 785
b0d623f7
A
786 /* Don't update a defunct route */
787 if (rt->rt_flags & RTF_CONDEMNED)
788 return;
789
790 /* Add an extra ref for ourselves */
791 RT_ADDREF_LOCKED(rt);
2d21ac55 792
6d2010ae
A
793 /* Become a regular mutex, just in case */
794 RT_CONVERT_LOCK(rt);
795
c910b4d9
A
796 /*
797 * New gateway could require new ifaddr, ifp; flags may also
798 * be different; ifp may be specified by ll sockaddr when
799 * protocol address is ambiguous.
800 */
801 if (Ifpaddr && (ifa = ifa_ifwithnet_scoped(Ifpaddr, ifscope)) &&
91447636 802 (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate)) {
6d2010ae 803 IFA_REMREF(ifa);
c910b4d9
A
804 ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate, ifp);
805 } else {
39236c6e 806 if (ifa != NULL) {
6d2010ae 807 IFA_REMREF(ifa);
39236c6e 808 ifa = NULL;
91447636 809 }
39236c6e 810 if (Ifpaddr && (ifp = if_withname(Ifpaddr))) {
91447636
A
811 if (Gate) {
812 ifa = ifaof_ifpforaddr(Gate, ifp);
c910b4d9 813 } else {
91447636
A
814 ifnet_lock_shared(ifp);
815 ifa = TAILQ_FIRST(&ifp->if_addrhead);
b0d623f7 816 if (ifa != NULL)
6d2010ae 817 IFA_ADDREF(ifa);
91447636
A
818 ifnet_lock_done(ifp);
819 }
c910b4d9
A
820 } else if (Ifaaddr &&
821 (ifa = ifa_ifwithaddr_scoped(Ifaaddr, ifscope))) {
91447636 822 ifp = ifa->ifa_ifp;
b0d623f7
A
823 } else if (Gate != NULL) {
824 /*
825 * Safe to drop rt_lock and use rt_key, since holding
826 * rnh_lock here prevents another thread from calling
827 * rt_setgate() on this route. We cannot hold the
828 * lock across ifa_ifwithroute since the lookup done
829 * by that routine may point to the same route.
830 */
831 RT_UNLOCK(rt);
832 if ((ifa = ifa_ifwithroute_scoped_locked(rt->rt_flags,
833 rt_key(rt), Gate, ifscope)) != NULL)
834 ifp = ifa->ifa_ifp;
835 RT_LOCK(rt);
836 /* Don't update a defunct route */
837 if (rt->rt_flags & RTF_CONDEMNED) {
838 if (ifa != NULL)
6d2010ae 839 IFA_REMREF(ifa);
b0d623f7
A
840 /* Release extra ref */
841 RT_REMREF_LOCKED(rt);
842 return;
843 }
91447636
A
844 }
845 }
39236c6e
A
846
847 /* trigger route cache reevaluation */
848 if (rt_key(rt)->sa_family == AF_INET)
849 routegenid_inet_update();
850#if INET6
851 else if (rt_key(rt)->sa_family == AF_INET6)
852 routegenid_inet6_update();
853#endif /* INET6 */
854
855 if (ifa != NULL) {
91447636 856 struct ifaddr *oifa = rt->rt_ifa;
1c79356b 857 if (oifa != ifa) {
6d2010ae
A
858 if (oifa != NULL) {
859 IFA_LOCK_SPIN(oifa);
860 ifa_rtrequest = oifa->ifa_rtrequest;
861 IFA_UNLOCK(oifa);
862 if (ifa_rtrequest != NULL)
863 ifa_rtrequest(RTM_DELETE, rt, Gate);
864 }
9bccf70c 865 rtsetifa(rt, ifa);
6d2010ae
A
866
867 if (rt->rt_ifp != ifp) {
868 /*
869 * Purge any link-layer info caching.
870 */
871 if (rt->rt_llinfo_purge != NULL)
872 rt->rt_llinfo_purge(rt);
873
874 /*
875 * Adjust route ref count for the interfaces.
876 */
877 if (rt->rt_if_ref_fn != NULL) {
878 rt->rt_if_ref_fn(ifp, 1);
879 rt->rt_if_ref_fn(rt->rt_ifp, -1);
880 }
d1ecb069 881 }
c910b4d9
A
882 rt->rt_ifp = ifp;
883 /*
884 * If this is the (non-scoped) default route, record
885 * the interface index used for the primary ifscope.
886 */
6d2010ae
A
887 if (rt_primary_default(rt, rt_key(rt))) {
888 set_primary_ifscope(rt_key(rt)->sa_family,
889 rt->rt_ifp->if_index);
890 }
39236c6e
A
891 /*
892 * If rmx_mtu is not locked, update it
893 * to the MTU used by the new interface.
894 */
895 if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
896 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
897
6d2010ae
A
898 if (rt->rt_ifa != NULL) {
899 IFA_LOCK_SPIN(rt->rt_ifa);
900 ifa_rtrequest = rt->rt_ifa->ifa_rtrequest;
901 IFA_UNLOCK(rt->rt_ifa);
902 if (ifa_rtrequest != NULL)
903 ifa_rtrequest(RTM_ADD, rt, Gate);
904 }
905 IFA_REMREF(ifa);
b0d623f7
A
906 /* Release extra ref */
907 RT_REMREF_LOCKED(rt);
908 return;
91447636 909 }
6d2010ae 910 IFA_REMREF(ifa);
39236c6e 911 ifa = NULL;
1c79356b 912 }
b0d623f7 913
1c79356b 914 /* XXX: to reset gateway to correct value, at RTM_CHANGE */
6d2010ae
A
915 if (rt->rt_ifa != NULL) {
916 IFA_LOCK_SPIN(rt->rt_ifa);
917 ifa_rtrequest = rt->rt_ifa->ifa_rtrequest;
918 IFA_UNLOCK(rt->rt_ifa);
919 if (ifa_rtrequest != NULL)
920 ifa_rtrequest(RTM_ADD, rt, Gate);
921 }
1c79356b 922
39236c6e
A
923 /*
924 * Workaround for local address routes pointing to the loopback
925 * interface added by configd, until <rdar://problem/12970142>.
926 */
927 if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
928 (rt->rt_flags & RTF_HOST) && rt->rt_ifa->ifa_ifp == rt->rt_ifp) {
929 ifa = ifa_ifwithaddr(rt_key(rt));
930 if (ifa != NULL) {
931 if (ifa != rt->rt_ifa)
932 rtsetifa(rt, ifa);
933 IFA_REMREF(ifa);
934 }
935 }
936
b0d623f7
A
937 /* Release extra ref */
938 RT_REMREF_LOCKED(rt);
939}
1c79356b 940
1c79356b
A
941/*
942 * Extract the addresses of the passed sockaddrs.
943 * Do a little sanity checking so as to avoid bad memory references.
944 * This data is derived straight from userland.
945 */
946static int
2d21ac55 947rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
1c79356b 948{
91447636
A
949 struct sockaddr *sa;
950 int i;
1c79356b 951
39236c6e 952 bzero(rtinfo->rti_info, sizeof (rtinfo->rti_info));
1c79356b
A
953 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
954 if ((rtinfo->rti_addrs & (1 << i)) == 0)
955 continue;
956 sa = (struct sockaddr *)cp;
957 /*
958 * It won't fit.
959 */
39236c6e 960 if ((cp + sa->sa_len) > cplim)
1c79356b 961 return (EINVAL);
1c79356b
A
962 /*
963 * there are no more.. quit now
964 * If there are more bits, they are in error.
39236c6e 965 * I've seen this. route(1) can evidently generate these.
1c79356b
A
966 * This causes kernel to core dump.
967 * for compatibility, If we see this, point to a safe address.
968 */
969 if (sa->sa_len == 0) {
970 rtinfo->rti_info[i] = &sa_zero;
971 return (0); /* should be EINVAL but for compat */
972 }
1c79356b
A
973 /* accept it */
974 rtinfo->rti_info[i] = sa;
b0d623f7 975 ADVANCE32(cp, sa);
1c79356b
A
976 }
977 return (0);
978}
979
980static struct mbuf *
b0d623f7 981rt_msg1(int type, struct rt_addrinfo *rtinfo)
1c79356b 982{
91447636
A
983 struct rt_msghdr *rtm;
984 struct mbuf *m;
985 int i;
1c79356b
A
986 int len, dlen;
987
1c79356b
A
988 switch (type) {
989
990 case RTM_DELADDR:
991 case RTM_NEWADDR:
39236c6e 992 len = sizeof (struct ifa_msghdr);
1c79356b
A
993 break;
994
995 case RTM_DELMADDR:
996 case RTM_NEWMADDR:
39236c6e 997 len = sizeof (struct ifma_msghdr);
1c79356b
A
998 break;
999
1000 case RTM_IFINFO:
39236c6e 1001 len = sizeof (struct if_msghdr);
1c79356b
A
1002 break;
1003
1004 default:
39236c6e 1005 len = sizeof (struct rt_msghdr);
1c79356b 1006 }
9bccf70c 1007 if (len > MCLBYTES)
1c79356b 1008 panic("rt_msg1");
9bccf70c
A
1009 m = m_gethdr(M_DONTWAIT, MT_DATA);
1010 if (m && len > MHLEN) {
1011 MCLGET(m, M_DONTWAIT);
39236c6e 1012 if (!(m->m_flags & M_EXT)) {
9bccf70c
A
1013 m_free(m);
1014 m = NULL;
1015 }
1016 }
39236c6e
A
1017 if (m == NULL)
1018 return (NULL);
1c79356b 1019 m->m_pkthdr.len = m->m_len = len;
39236c6e 1020 m->m_pkthdr.rcvif = NULL;
1c79356b
A
1021 rtm = mtod(m, struct rt_msghdr *);
1022 bzero((caddr_t)rtm, len);
1023 for (i = 0; i < RTAX_MAX; i++) {
b0d623f7 1024 struct sockaddr *sa, *hint;
39236c6e
A
1025 uint8_t ssbuf[SOCK_MAXADDRLEN + 1];
1026
1027 /*
1028 * Make sure to accomodate the largest possible size of sa_len.
1029 */
1030 _CASSERT(sizeof (ssbuf) == (SOCK_MAXADDRLEN + 1));
b0d623f7 1031
1c79356b
A
1032 if ((sa = rtinfo->rti_info[i]) == NULL)
1033 continue;
b0d623f7
A
1034
1035 switch (i) {
1036 case RTAX_DST:
1037 case RTAX_NETMASK:
1038 if ((hint = rtinfo->rti_info[RTAX_DST]) == NULL)
1039 hint = rtinfo->rti_info[RTAX_IFA];
1040
1041 /* Scrub away any trace of embedded interface scope */
39236c6e
A
1042 sa = rtm_scrub(type, i, hint, sa, &ssbuf,
1043 sizeof (ssbuf), NULL);
b0d623f7
A
1044 break;
1045
1046 default:
1047 break;
1048 }
1049
1c79356b 1050 rtinfo->rti_addrs |= (1 << i);
b0d623f7 1051 dlen = ROUNDUP32(sa->sa_len);
1c79356b
A
1052 m_copyback(m, len, dlen, (caddr_t)sa);
1053 len += dlen;
1054 }
1055 if (m->m_pkthdr.len != len) {
1056 m_freem(m);
1057 return (NULL);
1058 }
1059 rtm->rtm_msglen = len;
1060 rtm->rtm_version = RTM_VERSION;
1061 rtm->rtm_type = type;
1062 return (m);
1063}
1064
1065static int
39236c6e
A
1066rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w,
1067 kauth_cred_t* credp)
1c79356b 1068{
91447636 1069 int i;
1c79356b
A
1070 int len, dlen, second_time = 0;
1071 caddr_t cp0;
1072
1073 rtinfo->rti_addrs = 0;
1074again:
1075 switch (type) {
1076
1077 case RTM_DELADDR:
1078 case RTM_NEWADDR:
39236c6e 1079 len = sizeof (struct ifa_msghdr);
1c79356b
A
1080 break;
1081
91447636
A
1082 case RTM_DELMADDR:
1083 case RTM_NEWMADDR:
39236c6e 1084 len = sizeof (struct ifma_msghdr);
91447636
A
1085 break;
1086
1c79356b 1087 case RTM_IFINFO:
39236c6e 1088 len = sizeof (struct if_msghdr);
1c79356b
A
1089 break;
1090
91447636 1091 case RTM_IFINFO2:
39236c6e 1092 len = sizeof (struct if_msghdr2);
91447636
A
1093 break;
1094
1095 case RTM_NEWMADDR2:
39236c6e 1096 len = sizeof (struct ifma_msghdr2);
91447636
A
1097 break;
1098
6d2010ae
A
1099 case RTM_GET_EXT:
1100 len = sizeof (struct rt_msghdr_ext);
1101 break;
1102
91447636 1103 case RTM_GET2:
39236c6e 1104 len = sizeof (struct rt_msghdr2);
91447636
A
1105 break;
1106
1c79356b 1107 default:
39236c6e 1108 len = sizeof (struct rt_msghdr);
1c79356b
A
1109 }
1110 cp0 = cp;
1111 if (cp0)
1112 cp += len;
1113 for (i = 0; i < RTAX_MAX; i++) {
b0d623f7 1114 struct sockaddr *sa, *hint;
39236c6e 1115 uint8_t ssbuf[SOCK_MAXADDRLEN + 1];
1c79356b 1116
39236c6e
A
1117 /*
1118 * Make sure to accomodate the largest possible size of sa_len.
1119 */
1120 _CASSERT(sizeof (ssbuf) == (SOCK_MAXADDRLEN + 1));
1121
1122 if ((sa = rtinfo->rti_info[i]) == NULL)
1c79356b 1123 continue;
b0d623f7
A
1124
1125 switch (i) {
1126 case RTAX_DST:
1127 case RTAX_NETMASK:
1128 if ((hint = rtinfo->rti_info[RTAX_DST]) == NULL)
1129 hint = rtinfo->rti_info[RTAX_IFA];
1130
1131 /* Scrub away any trace of embedded interface scope */
39236c6e
A
1132 sa = rtm_scrub(type, i, hint, sa, &ssbuf,
1133 sizeof (ssbuf), NULL);
1134 break;
1135
1136 case RTAX_IFP:
1137 sa = rtm_scrub(type, i, NULL, sa, &ssbuf,
1138 sizeof (ssbuf), credp);
b0d623f7
A
1139 break;
1140
1141 default:
1142 break;
1143 }
1144
1c79356b 1145 rtinfo->rti_addrs |= (1 << i);
b0d623f7 1146 dlen = ROUNDUP32(sa->sa_len);
1c79356b
A
1147 if (cp) {
1148 bcopy((caddr_t)sa, cp, (unsigned)dlen);
1149 cp += dlen;
1150 }
1151 len += dlen;
1152 }
39236c6e 1153 if (cp == NULL && w != NULL && !second_time) {
91447636 1154 struct walkarg *rw = w;
1c79356b 1155
39236c6e 1156 if (rw->w_req != NULL) {
1c79356b 1157 if (rw->w_tmemsize < len) {
39236c6e 1158 if (rw->w_tmem != NULL)
1c79356b 1159 FREE(rw->w_tmem, M_RTABLE);
316670eb 1160 rw->w_tmem = _MALLOC(len, M_RTABLE, M_WAITOK);
39236c6e 1161 if (rw->w_tmem != NULL)
1c79356b
A
1162 rw->w_tmemsize = len;
1163 }
39236c6e 1164 if (rw->w_tmem != NULL) {
1c79356b
A
1165 cp = rw->w_tmem;
1166 second_time = 1;
1167 goto again;
1168 }
1169 }
1170 }
1171 if (cp) {
316670eb 1172 struct rt_msghdr *rtm = (struct rt_msghdr *)(void *)cp0;
1c79356b
A
1173
1174 rtm->rtm_version = RTM_VERSION;
1175 rtm->rtm_type = type;
1176 rtm->rtm_msglen = len;
1177 }
1178 return (len);
1179}
1180
1181/*
1182 * This routine is called to generate a message from the routing
91447636 1183 * socket indicating that a redirect has occurred, a routing lookup
1c79356b
A
1184 * has failed, or that a protocol has detected timeouts to a particular
1185 * destination.
1186 */
1187void
2d21ac55 1188rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
1c79356b 1189{
91447636
A
1190 struct rt_msghdr *rtm;
1191 struct mbuf *m;
1c79356b 1192 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
39236c6e 1193 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b
A
1194
1195 if (route_cb.any_count == 0)
1196 return;
1197 m = rt_msg1(type, rtinfo);
39236c6e 1198 if (m == NULL)
1c79356b
A
1199 return;
1200 rtm = mtod(m, struct rt_msghdr *);
1201 rtm->rtm_flags = RTF_DONE | flags;
1202 rtm->rtm_errno = error;
1203 rtm->rtm_addrs = rtinfo->rti_addrs;
6d2010ae 1204 route_proto.sp_family = sa ? sa->sa_family : 0;
1c79356b
A
1205 raw_input(m, &route_proto, &route_src, &route_dst);
1206}
1207
1208/*
1209 * This routine is called to generate a message from the routing
1210 * socket indicating that the status of a network interface has changed.
1211 */
1212void
39236c6e 1213rt_ifmsg(struct ifnet *ifp)
1c79356b 1214{
91447636 1215 struct if_msghdr *ifm;
1c79356b
A
1216 struct mbuf *m;
1217 struct rt_addrinfo info;
39236c6e 1218 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b
A
1219
1220 if (route_cb.any_count == 0)
1221 return;
39236c6e 1222 bzero((caddr_t)&info, sizeof (info));
1c79356b 1223 m = rt_msg1(RTM_IFINFO, &info);
39236c6e 1224 if (m == NULL)
1c79356b
A
1225 return;
1226 ifm = mtod(m, struct if_msghdr *);
1227 ifm->ifm_index = ifp->if_index;
1228 ifm->ifm_flags = (u_short)ifp->if_flags;
2d21ac55 1229 if_data_internal_to_if_data(ifp, &ifp->if_data, &ifm->ifm_data);
1c79356b 1230 ifm->ifm_addrs = 0;
1c79356b
A
1231 raw_input(m, &route_proto, &route_src, &route_dst);
1232}
1233
1234/*
1235 * This is called to generate messages from the routing socket
1236 * indicating a network interface has had addresses associated with it.
1237 * if we ever reverse the logic and replace messages TO the routing
1238 * socket indicate a request to configure interfaces, then it will
1239 * be unnecessary as the routing socket will automatically generate
1240 * copies of it.
91447636
A
1241 *
1242 * Since this is coming from the interface, it is expected that the
6d2010ae 1243 * interface will be locked. Caller must hold rnh_lock and rt_lock.
1c79356b
A
1244 */
1245void
2d21ac55 1246rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1c79356b
A
1247{
1248 struct rt_addrinfo info;
1249 struct sockaddr *sa = 0;
1250 int pass;
1251 struct mbuf *m = 0;
1252 struct ifnet *ifp = ifa->ifa_ifp;
39236c6e 1253 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b 1254
6d2010ae 1255 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7
A
1256 RT_LOCK_ASSERT_HELD(rt);
1257
1c79356b
A
1258 if (route_cb.any_count == 0)
1259 return;
6d2010ae
A
1260
1261 /* Become a regular mutex, just in case */
1262 RT_CONVERT_LOCK(rt);
1c79356b 1263 for (pass = 1; pass < 3; pass++) {
39236c6e 1264 bzero((caddr_t)&info, sizeof (info));
1c79356b
A
1265 if ((cmd == RTM_ADD && pass == 1) ||
1266 (cmd == RTM_DELETE && pass == 2)) {
91447636 1267 struct ifa_msghdr *ifam;
1c79356b
A
1268 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
1269
6d2010ae 1270 /* Lock ifp for if_lladdr */
b0d623f7 1271 ifnet_lock_shared(ifp);
6d2010ae
A
1272 IFA_LOCK(ifa);
1273 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
1274 /*
1275 * Holding ifnet lock here prevents the link address
1276 * from changing contents, so no need to hold its
1277 * lock. The link address is always present; it's
1278 * never freed.
1279 */
1280 info.rti_info[RTAX_IFP] = ifp->if_lladdr->ifa_addr;
1281 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1282 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
b0d623f7 1283 if ((m = rt_msg1(ncmd, &info)) == NULL) {
6d2010ae 1284 IFA_UNLOCK(ifa);
b0d623f7 1285 ifnet_lock_done(ifp);
1c79356b 1286 continue;
b0d623f7 1287 }
6d2010ae 1288 IFA_UNLOCK(ifa);
b0d623f7 1289 ifnet_lock_done(ifp);
1c79356b
A
1290 ifam = mtod(m, struct ifa_msghdr *);
1291 ifam->ifam_index = ifp->if_index;
6d2010ae 1292 IFA_LOCK_SPIN(ifa);
1c79356b
A
1293 ifam->ifam_metric = ifa->ifa_metric;
1294 ifam->ifam_flags = ifa->ifa_flags;
6d2010ae 1295 IFA_UNLOCK(ifa);
1c79356b
A
1296 ifam->ifam_addrs = info.rti_addrs;
1297 }
1298 if ((cmd == RTM_ADD && pass == 2) ||
1299 (cmd == RTM_DELETE && pass == 1)) {
91447636 1300 struct rt_msghdr *rtm;
1c79356b 1301
39236c6e 1302 if (rt == NULL)
1c79356b 1303 continue;
6d2010ae
A
1304 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1305 info.rti_info[RTAX_DST] = sa = rt_key(rt);
1306 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1c79356b
A
1307 if ((m = rt_msg1(cmd, &info)) == NULL)
1308 continue;
1309 rtm = mtod(m, struct rt_msghdr *);
1310 rtm->rtm_index = ifp->if_index;
1311 rtm->rtm_flags |= rt->rt_flags;
1312 rtm->rtm_errno = error;
1313 rtm->rtm_addrs = info.rti_addrs;
1314 }
1315 route_proto.sp_protocol = sa ? sa->sa_family : 0;
1316 raw_input(m, &route_proto, &route_src, &route_dst);
1317 }
1318}
1319
1320/*
1321 * This is the analogue to the rt_newaddrmsg which performs the same
1322 * function but for multicast group memberhips. This is easier since
1323 * there is no route state to worry about.
1324 */
1325void
2d21ac55 1326rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1c79356b
A
1327{
1328 struct rt_addrinfo info;
1329 struct mbuf *m = 0;
1330 struct ifnet *ifp = ifma->ifma_ifp;
1331 struct ifma_msghdr *ifmam;
39236c6e 1332 struct sockproto route_proto = { PF_ROUTE, 0 };
1c79356b
A
1333
1334 if (route_cb.any_count == 0)
1335 return;
1336
6d2010ae
A
1337 /* Lock ifp for if_lladdr */
1338 ifnet_lock_shared(ifp);
39236c6e 1339 bzero((caddr_t)&info, sizeof (info));
6d2010ae
A
1340 IFMA_LOCK(ifma);
1341 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
39236c6e
A
1342 /* lladdr doesn't need lock */
1343 info.rti_info[RTAX_IFP] = ifp->if_lladdr->ifa_addr;
6d2010ae 1344
1c79356b
A
1345 /*
1346 * If a link-layer address is present, present it as a ``gateway''
1347 * (similarly to how ARP entries, e.g., are presented).
1348 */
39236c6e
A
1349 info.rti_info[RTAX_GATEWAY] = (ifma->ifma_ll != NULL) ?
1350 ifma->ifma_ll->ifma_addr : NULL;
b0d623f7 1351 if ((m = rt_msg1(cmd, &info)) == NULL) {
6d2010ae
A
1352 IFMA_UNLOCK(ifma);
1353 ifnet_lock_done(ifp);
1c79356b 1354 return;
b0d623f7 1355 }
1c79356b 1356 ifmam = mtod(m, struct ifma_msghdr *);
6d2010ae 1357 ifmam->ifmam_index = ifp->if_index;
1c79356b
A
1358 ifmam->ifmam_addrs = info.rti_addrs;
1359 route_proto.sp_protocol = ifma->ifma_addr->sa_family;
6d2010ae
A
1360 IFMA_UNLOCK(ifma);
1361 ifnet_lock_done(ifp);
1c79356b
A
1362 raw_input(m, &route_proto, &route_src, &route_dst);
1363}
1364
39236c6e
A
1365const char *
1366rtm2str(int cmd)
1367{
1368 const char *c = "RTM_?";
1369
1370 switch (cmd) {
1371 case RTM_ADD:
1372 c = "RTM_ADD";
1373 break;
1374 case RTM_DELETE:
1375 c = "RTM_DELETE";
1376 break;
1377 case RTM_CHANGE:
1378 c = "RTM_CHANGE";
1379 break;
1380 case RTM_GET:
1381 c = "RTM_GET";
1382 break;
1383 case RTM_LOSING:
1384 c = "RTM_LOSING";
1385 break;
1386 case RTM_REDIRECT:
1387 c = "RTM_REDIRECT";
1388 break;
1389 case RTM_MISS:
1390 c = "RTM_MISS";
1391 break;
1392 case RTM_LOCK:
1393 c = "RTM_LOCK";
1394 break;
1395 case RTM_OLDADD:
1396 c = "RTM_OLDADD";
1397 break;
1398 case RTM_OLDDEL:
1399 c = "RTM_OLDDEL";
1400 break;
1401 case RTM_RESOLVE:
1402 c = "RTM_RESOLVE";
1403 break;
1404 case RTM_NEWADDR:
1405 c = "RTM_NEWADDR";
1406 break;
1407 case RTM_DELADDR:
1408 c = "RTM_DELADDR";
1409 break;
1410 case RTM_IFINFO:
1411 c = "RTM_IFINFO";
1412 break;
1413 case RTM_NEWMADDR:
1414 c = "RTM_NEWMADDR";
1415 break;
1416 case RTM_DELMADDR:
1417 c = "RTM_DELMADDR";
1418 break;
1419 case RTM_GET_SILENT:
1420 c = "RTM_GET_SILENT";
1421 break;
1422 case RTM_IFINFO2:
1423 c = "RTM_IFINFO2";
1424 break;
1425 case RTM_NEWMADDR2:
1426 c = "RTM_NEWMADDR2";
1427 break;
1428 case RTM_GET2:
1429 c = "RTM_GET2";
1430 break;
1431 case RTM_GET_EXT:
1432 c = "RTM_GET_EXT";
1433 break;
1434 }
1435
1436 return (c);
1437}
1438
1c79356b
A
1439/*
1440 * This is used in dumping the kernel table via sysctl().
1441 */
39236c6e 1442static int
2d21ac55 1443sysctl_dumpentry(struct radix_node *rn, void *vw)
1c79356b 1444{
91447636
A
1445 struct walkarg *w = vw;
1446 struct rtentry *rt = (struct rtentry *)rn;
1c79356b
A
1447 int error = 0, size;
1448 struct rt_addrinfo info;
39236c6e
A
1449 kauth_cred_t cred;
1450
1451 cred = kauth_cred_proc_ref(current_proc());
1c79356b 1452
b0d623f7 1453 RT_LOCK(rt);
39236c6e
A
1454 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1455 goto done;
1456 bzero((caddr_t)&info, sizeof (info));
6d2010ae
A
1457 info.rti_info[RTAX_DST] = rt_key(rt);
1458 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1459 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1460 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
1461
91447636 1462 if (w->w_op != NET_RT_DUMP2) {
39236c6e
A
1463 size = rt_msg2(RTM_GET, &info, NULL, w, &cred);
1464 if (w->w_req != NULL && w->w_tmem != NULL) {
316670eb
A
1465 struct rt_msghdr *rtm =
1466 (struct rt_msghdr *)(void *)w->w_tmem;
91447636
A
1467
1468 rtm->rtm_flags = rt->rt_flags;
1469 rtm->rtm_use = rt->rt_use;
6d2010ae 1470 rt_getmetrics(rt, &rtm->rtm_rmx);
91447636
A
1471 rtm->rtm_index = rt->rt_ifp->if_index;
1472 rtm->rtm_pid = 0;
6d2010ae
A
1473 rtm->rtm_seq = 0;
1474 rtm->rtm_errno = 0;
91447636
A
1475 rtm->rtm_addrs = info.rti_addrs;
1476 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
91447636
A
1477 }
1478 } else {
39236c6e
A
1479 size = rt_msg2(RTM_GET2, &info, NULL, w, &cred);
1480 if (w->w_req != NULL && w->w_tmem != NULL) {
316670eb
A
1481 struct rt_msghdr2 *rtm =
1482 (struct rt_msghdr2 *)(void *)w->w_tmem;
6d2010ae
A
1483
1484 rtm->rtm_flags = rt->rt_flags;
1485 rtm->rtm_use = rt->rt_use;
1486 rt_getmetrics(rt, &rtm->rtm_rmx);
1487 rtm->rtm_index = rt->rt_ifp->if_index;
1488 rtm->rtm_refcnt = rt->rt_refcnt;
91447636
A
1489 if (rt->rt_parent)
1490 rtm->rtm_parentflags = rt->rt_parent->rt_flags;
1491 else
1492 rtm->rtm_parentflags = 0;
6d2010ae
A
1493 rtm->rtm_reserved = 0;
1494 rtm->rtm_addrs = info.rti_addrs;
1495 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
91447636 1496 }
1c79356b 1497 }
39236c6e
A
1498
1499done:
b0d623f7 1500 RT_UNLOCK(rt);
39236c6e 1501 kauth_cred_unref(&cred);
1c79356b
A
1502 return (error);
1503}
1504
6d2010ae
A
1505/*
1506 * This is used for dumping extended information from route entries.
1507 */
39236c6e 1508static int
6d2010ae
A
1509sysctl_dumpentry_ext(struct radix_node *rn, void *vw)
1510{
1511 struct walkarg *w = vw;
1512 struct rtentry *rt = (struct rtentry *)rn;
1513 int error = 0, size;
1514 struct rt_addrinfo info;
39236c6e
A
1515 kauth_cred_t cred;
1516
1517 cred = kauth_cred_proc_ref(current_proc());
6d2010ae
A
1518
1519 RT_LOCK(rt);
39236c6e
A
1520 if (w->w_op == NET_RT_DUMPX_FLAGS && !(rt->rt_flags & w->w_arg))
1521 goto done;
6d2010ae
A
1522 bzero(&info, sizeof (info));
1523 info.rti_info[RTAX_DST] = rt_key(rt);
1524 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1525 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1526 info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
39236c6e
A
1527
1528 size = rt_msg2(RTM_GET_EXT, &info, NULL, w, &cred);
1529 if (w->w_req != NULL && w->w_tmem != NULL) {
316670eb
A
1530 struct rt_msghdr_ext *ertm =
1531 (struct rt_msghdr_ext *)(void *)w->w_tmem;
6d2010ae
A
1532
1533 ertm->rtm_flags = rt->rt_flags;
1534 ertm->rtm_use = rt->rt_use;
1535 rt_getmetrics(rt, &ertm->rtm_rmx);
1536 ertm->rtm_index = rt->rt_ifp->if_index;
1537 ertm->rtm_pid = 0;
1538 ertm->rtm_seq = 0;
1539 ertm->rtm_errno = 0;
1540 ertm->rtm_addrs = info.rti_addrs;
316670eb 1541 if (rt->rt_llinfo_get_ri == NULL) {
6d2010ae 1542 bzero(&ertm->rtm_ri, sizeof (ertm->rtm_ri));
316670eb
A
1543 ertm->rtm_ri.ri_rssi = IFNET_RSSI_UNKNOWN;
1544 ertm->rtm_ri.ri_lqm = IFNET_LQM_THRESH_OFF;
1545 ertm->rtm_ri.ri_npm = IFNET_NPM_THRESH_UNKNOWN;
39236c6e 1546 } else {
6d2010ae 1547 rt->rt_llinfo_get_ri(rt, &ertm->rtm_ri);
39236c6e 1548 }
6d2010ae 1549 error = SYSCTL_OUT(w->w_req, (caddr_t)ertm, size);
6d2010ae 1550 }
39236c6e
A
1551
1552done:
6d2010ae 1553 RT_UNLOCK(rt);
39236c6e 1554 kauth_cred_unref(&cred);
6d2010ae
A
1555 return (error);
1556}
1557
1558/*
1559 * rdar://9307819
39236c6e
A
1560 * To avoid to call copyout() while holding locks and to cause problems
1561 * in the paging path, sysctl_iflist() and sysctl_iflist2() contstruct
6d2010ae
A
1562 * the list in two passes. In the first pass we compute the total
1563 * length of the data we are going to copyout, then we release
39236c6e 1564 * all locks to allocate a temporary buffer that gets filled
6d2010ae
A
1565 * in the second pass.
1566 *
39236c6e
A
1567 * Note that we are verifying the assumption that _MALLOC returns a buffer
1568 * that is at least 32 bits aligned and that the messages and addresses are
6d2010ae
A
1569 * 32 bits aligned.
1570 */
39236c6e 1571static int
6d2010ae 1572sysctl_iflist(int af, struct walkarg *w)
1c79356b 1573{
91447636
A
1574 struct ifnet *ifp;
1575 struct ifaddr *ifa;
1c79356b
A
1576 struct rt_addrinfo info;
1577 int len, error = 0;
6d2010ae
A
1578 int pass = 0;
1579 int total_len = 0, current_len = 0;
1580 char *total_buffer = NULL, *cp = NULL;
39236c6e
A
1581 kauth_cred_t cred;
1582
1583 cred = kauth_cred_proc_ref(current_proc());
1584
1585 bzero((caddr_t)&info, sizeof (info));
1c79356b 1586
6d2010ae
A
1587 for (pass = 0; pass < 2; pass++) {
1588 ifnet_head_lock_shared();
39236c6e 1589
6d2010ae
A
1590 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1591 if (error)
91447636 1592 break;
6d2010ae 1593 if (w->w_arg && w->w_arg != ifp->if_index)
1c79356b 1594 continue;
6d2010ae
A
1595 ifnet_lock_shared(ifp);
1596 /*
39236c6e
A
1597 * Holding ifnet lock here prevents the link address
1598 * from changing contents, so no need to hold the ifa
1599 * lock. The link address is always present; it's
1600 * never freed.
6d2010ae
A
1601 */
1602 ifa = ifp->if_lladdr;
1603 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
39236c6e 1604 len = rt_msg2(RTM_IFINFO, &info, NULL, NULL, &cred);
6d2010ae
A
1605 if (pass == 0) {
1606 total_len += len;
1607 } else {
1608 struct if_msghdr *ifm;
1609
1610 if (current_len + len > total_len) {
1611 ifnet_lock_done(ifp);
6d2010ae 1612 error = ENOBUFS;
91447636 1613 break;
6d2010ae
A
1614 }
1615 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
39236c6e
A
1616 len = rt_msg2(RTM_IFINFO, &info,
1617 (caddr_t)cp, NULL, &cred);
6d2010ae 1618 info.rti_info[RTAX_IFP] = NULL;
39236c6e 1619
316670eb 1620 ifm = (struct if_msghdr *)(void *)cp;
6d2010ae
A
1621 ifm->ifm_index = ifp->if_index;
1622 ifm->ifm_flags = (u_short)ifp->if_flags;
1623 if_data_internal_to_if_data(ifp, &ifp->if_data,
39236c6e 1624 &ifm->ifm_data);
6d2010ae
A
1625 ifm->ifm_addrs = info.rti_addrs;
1626
1627 cp += len;
39236c6e 1628 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae 1629 current_len += len;
1c79356b 1630 }
39236c6e 1631 while ((ifa = ifa->ifa_link.tqe_next) != NULL) {
6d2010ae
A
1632 IFA_LOCK(ifa);
1633 if (af && af != ifa->ifa_addr->sa_family) {
1634 IFA_UNLOCK(ifa);
1635 continue;
1636 }
1637 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1638 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1639 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
39236c6e
A
1640 len = rt_msg2(RTM_NEWADDR, &info, NULL, NULL,
1641 &cred);
6d2010ae
A
1642 if (pass == 0) {
1643 total_len += len;
1644 } else {
1645 struct ifa_msghdr *ifam;
1646
1647 if (current_len + len > total_len) {
1648 IFA_UNLOCK(ifa);
6d2010ae
A
1649 error = ENOBUFS;
1650 break;
1651 }
39236c6e
A
1652 len = rt_msg2(RTM_NEWADDR, &info,
1653 (caddr_t)cp, NULL, &cred);
1654
316670eb 1655 ifam = (struct ifa_msghdr *)(void *)cp;
39236c6e
A
1656 ifam->ifam_index =
1657 ifa->ifa_ifp->if_index;
6d2010ae
A
1658 ifam->ifam_flags = ifa->ifa_flags;
1659 ifam->ifam_metric = ifa->ifa_metric;
1660 ifam->ifam_addrs = info.rti_addrs;
1661
1662 cp += len;
39236c6e
A
1663 VERIFY(IS_P2ALIGNED(cp,
1664 sizeof (u_int32_t)));
6d2010ae
A
1665 current_len += len;
1666 }
1667 IFA_UNLOCK(ifa);
1668 }
1669 ifnet_lock_done(ifp);
39236c6e
A
1670 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1671 info.rti_info[RTAX_BRD] = NULL;
6d2010ae 1672 }
39236c6e 1673
6d2010ae 1674 ifnet_head_done();
39236c6e
A
1675
1676 if (error != 0) {
1677 if (error == ENOBUFS)
1678 printf("%s: current_len (%d) + len (%d) > "
1679 "total_len (%d)\n", __func__, current_len,
1680 len, total_len);
6d2010ae 1681 break;
39236c6e
A
1682 }
1683
6d2010ae
A
1684 if (pass == 0) {
1685 /* Better to return zero length buffer than ENOBUFS */
1686 if (total_len == 0)
1687 total_len = 1;
1688 total_len += total_len >> 3;
39236c6e
A
1689 total_buffer = _MALLOC(total_len, M_RTABLE,
1690 M_ZERO | M_WAITOK);
6d2010ae 1691 if (total_buffer == NULL) {
39236c6e
A
1692 printf("%s: _MALLOC(%d) failed\n", __func__,
1693 total_len);
6d2010ae
A
1694 error = ENOBUFS;
1695 break;
1696 }
1697 cp = total_buffer;
39236c6e 1698 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae
A
1699 } else {
1700 error = SYSCTL_OUT(w->w_req, total_buffer, current_len);
1701 if (error)
1702 break;
1c79356b 1703 }
1c79356b 1704 }
39236c6e 1705
6d2010ae
A
1706 if (total_buffer != NULL)
1707 _FREE(total_buffer, M_RTABLE);
39236c6e
A
1708
1709 kauth_cred_unref(&cred);
1710 return (error);
1c79356b
A
1711}
1712
39236c6e 1713static int
6d2010ae 1714sysctl_iflist2(int af, struct walkarg *w)
91447636
A
1715{
1716 struct ifnet *ifp;
1717 struct ifaddr *ifa;
1718 struct rt_addrinfo info;
1719 int len, error = 0;
6d2010ae
A
1720 int pass = 0;
1721 int total_len = 0, current_len = 0;
1722 char *total_buffer = NULL, *cp = NULL;
39236c6e 1723 kauth_cred_t cred;
6d2010ae 1724
39236c6e
A
1725 cred = kauth_cred_proc_ref(current_proc());
1726
1727 bzero((caddr_t)&info, sizeof (info));
6d2010ae
A
1728
1729 for (pass = 0; pass < 2; pass++) {
39236c6e
A
1730 struct ifmultiaddr *ifma;
1731
6d2010ae 1732 ifnet_head_lock_shared();
39236c6e 1733
6d2010ae
A
1734 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1735 if (error)
91447636 1736 break;
6d2010ae 1737 if (w->w_arg && w->w_arg != ifp->if_index)
91447636 1738 continue;
6d2010ae
A
1739 ifnet_lock_shared(ifp);
1740 /*
39236c6e
A
1741 * Holding ifnet lock here prevents the link address
1742 * from changing contents, so no need to hold the ifa
1743 * lock. The link address is always present; it's
1744 * never freed.
6d2010ae
A
1745 */
1746 ifa = ifp->if_lladdr;
1747 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
39236c6e 1748 len = rt_msg2(RTM_IFINFO2, &info, NULL, NULL, &cred);
6d2010ae
A
1749 if (pass == 0) {
1750 total_len += len;
1751 } else {
1752 struct if_msghdr2 *ifm;
1753
1754 if (current_len + len > total_len) {
1755 ifnet_lock_done(ifp);
6d2010ae 1756 error = ENOBUFS;
91447636 1757 break;
6d2010ae
A
1758 }
1759 info.rti_info[RTAX_IFP] = ifa->ifa_addr;
39236c6e
A
1760 len = rt_msg2(RTM_IFINFO2, &info,
1761 (caddr_t)cp, NULL, &cred);
6d2010ae 1762 info.rti_info[RTAX_IFP] = NULL;
39236c6e 1763
316670eb 1764 ifm = (struct if_msghdr2 *)(void *)cp;
6d2010ae
A
1765 ifm->ifm_addrs = info.rti_addrs;
1766 ifm->ifm_flags = (u_short)ifp->if_flags;
1767 ifm->ifm_index = ifp->if_index;
316670eb
A
1768 ifm->ifm_snd_len = IFCQ_LEN(&ifp->if_snd);
1769 ifm->ifm_snd_maxlen = IFCQ_MAXLEN(&ifp->if_snd);
1770 ifm->ifm_snd_drops =
1771 ifp->if_snd.ifcq_dropcnt.packets;
6d2010ae 1772 ifm->ifm_timer = ifp->if_timer;
39236c6e
A
1773 if_data_internal_to_if_data64(ifp,
1774 &ifp->if_data, &ifm->ifm_data);
6d2010ae
A
1775
1776 cp += len;
39236c6e 1777 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae 1778 current_len += len;
91447636 1779 }
39236c6e 1780 while ((ifa = ifa->ifa_link.tqe_next) != NULL) {
6d2010ae
A
1781 IFA_LOCK(ifa);
1782 if (af && af != ifa->ifa_addr->sa_family) {
1783 IFA_UNLOCK(ifa);
91447636 1784 continue;
6d2010ae
A
1785 }
1786 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1787 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1788 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
39236c6e
A
1789 len = rt_msg2(RTM_NEWADDR, &info, NULL, NULL,
1790 &cred);
6d2010ae
A
1791 if (pass == 0) {
1792 total_len += len;
1793 } else {
1794 struct ifa_msghdr *ifam;
39236c6e 1795
6d2010ae
A
1796 if (current_len + len > total_len) {
1797 IFA_UNLOCK(ifa);
6d2010ae 1798 error = ENOBUFS;
91447636 1799 break;
6d2010ae 1800 }
39236c6e
A
1801 len = rt_msg2(RTM_NEWADDR, &info,
1802 (caddr_t)cp, NULL, &cred);
6d2010ae 1803
316670eb 1804 ifam = (struct ifa_msghdr *)(void *)cp;
39236c6e
A
1805 ifam->ifam_index =
1806 ifa->ifa_ifp->if_index;
6d2010ae
A
1807 ifam->ifam_flags = ifa->ifa_flags;
1808 ifam->ifam_metric = ifa->ifa_metric;
1809 ifam->ifam_addrs = info.rti_addrs;
1810
1811 cp += len;
39236c6e
A
1812 VERIFY(IS_P2ALIGNED(cp,
1813 sizeof (u_int32_t)));
6d2010ae
A
1814 current_len += len;
1815 }
1816 IFA_UNLOCK(ifa);
1817 }
1818 if (error) {
1819 ifnet_lock_done(ifp);
1820 break;
1821 }
39236c6e
A
1822
1823 for (ifma = LIST_FIRST(&ifp->if_multiaddrs);
1824 ifma != NULL; ifma = LIST_NEXT(ifma, ifma_link)) {
1825 struct ifaddr *ifa0;
1826
1827 IFMA_LOCK(ifma);
1828 if (af && af != ifma->ifma_addr->sa_family) {
1829 IFMA_UNLOCK(ifma);
1830 continue;
1831 }
1832 bzero((caddr_t)&info, sizeof (info));
1833 info.rti_info[RTAX_IFA] = ifma->ifma_addr;
1834 /*
1835 * Holding ifnet lock here prevents the link
1836 * address from changing contents, so no need
1837 * to hold the ifa0 lock. The link address is
1838 * always present; it's never freed.
1839 */
1840 ifa0 = ifp->if_lladdr;
1841 info.rti_info[RTAX_IFP] = ifa0->ifa_addr;
1842 if (ifma->ifma_ll != NULL)
1843 info.rti_info[RTAX_GATEWAY] =
1844 ifma->ifma_ll->ifma_addr;
1845 len = rt_msg2(RTM_NEWMADDR2, &info, NULL, NULL,
1846 &cred);
1847 if (pass == 0) {
1848 total_len += len;
1849 } else {
1850 struct ifma_msghdr2 *ifmam;
1851
1852 if (current_len + len > total_len) {
6d2010ae 1853 IFMA_UNLOCK(ifma);
39236c6e
A
1854 error = ENOBUFS;
1855 break;
6d2010ae 1856 }
39236c6e
A
1857 len = rt_msg2(RTM_NEWMADDR2, &info,
1858 (caddr_t)cp, NULL, &cred);
1859
1860 ifmam =
1861 (struct ifma_msghdr2 *)(void *)cp;
1862 ifmam->ifmam_addrs = info.rti_addrs;
1863 ifmam->ifmam_flags = 0;
1864 ifmam->ifmam_index =
1865 ifma->ifma_ifp->if_index;
1866 ifmam->ifmam_refcount =
1867 ifma->ifma_reqcnt;
1868
1869 cp += len;
1870 VERIFY(IS_P2ALIGNED(cp,
1871 sizeof (u_int32_t)));
1872 current_len += len;
91447636 1873 }
39236c6e 1874 IFMA_UNLOCK(ifma);
91447636 1875 }
6d2010ae 1876 ifnet_lock_done(ifp);
39236c6e
A
1877 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1878 info.rti_info[RTAX_BRD] = NULL;
6d2010ae
A
1879 }
1880 ifnet_head_done();
39236c6e
A
1881
1882 if (error) {
1883 if (error == ENOBUFS)
1884 printf("%s: current_len (%d) + len (%d) > "
1885 "total_len (%d)\n", __func__, current_len,
1886 len, total_len);
6d2010ae 1887 break;
39236c6e
A
1888 }
1889
6d2010ae
A
1890 if (pass == 0) {
1891 /* Better to return zero length buffer than ENOBUFS */
1892 if (total_len == 0)
1893 total_len = 1;
1894 total_len += total_len >> 3;
39236c6e
A
1895 total_buffer = _MALLOC(total_len, M_RTABLE,
1896 M_ZERO | M_WAITOK);
6d2010ae 1897 if (total_buffer == NULL) {
39236c6e
A
1898 printf("%s: _MALLOC(%d) failed\n", __func__,
1899 total_len);
6d2010ae
A
1900 error = ENOBUFS;
1901 break;
1902 }
1903 cp = total_buffer;
39236c6e 1904 VERIFY(IS_P2ALIGNED(cp, sizeof (u_int32_t)));
6d2010ae
A
1905 } else {
1906 error = SYSCTL_OUT(w->w_req, total_buffer, current_len);
1907 if (error)
1908 break;
91447636 1909 }
91447636 1910 }
39236c6e 1911
6d2010ae
A
1912 if (total_buffer != NULL)
1913 _FREE(total_buffer, M_RTABLE);
39236c6e
A
1914
1915 kauth_cred_unref(&cred);
1916 return (error);
91447636
A
1917}
1918
1919
1920static int
1921sysctl_rtstat(struct sysctl_req *req)
1922{
39236c6e 1923 return (SYSCTL_OUT(req, &rtstat, sizeof (struct rtstat)));
91447636
A
1924}
1925
1926static int
1927sysctl_rttrash(struct sysctl_req *req)
1928{
39236c6e 1929 return (SYSCTL_OUT(req, &rttrash, sizeof (rttrash)));
d1ecb069 1930}
91447636 1931
1c79356b
A
1932static int
1933sysctl_rtsock SYSCTL_HANDLER_ARGS
1934{
c910b4d9 1935#pragma unused(oidp)
1c79356b
A
1936 int *name = (int *)arg1;
1937 u_int namelen = arg2;
91447636
A
1938 struct radix_node_head *rnh;
1939 int i, error = EINVAL;
1c79356b
A
1940 u_char af;
1941 struct walkarg w;
1942
1943 name ++;
1944 namelen--;
1945 if (req->newptr)
1946 return (EPERM);
1947 if (namelen != 3)
1948 return (EINVAL);
1949 af = name[0];
39236c6e 1950 Bzero(&w, sizeof (w));
1c79356b
A
1951 w.w_op = name[1];
1952 w.w_arg = name[2];
1953 w.w_req = req;
1954
1c79356b
A
1955 switch (w.w_op) {
1956
1957 case NET_RT_DUMP:
91447636 1958 case NET_RT_DUMP2:
1c79356b 1959 case NET_RT_FLAGS:
b0d623f7 1960 lck_mtx_lock(rnh_lock);
1c79356b
A
1961 for (i = 1; i <= AF_MAX; i++)
1962 if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
1963 (error = rnh->rnh_walktree(rnh,
6d2010ae
A
1964 sysctl_dumpentry, &w)))
1965 break;
1966 lck_mtx_unlock(rnh_lock);
1967 break;
1968 case NET_RT_DUMPX:
1969 case NET_RT_DUMPX_FLAGS:
1970 lck_mtx_lock(rnh_lock);
1971 for (i = 1; i <= AF_MAX; i++)
1972 if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
1973 (error = rnh->rnh_walktree(rnh,
1974 sysctl_dumpentry_ext, &w)))
1c79356b 1975 break;
b0d623f7 1976 lck_mtx_unlock(rnh_lock);
1c79356b 1977 break;
1c79356b
A
1978 case NET_RT_IFLIST:
1979 error = sysctl_iflist(af, &w);
91447636
A
1980 break;
1981 case NET_RT_IFLIST2:
1982 error = sysctl_iflist2(af, &w);
1983 break;
1984 case NET_RT_STAT:
1985 error = sysctl_rtstat(req);
1986 break;
1987 case NET_RT_TRASH:
1988 error = sysctl_rttrash(req);
1989 break;
1c79356b 1990 }
39236c6e 1991 if (w.w_tmem != NULL)
1c79356b
A
1992 FREE(w.w_tmem, M_RTABLE);
1993 return (error);
1994}
1995
1c79356b
A
1996/*
1997 * Definitions of protocols supported in the ROUTE domain.
1998 */
1c79356b 1999static struct protosw routesw[] = {
39236c6e
A
2000{
2001 .pr_type = SOCK_RAW,
2002 .pr_protocol = 0,
2003 .pr_flags = PR_ATOMIC|PR_ADDR,
2004 .pr_output = route_output,
2005 .pr_ctlinput = raw_ctlinput,
2006 .pr_init = raw_init,
2007 .pr_usrreqs = &route_usrreqs,
1c79356b
A
2008}
2009};
2010
39236c6e 2011static int route_proto_count = (sizeof (routesw) / sizeof (struct protosw));
1c79356b 2012
39236c6e
A
2013struct domain routedomain_s = {
2014 .dom_family = PF_ROUTE,
2015 .dom_name = "route",
2016 .dom_init = route_dinit,
2017};
2018
2019static void
2020route_dinit(struct domain *dp)
2021{
2022 struct protosw *pr;
2023 int i;
1c79356b 2024
39236c6e
A
2025 VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
2026 VERIFY(routedomain == NULL);
2027
2028 routedomain = dp;
2029
2030 for (i = 0, pr = &routesw[0]; i < route_proto_count; i++, pr++)
2031 net_add_proto(pr, dp, 1);
2032
2033 route_init();
2034}