]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/rtsock.c
xnu-1504.15.3.tar.gz
[apple/xnu.git] / bsd / net / rtsock.c
1 /*
2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
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>
75 #include <sys/syslog.h>
76 #include <kern/lock.h>
77
78 #include <net/if.h>
79 #include <net/route.h>
80 #include <net/dlil.h>
81 #include <net/raw_cb.h>
82 #include <netinet/in.h>
83 #include <netinet/in_var.h>
84 #include <netinet/in_arp.h>
85 #include <netinet6/nd6.h>
86
87 #include <machine/spl.h>
88
89 extern struct rtstat rtstat;
90 extern int check_routeselfref;
91 extern struct domain routedomain;
92
93 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
94
95 static struct sockaddr route_dst = { 2, PF_ROUTE, { 0, } };
96 static struct sockaddr route_src = { 2, PF_ROUTE, { 0, } };
97 static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, { 0, } };
98 static struct sockproto route_proto = { PF_ROUTE, 0 };
99
100 struct walkarg {
101 int w_tmemsize;
102 int w_op, w_arg;
103 caddr_t w_tmem;
104 struct sysctl_req *w_req;
105 };
106
107 static struct mbuf *rt_msg1(int, struct rt_addrinfo *);
108 static int rt_msg2(int, struct rt_addrinfo *, caddr_t, struct walkarg *);
109 static int rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
110 static int sysctl_dumpentry(struct radix_node *rn, void *vw);
111 static int sysctl_iflist(int af, struct walkarg *w);
112 static int sysctl_iflist2(int af, struct walkarg *w);
113 static int route_output(struct mbuf *, struct socket *);
114 static void rt_setmetrics(u_int32_t, struct rt_metrics *, struct rt_metrics *);
115 static void rt_setif(struct rtentry *, struct sockaddr *, struct sockaddr *,
116 struct sockaddr *, unsigned int);
117 #if IFNET_ROUTE_REFCNT
118 static void rt_drainall(void);
119 #endif /* IFNET_ROUTE_REFCNT */
120
121 #define SIN(sa) ((struct sockaddr_in *)(size_t)(sa))
122
123 /* Sleazy use of local variables throughout file, warning!!!! */
124 #define dst info.rti_info[RTAX_DST]
125 #define gate info.rti_info[RTAX_GATEWAY]
126 #define netmask info.rti_info[RTAX_NETMASK]
127 #define genmask info.rti_info[RTAX_GENMASK]
128 #define ifpaddr info.rti_info[RTAX_IFP]
129 #define ifaaddr info.rti_info[RTAX_IFA]
130 #define brdaddr info.rti_info[RTAX_BRD]
131
132 SYSCTL_NODE(_net, OID_AUTO, idle, CTLFLAG_RW, 0, "idle network monitoring");
133
134 #if IFNET_ROUTE_REFCNT
135 static struct timeval last_ts;
136
137 SYSCTL_NODE(_net_idle, OID_AUTO, route, CTLFLAG_RW, 0, "idle route monitoring");
138
139 static int rt_if_idle_drain_interval = RT_IF_IDLE_DRAIN_INTERVAL;
140 SYSCTL_INT(_net_idle_route, OID_AUTO, drain_interval, CTLFLAG_RW,
141 &rt_if_idle_drain_interval, 0, "Default interval for draining "
142 "routes when doing interface idle reference counting.");
143 #endif /* IFNET_ROUTE_REFCNT */
144
145 /*
146 * It really doesn't make any sense at all for this code to share much
147 * with raw_usrreq.c, since its functionality is so restricted. XXX
148 */
149 static int
150 rts_abort(struct socket *so)
151 {
152 int error;
153
154 error = raw_usrreqs.pru_abort(so);
155 return error;
156 }
157
158 /* pru_accept is EOPNOTSUPP */
159
160 static int
161 rts_attach(struct socket *so, int proto, __unused struct proc *p)
162 {
163 struct rawcb *rp;
164 int error;
165
166 if (sotorawcb(so) != 0)
167 return EISCONN; /* XXX panic? */
168 MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */
169 if (rp == 0)
170 return ENOBUFS;
171 bzero(rp, sizeof *rp);
172
173 /*
174 * The splnet() is necessary to block protocols from sending
175 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
176 * this PCB is extant but incompletely initialized.
177 * Probably we should try to do more of this work beforehand and
178 * eliminate the spl.
179 */
180 so->so_pcb = (caddr_t)rp;
181 error = raw_attach(so, proto); /* don't use raw_usrreqs.pru_attach, it checks for SS_PRIV */
182 rp = sotorawcb(so);
183 if (error) {
184 FREE(rp, M_PCB);
185 so->so_pcb = NULL;
186 so->so_flags |= SOF_PCBCLEARING;
187 return error;
188 }
189
190 switch(rp->rcb_proto.sp_protocol) {
191 //####LD route_cb needs looking
192 case AF_INET:
193 route_cb.ip_count++;
194 break;
195 case AF_INET6:
196 route_cb.ip6_count++;
197 break;
198 case AF_IPX:
199 route_cb.ipx_count++;
200 break;
201 case AF_NS:
202 route_cb.ns_count++;
203 break;
204 }
205 rp->rcb_faddr = &route_src;
206 route_cb.any_count++;
207 /* the socket is already locked when we enter rts_attach */
208 soisconnected(so);
209 so->so_options |= SO_USELOOPBACK;
210 return 0;
211 }
212
213 static int
214 rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
215 {
216 int error;
217 error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
218 return error;
219 }
220
221 static int
222 rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
223 {
224 int error;
225 error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
226 return error;
227 }
228
229 /* pru_connect2 is EOPNOTSUPP */
230 /* pru_control is EOPNOTSUPP */
231
232 static int
233 rts_detach(struct socket *so)
234 {
235 struct rawcb *rp = sotorawcb(so);
236 int error;
237
238 if (rp != 0) {
239 switch(rp->rcb_proto.sp_protocol) {
240 case AF_INET:
241 route_cb.ip_count--;
242 break;
243 case AF_INET6:
244 route_cb.ip6_count--;
245 break;
246 case AF_IPX:
247 route_cb.ipx_count--;
248 break;
249 case AF_NS:
250 route_cb.ns_count--;
251 break;
252 }
253 route_cb.any_count--;
254 }
255 error = raw_usrreqs.pru_detach(so);
256 return error;
257 }
258
259 static int
260 rts_disconnect(struct socket *so)
261 {
262 int error;
263 error = raw_usrreqs.pru_disconnect(so);
264 return error;
265 }
266
267 /* pru_listen is EOPNOTSUPP */
268
269 static int
270 rts_peeraddr(struct socket *so, struct sockaddr **nam)
271 {
272 int error;
273 error = raw_usrreqs.pru_peeraddr(so, nam);
274 return error;
275 }
276
277 /* pru_rcvd is EOPNOTSUPP */
278 /* pru_rcvoob is EOPNOTSUPP */
279
280 static int
281 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
282 struct mbuf *control, struct proc *p)
283 {
284 int error;
285 error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
286 return error;
287 }
288
289 /* pru_sense is null */
290
291 static int
292 rts_shutdown(struct socket *so)
293 {
294 int error;
295 error = raw_usrreqs.pru_shutdown(so);
296 return error;
297 }
298
299 static int
300 rts_sockaddr(struct socket *so, struct sockaddr **nam)
301 {
302 int error;
303 error = raw_usrreqs.pru_sockaddr(so, nam);
304 return error;
305 }
306
307 static struct pr_usrreqs route_usrreqs = {
308 rts_abort, pru_accept_notsupp, rts_attach, rts_bind,
309 rts_connect, pru_connect2_notsupp, pru_control_notsupp,
310 rts_detach, rts_disconnect, pru_listen_notsupp, rts_peeraddr,
311 pru_rcvd_notsupp, pru_rcvoob_notsupp, rts_send, pru_sense_null,
312 rts_shutdown, rts_sockaddr, sosend, soreceive, pru_sopoll_notsupp
313 };
314
315 /*ARGSUSED*/
316 static int
317 route_output(struct mbuf *m, struct socket *so)
318 {
319 struct rt_msghdr *rtm = NULL;
320 struct rtentry *rt = NULL;
321 struct rtentry *saved_nrt = NULL;
322 struct radix_node_head *rnh;
323 struct rt_addrinfo info;
324 int len, error = 0;
325 struct ifnet *ifp = NULL;
326 #ifndef __APPLE__
327 struct proc *curproc = current_proc();
328 #endif
329 struct sockaddr_in dst_in, gate_in;
330 int sendonlytoself = 0;
331 unsigned int ifscope = IFSCOPE_NONE;
332
333 #define senderr(e) { error = e; goto flush;}
334 if (m == NULL ||
335 ((m->m_len < sizeof(intptr_t)) && (m = m_pullup(m, sizeof(intptr_t))) == 0))
336 return (ENOBUFS);
337 if ((m->m_flags & M_PKTHDR) == 0)
338 panic("route_output");
339
340 /* unlock the socket (but keep a reference) it won't be accessed until raw_input appends to it. */
341 socket_unlock(so, 0);
342 lck_mtx_lock(rnh_lock);
343
344 len = m->m_pkthdr.len;
345 if (len < sizeof(*rtm) ||
346 len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
347 dst = NULL;
348 senderr(EINVAL);
349 }
350 R_Malloc(rtm, struct rt_msghdr *, len);
351 if (rtm == NULL) {
352 dst = NULL;
353 senderr(ENOBUFS);
354 }
355 m_copydata(m, 0, len, (caddr_t)rtm);
356 if (rtm->rtm_version != RTM_VERSION) {
357 dst = NULL;
358 senderr(EPROTONOSUPPORT);
359 }
360
361 /*
362 * Silent version of RTM_GET for Reachabiltiy APIs. We may change
363 * all RTM_GETs to be silent in the future, so this is private for now.
364 */
365 if (rtm->rtm_type == RTM_GET_SILENT) {
366 if ((so->so_options & SO_USELOOPBACK) == 0)
367 senderr(EINVAL);
368 sendonlytoself = 1;
369 rtm->rtm_type = RTM_GET;
370 }
371
372 /*
373 * Perform permission checking, only privileged sockets
374 * may perform operations other than RTM_GET
375 */
376 if (rtm->rtm_type != RTM_GET && (so->so_state & SS_PRIV) == 0) {
377 dst = NULL;
378 senderr(EPERM);
379 }
380
381 rtm->rtm_pid = proc_selfpid();
382 info.rti_addrs = rtm->rtm_addrs;
383 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
384 dst = NULL;
385 senderr(EINVAL);
386 }
387 if (dst == NULL || (dst->sa_family >= AF_MAX) ||
388 (gate != NULL && (gate->sa_family >= AF_MAX))) {
389 senderr(EINVAL);
390 }
391
392 if (dst->sa_family == AF_INET && dst->sa_len != sizeof (dst_in)) {
393 /* At minimum, we need up to sin_addr */
394 if (dst->sa_len < offsetof(struct sockaddr_in, sin_zero))
395 senderr(EINVAL);
396 bzero(&dst_in, sizeof (dst_in));
397 dst_in.sin_len = sizeof (dst_in);
398 dst_in.sin_family = AF_INET;
399 dst_in.sin_port = SIN(dst)->sin_port;
400 dst_in.sin_addr = SIN(dst)->sin_addr;
401 dst = (struct sockaddr *)&dst_in;
402 }
403
404 if (gate != NULL &&
405 gate->sa_family == AF_INET && gate->sa_len != sizeof (gate_in)) {
406 /* At minimum, we need up to sin_addr */
407 if (gate->sa_len < offsetof(struct sockaddr_in, sin_zero))
408 senderr(EINVAL);
409 bzero(&gate_in, sizeof (gate_in));
410 gate_in.sin_len = sizeof (gate_in);
411 gate_in.sin_family = AF_INET;
412 gate_in.sin_port = SIN(gate)->sin_port;
413 gate_in.sin_addr = SIN(gate)->sin_addr;
414 gate = (struct sockaddr *)&gate_in;
415 }
416
417 if (genmask) {
418 struct radix_node *t;
419 t = rn_addmask((caddr_t)genmask, 0, 1);
420 if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
421 genmask = (struct sockaddr *)(t->rn_key);
422 else
423 senderr(ENOBUFS);
424 }
425
426 /*
427 * If RTF_IFSCOPE flag is set, then rtm_index specifies the scope.
428 */
429 if (rtm->rtm_flags & RTF_IFSCOPE) {
430 /* Scoped routing is for AF_INET only */
431 if (dst->sa_family != AF_INET)
432 senderr(EINVAL);
433 ifscope = rtm->rtm_index;
434 }
435
436 switch (rtm->rtm_type) {
437
438 case RTM_ADD:
439 if (gate == NULL)
440 senderr(EINVAL);
441
442 #ifdef __APPLE__
443 /* XXX LD11JUL02 Special case for AOL 5.1.2 connectivity issue to AirPort BS (Radar 2969954)
444 * AOL is adding a circular route ("10.0.1.1/32 10.0.1.1") when establishing its ppp tunnel
445 * to the AP BaseStation by removing the default gateway and replacing it with their tunnel entry point.
446 * There is no apparent reason to add this route as there is a valid 10.0.1.1/24 route to the BS.
447 * That circular route was ignored on previous version of MacOS X because of a routing bug
448 * corrected with the merge to FreeBSD4.4 (a route generated from an RTF_CLONING route had the RTF_WASCLONED
449 * flag set but did not have a reference to the parent route) and that entry was left in the RT. This workaround is
450 * made in order to provide binary compatibility with AOL.
451 * If we catch a process adding a circular route with a /32 from the routing socket, we error it out instead of
452 * confusing the routing table with a wrong route to the previous default gateway
453 */
454 {
455 #define satosinaddr(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr)
456
457 if (check_routeselfref && (dst && dst->sa_family == AF_INET) &&
458 (netmask && satosinaddr(netmask) == INADDR_BROADCAST) &&
459 (gate && satosinaddr(dst) == satosinaddr(gate))) {
460 log(LOG_WARNING, "route_output: circular route %ld.%ld.%ld.%ld/32 ignored\n",
461 (ntohl(satosinaddr(gate)>>24))&0xff,
462 (ntohl(satosinaddr(gate)>>16))&0xff,
463 (ntohl(satosinaddr(gate)>>8))&0xff,
464 (ntohl(satosinaddr(gate)))&0xff);
465
466 senderr(EINVAL);
467 }
468 }
469 #endif
470 error = rtrequest_scoped_locked(RTM_ADD, dst, gate,
471 netmask, rtm->rtm_flags, &saved_nrt, ifscope);
472 if (error == 0 && saved_nrt) {
473 RT_LOCK(saved_nrt);
474 #ifdef __APPLE__
475 /*
476 * If the route request specified an interface with
477 * IFA and/or IFP, we set the requested interface on
478 * the route with rt_setif. It would be much better
479 * to do this inside rtrequest, but that would
480 * require passing the desired interface, in some
481 * form, to rtrequest. Since rtrequest is called in
482 * so many places (roughly 40 in our source), adding
483 * a parameter is to much for us to swallow; this is
484 * something for the FreeBSD developers to tackle.
485 * Instead, we let rtrequest compute whatever
486 * interface it wants, then come in behind it and
487 * stick in the interface that we really want. This
488 * works reasonably well except when rtrequest can't
489 * figure out what interface to use (with
490 * ifa_withroute) and returns ENETUNREACH. Ideally
491 * it shouldn't matter if rtrequest can't figure out
492 * the interface if we're going to explicitly set it
493 * ourselves anyway. But practically we can't
494 * recover here because rtrequest will not do any of
495 * the work necessary to add the route if it can't
496 * find an interface. As long as there is a default
497 * route that leads to some interface, rtrequest will
498 * find an interface, so this problem should be
499 * rarely encountered.
500 * dwiggins@bbn.com
501 */
502
503 rt_setif(saved_nrt, ifpaddr, ifaaddr, gate,
504 ifscope);
505 #endif
506 rt_setmetrics(rtm->rtm_inits,
507 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
508 saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
509 saved_nrt->rt_rmx.rmx_locks |=
510 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
511 saved_nrt->rt_genmask = genmask;
512 RT_REMREF_LOCKED(saved_nrt);
513 RT_UNLOCK(saved_nrt);
514 }
515 break;
516
517 case RTM_DELETE:
518 error = rtrequest_scoped_locked(RTM_DELETE, dst,
519 gate, netmask, rtm->rtm_flags, &saved_nrt, ifscope);
520 if (error == 0) {
521 rt = saved_nrt;
522 RT_LOCK(rt);
523 goto report;
524 }
525 break;
526
527 case RTM_GET:
528 case RTM_CHANGE:
529 case RTM_LOCK:
530 if ((rnh = rt_tables[dst->sa_family]) == NULL)
531 senderr(EAFNOSUPPORT);
532
533 /*
534 * Lookup the best match based on the key-mask pair;
535 * callee adds a reference and checks for root node.
536 */
537 rt = rt_lookup(TRUE, dst, netmask, rnh, ifscope);
538 if (rt == NULL)
539 senderr(ESRCH);
540 RT_LOCK(rt);
541
542 switch(rtm->rtm_type) {
543
544 case RTM_GET: {
545 struct ifaddr *ifa2;
546 report:
547 ifa2 = NULL;
548 RT_LOCK_ASSERT_HELD(rt);
549 dst = rt_key(rt);
550 gate = rt->rt_gateway;
551 netmask = rt_mask(rt);
552 genmask = rt->rt_genmask;
553 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
554 ifp = rt->rt_ifp;
555 if (ifp) {
556 ifnet_lock_shared(ifp);
557 ifa2 = ifp->if_addrhead.tqh_first;
558 ifpaddr = ifa2->ifa_addr;
559 ifaref(ifa2);
560 ifnet_lock_done(ifp);
561 ifaaddr = rt->rt_ifa->ifa_addr;
562 rtm->rtm_index = ifp->if_index;
563 } else {
564 ifpaddr = 0;
565 ifaaddr = 0;
566 }
567 }
568 len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
569 (struct walkarg *)0);
570 if (len > rtm->rtm_msglen) {
571 struct rt_msghdr *new_rtm;
572 R_Malloc(new_rtm, struct rt_msghdr *, len);
573 if (new_rtm == 0) {
574 RT_UNLOCK(rt);
575 if (ifa2 != NULL)
576 ifafree(ifa2);
577 senderr(ENOBUFS);
578 }
579 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
580 R_Free(rtm); rtm = new_rtm;
581 }
582 (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
583 (struct walkarg *)0);
584 rtm->rtm_flags = rt->rt_flags;
585 rtm->rtm_rmx = rt->rt_rmx;
586 rtm->rtm_addrs = info.rti_addrs;
587 if (ifa2 != NULL)
588 ifafree(ifa2);
589 }
590 break;
591
592 case RTM_CHANGE:
593 if (gate && (error = rt_setgate(rt,
594 rt_key(rt), gate))) {
595 RT_UNLOCK(rt);
596 senderr(error);
597 }
598 /*
599 * If they tried to change things but didn't specify
600 * the required gateway, then just use the old one.
601 * This can happen if the user tries to change the
602 * flags on the default route without changing the
603 * default gateway. Changing flags still doesn't work.
604 */
605 if ((rt->rt_flags & RTF_GATEWAY) && !gate)
606 gate = rt->rt_gateway;
607
608 #ifdef __APPLE__
609 /*
610 * On Darwin, we call rt_setif which contains the
611 * equivalent to the code found at this very spot
612 * in BSD.
613 */
614 rt_setif(rt, ifpaddr, ifaaddr, gate,
615 ifscope);
616 #endif
617
618 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
619 &rt->rt_rmx);
620 #ifndef __APPLE__
621 /* rt_setif, called above does this for us on darwin */
622 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
623 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
624 #endif
625 if (genmask)
626 rt->rt_genmask = genmask;
627 /*
628 * Fall into
629 */
630 case RTM_LOCK:
631 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
632 rt->rt_rmx.rmx_locks |=
633 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
634 break;
635 }
636 RT_UNLOCK(rt);
637 break;
638
639 default:
640 senderr(EOPNOTSUPP);
641 }
642 flush:
643 if (rtm) {
644 if (error)
645 rtm->rtm_errno = error;
646 else
647 rtm->rtm_flags |= RTF_DONE;
648 }
649 if (rt != NULL) {
650 RT_LOCK_ASSERT_NOTHELD(rt);
651 rtfree_locked(rt);
652 }
653 lck_mtx_unlock(rnh_lock);
654 socket_lock(so, 0); /* relock the socket now */
655 {
656 struct rawcb *rp = 0;
657 /*
658 * Check to see if we don't want our own messages.
659 */
660 if ((so->so_options & SO_USELOOPBACK) == 0) {
661 if (route_cb.any_count <= 1) {
662 if (rtm)
663 R_Free(rtm);
664 m_freem(m);
665 return (error);
666 }
667 /* There is another listener, so construct message */
668 rp = sotorawcb(so);
669 }
670 if (rtm) {
671 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
672 if (m->m_pkthdr.len < rtm->rtm_msglen) {
673 m_freem(m);
674 m = NULL;
675 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
676 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
677 R_Free(rtm);
678 }
679 if (sendonlytoself && m) {
680 error = 0;
681 if (sbappendaddr(&so->so_rcv, &route_src, m, (struct mbuf*)0, &error) != 0) {
682 sorwakeup(so);
683 }
684 if (error)
685 return error;
686 } else {
687 if (rp)
688 rp->rcb_proto.sp_family = 0; /* Avoid us */
689 if (dst)
690 route_proto.sp_protocol = dst->sa_family;
691 if (m) {
692 socket_unlock(so, 0);
693 raw_input(m, &route_proto, &route_src, &route_dst);
694 socket_lock(so, 0);
695 }
696 if (rp)
697 rp->rcb_proto.sp_family = PF_ROUTE;
698 }
699 }
700 return (error);
701 }
702
703 static void
704 rt_setmetrics(u_int32_t which, struct rt_metrics *in, struct rt_metrics *out)
705 {
706 #define metric(f, e) if (which & (f)) out->e = in->e;
707 metric(RTV_RPIPE, rmx_recvpipe);
708 metric(RTV_SPIPE, rmx_sendpipe);
709 metric(RTV_SSTHRESH, rmx_ssthresh);
710 metric(RTV_RTT, rmx_rtt);
711 metric(RTV_RTTVAR, rmx_rttvar);
712 metric(RTV_HOPCOUNT, rmx_hopcount);
713 metric(RTV_MTU, rmx_mtu);
714 metric(RTV_EXPIRE, rmx_expire);
715 #undef metric
716 }
717
718 /*
719 * Set route's interface given ifpaddr, ifaaddr, and gateway.
720 */
721 static void
722 rt_setif(struct rtentry *rt, struct sockaddr *Ifpaddr, struct sockaddr *Ifaaddr,
723 struct sockaddr *Gate, unsigned int ifscope)
724 {
725 struct ifaddr *ifa = 0;
726 struct ifnet *ifp = 0;
727
728 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
729
730 RT_LOCK_ASSERT_HELD(rt);
731
732 /* trigger route cache reevaluation */
733 if (use_routegenid)
734 routegenid_update();
735
736 /* Don't update a defunct route */
737 if (rt->rt_flags & RTF_CONDEMNED)
738 return;
739
740 /* Add an extra ref for ourselves */
741 RT_ADDREF_LOCKED(rt);
742
743 /*
744 * New gateway could require new ifaddr, ifp; flags may also
745 * be different; ifp may be specified by ll sockaddr when
746 * protocol address is ambiguous.
747 */
748 if (Ifpaddr && (ifa = ifa_ifwithnet_scoped(Ifpaddr, ifscope)) &&
749 (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate)) {
750 ifafree(ifa);
751 ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate, ifp);
752 } else {
753 if (ifa) {
754 ifafree(ifa);
755 ifa = 0;
756 }
757 if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
758 if (Gate) {
759 ifa = ifaof_ifpforaddr(Gate, ifp);
760 } else {
761 ifnet_lock_shared(ifp);
762 ifa = TAILQ_FIRST(&ifp->if_addrhead);
763 if (ifa != NULL)
764 ifaref(ifa);
765 ifnet_lock_done(ifp);
766 }
767 } else if (Ifaaddr &&
768 (ifa = ifa_ifwithaddr_scoped(Ifaaddr, ifscope))) {
769 ifp = ifa->ifa_ifp;
770 } else if (Gate != NULL) {
771 /*
772 * Safe to drop rt_lock and use rt_key, since holding
773 * rnh_lock here prevents another thread from calling
774 * rt_setgate() on this route. We cannot hold the
775 * lock across ifa_ifwithroute since the lookup done
776 * by that routine may point to the same route.
777 */
778 RT_UNLOCK(rt);
779 if ((ifa = ifa_ifwithroute_scoped_locked(rt->rt_flags,
780 rt_key(rt), Gate, ifscope)) != NULL)
781 ifp = ifa->ifa_ifp;
782 RT_LOCK(rt);
783 /* Don't update a defunct route */
784 if (rt->rt_flags & RTF_CONDEMNED) {
785 if (ifa != NULL)
786 ifafree(ifa);
787 /* Release extra ref */
788 RT_REMREF_LOCKED(rt);
789 return;
790 }
791 }
792 }
793 if (ifa) {
794 struct ifaddr *oifa = rt->rt_ifa;
795 if (oifa != ifa) {
796 if (oifa && oifa->ifa_rtrequest)
797 oifa->ifa_rtrequest(RTM_DELETE, rt, Gate);
798 rtsetifa(rt, ifa);
799 #if IFNET_ROUTE_REFCNT
800 /*
801 * Adjust route ref count for the interfaces.
802 */
803 if (rt->rt_if_ref_fn != NULL && rt->rt_ifp != ifp) {
804 rt->rt_if_ref_fn(ifp, 1);
805 rt->rt_if_ref_fn(rt->rt_ifp, -1);
806 }
807 #endif /* IFNET_ROUTE_REFCNT */
808 rt->rt_ifp = ifp;
809 /*
810 * If this is the (non-scoped) default route, record
811 * the interface index used for the primary ifscope.
812 */
813 if (rt_inet_default(rt, rt_key(rt)))
814 set_primary_ifscope(rt->rt_ifp->if_index);
815 rt->rt_rmx.rmx_mtu = ifp->if_mtu;
816 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
817 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
818 ifafree(ifa);
819 /* Release extra ref */
820 RT_REMREF_LOCKED(rt);
821 return;
822 }
823 ifafree(ifa);
824 }
825
826 /* XXX: to reset gateway to correct value, at RTM_CHANGE */
827 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
828 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
829
830 /* Release extra ref */
831 RT_REMREF_LOCKED(rt);
832 }
833
834 #define ROUNDUP32(a) \
835 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
836 #define ADVANCE32(x, n) (x += ROUNDUP32((n)->sa_len))
837
838
839 /*
840 * Extract the addresses of the passed sockaddrs.
841 * Do a little sanity checking so as to avoid bad memory references.
842 * This data is derived straight from userland.
843 */
844 static int
845 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
846 {
847 struct sockaddr *sa;
848 int i;
849
850 bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
851 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
852 if ((rtinfo->rti_addrs & (1 << i)) == 0)
853 continue;
854 sa = (struct sockaddr *)cp;
855 /*
856 * It won't fit.
857 */
858 if ( (cp + sa->sa_len) > cplim ) {
859 return (EINVAL);
860 }
861
862 /*
863 * there are no more.. quit now
864 * If there are more bits, they are in error.
865 * I've seen this. route(1) can evidently generate these.
866 * This causes kernel to core dump.
867 * for compatibility, If we see this, point to a safe address.
868 */
869 if (sa->sa_len == 0) {
870 rtinfo->rti_info[i] = &sa_zero;
871 return (0); /* should be EINVAL but for compat */
872 }
873
874 /* accept it */
875 rtinfo->rti_info[i] = sa;
876 ADVANCE32(cp, sa);
877 }
878 return (0);
879 }
880
881 static struct mbuf *
882 rt_msg1(int type, struct rt_addrinfo *rtinfo)
883 {
884 struct rt_msghdr *rtm;
885 struct mbuf *m;
886 int i;
887 int len, dlen;
888
889 switch (type) {
890
891 case RTM_DELADDR:
892 case RTM_NEWADDR:
893 len = sizeof(struct ifa_msghdr);
894 break;
895
896 case RTM_DELMADDR:
897 case RTM_NEWMADDR:
898 len = sizeof(struct ifma_msghdr);
899 break;
900
901 case RTM_IFINFO:
902 len = sizeof(struct if_msghdr);
903 break;
904
905 default:
906 len = sizeof(struct rt_msghdr);
907 }
908 if (len > MCLBYTES)
909 panic("rt_msg1");
910 m = m_gethdr(M_DONTWAIT, MT_DATA);
911 if (m && len > MHLEN) {
912 MCLGET(m, M_DONTWAIT);
913 if ((m->m_flags & M_EXT) == 0) {
914 m_free(m);
915 m = NULL;
916 }
917 }
918 if (m == 0)
919 return (m);
920 m->m_pkthdr.len = m->m_len = len;
921 m->m_pkthdr.rcvif = 0;
922 rtm = mtod(m, struct rt_msghdr *);
923 bzero((caddr_t)rtm, len);
924 for (i = 0; i < RTAX_MAX; i++) {
925 struct sockaddr *sa, *hint;
926 struct sockaddr_storage ss;
927
928 if ((sa = rtinfo->rti_info[i]) == NULL)
929 continue;
930
931 switch (i) {
932 case RTAX_DST:
933 case RTAX_NETMASK:
934 if ((hint = rtinfo->rti_info[RTAX_DST]) == NULL)
935 hint = rtinfo->rti_info[RTAX_IFA];
936
937 /* Scrub away any trace of embedded interface scope */
938 sa = rtm_scrub_ifscope(i, hint, sa, &ss);
939 break;
940
941 default:
942 break;
943 }
944
945 rtinfo->rti_addrs |= (1 << i);
946 dlen = ROUNDUP32(sa->sa_len);
947 m_copyback(m, len, dlen, (caddr_t)sa);
948 len += dlen;
949 }
950 if (m->m_pkthdr.len != len) {
951 m_freem(m);
952 return (NULL);
953 }
954 rtm->rtm_msglen = len;
955 rtm->rtm_version = RTM_VERSION;
956 rtm->rtm_type = type;
957 return (m);
958 }
959
960 static int
961 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
962 {
963 int i;
964 int len, dlen, second_time = 0;
965 caddr_t cp0;
966
967 rtinfo->rti_addrs = 0;
968 again:
969 switch (type) {
970
971 case RTM_DELADDR:
972 case RTM_NEWADDR:
973 len = sizeof(struct ifa_msghdr);
974 break;
975
976 case RTM_DELMADDR:
977 case RTM_NEWMADDR:
978 len = sizeof(struct ifma_msghdr);
979 break;
980
981 case RTM_IFINFO:
982 len = sizeof(struct if_msghdr);
983 break;
984
985 case RTM_IFINFO2:
986 len = sizeof(struct if_msghdr2);
987 break;
988
989 case RTM_NEWMADDR2:
990 len = sizeof(struct ifma_msghdr2);
991 break;
992
993 case RTM_GET2:
994 len = sizeof(struct rt_msghdr2);
995 break;
996
997 default:
998 len = sizeof(struct rt_msghdr);
999 }
1000 cp0 = cp;
1001 if (cp0)
1002 cp += len;
1003 for (i = 0; i < RTAX_MAX; i++) {
1004 struct sockaddr *sa, *hint;
1005 struct sockaddr_storage ss;
1006
1007 if ((sa = rtinfo->rti_info[i]) == 0)
1008 continue;
1009
1010 switch (i) {
1011 case RTAX_DST:
1012 case RTAX_NETMASK:
1013 if ((hint = rtinfo->rti_info[RTAX_DST]) == NULL)
1014 hint = rtinfo->rti_info[RTAX_IFA];
1015
1016 /* Scrub away any trace of embedded interface scope */
1017 sa = rtm_scrub_ifscope(i, hint, sa, &ss);
1018 break;
1019
1020 default:
1021 break;
1022 }
1023
1024 rtinfo->rti_addrs |= (1 << i);
1025 dlen = ROUNDUP32(sa->sa_len);
1026 if (cp) {
1027 bcopy((caddr_t)sa, cp, (unsigned)dlen);
1028 cp += dlen;
1029 }
1030 len += dlen;
1031 }
1032 if (cp == 0 && w != NULL && !second_time) {
1033 struct walkarg *rw = w;
1034
1035 if (rw->w_req) {
1036 if (rw->w_tmemsize < len) {
1037 if (rw->w_tmem)
1038 FREE(rw->w_tmem, M_RTABLE);
1039 rw->w_tmem = (caddr_t)
1040 _MALLOC(len, M_RTABLE, M_WAITOK); /*###LD0412 was NOWAIT */
1041 if (rw->w_tmem)
1042 rw->w_tmemsize = len;
1043 }
1044 if (rw->w_tmem) {
1045 cp = rw->w_tmem;
1046 second_time = 1;
1047 goto again;
1048 }
1049 }
1050 }
1051 if (cp) {
1052 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
1053
1054 rtm->rtm_version = RTM_VERSION;
1055 rtm->rtm_type = type;
1056 rtm->rtm_msglen = len;
1057 }
1058 return (len);
1059 }
1060
1061 /*
1062 * This routine is called to generate a message from the routing
1063 * socket indicating that a redirect has occurred, a routing lookup
1064 * has failed, or that a protocol has detected timeouts to a particular
1065 * destination.
1066 */
1067 void
1068 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
1069 {
1070 struct rt_msghdr *rtm;
1071 struct mbuf *m;
1072 struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
1073
1074 if (route_cb.any_count == 0)
1075 return;
1076 m = rt_msg1(type, rtinfo);
1077 if (m == 0)
1078 return;
1079 rtm = mtod(m, struct rt_msghdr *);
1080 rtm->rtm_flags = RTF_DONE | flags;
1081 rtm->rtm_errno = error;
1082 rtm->rtm_addrs = rtinfo->rti_addrs;
1083 route_proto.sp_protocol = sa ? sa->sa_family : 0;
1084 raw_input(m, &route_proto, &route_src, &route_dst);
1085 }
1086
1087 /*
1088 * This routine is called to generate a message from the routing
1089 * socket indicating that the status of a network interface has changed.
1090 */
1091 void
1092 rt_ifmsg(
1093 struct ifnet *ifp)
1094 {
1095 struct if_msghdr *ifm;
1096 struct mbuf *m;
1097 struct rt_addrinfo info;
1098
1099 if (route_cb.any_count == 0)
1100 return;
1101 bzero((caddr_t)&info, sizeof(info));
1102 m = rt_msg1(RTM_IFINFO, &info);
1103 if (m == 0)
1104 return;
1105 ifm = mtod(m, struct if_msghdr *);
1106 ifm->ifm_index = ifp->if_index;
1107 ifm->ifm_flags = (u_short)ifp->if_flags;
1108 if_data_internal_to_if_data(ifp, &ifp->if_data, &ifm->ifm_data);
1109 ifm->ifm_addrs = 0;
1110 route_proto.sp_protocol = 0;
1111 raw_input(m, &route_proto, &route_src, &route_dst);
1112 }
1113
1114 /*
1115 * This is called to generate messages from the routing socket
1116 * indicating a network interface has had addresses associated with it.
1117 * if we ever reverse the logic and replace messages TO the routing
1118 * socket indicate a request to configure interfaces, then it will
1119 * be unnecessary as the routing socket will automatically generate
1120 * copies of it.
1121 *
1122 * Since this is coming from the interface, it is expected that the
1123 * interface will be locked. Caller must hold rt_lock.
1124 */
1125 void
1126 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1127 {
1128 struct rt_addrinfo info;
1129 struct sockaddr *sa = 0;
1130 int pass;
1131 struct mbuf *m = 0;
1132 struct ifnet *ifp = ifa->ifa_ifp;
1133
1134 RT_LOCK_ASSERT_HELD(rt);
1135
1136 if (route_cb.any_count == 0)
1137 return;
1138 for (pass = 1; pass < 3; pass++) {
1139 bzero((caddr_t)&info, sizeof(info));
1140 if ((cmd == RTM_ADD && pass == 1) ||
1141 (cmd == RTM_DELETE && pass == 2)) {
1142 struct ifa_msghdr *ifam;
1143 int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
1144
1145 /* Lock ifp for if_addrhead */
1146 ifnet_lock_shared(ifp);
1147 ifaaddr = sa = ifa->ifa_addr;
1148 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
1149 netmask = ifa->ifa_netmask;
1150 brdaddr = ifa->ifa_dstaddr;
1151 if ((m = rt_msg1(ncmd, &info)) == NULL) {
1152 ifnet_lock_done(ifp);
1153 continue;
1154 }
1155 ifnet_lock_done(ifp);
1156 ifam = mtod(m, struct ifa_msghdr *);
1157 ifam->ifam_index = ifp->if_index;
1158 ifam->ifam_metric = ifa->ifa_metric;
1159 ifam->ifam_flags = ifa->ifa_flags;
1160 ifam->ifam_addrs = info.rti_addrs;
1161 }
1162 if ((cmd == RTM_ADD && pass == 2) ||
1163 (cmd == RTM_DELETE && pass == 1)) {
1164 struct rt_msghdr *rtm;
1165
1166 if (rt == 0)
1167 continue;
1168 netmask = rt_mask(rt);
1169 dst = sa = rt_key(rt);
1170 gate = rt->rt_gateway;
1171 if ((m = rt_msg1(cmd, &info)) == NULL)
1172 continue;
1173 rtm = mtod(m, struct rt_msghdr *);
1174 rtm->rtm_index = ifp->if_index;
1175 rtm->rtm_flags |= rt->rt_flags;
1176 rtm->rtm_errno = error;
1177 rtm->rtm_addrs = info.rti_addrs;
1178 }
1179 route_proto.sp_protocol = sa ? sa->sa_family : 0;
1180 raw_input(m, &route_proto, &route_src, &route_dst);
1181 }
1182 }
1183
1184 /*
1185 * This is the analogue to the rt_newaddrmsg which performs the same
1186 * function but for multicast group memberhips. This is easier since
1187 * there is no route state to worry about.
1188 */
1189 void
1190 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1191 {
1192 struct rt_addrinfo info;
1193 struct mbuf *m = 0;
1194 struct ifnet *ifp = ifma->ifma_ifp;
1195 struct ifma_msghdr *ifmam;
1196
1197 if (route_cb.any_count == 0)
1198 return;
1199
1200 bzero((caddr_t)&info, sizeof(info));
1201 ifaaddr = ifma->ifma_addr;
1202 /* Lock ifp for if_addrhead */
1203 if (ifp != NULL)
1204 ifnet_lock_shared(ifp);
1205 if (ifp && ifp->if_addrhead.tqh_first)
1206 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
1207 else
1208 ifpaddr = NULL;
1209 /*
1210 * If a link-layer address is present, present it as a ``gateway''
1211 * (similarly to how ARP entries, e.g., are presented).
1212 */
1213 gate = ifma->ifma_ll->ifma_addr;
1214 if ((m = rt_msg1(cmd, &info)) == NULL) {
1215 if (ifp != NULL)
1216 ifnet_lock_done(ifp);
1217 return;
1218 }
1219 if (ifp != NULL)
1220 ifnet_lock_done(ifp);
1221 ifmam = mtod(m, struct ifma_msghdr *);
1222 ifmam->ifmam_index = ifp ? ifp->if_index : 0;
1223 ifmam->ifmam_addrs = info.rti_addrs;
1224 route_proto.sp_protocol = ifma->ifma_addr->sa_family;
1225 raw_input(m, &route_proto, &route_src, &route_dst);
1226 }
1227
1228 /*
1229 * This is used in dumping the kernel table via sysctl().
1230 */
1231 int
1232 sysctl_dumpentry(struct radix_node *rn, void *vw)
1233 {
1234 struct walkarg *w = vw;
1235 struct rtentry *rt = (struct rtentry *)rn;
1236 int error = 0, size;
1237 struct rt_addrinfo info;
1238
1239 RT_LOCK(rt);
1240 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) {
1241 RT_UNLOCK(rt);
1242 return 0;
1243 }
1244 bzero((caddr_t)&info, sizeof(info));
1245 dst = rt_key(rt);
1246 gate = rt->rt_gateway;
1247 netmask = rt_mask(rt);
1248 genmask = rt->rt_genmask;
1249 if (w->w_op != NET_RT_DUMP2) {
1250 size = rt_msg2(RTM_GET, &info, 0, w);
1251 if (w->w_req && w->w_tmem) {
1252 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
1253
1254 rtm->rtm_flags = rt->rt_flags;
1255 rtm->rtm_use = rt->rt_use;
1256 rtm->rtm_rmx = rt->rt_rmx;
1257 rtm->rtm_index = rt->rt_ifp->if_index;
1258 rtm->rtm_pid = 0;
1259 rtm->rtm_seq = 0;
1260 rtm->rtm_errno = 0;
1261 rtm->rtm_addrs = info.rti_addrs;
1262 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
1263 RT_UNLOCK(rt);
1264 return (error);
1265 }
1266 } else {
1267 size = rt_msg2(RTM_GET2, &info, 0, w);
1268 if (w->w_req && w->w_tmem) {
1269 struct rt_msghdr2 *rtm = (struct rt_msghdr2 *)w->w_tmem;
1270
1271 rtm->rtm_flags = rt->rt_flags;
1272 rtm->rtm_use = rt->rt_use;
1273 rtm->rtm_rmx = rt->rt_rmx;
1274 rtm->rtm_index = rt->rt_ifp->if_index;
1275 rtm->rtm_refcnt = rt->rt_refcnt;
1276 if (rt->rt_parent)
1277 rtm->rtm_parentflags = rt->rt_parent->rt_flags;
1278 else
1279 rtm->rtm_parentflags = 0;
1280 rtm->rtm_reserved = 0;
1281 rtm->rtm_addrs = info.rti_addrs;
1282 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
1283 RT_UNLOCK(rt);
1284 return (error);
1285
1286 }
1287 }
1288 RT_UNLOCK(rt);
1289 return (error);
1290 }
1291
1292 int
1293 sysctl_iflist(
1294 int af,
1295 struct walkarg *w)
1296 {
1297 struct ifnet *ifp;
1298 struct ifaddr *ifa;
1299 struct rt_addrinfo info;
1300 int len, error = 0;
1301
1302 bzero((caddr_t)&info, sizeof(info));
1303 ifnet_head_lock_shared();
1304 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1305 if (error)
1306 break;
1307 if (w->w_arg && w->w_arg != ifp->if_index)
1308 continue;
1309 ifnet_lock_shared(ifp);
1310 ifa = ifp->if_addrhead.tqh_first;
1311 ifpaddr = ifa->ifa_addr;
1312 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
1313 ifpaddr = 0;
1314 if (w->w_req && w->w_tmem) {
1315 struct if_msghdr *ifm;
1316
1317 ifm = (struct if_msghdr *)w->w_tmem;
1318 ifm->ifm_index = ifp->if_index;
1319 ifm->ifm_flags = (u_short)ifp->if_flags;
1320 if_data_internal_to_if_data(ifp, &ifp->if_data, &ifm->ifm_data);
1321 ifm->ifm_addrs = info.rti_addrs;
1322 error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
1323 if (error) {
1324 ifnet_lock_done(ifp);
1325 break;
1326 }
1327 }
1328 while ((ifa = ifa->ifa_link.tqe_next) != 0) {
1329 if (af && af != ifa->ifa_addr->sa_family)
1330 continue;
1331 ifaaddr = ifa->ifa_addr;
1332 netmask = ifa->ifa_netmask;
1333 brdaddr = ifa->ifa_dstaddr;
1334 len = rt_msg2(RTM_NEWADDR, &info, 0, w);
1335 if (w->w_req && w->w_tmem) {
1336 struct ifa_msghdr *ifam;
1337
1338 ifam = (struct ifa_msghdr *)w->w_tmem;
1339 ifam->ifam_index = ifa->ifa_ifp->if_index;
1340 ifam->ifam_flags = ifa->ifa_flags;
1341 ifam->ifam_metric = ifa->ifa_metric;
1342 ifam->ifam_addrs = info.rti_addrs;
1343 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1344 if (error)
1345 break;
1346 }
1347 }
1348 ifnet_lock_done(ifp);
1349 ifaaddr = netmask = brdaddr = 0;
1350 }
1351 ifnet_head_done();
1352 return error;
1353 }
1354
1355 int
1356 sysctl_iflist2(
1357 int af,
1358 struct walkarg *w)
1359 {
1360 struct ifnet *ifp;
1361 struct ifaddr *ifa;
1362 struct rt_addrinfo info;
1363 int len, error = 0;
1364
1365 bzero((caddr_t)&info, sizeof(info));
1366 ifnet_head_lock_shared();
1367 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1368 if (error)
1369 break;
1370 if (w->w_arg && w->w_arg != ifp->if_index)
1371 continue;
1372 ifnet_lock_shared(ifp);
1373 ifa = ifp->if_addrhead.tqh_first;
1374 ifpaddr = ifa->ifa_addr;
1375 len = rt_msg2(RTM_IFINFO2, &info, (caddr_t)0, w);
1376 ifpaddr = 0;
1377 if (w->w_req && w->w_tmem) {
1378 struct if_msghdr2 *ifm;
1379
1380 ifm = (struct if_msghdr2 *)w->w_tmem;
1381 ifm->ifm_addrs = info.rti_addrs;
1382 ifm->ifm_flags = (u_short)ifp->if_flags;
1383 ifm->ifm_index = ifp->if_index;
1384 ifm->ifm_snd_len = ifp->if_snd.ifq_len;
1385 ifm->ifm_snd_maxlen = ifp->if_snd.ifq_maxlen;
1386 ifm->ifm_snd_drops = ifp->if_snd.ifq_drops;
1387 ifm->ifm_timer = ifp->if_timer;
1388 if_data_internal_to_if_data64(ifp, &ifp->if_data, &ifm->ifm_data);
1389 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1390 if (error) {
1391 ifnet_lock_done(ifp);
1392 break;
1393 }
1394 }
1395 while ((ifa = ifa->ifa_link.tqe_next) != 0) {
1396 if (af && af != ifa->ifa_addr->sa_family)
1397 continue;
1398 ifaaddr = ifa->ifa_addr;
1399 netmask = ifa->ifa_netmask;
1400 brdaddr = ifa->ifa_dstaddr;
1401 len = rt_msg2(RTM_NEWADDR, &info, 0, w);
1402 if (w->w_req && w->w_tmem) {
1403 struct ifa_msghdr *ifam;
1404
1405 ifam = (struct ifa_msghdr *)w->w_tmem;
1406 ifam->ifam_index = ifa->ifa_ifp->if_index;
1407 ifam->ifam_flags = ifa->ifa_flags;
1408 ifam->ifam_metric = ifa->ifa_metric;
1409 ifam->ifam_addrs = info.rti_addrs;
1410 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1411 if (error)
1412 break;
1413 }
1414 }
1415 if (error) {
1416 ifnet_lock_done(ifp);
1417 break;
1418 }
1419 {
1420 struct ifmultiaddr *ifma;
1421
1422 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1423 ifma = ifma->ifma_link.le_next) {
1424 if (af && af != ifma->ifma_addr->sa_family)
1425 continue;
1426 bzero((caddr_t)&info, sizeof(info));
1427 ifaaddr = ifma->ifma_addr;
1428 if (ifp->if_addrhead.tqh_first)
1429 ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
1430 if (ifma->ifma_ll)
1431 gate = ifma->ifma_ll->ifma_addr;
1432 len = rt_msg2(RTM_NEWMADDR2, &info, 0, w);
1433 if (w->w_req && w->w_tmem) {
1434 struct ifma_msghdr2 *ifmam;
1435
1436 ifmam = (struct ifma_msghdr2 *)w->w_tmem;
1437 ifmam->ifmam_addrs = info.rti_addrs;
1438 ifmam->ifmam_flags = 0;
1439 ifmam->ifmam_index = ifma->ifma_ifp->if_index;
1440 ifmam->ifmam_refcount = ifma->ifma_refcount;
1441 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1442 if (error)
1443 break;
1444 }
1445 }
1446 }
1447 ifnet_lock_done(ifp);
1448 ifaaddr = netmask = brdaddr = 0;
1449 }
1450 ifnet_head_done();
1451 return error;
1452 }
1453
1454
1455 static int
1456 sysctl_rtstat(struct sysctl_req *req)
1457 {
1458 int error;
1459
1460 error = SYSCTL_OUT(req, &rtstat, sizeof(struct rtstat));
1461 if (error)
1462 return (error);
1463
1464 return 0;
1465 }
1466
1467 static int
1468 sysctl_rttrash(struct sysctl_req *req)
1469 {
1470 int error;
1471
1472 error = SYSCTL_OUT(req, &rttrash, sizeof(rttrash));
1473 if (error)
1474 return (error);
1475
1476 return 0;
1477 }
1478
1479 #if IFNET_ROUTE_REFCNT
1480 /*
1481 * Called from pfslowtimo(), protected by domain_proto_mtx
1482 */
1483 static void
1484 rt_drainall(void)
1485 {
1486 struct timeval delta_ts, current_ts;
1487
1488 /*
1489 * This test is done without holding rnh_lock; in the even that
1490 * we read stale value, it will only cause an extra (or miss)
1491 * drain and is therefore harmless.
1492 */
1493 if (ifnet_aggressive_drainers == 0) {
1494 if (timerisset(&last_ts))
1495 timerclear(&last_ts);
1496 return;
1497 }
1498
1499 microuptime(&current_ts);
1500 timersub(&current_ts, &last_ts, &delta_ts);
1501
1502 if (delta_ts.tv_sec >= rt_if_idle_drain_interval) {
1503 timerclear(&last_ts);
1504
1505 in_rtqdrain(); /* protocol cloned routes: INET */
1506 in6_rtqdrain(); /* protocol cloned routes: INET6 */
1507 in_arpdrain(NULL); /* cloned routes: ARP */
1508 nd6_drain(NULL); /* cloned routes: ND6 */
1509
1510 last_ts.tv_sec = current_ts.tv_sec;
1511 last_ts.tv_usec = current_ts.tv_usec;
1512 }
1513 }
1514
1515 void
1516 rt_aggdrain(int on)
1517 {
1518 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
1519
1520 if (on)
1521 routedomain.dom_protosw->pr_flags |= PR_AGGDRAIN;
1522 else
1523 routedomain.dom_protosw->pr_flags &= ~PR_AGGDRAIN;
1524 }
1525 #endif /* IFNET_ROUTE_REFCNT */
1526
1527 static int
1528 sysctl_rtsock SYSCTL_HANDLER_ARGS
1529 {
1530 #pragma unused(oidp)
1531 int *name = (int *)arg1;
1532 u_int namelen = arg2;
1533 struct radix_node_head *rnh;
1534 int i, error = EINVAL;
1535 u_char af;
1536 struct walkarg w;
1537
1538 name ++;
1539 namelen--;
1540 if (req->newptr)
1541 return (EPERM);
1542 if (namelen != 3)
1543 return (EINVAL);
1544 af = name[0];
1545 Bzero(&w, sizeof(w));
1546 w.w_op = name[1];
1547 w.w_arg = name[2];
1548 w.w_req = req;
1549
1550 switch (w.w_op) {
1551
1552 case NET_RT_DUMP:
1553 case NET_RT_DUMP2:
1554 case NET_RT_FLAGS:
1555 lck_mtx_lock(rnh_lock);
1556 for (i = 1; i <= AF_MAX; i++)
1557 if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
1558 (error = rnh->rnh_walktree(rnh,
1559 sysctl_dumpentry, &w)))
1560 break;
1561 lck_mtx_unlock(rnh_lock);
1562 break;
1563 case NET_RT_IFLIST:
1564 error = sysctl_iflist(af, &w);
1565 break;
1566 case NET_RT_IFLIST2:
1567 error = sysctl_iflist2(af, &w);
1568 break;
1569 case NET_RT_STAT:
1570 error = sysctl_rtstat(req);
1571 break;
1572 case NET_RT_TRASH:
1573 error = sysctl_rttrash(req);
1574 break;
1575 }
1576 if (w.w_tmem)
1577 FREE(w.w_tmem, M_RTABLE);
1578 return (error);
1579 }
1580
1581 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1582
1583 /*
1584 * Definitions of protocols supported in the ROUTE domain.
1585 */
1586 static struct protosw routesw[] = {
1587 { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
1588 0, route_output, raw_ctlinput, 0,
1589 0,
1590 raw_init, 0, 0,
1591 #if IFNET_ROUTE_REFCNT
1592 rt_drainall,
1593 #else
1594 0,
1595 #endif /* IFNET_ROUTE_REFCNT */
1596 0,
1597 &route_usrreqs,
1598 0, 0, 0,
1599 { 0, 0 }, 0, { 0 }
1600 }
1601 };
1602
1603 struct domain routedomain =
1604 { PF_ROUTE, "route", route_init, 0, 0,
1605 routesw,
1606 NULL, NULL, 0, 0, 0, 0, NULL, 0,
1607 { 0, 0 } };
1608
1609 DOMAIN_SET(route);
1610