rtsock.c revision 1.164.2.5 1 /* $NetBSD: rtsock.c,v 1.164.2.5 2016/03/19 11:30:32 skrll Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1988, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. 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.7 (Berkeley) 10/12/95
61 */
62
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.164.2.5 2016/03/19 11:30:32 skrll Exp $");
65
66 #ifdef _KERNEL_OPT
67 #include "opt_inet.h"
68 #include "opt_mpls.h"
69 #include "opt_compat_netbsd.h"
70 #include "opt_sctp.h"
71 #endif
72
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/proc.h>
76 #include <sys/socket.h>
77 #include <sys/socketvar.h>
78 #include <sys/domain.h>
79 #include <sys/protosw.h>
80 #include <sys/sysctl.h>
81 #include <sys/kauth.h>
82 #include <sys/kmem.h>
83 #include <sys/intr.h>
84 #ifdef RTSOCK_DEBUG
85 #include <netinet/in.h>
86 #endif /* RTSOCK_DEBUG */
87
88 #include <net/if.h>
89 #include <net/route.h>
90 #include <net/raw_cb.h>
91
92 #include <netmpls/mpls.h>
93
94 #ifdef SCTP
95 extern void sctp_add_ip_address(struct ifaddr *);
96 extern void sctp_delete_ip_address(struct ifaddr *);
97 #endif
98
99 #if defined(COMPAT_14) || defined(COMPAT_50)
100 #include <compat/net/if.h>
101 #include <compat/net/route.h>
102 #endif
103 #ifdef COMPAT_RTSOCK
104 #define RTM_XVERSION RTM_OVERSION
105 #define RT_XADVANCE(a,b) RT_OADVANCE(a,b)
106 #define RT_XROUNDUP(n) RT_OROUNDUP(n)
107 #define PF_XROUTE PF_OROUTE
108 #define rt_xmsghdr rt_msghdr50
109 #define if_xmsghdr if_msghdr /* if_msghdr50 is for RTM_OIFINFO */
110 #define ifa_xmsghdr ifa_msghdr50
111 #define if_xannouncemsghdr if_announcemsghdr50
112 #define COMPATNAME(x) compat_50_ ## x
113 #define DOMAINNAME "oroute"
114 CTASSERT(sizeof(struct ifa_xmsghdr) == 20);
115 DOMAIN_DEFINE(compat_50_routedomain); /* forward declare and add to link set */
116 #else /* COMPAT_RTSOCK */
117 #define RTM_XVERSION RTM_VERSION
118 #define RT_XADVANCE(a,b) RT_ADVANCE(a,b)
119 #define RT_XROUNDUP(n) RT_ROUNDUP(n)
120 #define PF_XROUTE PF_ROUTE
121 #define rt_xmsghdr rt_msghdr
122 #define if_xmsghdr if_msghdr
123 #define ifa_xmsghdr ifa_msghdr
124 #define if_xannouncemsghdr if_announcemsghdr
125 #define COMPATNAME(x) x
126 #define DOMAINNAME "route"
127 CTASSERT(sizeof(struct ifa_xmsghdr) == 24);
128 #ifdef COMPAT_50
129 #define COMPATCALL(name, args) compat_50_ ## name args
130 #endif
131 DOMAIN_DEFINE(routedomain); /* forward declare and add to link set */
132 #undef COMPAT_50
133 #undef COMPAT_14
134 #endif /* COMPAT_RTSOCK */
135
136 #ifndef COMPATCALL
137 #define COMPATCALL(name, args) do { } while (/*CONSTCOND*/ 0)
138 #endif
139
140 #ifdef RTSOCK_DEBUG
141 #define RT_IN_PRINT(b, a) (in_print((b), sizeof(b), \
142 &((const struct sockaddr_in *)info.rti_info[(a)])->sin_addr), (b))
143 #endif /* RTSOCK_DEBUG */
144
145 struct route_info COMPATNAME(route_info) = {
146 .ri_dst = { .sa_len = 2, .sa_family = PF_XROUTE, },
147 .ri_src = { .sa_len = 2, .sa_family = PF_XROUTE, },
148 .ri_maxqlen = IFQ_MAXLEN,
149 };
150
151 #define PRESERVED_RTF (RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_DONE | RTF_MASK)
152
153 static void COMPATNAME(route_init)(void);
154 static int COMPATNAME(route_output)(struct mbuf *, struct socket *);
155
156 static int rt_msg2(int, struct rt_addrinfo *, void *, struct rt_walkarg *, int *);
157 static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *);
158 static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int,
159 struct rt_addrinfo *);
160 static void rt_setmetrics(int, const struct rt_xmsghdr *, struct rtentry *);
161 static void rtm_setmetrics(const struct rtentry *, struct rt_xmsghdr *);
162 static void sysctl_net_route_setup(struct sysctllog **);
163 static int sysctl_dumpentry(struct rtentry *, void *);
164 static int sysctl_iflist(int, struct rt_walkarg *, int);
165 static int sysctl_rtable(SYSCTLFN_PROTO);
166 static void rt_adjustcount(int, int);
167
168 static const struct protosw COMPATNAME(route_protosw)[];
169
170 static void
171 rt_adjustcount(int af, int cnt)
172 {
173 struct route_cb * const cb = &COMPATNAME(route_info).ri_cb;
174
175 cb->any_count += cnt;
176
177 switch (af) {
178 case AF_INET:
179 cb->ip_count += cnt;
180 return;
181 #ifdef INET6
182 case AF_INET6:
183 cb->ip6_count += cnt;
184 return;
185 #endif
186 case AF_MPLS:
187 cb->mpls_count += cnt;
188 return;
189 }
190 }
191
192 static int
193 COMPATNAME(route_attach)(struct socket *so, int proto)
194 {
195 struct rawcb *rp;
196 int s, error;
197
198 KASSERT(sotorawcb(so) == NULL);
199 rp = kmem_zalloc(sizeof(*rp), KM_SLEEP);
200 rp->rcb_len = sizeof(*rp);
201 so->so_pcb = rp;
202
203 s = splsoftnet();
204 if ((error = raw_attach(so, proto)) == 0) {
205 rt_adjustcount(rp->rcb_proto.sp_protocol, 1);
206 rp->rcb_laddr = &COMPATNAME(route_info).ri_src;
207 rp->rcb_faddr = &COMPATNAME(route_info).ri_dst;
208 }
209 splx(s);
210
211 if (error) {
212 kmem_free(rp, sizeof(*rp));
213 so->so_pcb = NULL;
214 return error;
215 }
216
217 soisconnected(so);
218 so->so_options |= SO_USELOOPBACK;
219 KASSERT(solocked(so));
220
221 return error;
222 }
223
224 static void
225 COMPATNAME(route_detach)(struct socket *so)
226 {
227 struct rawcb *rp = sotorawcb(so);
228 int s;
229
230 KASSERT(rp != NULL);
231 KASSERT(solocked(so));
232
233 s = splsoftnet();
234 rt_adjustcount(rp->rcb_proto.sp_protocol, -1);
235 raw_detach(so);
236 splx(s);
237 }
238
239 static int
240 COMPATNAME(route_accept)(struct socket *so, struct sockaddr *nam)
241 {
242 KASSERT(solocked(so));
243
244 panic("route_accept");
245
246 return EOPNOTSUPP;
247 }
248
249 static int
250 COMPATNAME(route_bind)(struct socket *so, struct sockaddr *nam, struct lwp *l)
251 {
252 KASSERT(solocked(so));
253
254 return EOPNOTSUPP;
255 }
256
257 static int
258 COMPATNAME(route_listen)(struct socket *so, struct lwp *l)
259 {
260 KASSERT(solocked(so));
261
262 return EOPNOTSUPP;
263 }
264
265 static int
266 COMPATNAME(route_connect)(struct socket *so, struct sockaddr *nam, struct lwp *l)
267 {
268 KASSERT(solocked(so));
269
270 return EOPNOTSUPP;
271 }
272
273 static int
274 COMPATNAME(route_connect2)(struct socket *so, struct socket *so2)
275 {
276 KASSERT(solocked(so));
277
278 return EOPNOTSUPP;
279 }
280
281 static int
282 COMPATNAME(route_disconnect)(struct socket *so)
283 {
284 struct rawcb *rp = sotorawcb(so);
285 int s;
286
287 KASSERT(solocked(so));
288 KASSERT(rp != NULL);
289
290 s = splsoftnet();
291 soisdisconnected(so);
292 raw_disconnect(rp);
293 splx(s);
294
295 return 0;
296 }
297
298 static int
299 COMPATNAME(route_shutdown)(struct socket *so)
300 {
301 int s;
302
303 KASSERT(solocked(so));
304
305 /*
306 * Mark the connection as being incapable of further input.
307 */
308 s = splsoftnet();
309 socantsendmore(so);
310 splx(s);
311 return 0;
312 }
313
314 static int
315 COMPATNAME(route_abort)(struct socket *so)
316 {
317 KASSERT(solocked(so));
318
319 panic("route_abort");
320
321 return EOPNOTSUPP;
322 }
323
324 static int
325 COMPATNAME(route_ioctl)(struct socket *so, u_long cmd, void *nam,
326 struct ifnet * ifp)
327 {
328 return EOPNOTSUPP;
329 }
330
331 static int
332 COMPATNAME(route_stat)(struct socket *so, struct stat *ub)
333 {
334 KASSERT(solocked(so));
335
336 return 0;
337 }
338
339 static int
340 COMPATNAME(route_peeraddr)(struct socket *so, struct sockaddr *nam)
341 {
342 struct rawcb *rp = sotorawcb(so);
343
344 KASSERT(solocked(so));
345 KASSERT(rp != NULL);
346 KASSERT(nam != NULL);
347
348 if (rp->rcb_faddr == NULL)
349 return ENOTCONN;
350
351 raw_setpeeraddr(rp, nam);
352 return 0;
353 }
354
355 static int
356 COMPATNAME(route_sockaddr)(struct socket *so, struct sockaddr *nam)
357 {
358 struct rawcb *rp = sotorawcb(so);
359
360 KASSERT(solocked(so));
361 KASSERT(rp != NULL);
362 KASSERT(nam != NULL);
363
364 if (rp->rcb_faddr == NULL)
365 return ENOTCONN;
366
367 raw_setsockaddr(rp, nam);
368 return 0;
369 }
370
371 static int
372 COMPATNAME(route_rcvd)(struct socket *so, int flags, struct lwp *l)
373 {
374 KASSERT(solocked(so));
375
376 return EOPNOTSUPP;
377 }
378
379 static int
380 COMPATNAME(route_recvoob)(struct socket *so, struct mbuf *m, int flags)
381 {
382 KASSERT(solocked(so));
383
384 return EOPNOTSUPP;
385 }
386
387 static int
388 COMPATNAME(route_send)(struct socket *so, struct mbuf *m,
389 struct sockaddr *nam, struct mbuf *control, struct lwp *l)
390 {
391 int error = 0;
392 int s;
393
394 KASSERT(solocked(so));
395 KASSERT(so->so_proto == &COMPATNAME(route_protosw)[0]);
396
397 s = splsoftnet();
398 error = raw_send(so, m, nam, control, l, &COMPATNAME(route_output));
399 splx(s);
400
401 return error;
402 }
403
404 static int
405 COMPATNAME(route_sendoob)(struct socket *so, struct mbuf *m,
406 struct mbuf *control)
407 {
408 KASSERT(solocked(so));
409
410 m_freem(m);
411 m_freem(control);
412
413 return EOPNOTSUPP;
414 }
415 static int
416 COMPATNAME(route_purgeif)(struct socket *so, struct ifnet *ifp)
417 {
418
419 panic("route_purgeif");
420
421 return EOPNOTSUPP;
422 }
423
424 /*ARGSUSED*/
425 int
426 COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
427 {
428 struct sockproto proto = { .sp_family = PF_XROUTE, };
429 struct rt_xmsghdr *rtm = NULL;
430 struct rt_xmsghdr *old_rtm = NULL;
431 struct rtentry *rt = NULL;
432 struct rtentry *saved_nrt = NULL;
433 struct rt_addrinfo info;
434 int len, error = 0;
435 struct ifnet *ifp = NULL;
436 struct ifaddr *ifa = NULL;
437 sa_family_t family;
438
439 #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0)
440 if (m == NULL || ((m->m_len < sizeof(int32_t)) &&
441 (m = m_pullup(m, sizeof(int32_t))) == NULL))
442 return ENOBUFS;
443 if ((m->m_flags & M_PKTHDR) == 0)
444 panic("%s", __func__);
445 len = m->m_pkthdr.len;
446 if (len < sizeof(*rtm) ||
447 len != mtod(m, struct rt_xmsghdr *)->rtm_msglen) {
448 info.rti_info[RTAX_DST] = NULL;
449 senderr(EINVAL);
450 }
451 R_Malloc(rtm, struct rt_xmsghdr *, len);
452 if (rtm == NULL) {
453 info.rti_info[RTAX_DST] = NULL;
454 senderr(ENOBUFS);
455 }
456 m_copydata(m, 0, len, rtm);
457 if (rtm->rtm_version != RTM_XVERSION) {
458 info.rti_info[RTAX_DST] = NULL;
459 senderr(EPROTONOSUPPORT);
460 }
461 rtm->rtm_pid = curproc->p_pid;
462 memset(&info, 0, sizeof(info));
463 info.rti_addrs = rtm->rtm_addrs;
464 if (rt_xaddrs(rtm->rtm_type, (const char *)(rtm + 1), len + (char *)rtm,
465 &info)) {
466 senderr(EINVAL);
467 }
468 info.rti_flags = rtm->rtm_flags;
469 #ifdef RTSOCK_DEBUG
470 if (info.rti_info[RTAX_DST]->sa_family == AF_INET) {
471 char abuf[INET_ADDRSTRLEN];
472 printf("%s: extracted info.rti_info[RTAX_DST] %s\n", __func__,
473 RT_IN_PRINT(abuf, RTAX_DST));
474 }
475 #endif /* RTSOCK_DEBUG */
476 if (info.rti_info[RTAX_DST] == NULL ||
477 (info.rti_info[RTAX_DST]->sa_family >= AF_MAX)) {
478 senderr(EINVAL);
479 }
480 if (info.rti_info[RTAX_GATEWAY] != NULL &&
481 (info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) {
482 senderr(EINVAL);
483 }
484
485 /*
486 * Verify that the caller has the appropriate privilege; RTM_GET
487 * is the only operation the non-superuser is allowed.
488 */
489 if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_ROUTE,
490 0, rtm, NULL, NULL) != 0)
491 senderr(EACCES);
492
493 switch (rtm->rtm_type) {
494
495 case RTM_ADD:
496 if (info.rti_info[RTAX_GATEWAY] == NULL) {
497 senderr(EINVAL);
498 }
499 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
500 if (error == 0) {
501 rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt);
502 rtfree(saved_nrt);
503 }
504 break;
505
506 case RTM_DELETE:
507 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
508 if (error == 0) {
509 rt = saved_nrt;
510 goto report;
511 }
512 break;
513
514 case RTM_GET:
515 case RTM_CHANGE:
516 case RTM_LOCK:
517 /* XXX This will mask info.rti_info[RTAX_DST] with
518 * info.rti_info[RTAX_NETMASK] before
519 * searching. It did not used to do that. --dyoung
520 */
521 rt = NULL;
522 error = rtrequest1(RTM_GET, &info, &rt);
523 if (error != 0)
524 senderr(error);
525 if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
526 if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt),
527 info.rti_info[RTAX_DST]->sa_len) != 0)
528 senderr(ESRCH);
529 if (info.rti_info[RTAX_NETMASK] == NULL &&
530 rt_mask(rt) != NULL)
531 senderr(ETOOMANYREFS);
532 }
533
534 switch (rtm->rtm_type) {
535 case RTM_GET:
536 report:
537 info.rti_info[RTAX_DST] = rt_getkey(rt);
538 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
539 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
540 info.rti_info[RTAX_TAG] = rt_gettag(rt);
541 if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0)
542 ;
543 else if ((ifp = rt->rt_ifp) != NULL) {
544 const struct ifaddr *rtifa;
545 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr;
546 /* rtifa used to be simply rt->rt_ifa.
547 * If rt->rt_ifa != NULL, then
548 * rt_get_ifa() != NULL. So this
549 * ought to still be safe. --dyoung
550 */
551 rtifa = rt_get_ifa(rt);
552 info.rti_info[RTAX_IFA] = rtifa->ifa_addr;
553 #ifdef RTSOCK_DEBUG
554 if (info.rti_info[RTAX_IFA]->sa_family ==
555 AF_INET) {
556 char ibuf[INET_ADDRSTRLEN];
557 char abuf[INET_ADDRSTRLEN];
558 printf("%s: copying out RTAX_IFA %s "
559 "for info.rti_info[RTAX_DST] %s "
560 "ifa_getifa %p ifa_seqno %p\n",
561 __func__,
562 RT_IN_PRINT(ibuf, RTAX_IFA),
563 RT_IN_PRINT(abuf, RTAX_DST),
564 (void *)rtifa->ifa_getifa,
565 rtifa->ifa_seqno);
566 }
567 #endif /* RTSOCK_DEBUG */
568 if (ifp->if_flags & IFF_POINTOPOINT) {
569 info.rti_info[RTAX_BRD] =
570 rtifa->ifa_dstaddr;
571 } else
572 info.rti_info[RTAX_BRD] = NULL;
573 rtm->rtm_index = ifp->if_index;
574 } else {
575 info.rti_info[RTAX_IFP] = NULL;
576 info.rti_info[RTAX_IFA] = NULL;
577 }
578 (void)rt_msg2(rtm->rtm_type, &info, NULL, NULL, &len);
579 if (len > rtm->rtm_msglen) {
580 old_rtm = rtm;
581 R_Malloc(rtm, struct rt_xmsghdr *, len);
582 if (rtm == NULL)
583 senderr(ENOBUFS);
584 (void)memcpy(rtm, old_rtm, old_rtm->rtm_msglen);
585 }
586 (void)rt_msg2(rtm->rtm_type, &info, rtm, NULL, 0);
587 rtm->rtm_flags = rt->rt_flags;
588 rtm_setmetrics(rt, rtm);
589 rtm->rtm_addrs = info.rti_addrs;
590 break;
591
592 case RTM_CHANGE:
593 /*
594 * new gateway could require new ifaddr, ifp;
595 * flags may also be different; ifp may be specified
596 * by ll sockaddr when protocol address is ambiguous
597 */
598 if ((error = rt_getifa(&info)) != 0)
599 senderr(error);
600 if (info.rti_info[RTAX_GATEWAY] &&
601 rt_setgate(rt, info.rti_info[RTAX_GATEWAY]))
602 senderr(EDQUOT);
603 if (info.rti_info[RTAX_TAG])
604 rt_settag(rt, info.rti_info[RTAX_TAG]);
605 /* new gateway could require new ifaddr, ifp;
606 flags may also be different; ifp may be specified
607 by ll sockaddr when protocol address is ambiguous */
608 if (info.rti_info[RTAX_IFP] &&
609 (ifa = ifa_ifwithnet(info.rti_info[RTAX_IFP])) &&
610 (ifp = ifa->ifa_ifp) && (info.rti_info[RTAX_IFA] ||
611 info.rti_info[RTAX_GATEWAY])) {
612 if (info.rti_info[RTAX_IFA] == NULL ||
613 (ifa = ifa_ifwithaddr(
614 info.rti_info[RTAX_IFA])) == NULL)
615 ifa = ifaof_ifpforaddr(
616 info.rti_info[RTAX_IFA] ?
617 info.rti_info[RTAX_IFA] :
618 info.rti_info[RTAX_GATEWAY], ifp);
619 } else if ((info.rti_info[RTAX_IFA] &&
620 (ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]))) ||
621 (info.rti_info[RTAX_GATEWAY] &&
622 (ifa = ifa_ifwithroute(rt->rt_flags,
623 rt_getkey(rt), info.rti_info[RTAX_GATEWAY])))) {
624 ifp = ifa->ifa_ifp;
625 }
626 if (ifa) {
627 struct ifaddr *oifa = rt->rt_ifa;
628 if (oifa != ifa) {
629 if (oifa && oifa->ifa_rtrequest) {
630 oifa->ifa_rtrequest(RTM_DELETE,
631 rt, &info);
632 }
633 rt_replace_ifa(rt, ifa);
634 rt->rt_ifp = ifp;
635 }
636 }
637 if (ifp && rt->rt_ifp != ifp)
638 rt->rt_ifp = ifp;
639 rt_setmetrics(rtm->rtm_inits, rtm, rt);
640 if (rt->rt_flags != info.rti_flags)
641 rt->rt_flags = (info.rti_flags & ~PRESERVED_RTF)
642 | (rt->rt_flags & PRESERVED_RTF);
643 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
644 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
645 /*FALLTHROUGH*/
646 case RTM_LOCK:
647 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
648 rt->rt_rmx.rmx_locks |=
649 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
650 break;
651 }
652 break;
653
654 default:
655 senderr(EOPNOTSUPP);
656 }
657
658 flush:
659 if (rtm) {
660 if (error)
661 rtm->rtm_errno = error;
662 else
663 rtm->rtm_flags |= RTF_DONE;
664 }
665 family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family :
666 0;
667 /* We cannot free old_rtm until we have stopped using the
668 * pointers in info, some of which may point to sockaddrs
669 * in old_rtm.
670 */
671 if (old_rtm != NULL)
672 Free(old_rtm);
673 if (rt)
674 rtfree(rt);
675 {
676 struct rawcb *rp = NULL;
677 /*
678 * Check to see if we don't want our own messages.
679 */
680 if ((so->so_options & SO_USELOOPBACK) == 0) {
681 if (COMPATNAME(route_info).ri_cb.any_count <= 1) {
682 if (rtm)
683 Free(rtm);
684 m_freem(m);
685 return error;
686 }
687 /* There is another listener, so construct message */
688 rp = sotorawcb(so);
689 }
690 if (rtm) {
691 m_copyback(m, 0, rtm->rtm_msglen, rtm);
692 if (m->m_pkthdr.len < rtm->rtm_msglen) {
693 m_freem(m);
694 m = NULL;
695 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
696 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
697 Free(rtm);
698 }
699 if (rp)
700 rp->rcb_proto.sp_family = 0; /* Avoid us */
701 if (family)
702 proto.sp_protocol = family;
703 if (m)
704 raw_input(m, &proto, &COMPATNAME(route_info).ri_src,
705 &COMPATNAME(route_info).ri_dst);
706 if (rp)
707 rp->rcb_proto.sp_family = PF_XROUTE;
708 }
709 return error;
710 }
711
712 static void
713 rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out)
714 {
715 #define metric(f, e) if (which & (f)) out->rt_rmx.e = in->rtm_rmx.e;
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 #undef metric
724 if (which & RTV_EXPIRE) {
725 out->rt_rmx.rmx_expire = in->rtm_rmx.rmx_expire ?
726 time_wall_to_mono(in->rtm_rmx.rmx_expire) : 0;
727 }
728 }
729
730 static void
731 rtm_setmetrics(const struct rtentry *in, struct rt_xmsghdr *out)
732 {
733 #define metric(e) out->rtm_rmx.e = in->rt_rmx.e;
734 metric(rmx_recvpipe);
735 metric(rmx_sendpipe);
736 metric(rmx_ssthresh);
737 metric(rmx_rtt);
738 metric(rmx_rttvar);
739 metric(rmx_hopcount);
740 metric(rmx_mtu);
741 #undef metric
742 out->rtm_rmx.rmx_expire = in->rt_rmx.rmx_expire ?
743 time_mono_to_wall(in->rt_rmx.rmx_expire) : 0;
744 }
745
746 static int
747 rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim,
748 struct rt_addrinfo *rtinfo)
749 {
750 const struct sockaddr *sa = NULL; /* Quell compiler warning */
751 int i;
752
753 for (i = 0; i < RTAX_MAX && cp < cplim; i++) {
754 if ((rtinfo->rti_addrs & (1 << i)) == 0)
755 continue;
756 rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp;
757 RT_XADVANCE(cp, sa);
758 }
759
760 /*
761 * Check for extra addresses specified, except RTM_GET asking
762 * for interface info.
763 */
764 if (rtmtype == RTM_GET) {
765 if (((rtinfo->rti_addrs &
766 (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0)
767 return 1;
768 } else if ((rtinfo->rti_addrs & (~0 << i)) != 0)
769 return 1;
770 /* Check for bad data length. */
771 if (cp != cplim) {
772 if (i == RTAX_NETMASK + 1 && sa != NULL &&
773 cp - RT_XROUNDUP(sa->sa_len) + sa->sa_len == cplim)
774 /*
775 * The last sockaddr was info.rti_info[RTAX_NETMASK].
776 * We accept this for now for the sake of old
777 * binaries or third party softwares.
778 */
779 ;
780 else
781 return 1;
782 }
783 return 0;
784 }
785
786 static int
787 rt_getlen(int type)
788 {
789 #ifndef COMPAT_RTSOCK
790 CTASSERT(__alignof(struct ifa_msghdr) >= sizeof(uint64_t));
791 CTASSERT(__alignof(struct if_msghdr) >= sizeof(uint64_t));
792 CTASSERT(__alignof(struct if_announcemsghdr) >= sizeof(uint64_t));
793 CTASSERT(__alignof(struct rt_msghdr) >= sizeof(uint64_t));
794 #endif
795
796 switch (type) {
797 case RTM_DELADDR:
798 case RTM_NEWADDR:
799 case RTM_CHGADDR:
800 return sizeof(struct ifa_xmsghdr);
801
802 case RTM_OOIFINFO:
803 #ifdef COMPAT_14
804 return sizeof(struct if_msghdr14);
805 #else
806 #ifdef DIAGNOSTIC
807 printf("RTM_OOIFINFO\n");
808 #endif
809 return -1;
810 #endif
811 case RTM_OIFINFO:
812 #ifdef COMPAT_50
813 return sizeof(struct if_msghdr50);
814 #else
815 #ifdef DIAGNOSTIC
816 printf("RTM_OIFINFO\n");
817 #endif
818 return -1;
819 #endif
820
821 case RTM_IFINFO:
822 return sizeof(struct if_xmsghdr);
823
824 case RTM_IFANNOUNCE:
825 case RTM_IEEE80211:
826 return sizeof(struct if_xannouncemsghdr);
827
828 default:
829 return sizeof(struct rt_xmsghdr);
830 }
831 }
832
833
834 struct mbuf *
835 COMPATNAME(rt_msg1)(int type, struct rt_addrinfo *rtinfo, void *data, int datalen)
836 {
837 struct rt_xmsghdr *rtm;
838 struct mbuf *m;
839 int i;
840 const struct sockaddr *sa;
841 int len, dlen;
842
843 m = m_gethdr(M_DONTWAIT, MT_DATA);
844 if (m == NULL)
845 return m;
846 MCLAIM(m, &COMPATNAME(routedomain).dom_mowner);
847
848 if ((len = rt_getlen(type)) == -1)
849 goto out;
850 if (len > MHLEN + MLEN)
851 panic("%s: message too long", __func__);
852 else if (len > MHLEN) {
853 m->m_next = m_get(M_DONTWAIT, MT_DATA);
854 if (m->m_next == NULL)
855 goto out;
856 MCLAIM(m->m_next, m->m_owner);
857 m->m_pkthdr.len = len;
858 m->m_len = MHLEN;
859 m->m_next->m_len = len - MHLEN;
860 } else {
861 m->m_pkthdr.len = m->m_len = len;
862 }
863 m->m_pkthdr.rcvif = NULL;
864 m_copyback(m, 0, datalen, data);
865 if (len > datalen)
866 (void)memset(mtod(m, char *) + datalen, 0, len - datalen);
867 rtm = mtod(m, struct rt_xmsghdr *);
868 for (i = 0; i < RTAX_MAX; i++) {
869 if ((sa = rtinfo->rti_info[i]) == NULL)
870 continue;
871 rtinfo->rti_addrs |= (1 << i);
872 dlen = RT_XROUNDUP(sa->sa_len);
873 m_copyback(m, len, sa->sa_len, sa);
874 if (dlen != sa->sa_len) {
875 /*
876 * Up to 6 + 1 nul's since roundup is to
877 * sizeof(uint64_t) (8 bytes)
878 */
879 m_copyback(m, len + sa->sa_len,
880 dlen - sa->sa_len, "\0\0\0\0\0\0");
881 }
882 len += dlen;
883 }
884 if (m->m_pkthdr.len != len)
885 goto out;
886 rtm->rtm_msglen = len;
887 rtm->rtm_version = RTM_XVERSION;
888 rtm->rtm_type = type;
889 return m;
890 out:
891 m_freem(m);
892 return NULL;
893 }
894
895 /*
896 * rt_msg2
897 *
898 * fills 'cp' or 'w'.w_tmem with the routing socket message and
899 * returns the length of the message in 'lenp'.
900 *
901 * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold
902 * the message
903 * otherwise walkarg's w_needed is updated and if the user buffer is
904 * specified and w_needed indicates space exists the information is copied
905 * into the temp space (w_tmem). w_tmem is [re]allocated if necessary,
906 * if the allocation fails ENOBUFS is returned.
907 */
908 static int
909 rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w,
910 int *lenp)
911 {
912 int i;
913 int len, dlen, second_time = 0;
914 char *cp0, *cp = cpv;
915
916 rtinfo->rti_addrs = 0;
917 again:
918 if ((len = rt_getlen(type)) == -1)
919 return EINVAL;
920
921 if ((cp0 = cp) != NULL)
922 cp += len;
923 for (i = 0; i < RTAX_MAX; i++) {
924 const struct sockaddr *sa;
925
926 if ((sa = rtinfo->rti_info[i]) == NULL)
927 continue;
928 rtinfo->rti_addrs |= (1 << i);
929 dlen = RT_XROUNDUP(sa->sa_len);
930 if (cp) {
931 int diff = dlen - sa->sa_len;
932 (void)memcpy(cp, sa, (size_t)sa->sa_len);
933 cp += sa->sa_len;
934 if (diff > 0) {
935 (void)memset(cp, 0, (size_t)diff);
936 cp += diff;
937 }
938 }
939 len += dlen;
940 }
941 if (cp == NULL && w != NULL && !second_time) {
942 struct rt_walkarg *rw = w;
943
944 rw->w_needed += len;
945 if (rw->w_needed <= 0 && rw->w_where) {
946 if (rw->w_tmemsize < len) {
947 if (rw->w_tmem)
948 free(rw->w_tmem, M_RTABLE);
949 rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT);
950 if (rw->w_tmem)
951 rw->w_tmemsize = len;
952 else
953 rw->w_tmemsize = 0;
954 }
955 if (rw->w_tmem) {
956 cp = rw->w_tmem;
957 second_time = 1;
958 goto again;
959 } else {
960 rw->w_tmemneeded = len;
961 return ENOBUFS;
962 }
963 }
964 }
965 if (cp) {
966 struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)cp0;
967
968 rtm->rtm_version = RTM_XVERSION;
969 rtm->rtm_type = type;
970 rtm->rtm_msglen = len;
971 }
972 if (lenp)
973 *lenp = len;
974 return 0;
975 }
976
977 /*
978 * This routine is called to generate a message from the routing
979 * socket indicating that a redirect has occurred, a routing lookup
980 * has failed, or that a protocol has detected timeouts to a particular
981 * destination.
982 */
983 void
984 COMPATNAME(rt_missmsg)(int type, const struct rt_addrinfo *rtinfo, int flags,
985 int error)
986 {
987 struct rt_xmsghdr rtm;
988 struct mbuf *m;
989 const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
990 struct rt_addrinfo info = *rtinfo;
991
992 COMPATCALL(rt_missmsg, (type, rtinfo, flags, error));
993 if (COMPATNAME(route_info).ri_cb.any_count == 0)
994 return;
995 memset(&rtm, 0, sizeof(rtm));
996 rtm.rtm_flags = RTF_DONE | flags;
997 rtm.rtm_errno = error;
998 m = COMPATNAME(rt_msg1)(type, &info, &rtm, sizeof(rtm));
999 if (m == NULL)
1000 return;
1001 mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs;
1002 COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0);
1003 }
1004
1005 /*
1006 * This routine is called to generate a message from the routing
1007 * socket indicating that the status of a network interface has changed.
1008 */
1009 void
1010 COMPATNAME(rt_ifmsg)(struct ifnet *ifp)
1011 {
1012 struct if_xmsghdr ifm;
1013 struct mbuf *m;
1014 struct rt_addrinfo info;
1015
1016 COMPATCALL(rt_ifmsg, (ifp));
1017 if (COMPATNAME(route_info).ri_cb.any_count == 0)
1018 return;
1019 (void)memset(&info, 0, sizeof(info));
1020 (void)memset(&ifm, 0, sizeof(ifm));
1021 ifm.ifm_index = ifp->if_index;
1022 ifm.ifm_flags = ifp->if_flags;
1023 ifm.ifm_data = ifp->if_data;
1024 ifm.ifm_addrs = 0;
1025 m = COMPATNAME(rt_msg1)(RTM_IFINFO, &info, &ifm, sizeof(ifm));
1026 if (m == NULL)
1027 return;
1028 COMPATNAME(route_enqueue)(m, 0);
1029 #ifdef COMPAT_14
1030 compat_14_rt_oifmsg(ifp);
1031 #endif
1032 #ifdef COMPAT_50
1033 compat_50_rt_oifmsg(ifp);
1034 #endif
1035 }
1036
1037
1038 /*
1039 * This is called to generate messages from the routing socket
1040 * indicating a network interface has had addresses associated with it.
1041 * if we ever reverse the logic and replace messages TO the routing
1042 * socket indicate a request to configure interfaces, then it will
1043 * be unnecessary as the routing socket will automatically generate
1044 * copies of it.
1045 */
1046 void
1047 COMPATNAME(rt_newaddrmsg)(int cmd, struct ifaddr *ifa, int error,
1048 struct rtentry *rt)
1049 {
1050 #define cmdpass(__cmd, __pass) (((__cmd) << 2) | (__pass))
1051 struct rt_addrinfo info;
1052 const struct sockaddr *sa;
1053 int pass;
1054 struct mbuf *m;
1055 struct ifnet *ifp;
1056 struct rt_xmsghdr rtm;
1057 struct ifa_xmsghdr ifam;
1058 int ncmd;
1059
1060 KASSERT(ifa != NULL);
1061 ifp = ifa->ifa_ifp;
1062 #ifdef SCTP
1063 if (cmd == RTM_ADD) {
1064 sctp_add_ip_address(ifa);
1065 } else if (cmd == RTM_DELETE) {
1066 sctp_delete_ip_address(ifa);
1067 }
1068 #endif
1069
1070 COMPATCALL(rt_newaddrmsg, (cmd, ifa, error, rt));
1071 if (COMPATNAME(route_info).ri_cb.any_count == 0)
1072 return;
1073 for (pass = 1; pass < 3; pass++) {
1074 memset(&info, 0, sizeof(info));
1075 switch (cmdpass(cmd, pass)) {
1076 case cmdpass(RTM_ADD, 1):
1077 case cmdpass(RTM_CHANGE, 1):
1078 case cmdpass(RTM_DELETE, 2):
1079 case cmdpass(RTM_NEWADDR, 1):
1080 case cmdpass(RTM_DELADDR, 1):
1081 case cmdpass(RTM_CHGADDR, 1):
1082 switch (cmd) {
1083 case RTM_ADD:
1084 ncmd = RTM_NEWADDR;
1085 break;
1086 case RTM_DELETE:
1087 ncmd = RTM_DELADDR;
1088 break;
1089 case RTM_CHANGE:
1090 ncmd = RTM_CHGADDR;
1091 break;
1092 default:
1093 ncmd = cmd;
1094 }
1095 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr;
1096 KASSERT(ifp->if_dl != NULL);
1097 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr;
1098 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1099 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
1100 memset(&ifam, 0, sizeof(ifam));
1101 ifam.ifam_index = ifp->if_index;
1102 ifam.ifam_metric = ifa->ifa_metric;
1103 ifam.ifam_flags = ifa->ifa_flags;
1104 m = COMPATNAME(rt_msg1)(ncmd, &info, &ifam, sizeof(ifam));
1105 if (m == NULL)
1106 continue;
1107 mtod(m, struct ifa_xmsghdr *)->ifam_addrs =
1108 info.rti_addrs;
1109 break;
1110 case cmdpass(RTM_ADD, 2):
1111 case cmdpass(RTM_CHANGE, 2):
1112 case cmdpass(RTM_DELETE, 1):
1113 if (rt == NULL)
1114 continue;
1115 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1116 info.rti_info[RTAX_DST] = sa = rt_getkey(rt);
1117 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1118 memset(&rtm, 0, sizeof(rtm));
1119 rtm.rtm_index = ifp->if_index;
1120 rtm.rtm_flags |= rt->rt_flags;
1121 rtm.rtm_errno = error;
1122 m = COMPATNAME(rt_msg1)(cmd, &info, &rtm, sizeof(rtm));
1123 if (m == NULL)
1124 continue;
1125 mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs;
1126 break;
1127 default:
1128 continue;
1129 }
1130 #ifdef DIAGNOSTIC
1131 if (m == NULL)
1132 panic("%s: called with wrong command", __func__);
1133 #endif
1134 COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0);
1135 }
1136 #undef cmdpass
1137 }
1138
1139 static struct mbuf *
1140 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
1141 struct rt_addrinfo *info)
1142 {
1143 struct if_xannouncemsghdr ifan;
1144
1145 memset(info, 0, sizeof(*info));
1146 memset(&ifan, 0, sizeof(ifan));
1147 ifan.ifan_index = ifp->if_index;
1148 strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name));
1149 ifan.ifan_what = what;
1150 return COMPATNAME(rt_msg1)(type, info, &ifan, sizeof(ifan));
1151 }
1152
1153 /*
1154 * This is called to generate routing socket messages indicating
1155 * network interface arrival and departure.
1156 */
1157 void
1158 COMPATNAME(rt_ifannouncemsg)(struct ifnet *ifp, int what)
1159 {
1160 struct mbuf *m;
1161 struct rt_addrinfo info;
1162
1163 COMPATCALL(rt_ifannouncemsg, (ifp, what));
1164 if (COMPATNAME(route_info).ri_cb.any_count == 0)
1165 return;
1166 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info);
1167 if (m == NULL)
1168 return;
1169 COMPATNAME(route_enqueue)(m, 0);
1170 }
1171
1172 /*
1173 * This is called to generate routing socket messages indicating
1174 * IEEE80211 wireless events.
1175 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
1176 */
1177 void
1178 COMPATNAME(rt_ieee80211msg)(struct ifnet *ifp, int what, void *data,
1179 size_t data_len)
1180 {
1181 struct mbuf *m;
1182 struct rt_addrinfo info;
1183
1184 COMPATCALL(rt_ieee80211msg, (ifp, what, data, data_len));
1185 if (COMPATNAME(route_info).ri_cb.any_count == 0)
1186 return;
1187 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
1188 if (m == NULL)
1189 return;
1190 /*
1191 * Append the ieee80211 data. Try to stick it in the
1192 * mbuf containing the ifannounce msg; otherwise allocate
1193 * a new mbuf and append.
1194 *
1195 * NB: we assume m is a single mbuf.
1196 */
1197 if (data_len > M_TRAILINGSPACE(m)) {
1198 struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
1199 if (n == NULL) {
1200 m_freem(m);
1201 return;
1202 }
1203 (void)memcpy(mtod(n, void *), data, data_len);
1204 n->m_len = data_len;
1205 m->m_next = n;
1206 } else if (data_len > 0) {
1207 (void)memcpy(mtod(m, uint8_t *) + m->m_len, data, data_len);
1208 m->m_len += data_len;
1209 }
1210 if (m->m_flags & M_PKTHDR)
1211 m->m_pkthdr.len += data_len;
1212 mtod(m, struct if_xannouncemsghdr *)->ifan_msglen += data_len;
1213 COMPATNAME(route_enqueue)(m, 0);
1214 }
1215
1216 /*
1217 * This is used in dumping the kernel table via sysctl().
1218 */
1219 static int
1220 sysctl_dumpentry(struct rtentry *rt, void *v)
1221 {
1222 struct rt_walkarg *w = v;
1223 int error = 0, size;
1224 struct rt_addrinfo info;
1225
1226 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1227 return 0;
1228 memset(&info, 0, sizeof(info));
1229 info.rti_info[RTAX_DST] = rt_getkey(rt);
1230 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
1231 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
1232 info.rti_info[RTAX_TAG] = rt_gettag(rt);
1233 if (rt->rt_ifp) {
1234 const struct ifaddr *rtifa;
1235 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr;
1236 /* rtifa used to be simply rt->rt_ifa. If rt->rt_ifa != NULL,
1237 * then rt_get_ifa() != NULL. So this ought to still be safe.
1238 * --dyoung
1239 */
1240 rtifa = rt_get_ifa(rt);
1241 info.rti_info[RTAX_IFA] = rtifa->ifa_addr;
1242 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1243 info.rti_info[RTAX_BRD] = rtifa->ifa_dstaddr;
1244 }
1245 if ((error = rt_msg2(RTM_GET, &info, 0, w, &size)))
1246 return error;
1247 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
1248 struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)w->w_tmem;
1249
1250 rtm->rtm_flags = rt->rt_flags;
1251 rtm->rtm_use = rt->rt_use;
1252 rtm_setmetrics(rt, rtm);
1253 KASSERT(rt->rt_ifp != NULL);
1254 rtm->rtm_index = rt->rt_ifp->if_index;
1255 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1256 rtm->rtm_addrs = info.rti_addrs;
1257 if ((error = copyout(rtm, w->w_where, size)) != 0)
1258 w->w_where = NULL;
1259 else
1260 w->w_where = (char *)w->w_where + size;
1261 }
1262 return error;
1263 }
1264
1265 static int
1266 sysctl_iflist(int af, struct rt_walkarg *w, int type)
1267 {
1268 struct ifnet *ifp;
1269 struct ifaddr *ifa;
1270 struct rt_addrinfo info;
1271 int len, error = 0;
1272
1273 memset(&info, 0, sizeof(info));
1274 IFNET_FOREACH(ifp) {
1275 if (w->w_arg && w->w_arg != ifp->if_index)
1276 continue;
1277 if (IFADDR_EMPTY(ifp))
1278 continue;
1279 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr;
1280 switch (type) {
1281 case NET_RT_IFLIST:
1282 error = rt_msg2(RTM_IFINFO, &info, NULL, w, &len);
1283 break;
1284 #ifdef COMPAT_14
1285 case NET_RT_OOIFLIST:
1286 error = rt_msg2(RTM_OOIFINFO, &info, NULL, w, &len);
1287 break;
1288 #endif
1289 #ifdef COMPAT_50
1290 case NET_RT_OIFLIST:
1291 error = rt_msg2(RTM_OIFINFO, &info, NULL, w, &len);
1292 break;
1293 #endif
1294 default:
1295 panic("sysctl_iflist(1)");
1296 }
1297 if (error)
1298 return error;
1299 info.rti_info[RTAX_IFP] = NULL;
1300 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
1301 switch (type) {
1302 case NET_RT_IFLIST: {
1303 struct if_xmsghdr *ifm;
1304
1305 ifm = (struct if_xmsghdr *)w->w_tmem;
1306 ifm->ifm_index = ifp->if_index;
1307 ifm->ifm_flags = ifp->if_flags;
1308 ifm->ifm_data = ifp->if_data;
1309 ifm->ifm_addrs = info.rti_addrs;
1310 error = copyout(ifm, w->w_where, len);
1311 if (error)
1312 return error;
1313 w->w_where = (char *)w->w_where + len;
1314 break;
1315 }
1316
1317 #ifdef COMPAT_14
1318 case NET_RT_OOIFLIST:
1319 error = compat_14_iflist(ifp, w, &info, len);
1320 if (error)
1321 return error;
1322 break;
1323 #endif
1324 #ifdef COMPAT_50
1325 case NET_RT_OIFLIST:
1326 error = compat_50_iflist(ifp, w, &info, len);
1327 if (error)
1328 return error;
1329 break;
1330 #endif
1331 default:
1332 panic("sysctl_iflist(2)");
1333 }
1334 }
1335 IFADDR_FOREACH(ifa, ifp) {
1336 if (af && af != ifa->ifa_addr->sa_family)
1337 continue;
1338 info.rti_info[RTAX_IFA] = ifa->ifa_addr;
1339 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
1340 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
1341 if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len)))
1342 return error;
1343 if (w->w_where && w->w_tmem && w->w_needed <= 0) {
1344 struct ifa_xmsghdr *ifam;
1345
1346 ifam = (struct ifa_xmsghdr *)w->w_tmem;
1347 ifam->ifam_index = ifa->ifa_ifp->if_index;
1348 ifam->ifam_flags = ifa->ifa_flags;
1349 ifam->ifam_metric = ifa->ifa_metric;
1350 ifam->ifam_addrs = info.rti_addrs;
1351 error = copyout(w->w_tmem, w->w_where, len);
1352 if (error)
1353 return error;
1354 w->w_where = (char *)w->w_where + len;
1355 }
1356 }
1357 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] =
1358 info.rti_info[RTAX_BRD] = NULL;
1359 }
1360 return 0;
1361 }
1362
1363 static int
1364 sysctl_rtable(SYSCTLFN_ARGS)
1365 {
1366 void *where = oldp;
1367 size_t *given = oldlenp;
1368 int i, s, error = EINVAL;
1369 u_char af;
1370 struct rt_walkarg w;
1371
1372 if (namelen == 1 && name[0] == CTL_QUERY)
1373 return sysctl_query(SYSCTLFN_CALL(rnode));
1374
1375 if (newp)
1376 return EPERM;
1377 if (namelen != 3)
1378 return EINVAL;
1379 af = name[0];
1380 w.w_tmemneeded = 0;
1381 w.w_tmemsize = 0;
1382 w.w_tmem = NULL;
1383 again:
1384 /* we may return here if a later [re]alloc of the t_mem buffer fails */
1385 if (w.w_tmemneeded) {
1386 w.w_tmem = malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK);
1387 w.w_tmemsize = w.w_tmemneeded;
1388 w.w_tmemneeded = 0;
1389 }
1390 w.w_op = name[1];
1391 w.w_arg = name[2];
1392 w.w_given = *given;
1393 w.w_needed = 0 - w.w_given;
1394 w.w_where = where;
1395
1396 s = splsoftnet();
1397 switch (w.w_op) {
1398
1399 case NET_RT_DUMP:
1400 case NET_RT_FLAGS:
1401 for (i = 1; i <= AF_MAX; i++)
1402 if ((af == 0 || af == i) &&
1403 (error = rt_walktree(i, sysctl_dumpentry, &w)))
1404 break;
1405 break;
1406
1407 #ifdef COMPAT_14
1408 case NET_RT_OOIFLIST:
1409 error = sysctl_iflist(af, &w, w.w_op);
1410 break;
1411 #endif
1412 #ifdef COMPAT_50
1413 case NET_RT_OIFLIST:
1414 error = sysctl_iflist(af, &w, w.w_op);
1415 break;
1416 #endif
1417 case NET_RT_IFLIST:
1418 error = sysctl_iflist(af, &w, w.w_op);
1419 break;
1420 }
1421 splx(s);
1422
1423 /* check to see if we couldn't allocate memory with NOWAIT */
1424 if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded)
1425 goto again;
1426
1427 if (w.w_tmem)
1428 free(w.w_tmem, M_RTABLE);
1429 w.w_needed += w.w_given;
1430 if (where) {
1431 *given = (char *)w.w_where - (char *)where;
1432 if (*given < w.w_needed)
1433 return ENOMEM;
1434 } else {
1435 *given = (11 * w.w_needed) / 10;
1436 }
1437 return error;
1438 }
1439
1440 /*
1441 * Routing message software interrupt routine
1442 */
1443 static void
1444 COMPATNAME(route_intr)(void *cookie)
1445 {
1446 struct sockproto proto = { .sp_family = PF_XROUTE, };
1447 struct route_info * const ri = &COMPATNAME(route_info);
1448 struct mbuf *m;
1449 int s;
1450
1451 mutex_enter(softnet_lock);
1452 KERNEL_LOCK(1, NULL);
1453 while (!IF_IS_EMPTY(&ri->ri_intrq)) {
1454 s = splnet();
1455 IF_DEQUEUE(&ri->ri_intrq, m);
1456 splx(s);
1457 if (m == NULL)
1458 break;
1459 proto.sp_protocol = M_GETCTX(m, uintptr_t);
1460 raw_input(m, &proto, &ri->ri_src, &ri->ri_dst);
1461 }
1462 KERNEL_UNLOCK_ONE(NULL);
1463 mutex_exit(softnet_lock);
1464 }
1465
1466 /*
1467 * Enqueue a message to the software interrupt routine.
1468 */
1469 void
1470 COMPATNAME(route_enqueue)(struct mbuf *m, int family)
1471 {
1472 struct route_info * const ri = &COMPATNAME(route_info);
1473 int s, wasempty;
1474
1475 s = splnet();
1476 if (IF_QFULL(&ri->ri_intrq)) {
1477 IF_DROP(&ri->ri_intrq);
1478 m_freem(m);
1479 } else {
1480 wasempty = IF_IS_EMPTY(&ri->ri_intrq);
1481 M_SETCTX(m, (uintptr_t)family);
1482 IF_ENQUEUE(&ri->ri_intrq, m);
1483 if (wasempty)
1484 softint_schedule(ri->ri_sih);
1485 }
1486 splx(s);
1487 }
1488
1489 static void
1490 COMPATNAME(route_init)(void)
1491 {
1492 struct route_info * const ri = &COMPATNAME(route_info);
1493
1494 #ifndef COMPAT_RTSOCK
1495 rt_init();
1496 #endif
1497
1498 sysctl_net_route_setup(NULL);
1499 ri->ri_intrq.ifq_maxlen = ri->ri_maxqlen;
1500 ri->ri_sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE,
1501 COMPATNAME(route_intr), NULL);
1502 }
1503
1504 /*
1505 * Definitions of protocols supported in the ROUTE domain.
1506 */
1507 #ifndef COMPAT_RTSOCK
1508 PR_WRAP_USRREQS(route);
1509 #else
1510 PR_WRAP_USRREQS(compat_50_route);
1511 #endif
1512
1513 static const struct pr_usrreqs route_usrreqs = {
1514 .pr_attach = COMPATNAME(route_attach_wrapper),
1515 .pr_detach = COMPATNAME(route_detach_wrapper),
1516 .pr_accept = COMPATNAME(route_accept_wrapper),
1517 .pr_bind = COMPATNAME(route_bind_wrapper),
1518 .pr_listen = COMPATNAME(route_listen_wrapper),
1519 .pr_connect = COMPATNAME(route_connect_wrapper),
1520 .pr_connect2 = COMPATNAME(route_connect2_wrapper),
1521 .pr_disconnect = COMPATNAME(route_disconnect_wrapper),
1522 .pr_shutdown = COMPATNAME(route_shutdown_wrapper),
1523 .pr_abort = COMPATNAME(route_abort_wrapper),
1524 .pr_ioctl = COMPATNAME(route_ioctl_wrapper),
1525 .pr_stat = COMPATNAME(route_stat_wrapper),
1526 .pr_peeraddr = COMPATNAME(route_peeraddr_wrapper),
1527 .pr_sockaddr = COMPATNAME(route_sockaddr_wrapper),
1528 .pr_rcvd = COMPATNAME(route_rcvd_wrapper),
1529 .pr_recvoob = COMPATNAME(route_recvoob_wrapper),
1530 .pr_send = COMPATNAME(route_send_wrapper),
1531 .pr_sendoob = COMPATNAME(route_sendoob_wrapper),
1532 .pr_purgeif = COMPATNAME(route_purgeif_wrapper),
1533 };
1534
1535 static const struct protosw COMPATNAME(route_protosw)[] = {
1536 {
1537 .pr_type = SOCK_RAW,
1538 .pr_domain = &COMPATNAME(routedomain),
1539 .pr_flags = PR_ATOMIC|PR_ADDR,
1540 .pr_input = raw_input,
1541 .pr_ctlinput = raw_ctlinput,
1542 .pr_usrreqs = &route_usrreqs,
1543 .pr_init = raw_init,
1544 },
1545 };
1546
1547 struct domain COMPATNAME(routedomain) = {
1548 .dom_family = PF_XROUTE,
1549 .dom_name = DOMAINNAME,
1550 .dom_init = COMPATNAME(route_init),
1551 .dom_protosw = COMPATNAME(route_protosw),
1552 .dom_protoswNPROTOSW =
1553 &COMPATNAME(route_protosw)[__arraycount(COMPATNAME(route_protosw))],
1554 };
1555
1556 static void
1557 sysctl_net_route_setup(struct sysctllog **clog)
1558 {
1559 const struct sysctlnode *rnode = NULL;
1560
1561 sysctl_createv(clog, 0, NULL, &rnode,
1562 CTLFLAG_PERMANENT,
1563 CTLTYPE_NODE, DOMAINNAME,
1564 SYSCTL_DESCR("PF_ROUTE information"),
1565 NULL, 0, NULL, 0,
1566 CTL_NET, PF_XROUTE, CTL_EOL);
1567
1568 sysctl_createv(clog, 0, NULL, NULL,
1569 CTLFLAG_PERMANENT,
1570 CTLTYPE_NODE, "rtable",
1571 SYSCTL_DESCR("Routing table information"),
1572 sysctl_rtable, 0, NULL, 0,
1573 CTL_NET, PF_XROUTE, 0 /* any protocol */, CTL_EOL);
1574
1575 sysctl_createv(clog, 0, &rnode, NULL,
1576 CTLFLAG_PERMANENT,
1577 CTLTYPE_STRUCT, "stats",
1578 SYSCTL_DESCR("Routing statistics"),
1579 NULL, 0, &rtstat, sizeof(rtstat),
1580 CTL_CREATE, CTL_EOL);
1581 }
1582