2 * Copyright (c) 2004, 2005 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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 DragonFly Project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific, prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright (c) 1988, 1991, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)rtsock.c 8.7 (Berkeley) 10/12/95
62 * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/sysctl.h>
71 #include <sys/malloc.h>
73 #include <sys/protosw.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/domain.h>
79 #include <sys/thread2.h>
80 #include <sys/socketvar2.h>
83 #include <net/if_var.h>
84 #include <net/route.h>
85 #include <net/raw_cb.h>
86 #include <net/netmsg2.h>
87 #include <net/netisr2.h>
89 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
91 static struct route_cb {
98 static const struct sockaddr route_src = { 2, PF_ROUTE, };
104 struct sysctl_req *w_req;
107 #ifndef RTTABLE_DUMP_MSGCNT_MAX
108 /* Should be large enough for dupkeys */
109 #define RTTABLE_DUMP_MSGCNT_MAX 64
112 struct rttable_walkarg {
123 struct sockaddr_storage w_key0;
124 struct sockaddr_storage w_mask0;
127 struct netmsg_rttable_walk {
128 struct netmsg_base base;
130 struct rttable_walkarg *w;
134 struct rawcb rocb_rcb;
135 unsigned int rocb_msgfilter;
137 #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
140 rt_msg_mbuf (int, struct rt_addrinfo *);
141 static void rt_msg_buffer (int, struct rt_addrinfo *, void *buf, int len);
142 static int rt_msgsize(int type, const struct rt_addrinfo *rtinfo);
143 static int rt_xaddrs (char *, char *, struct rt_addrinfo *);
144 static int sysctl_rttable(int af, struct sysctl_req *req, int op, int arg);
145 static int sysctl_iflist (int af, struct walkarg *w);
146 static int route_output(struct mbuf *, struct socket *, ...);
147 static void rt_setmetrics (u_long, struct rt_metrics *,
148 struct rt_metrics *);
151 * It really doesn't make any sense at all for this code to share much
152 * with raw_usrreq.c, since its functionality is so restricted. XXX
155 rts_abort(netmsg_t msg)
158 raw_usrreqs.pru_abort(msg);
159 /* msg invalid now */
164 rts_filter(struct mbuf *m, const struct sockproto *proto,
165 const struct rawcb *rp)
167 const struct routecb *rop = (const struct routecb *)rp;
168 const struct rt_msghdr *rtm;
171 KKASSERT(proto != NULL);
172 KKASSERT(rp != NULL);
174 /* Wrong family for this socket. */
175 if (proto->sp_family != PF_ROUTE)
178 /* If no filter set, just return. */
179 if (rop->rocb_msgfilter == 0)
182 /* Ensure we can access rtm_type */
184 offsetof(struct rt_msghdr, rtm_type) + sizeof(rtm->rtm_type))
187 rtm = mtod(m, const struct rt_msghdr *);
188 /* If the rtm type is filtered out, return a positive. */
189 if (!(rop->rocb_msgfilter & ROUTE_FILTER(rtm->rtm_type)))
192 /* Passed the filter. */
197 /* pru_accept is EOPNOTSUPP */
200 rts_attach(netmsg_t msg)
202 struct socket *so = msg->base.nm_so;
203 struct pru_attach_info *ai = msg->attach.nm_ai;
206 int proto = msg->attach.nm_proto;
210 if (sotorawcb(so) != NULL) {
215 rop = kmalloc(sizeof *rop, M_PCB, M_WAITOK | M_ZERO);
219 * The critical section is necessary to block protocols from sending
220 * error notifications (like RTM_REDIRECT or RTM_LOSING) while
221 * this PCB is extant but incompletely initialized.
222 * Probably we should try to do more of this work beforehand and
223 * eliminate the critical section.
226 soreference(so); /* so_pcb assignment */
227 error = raw_attach(so, proto, ai->sb_rlimit);
233 switch(rp->rcb_proto.sp_protocol) {
238 route_cb.ip6_count++;
241 rp->rcb_faddr = &route_src;
242 rp->rcb_filter = rts_filter;
243 route_cb.any_count++;
245 so->so_options |= SO_USELOOPBACK;
249 lwkt_replymsg(&msg->lmsg, error);
253 rts_bind(netmsg_t msg)
256 raw_usrreqs.pru_bind(msg); /* xxx just EINVAL */
257 /* msg invalid now */
262 rts_connect(netmsg_t msg)
265 raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */
266 /* msg invalid now */
270 /* pru_connect2 is EOPNOTSUPP */
271 /* pru_control is EOPNOTSUPP */
274 rts_detach(netmsg_t msg)
276 struct socket *so = msg->base.nm_so;
277 struct rawcb *rp = sotorawcb(so);
281 switch(rp->rcb_proto.sp_protocol) {
286 route_cb.ip6_count--;
289 route_cb.any_count--;
291 raw_usrreqs.pru_detach(msg);
292 /* msg invalid now */
297 rts_disconnect(netmsg_t msg)
300 raw_usrreqs.pru_disconnect(msg);
301 /* msg invalid now */
305 /* pru_listen is EOPNOTSUPP */
308 rts_peeraddr(netmsg_t msg)
311 raw_usrreqs.pru_peeraddr(msg);
312 /* msg invalid now */
316 /* pru_rcvd is EOPNOTSUPP */
317 /* pru_rcvoob is EOPNOTSUPP */
320 rts_send(netmsg_t msg)
323 raw_usrreqs.pru_send(msg);
324 /* msg invalid now */
328 /* pru_sense is null */
331 rts_shutdown(netmsg_t msg)
334 raw_usrreqs.pru_shutdown(msg);
335 /* msg invalid now */
340 rts_sockaddr(netmsg_t msg)
343 raw_usrreqs.pru_sockaddr(msg);
344 /* msg invalid now */
348 static struct pr_usrreqs route_usrreqs = {
349 .pru_abort = rts_abort,
350 .pru_accept = pr_generic_notsupp,
351 .pru_attach = rts_attach,
352 .pru_bind = rts_bind,
353 .pru_connect = rts_connect,
354 .pru_connect2 = pr_generic_notsupp,
355 .pru_control = pr_generic_notsupp,
356 .pru_detach = rts_detach,
357 .pru_disconnect = rts_disconnect,
358 .pru_listen = pr_generic_notsupp,
359 .pru_peeraddr = rts_peeraddr,
360 .pru_rcvd = pr_generic_notsupp,
361 .pru_rcvoob = pr_generic_notsupp,
362 .pru_send = rts_send,
363 .pru_sense = pru_sense_null,
364 .pru_shutdown = rts_shutdown,
365 .pru_sockaddr = rts_sockaddr,
366 .pru_sosend = sosend,
367 .pru_soreceive = soreceive
370 static __inline sa_family_t
371 familyof(struct sockaddr *sa)
373 return (sa != NULL ? sa->sa_family : 0);
377 * Routing socket input function. The packet must be serialized onto cpu 0.
378 * We use the cpu0_soport() netisr processing loop to handle it.
380 * This looks messy but it means that anyone, including interrupt code,
381 * can send a message to the routing socket.
384 rts_input_handler(netmsg_t msg)
386 static const struct sockaddr route_dst = { 2, PF_ROUTE, };
387 struct sockproto route_proto;
388 struct netmsg_packet *pmsg = &msg->packet;
393 family = pmsg->base.lmsg.u.ms_result;
394 route_proto.sp_family = PF_ROUTE;
395 route_proto.sp_protocol = family;
400 skip = m->m_pkthdr.header;
401 m->m_pkthdr.header = NULL;
403 raw_input(m, &route_proto, &route_src, &route_dst, skip);
407 rts_input_skip(struct mbuf *m, sa_family_t family, struct rawcb *skip)
409 struct netmsg_packet *pmsg;
414 port = netisr_cpuport(0); /* XXX same as for routing socket */
415 pmsg = &m->m_hdr.mh_netmsg;
416 netmsg_init(&pmsg->base, NULL, &netisr_apanic_rport,
417 0, rts_input_handler);
419 pmsg->base.lmsg.u.ms_result = family;
420 m->m_pkthdr.header = skip; /* XXX steal field in pkthdr */
421 lwkt_sendmsg(port, &pmsg->base.lmsg);
425 rts_input(struct mbuf *m, sa_family_t family)
427 rts_input_skip(m, family, NULL);
431 route_ctloutput(netmsg_t msg)
433 struct socket *so = msg->ctloutput.base.nm_so;
434 struct sockopt *sopt = msg->ctloutput.nm_sopt;
435 struct routecb *rop = sotoroutecb(so);
437 unsigned int msgfilter;
439 if (sopt->sopt_level != AF_ROUTE) {
446 switch (sopt->sopt_dir) {
448 switch (sopt->sopt_name) {
449 case ROUTE_MSGFILTER:
450 error = soopt_to_kbuf(sopt, &msgfilter,
451 sizeof(msgfilter), sizeof(msgfilter));
453 rop->rocb_msgfilter = msgfilter;
461 switch (sopt->sopt_name) {
462 case ROUTE_MSGFILTER:
463 msgfilter = rop->rocb_msgfilter;
464 soopt_from_kbuf(sopt, &msgfilter, sizeof(msgfilter));
472 lwkt_replymsg(&msg->ctloutput.base.lmsg, error);
478 reallocbuf_nofree(void *ptr, size_t len, size_t olen)
482 newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
485 bcopy(ptr, newptr, olen);
490 * Internal helper routine for route_output().
493 _fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt,
494 struct rt_addrinfo *rtinfo)
497 struct rt_msghdr *rtm = *prtm;
499 /* Fill in rt_addrinfo for call to rt_msg_buffer(). */
500 rtinfo->rti_dst = rt_key(rt);
501 rtinfo->rti_gateway = rt->rt_gateway;
502 rtinfo->rti_netmask = rt_mask(rt); /* might be NULL */
503 rtinfo->rti_genmask = rt->rt_genmask; /* might be NULL */
504 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
505 if (rt->rt_ifp != NULL) {
506 rtinfo->rti_ifpaddr =
507 TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])
509 rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr;
510 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
511 rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
512 rtm->rtm_index = rt->rt_ifp->if_index;
514 rtinfo->rti_ifpaddr = NULL;
515 rtinfo->rti_ifaaddr = NULL;
517 } else if (rt->rt_ifp != NULL) {
518 rtm->rtm_index = rt->rt_ifp->if_index;
521 msglen = rt_msgsize(rtm->rtm_type, rtinfo);
522 if (rtm->rtm_msglen < msglen) {
523 /* NOTE: Caller will free the old rtm accordingly */
524 rtm = reallocbuf_nofree(rtm, msglen, rtm->rtm_msglen);
529 rt_msg_buffer(rtm->rtm_type, rtinfo, rtm, msglen);
531 rtm->rtm_flags = rt->rt_flags;
532 rtm->rtm_rmx = rt->rt_rmx;
533 rtm->rtm_addrs = rtinfo->rti_addrs;
539 struct rt_msghdr *bak_rtm;
540 struct rt_msghdr *new_rtm;
544 fillrtmsg(struct rtm_arg *arg, struct rtentry *rt,
545 struct rt_addrinfo *rtinfo)
547 struct rt_msghdr *rtm = arg->new_rtm;
550 error = _fillrtmsg(&rtm, rt, rtinfo);
552 if (arg->new_rtm != rtm) {
554 * _fillrtmsg() just allocated a new rtm;
555 * if the previously allocated rtm is not
556 * the backing rtm, it should be freed.
558 if (arg->new_rtm != arg->bak_rtm)
559 kfree(arg->new_rtm, M_RTABLE);
566 static void route_output_add_callback(int, int, struct rt_addrinfo *,
567 struct rtentry *, void *);
568 static void route_output_delete_callback(int, int, struct rt_addrinfo *,
569 struct rtentry *, void *);
570 static int route_output_get_callback(int, struct rt_addrinfo *,
571 struct rtentry *, void *, int);
572 static int route_output_change_callback(int, struct rt_addrinfo *,
573 struct rtentry *, void *, int);
574 static int route_output_lock_callback(int, struct rt_addrinfo *,
575 struct rtentry *, void *, int);
579 route_output(struct mbuf *m, struct socket *so, ...)
582 struct rt_msghdr *rtm = NULL;
583 struct rawcb *rp = NULL;
584 struct pr_output_info *oi;
585 struct rt_addrinfo rtinfo;
593 oi = __va_arg(ap, struct pr_output_info *);
596 family = familyof(NULL);
598 #define gotoerr(e) { error = e; goto flush;}
601 (m->m_len < sizeof(long) &&
602 (m = m_pullup(m, sizeof(long))) == NULL))
604 len = m->m_pkthdr.len;
605 if (len < sizeof(struct rt_msghdr) ||
606 len != mtod(m, struct rt_msghdr *)->rtm_msglen)
609 rtm = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
613 m_copydata(m, 0, len, (caddr_t)rtm);
614 if (rtm->rtm_version != RTM_VERSION)
615 gotoerr(EPROTONOSUPPORT);
617 rtm->rtm_pid = oi->p_pid;
618 bzero(&rtinfo, sizeof(struct rt_addrinfo));
619 rtinfo.rti_addrs = rtm->rtm_addrs;
620 if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0)
623 rtinfo.rti_flags = rtm->rtm_flags;
624 if (rtinfo.rti_dst == NULL || rtinfo.rti_dst->sa_family >= AF_MAX ||
625 (rtinfo.rti_gateway && rtinfo.rti_gateway->sa_family >= AF_MAX))
628 family = familyof(rtinfo.rti_dst);
631 * Verify that the caller has the appropriate privilege; RTM_GET
632 * is the only operation the non-superuser is allowed.
634 if (rtm->rtm_type != RTM_GET &&
635 priv_check_cred(so->so_cred, PRIV_ROOT, 0) != 0)
638 if (rtinfo.rti_genmask != NULL) {
639 error = rtmask_add_global(rtinfo.rti_genmask,
640 rtm->rtm_type != RTM_GET ?
641 RTREQ_PRIO_HIGH : RTREQ_PRIO_NORM);
646 switch (rtm->rtm_type) {
648 if (rtinfo.rti_gateway == NULL) {
651 error = rtrequest1_global(RTM_ADD, &rtinfo,
652 route_output_add_callback, rtm, RTREQ_PRIO_HIGH);
657 * Backing rtm (bak_rtm) could _not_ be freed during
658 * rtrequest1_global or rtsearch_global, even if the
659 * callback reallocates the rtm due to its size changes,
660 * since rtinfo points to the backing rtm's memory area.
661 * After rtrequest1_global or rtsearch_global returns,
662 * it is safe to free the backing rtm, since rtinfo will
663 * not be used anymore.
665 * new_rtm will be used to save the new rtm allocated
666 * by rtrequest1_global or rtsearch_global.
670 error = rtrequest1_global(RTM_DELETE, &rtinfo,
671 route_output_delete_callback, &arg, RTREQ_PRIO_HIGH);
673 if (rtm != arg.bak_rtm)
674 kfree(arg.bak_rtm, M_RTABLE);
677 /* See the comment in RTM_DELETE */
680 error = rtsearch_global(RTM_GET, &rtinfo,
681 route_output_get_callback, &arg, RTS_NOEXACTMATCH,
684 if (rtm != arg.bak_rtm)
685 kfree(arg.bak_rtm, M_RTABLE);
688 error = rtsearch_global(RTM_CHANGE, &rtinfo,
689 route_output_change_callback, rtm, RTS_EXACTMATCH,
693 error = rtsearch_global(RTM_LOCK, &rtinfo,
694 route_output_lock_callback, rtm, RTS_EXACTMATCH,
704 rtm->rtm_errno = error;
706 rtm->rtm_flags |= RTF_DONE;
710 * Check to see if we don't want our own messages.
712 if (!(so->so_options & SO_USELOOPBACK)) {
713 if (route_cb.any_count <= 1) {
715 kfree(rtm, M_RTABLE);
719 /* There is another listener, so construct message */
723 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
724 if (m->m_pkthdr.len < rtm->rtm_msglen) {
727 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
728 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
729 kfree(rtm, M_RTABLE);
732 rts_input_skip(m, family, rp);
737 route_output_add_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
738 struct rtentry *rt, void *arg)
740 struct rt_msghdr *rtm = arg;
742 if (error == 0 && rt != NULL) {
743 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
745 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
746 rt->rt_rmx.rmx_locks |=
747 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
748 if (rtinfo->rti_genmask != NULL) {
749 rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask);
750 if (rt->rt_genmask == NULL) {
752 * This should not happen, since we
753 * have already installed genmask
754 * on each CPU before we reach here.
756 panic("genmask is gone!?");
759 rt->rt_genmask = NULL;
761 rtm->rtm_index = rt->rt_ifp->if_index;
766 route_output_delete_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
767 struct rtentry *rt, void *arg)
769 if (error == 0 && rt) {
771 if (fillrtmsg(arg, rt, rtinfo) != 0) {
773 /* XXX no way to return the error */
777 if (rt && rt->rt_refcnt == 0) {
784 route_output_get_callback(int cmd, struct rt_addrinfo *rtinfo,
785 struct rtentry *rt, void *arg, int found_cnt)
787 int error, found = 0;
789 if (((rtinfo->rti_flags ^ rt->rt_flags) & RTF_HOST) == 0)
792 error = fillrtmsg(arg, rt, rtinfo);
793 if (!error && found) {
794 /* Got the exact match, we could return now! */
801 route_output_change_callback(int cmd, struct rt_addrinfo *rtinfo,
802 struct rtentry *rt, void *arg, int found_cnt)
804 struct rt_msghdr *rtm = arg;
809 * new gateway could require new ifaddr, ifp;
810 * flags may also be different; ifp may be specified
811 * by ll sockaddr when protocol address is ambiguous
813 if (((rt->rt_flags & RTF_GATEWAY) && rtinfo->rti_gateway != NULL) ||
814 rtinfo->rti_ifpaddr != NULL ||
815 (rtinfo->rti_ifaaddr != NULL &&
816 !sa_equal(rtinfo->rti_ifaaddr, rt->rt_ifa->ifa_addr))) {
817 error = rt_getifa(rtinfo);
821 if (rtinfo->rti_gateway != NULL) {
823 * We only need to generate rtmsg upon the
824 * first route to be changed.
826 error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway);
830 if ((ifa = rtinfo->rti_ifa) != NULL) {
831 struct ifaddr *oifa = rt->rt_ifa;
834 if (oifa && oifa->ifa_rtrequest)
835 oifa->ifa_rtrequest(RTM_DELETE, rt);
839 rt->rt_ifp = rtinfo->rti_ifp;
842 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
843 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
844 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt);
845 if (rtinfo->rti_genmask != NULL) {
846 rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask);
847 if (rt->rt_genmask == NULL) {
849 * This should not happen, since we
850 * have already installed genmask
851 * on each CPU before we reach here.
853 panic("genmask is gone!?");
856 rtm->rtm_index = rt->rt_ifp->if_index;
858 rt_rtmsg(RTM_CHANGE, rt, rt->rt_ifp, 0);
864 route_output_lock_callback(int cmd, struct rt_addrinfo *rtinfo,
865 struct rtentry *rt, void *arg,
866 int found_cnt __unused)
868 struct rt_msghdr *rtm = arg;
870 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
871 rt->rt_rmx.rmx_locks |=
872 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
877 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
879 #define setmetric(flag, elt) if (which & (flag)) out->elt = in->elt;
880 setmetric(RTV_RPIPE, rmx_recvpipe);
881 setmetric(RTV_SPIPE, rmx_sendpipe);
882 setmetric(RTV_SSTHRESH, rmx_ssthresh);
883 setmetric(RTV_RTT, rmx_rtt);
884 setmetric(RTV_RTTVAR, rmx_rttvar);
885 setmetric(RTV_HOPCOUNT, rmx_hopcount);
886 setmetric(RTV_MTU, rmx_mtu);
887 setmetric(RTV_EXPIRE, rmx_expire);
888 setmetric(RTV_MSL, rmx_msl);
889 setmetric(RTV_IWMAXSEGS, rmx_iwmaxsegs);
890 setmetric(RTV_IWCAPSEGS, rmx_iwcapsegs);
895 * Extract the addresses of the passed sockaddrs.
896 * Do a little sanity checking so as to avoid bad memory references.
897 * This data is derived straight from userland.
900 rt_xaddrs(char *cp, char *cplim, struct rt_addrinfo *rtinfo)
905 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
906 if ((rtinfo->rti_addrs & (1 << i)) == 0)
908 sa = (struct sockaddr *)cp;
912 if ((cp + sa->sa_len) > cplim) {
917 * There are no more... Quit now.
918 * If there are more bits, they are in error.
919 * I've seen this. route(1) can evidently generate these.
920 * This causes kernel to core dump.
921 * For compatibility, if we see this, point to a safe address.
923 if (sa->sa_len == 0) {
924 static struct sockaddr sa_zero = {
925 sizeof sa_zero, AF_INET,
928 rtinfo->rti_info[i] = &sa_zero;
929 kprintf("rtsock: received more addr bits than sockaddrs.\n");
930 return (0); /* should be EINVAL but for compat */
933 /* Accept the sockaddr. */
934 rtinfo->rti_info[i] = sa;
935 cp += RT_ROUNDUP(sa->sa_len);
941 rt_msghdrsize(int type)
946 return sizeof(struct ifa_msghdr);
949 return sizeof(struct ifma_msghdr);
951 return sizeof(struct if_msghdr);
954 return sizeof(struct if_announcemsghdr);
956 return sizeof(struct rt_msghdr);
961 rt_msgsize(int type, const struct rt_addrinfo *rtinfo)
965 len = rt_msghdrsize(type);
966 for (i = 0; i < RTAX_MAX; i++) {
967 if (rtinfo->rti_info[i] != NULL)
968 len += RT_ROUNDUP(rtinfo->rti_info[i]->sa_len);
975 * Build a routing message in a buffer.
976 * Copy the addresses in the rtinfo->rti_info[] sockaddr array
977 * to the end of the buffer after the message header.
979 * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
980 * This side-effect can be avoided if we reorder the addrs bitmask field in all
981 * the route messages to line up so we can set it here instead of back in the
985 rt_msg_buffer(int type, struct rt_addrinfo *rtinfo, void *buf, int msglen)
987 struct rt_msghdr *rtm;
991 rtm = (struct rt_msghdr *) buf;
992 rtm->rtm_version = RTM_VERSION;
993 rtm->rtm_type = type;
994 rtm->rtm_msglen = msglen;
996 cp = (char *)buf + rt_msghdrsize(type);
997 rtinfo->rti_addrs = 0;
998 for (i = 0; i < RTAX_MAX; i++) {
1001 if ((sa = rtinfo->rti_info[i]) == NULL)
1003 rtinfo->rti_addrs |= (1 << i);
1004 dlen = RT_ROUNDUP(sa->sa_len);
1005 bcopy(sa, cp, dlen);
1011 * Build a routing message in a mbuf chain.
1012 * Copy the addresses in the rtinfo->rti_info[] sockaddr array
1013 * to the end of the mbuf after the message header.
1015 * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
1016 * This side-effect can be avoided if we reorder the addrs bitmask field in all
1017 * the route messages to line up so we can set it here instead of back in the
1020 static struct mbuf *
1021 rt_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
1024 struct rt_msghdr *rtm;
1028 hlen = rt_msghdrsize(type);
1029 KASSERT(hlen <= MCLBYTES, ("rt_msg_mbuf: hlen %d doesn't fit", hlen));
1031 m = m_getl(hlen, M_NOWAIT, MT_DATA, M_PKTHDR, NULL);
1035 m->m_pkthdr.len = m->m_len = hlen;
1036 m->m_pkthdr.rcvif = NULL;
1037 rtinfo->rti_addrs = 0;
1039 for (i = 0; i < RTAX_MAX; i++) {
1040 struct sockaddr *sa;
1043 if ((sa = rtinfo->rti_info[i]) == NULL)
1045 rtinfo->rti_addrs |= (1 << i);
1046 dlen = RT_ROUNDUP(sa->sa_len);
1047 m_copyback(m, len, dlen, (caddr_t)sa); /* can grow mbuf chain */
1050 if (m->m_pkthdr.len != len) { /* one of the m_copyback() calls failed */
1054 rtm = mtod(m, struct rt_msghdr *);
1056 rtm->rtm_msglen = len;
1057 rtm->rtm_version = RTM_VERSION;
1058 rtm->rtm_type = type;
1063 * This routine is called to generate a message from the routing
1064 * socket indicating that a redirect has occurred, a routing lookup
1065 * has failed, or that a protocol has detected timeouts to a particular
1069 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
1071 struct sockaddr *dst = rtinfo->rti_info[RTAX_DST];
1072 struct rt_msghdr *rtm;
1075 if (route_cb.any_count == 0)
1077 m = rt_msg_mbuf(type, rtinfo);
1080 rtm = mtod(m, struct rt_msghdr *);
1081 rtm->rtm_flags = RTF_DONE | flags;
1082 rtm->rtm_errno = error;
1083 rtm->rtm_addrs = rtinfo->rti_addrs;
1084 rts_input(m, familyof(dst));
1088 rt_dstmsg(int type, struct sockaddr *dst, int error)
1090 struct rt_msghdr *rtm;
1091 struct rt_addrinfo addrs;
1094 if (route_cb.any_count == 0)
1096 bzero(&addrs, sizeof(struct rt_addrinfo));
1097 addrs.rti_info[RTAX_DST] = dst;
1098 m = rt_msg_mbuf(type, &addrs);
1101 rtm = mtod(m, struct rt_msghdr *);
1102 rtm->rtm_flags = RTF_DONE;
1103 rtm->rtm_errno = error;
1104 rtm->rtm_addrs = addrs.rti_addrs;
1105 rts_input(m, familyof(dst));
1109 * This routine is called to generate a message from the routing
1110 * socket indicating that the status of a network interface has changed.
1113 rt_ifmsg(struct ifnet *ifp)
1115 struct if_msghdr *ifm;
1117 struct rt_addrinfo rtinfo;
1119 if (route_cb.any_count == 0)
1121 bzero(&rtinfo, sizeof(struct rt_addrinfo));
1122 m = rt_msg_mbuf(RTM_IFINFO, &rtinfo);
1125 ifm = mtod(m, struct if_msghdr *);
1126 ifm->ifm_index = ifp->if_index;
1127 ifm->ifm_flags = ifp->if_flags;
1128 ifm->ifm_data = ifp->if_data;
1134 rt_ifamsg(int cmd, struct ifaddr *ifa)
1136 struct ifa_msghdr *ifam;
1137 struct rt_addrinfo rtinfo;
1139 struct ifnet *ifp = ifa->ifa_ifp;
1141 bzero(&rtinfo, sizeof(struct rt_addrinfo));
1142 rtinfo.rti_ifaaddr = ifa->ifa_addr;
1143 rtinfo.rti_ifpaddr =
1144 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1145 rtinfo.rti_netmask = ifa->ifa_netmask;
1146 rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1148 m = rt_msg_mbuf(cmd, &rtinfo);
1152 ifam = mtod(m, struct ifa_msghdr *);
1153 ifam->ifam_index = ifp->if_index;
1154 ifam->ifam_metric = ifa->ifa_metric;
1155 ifam->ifam_flags = ifa->ifa_flags;
1156 ifam->ifam_addrs = rtinfo.rti_addrs;
1158 rts_input(m, familyof(ifa->ifa_addr));
1162 rt_rtmsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int error)
1164 struct rt_msghdr *rtm;
1165 struct rt_addrinfo rtinfo;
1167 struct sockaddr *dst;
1172 bzero(&rtinfo, sizeof(struct rt_addrinfo));
1173 rtinfo.rti_dst = dst = rt_key(rt);
1174 rtinfo.rti_gateway = rt->rt_gateway;
1175 rtinfo.rti_netmask = rt_mask(rt);
1177 rtinfo.rti_ifpaddr =
1178 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1180 if (rt->rt_ifa != NULL)
1181 rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr;
1183 m = rt_msg_mbuf(cmd, &rtinfo);
1187 rtm = mtod(m, struct rt_msghdr *);
1189 rtm->rtm_index = ifp->if_index;
1190 rtm->rtm_flags |= rt->rt_flags;
1191 rtm->rtm_errno = error;
1192 rtm->rtm_addrs = rtinfo.rti_addrs;
1194 rts_input(m, familyof(dst));
1198 * This is called to generate messages from the routing socket
1199 * indicating a network interface has had addresses associated with it.
1200 * if we ever reverse the logic and replace messages TO the routing
1201 * socket indicate a request to configure interfaces, then it will
1202 * be unnecessary as the routing socket will automatically generate
1206 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1208 if (route_cb.any_count == 0)
1211 if (cmd == RTM_ADD) {
1212 rt_ifamsg(RTM_NEWADDR, ifa);
1213 rt_rtmsg(RTM_ADD, rt, ifa->ifa_ifp, error);
1215 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
1216 rt_rtmsg(RTM_DELETE, rt, ifa->ifa_ifp, error);
1217 rt_ifamsg(RTM_DELADDR, ifa);
1222 * This is the analogue to the rt_newaddrmsg which performs the same
1223 * function but for multicast group memberhips. This is easier since
1224 * there is no route state to worry about.
1227 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1229 struct rt_addrinfo rtinfo;
1230 struct mbuf *m = NULL;
1231 struct ifnet *ifp = ifma->ifma_ifp;
1232 struct ifma_msghdr *ifmam;
1234 if (route_cb.any_count == 0)
1237 bzero(&rtinfo, sizeof(struct rt_addrinfo));
1238 rtinfo.rti_ifaaddr = ifma->ifma_addr;
1239 if (ifp != NULL && !TAILQ_EMPTY(&ifp->if_addrheads[mycpuid])) {
1240 rtinfo.rti_ifpaddr =
1241 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1244 * If a link-layer address is present, present it as a ``gateway''
1245 * (similarly to how ARP entries, e.g., are presented).
1247 rtinfo.rti_gateway = ifma->ifma_lladdr;
1249 m = rt_msg_mbuf(cmd, &rtinfo);
1253 ifmam = mtod(m, struct ifma_msghdr *);
1254 ifmam->ifmam_index = ifp->if_index;
1255 ifmam->ifmam_addrs = rtinfo.rti_addrs;
1257 rts_input(m, familyof(ifma->ifma_addr));
1260 static struct mbuf *
1261 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
1262 struct rt_addrinfo *info)
1264 struct if_announcemsghdr *ifan;
1267 if (route_cb.any_count == 0)
1270 bzero(info, sizeof(*info));
1271 m = rt_msg_mbuf(type, info);
1275 ifan = mtod(m, struct if_announcemsghdr *);
1276 ifan->ifan_index = ifp->if_index;
1277 strlcpy(ifan->ifan_name, ifp->if_xname, sizeof ifan->ifan_name);
1278 ifan->ifan_what = what;
1283 * This is called to generate routing socket messages indicating
1284 * IEEE80211 wireless events.
1285 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
1288 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
1290 struct rt_addrinfo info;
1293 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
1298 * Append the ieee80211 data. Try to stick it in the
1299 * mbuf containing the ifannounce msg; otherwise allocate
1300 * a new mbuf and append.
1302 * NB: we assume m is a single mbuf.
1304 if (data_len > M_TRAILINGSPACE(m)) {
1305 /* XXX use m_getb(data_len, M_NOWAIT, MT_DATA, 0); */
1306 struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
1311 KKASSERT(data_len <= M_TRAILINGSPACE(n));
1312 bcopy(data, mtod(n, void *), data_len);
1313 n->m_len = data_len;
1315 } else if (data_len > 0) {
1316 bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len);
1317 m->m_len += data_len;
1320 if (m->m_flags & M_PKTHDR)
1321 m->m_pkthdr.len += data_len;
1322 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
1327 * This is called to generate routing socket messages indicating
1328 * network interface arrival and departure.
1331 rt_ifannouncemsg(struct ifnet *ifp, int what)
1333 struct rt_addrinfo addrinfo;
1336 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &addrinfo);
1342 resizewalkarg(struct walkarg *w, int len)
1346 newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
1349 if (w->w_tmem != NULL)
1350 kfree(w->w_tmem, M_RTABLE);
1352 w->w_tmemsize = len;
1357 ifnet_compute_stats(struct ifnet *ifp)
1359 IFNET_STAT_GET(ifp, ipackets, ifp->if_ipackets);
1360 IFNET_STAT_GET(ifp, ierrors, ifp->if_ierrors);
1361 IFNET_STAT_GET(ifp, opackets, ifp->if_opackets);
1362 IFNET_STAT_GET(ifp, collisions, ifp->if_collisions);
1363 IFNET_STAT_GET(ifp, ibytes, ifp->if_ibytes);
1364 IFNET_STAT_GET(ifp, obytes, ifp->if_obytes);
1365 IFNET_STAT_GET(ifp, imcasts, ifp->if_imcasts);
1366 IFNET_STAT_GET(ifp, omcasts, ifp->if_omcasts);
1367 IFNET_STAT_GET(ifp, iqdrops, ifp->if_iqdrops);
1368 IFNET_STAT_GET(ifp, noproto, ifp->if_noproto);
1369 IFNET_STAT_GET(ifp, oqdrops, ifp->if_oqdrops);
1373 sysctl_iflist(int af, struct walkarg *w)
1376 struct rt_addrinfo rtinfo;
1379 bzero(&rtinfo, sizeof(struct rt_addrinfo));
1382 TAILQ_FOREACH(ifp, &ifnetlist, if_link) {
1383 struct ifaddr_container *ifac, *ifac_mark;
1384 struct ifaddr_marker mark;
1385 struct ifaddrhead *head;
1388 if (w->w_arg && w->w_arg != ifp->if_index)
1390 head = &ifp->if_addrheads[mycpuid];
1392 * There is no need to reference the first ifaddr
1393 * even if the following resizewalkarg() blocks,
1394 * since the first ifaddr will not be destroyed
1395 * when the ifnet lock is held.
1397 ifac = TAILQ_FIRST(head);
1399 rtinfo.rti_ifpaddr = ifa->ifa_addr;
1400 msglen = rt_msgsize(RTM_IFINFO, &rtinfo);
1401 if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0) {
1405 rt_msg_buffer(RTM_IFINFO, &rtinfo, w->w_tmem, msglen);
1406 rtinfo.rti_ifpaddr = NULL;
1407 if (w->w_req != NULL && w->w_tmem != NULL) {
1408 struct if_msghdr *ifm = w->w_tmem;
1410 ifm->ifm_index = ifp->if_index;
1411 ifm->ifm_flags = ifp->if_flags;
1412 ifnet_compute_stats(ifp);
1413 ifm->ifm_data = ifp->if_data;
1414 ifm->ifm_addrs = rtinfo.rti_addrs;
1415 error = SYSCTL_OUT(w->w_req, ifm, msglen);
1422 * Add a marker, since SYSCTL_OUT() could block and during
1423 * that period the list could be changed.
1425 ifa_marker_init(&mark, ifp);
1426 ifac_mark = &mark.ifac;
1427 TAILQ_INSERT_AFTER(head, ifac, ifac_mark, ifa_link);
1428 while ((ifac = TAILQ_NEXT(ifac_mark, ifa_link)) != NULL) {
1429 TAILQ_REMOVE(head, ifac_mark, ifa_link);
1430 TAILQ_INSERT_AFTER(head, ifac, ifac_mark, ifa_link);
1435 if (ifa->ifa_addr->sa_family == AF_UNSPEC)
1438 if (af && af != ifa->ifa_addr->sa_family)
1440 if (curproc->p_ucred->cr_prison &&
1441 prison_if(curproc->p_ucred, ifa->ifa_addr))
1443 rtinfo.rti_ifaaddr = ifa->ifa_addr;
1444 rtinfo.rti_netmask = ifa->ifa_netmask;
1445 rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1446 msglen = rt_msgsize(RTM_NEWADDR, &rtinfo);
1448 * Keep a reference on this ifaddr, so that it will
1449 * not be destroyed if the following resizewalkarg()
1453 if (w->w_tmemsize < msglen &&
1454 resizewalkarg(w, msglen) != 0) {
1456 TAILQ_REMOVE(head, ifac_mark, ifa_link);
1460 rt_msg_buffer(RTM_NEWADDR, &rtinfo, w->w_tmem, msglen);
1461 if (w->w_req != NULL) {
1462 struct ifa_msghdr *ifam = w->w_tmem;
1464 ifam->ifam_index = ifa->ifa_ifp->if_index;
1465 ifam->ifam_flags = ifa->ifa_flags;
1466 ifam->ifam_metric = ifa->ifa_metric;
1467 ifam->ifam_addrs = rtinfo.rti_addrs;
1468 error = SYSCTL_OUT(w->w_req, w->w_tmem, msglen);
1471 TAILQ_REMOVE(head, ifac_mark, ifa_link);
1478 TAILQ_REMOVE(head, ifac_mark, ifa_link);
1479 rtinfo.rti_netmask = NULL;
1480 rtinfo.rti_ifaaddr = NULL;
1481 rtinfo.rti_bcastaddr = NULL;
1488 rttable_walkarg_create(struct rttable_walkarg *w, int op, int arg)
1490 struct rt_addrinfo rtinfo;
1491 struct sockaddr_storage ss;
1494 memset(w, 0, sizeof(*w));
1498 memset(&ss, 0, sizeof(ss));
1499 ss.ss_len = sizeof(ss);
1501 memset(&rtinfo, 0, sizeof(rtinfo));
1502 for (i = 0; i < RTAX_MAX; ++i)
1503 rtinfo.rti_info[i] = (struct sockaddr *)&ss;
1504 msglen = rt_msgsize(RTM_GET, &rtinfo);
1506 w->w_bufsz = msglen * RTTABLE_DUMP_MSGCNT_MAX;
1507 w->w_buf = kmalloc(w->w_bufsz, M_TEMP, M_WAITOK | M_NULLOK);
1508 if (w->w_buf == NULL)
1514 rttable_walkarg_destroy(struct rttable_walkarg *w)
1516 kfree(w->w_buf, M_TEMP);
1520 rttable_entry_rtinfo(struct rt_addrinfo *rtinfo, struct radix_node *rn)
1522 struct rtentry *rt = (struct rtentry *)rn;
1524 bzero(rtinfo, sizeof(*rtinfo));
1525 rtinfo->rti_dst = rt_key(rt);
1526 rtinfo->rti_gateway = rt->rt_gateway;
1527 rtinfo->rti_netmask = rt_mask(rt);
1528 rtinfo->rti_genmask = rt->rt_genmask;
1529 if (rt->rt_ifp != NULL) {
1530 rtinfo->rti_ifpaddr =
1531 TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1532 rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr;
1533 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1534 rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
1539 rttable_walk_entry(struct radix_node *rn, void *xw)
1541 struct rttable_walkarg *w = xw;
1542 struct rtentry *rt = (struct rtentry *)rn;
1543 struct rt_addrinfo rtinfo;
1544 struct rt_msghdr *rtm;
1545 boolean_t save = FALSE;
1546 int msglen, w_bufleft;
1549 rttable_entry_rtinfo(&rtinfo, rn);
1550 msglen = rt_msgsize(RTM_GET, &rtinfo);
1552 w_bufleft = w->w_bufsz - w->w_buflen;
1554 if (rn->rn_dupedkey != NULL) {
1555 struct radix_node *rn1 = rn;
1556 int total_msglen = msglen;
1559 * Make sure that we have enough space left for all
1560 * dupedkeys, since rn_walktree_at always starts
1561 * from the first dupedkey.
1563 while ((rn1 = rn1->rn_dupedkey) != NULL) {
1564 struct rt_addrinfo rtinfo1;
1567 if (rn1->rn_flags & RNF_ROOT)
1570 rttable_entry_rtinfo(&rtinfo1, rn1);
1571 msglen1 = rt_msgsize(RTM_GET, &rtinfo1);
1572 total_msglen += msglen1;
1575 if (total_msglen > w_bufleft) {
1576 if (total_msglen > w->w_bufsz) {
1577 static int logged = 0;
1580 kprintf("buffer is too small for "
1581 "all dupedkeys, increase "
1582 "RTTABLE_DUMP_MSGCNT_MAX\n");
1589 } else if (msglen > w_bufleft) {
1595 * Not enough buffer left; remember the position
1596 * to start from upon next round.
1598 KASSERT(msglen <= w->w_bufsz, ("msg too long %d", msglen));
1600 KASSERT(rtinfo.rti_dst->sa_len <= sizeof(w->w_key0),
1601 ("key too long %d", rtinfo.rti_dst->sa_len));
1602 memset(&w->w_key0, 0, sizeof(w->w_key0));
1603 memcpy(&w->w_key0, rtinfo.rti_dst, rtinfo.rti_dst->sa_len);
1604 w->w_key = (const char *)&w->w_key0;
1606 if (rtinfo.rti_netmask != NULL) {
1608 rtinfo.rti_netmask->sa_len <= sizeof(w->w_mask0),
1609 ("mask too long %d", rtinfo.rti_netmask->sa_len));
1610 memset(&w->w_mask0, 0, sizeof(w->w_mask0));
1611 memcpy(&w->w_mask0, rtinfo.rti_netmask,
1612 rtinfo.rti_netmask->sa_len);
1613 w->w_mask = (const char *)&w->w_mask0;
1620 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1623 ptr = ((uint8_t *)w->w_buf) + w->w_buflen;
1624 rt_msg_buffer(RTM_GET, &rtinfo, ptr, msglen);
1626 rtm = (struct rt_msghdr *)ptr;
1627 rtm->rtm_flags = rt->rt_flags;
1628 rtm->rtm_use = rt->rt_use;
1629 rtm->rtm_rmx = rt->rt_rmx;
1630 rtm->rtm_index = rt->rt_ifp->if_index;
1631 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1632 rtm->rtm_addrs = rtinfo.rti_addrs;
1634 w->w_buflen += msglen;
1640 rttable_walk_dispatch(netmsg_t msg)
1642 struct netmsg_rttable_walk *nmsg = (struct netmsg_rttable_walk *)msg;
1643 struct radix_node_head *rnh = rt_tables[mycpuid][nmsg->af];
1644 struct rttable_walkarg *w = nmsg->w;
1647 error = rnh->rnh_walktree_at(rnh, w->w_key, w->w_mask,
1648 rttable_walk_entry, w);
1649 lwkt_replymsg(&nmsg->base.lmsg, error);
1653 sysctl_rttable(int af, struct sysctl_req *req, int op, int arg)
1655 struct rttable_walkarg w;
1658 error = rttable_walkarg_create(&w, op, arg);
1663 for (i = 1; i <= AF_MAX; i++) {
1664 if (rt_tables[mycpuid][i] != NULL && (af == 0 || af == i)) {
1668 struct netmsg_rttable_walk nmsg;
1670 netmsg_init(&nmsg.base, NULL,
1671 &curthread->td_msgport, 0,
1672 rttable_walk_dispatch);
1678 error = lwkt_domsg(netisr_cpuport(mycpuid),
1679 &nmsg.base.lmsg, 0);
1680 if (error && error != EJUSTRETURN)
1683 if (req != NULL && w.w_buflen > 0) {
1686 error1 = SYSCTL_OUT(req, w.w_buf,
1693 if (error == 0) /* done */
1699 rttable_walkarg_destroy(&w);
1704 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1706 int *name = (int *)arg1;
1707 u_int namelen = arg2;
1717 if (namelen != 3 && namelen != 4)
1720 bzero(&w, sizeof w);
1726 * Optional third argument specifies cpu, used primarily for
1727 * debugging the route table.
1730 if (name[3] < 0 || name[3] >= netisr_ncpus)
1735 * Target cpu is not specified, use cpu0 then, so that
1736 * the result set will be relatively stable.
1741 lwkt_migratecpu(cpu);
1746 error = sysctl_rttable(af, w.w_req, w.w_op, w.w_arg);
1750 error = sysctl_iflist(af, &w);
1753 if (w.w_tmem != NULL)
1754 kfree(w.w_tmem, M_RTABLE);
1756 lwkt_migratecpu(origcpu);
1760 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1763 * Definitions of protocols supported in the ROUTE domain.
1766 static struct domain routedomain; /* or at least forward */
1768 static struct protosw routesw[] = {
1770 .pr_type = SOCK_RAW,
1771 .pr_domain = &routedomain,
1773 .pr_flags = PR_ATOMIC|PR_ADDR,
1775 .pr_output = route_output,
1776 .pr_ctlinput = raw_ctlinput,
1777 .pr_ctloutput = route_ctloutput,
1778 .pr_ctlport = cpu0_ctlport,
1780 .pr_init = raw_init,
1781 .pr_usrreqs = &route_usrreqs
1785 static struct domain routedomain = {
1786 .dom_family = AF_ROUTE,
1787 .dom_name = "route",
1789 .dom_externalize = NULL,
1790 .dom_dispose = NULL,
1791 .dom_protosw = routesw,
1792 .dom_protoswNPROTOSW = &routesw[(sizeof routesw)/(sizeof routesw[0])],
1793 .dom_next = SLIST_ENTRY_INITIALIZER,
1794 .dom_rtattach = NULL,
1797 .dom_ifattach = NULL,
1798 .dom_ifdetach = NULL