inet6: only mark autoconf addresses tentative if detached
[dragonfly.git] / sys / net / rtsock.c
1 /*
2  * Copyright (c) 2004, 2005 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Jeffrey M. Hsu.
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 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.
18  *
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
30  * SUCH DAMAGE.
31  */
32
33 /*
34  * Copyright (c) 1988, 1991, 1993
35  *      The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
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.
48  *
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
59  * SUCH DAMAGE.
60  *
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 $
63  */
64
65 #include "opt_inet6.h"
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/sysctl.h>
71 #include <sys/proc.h>
72 #include <sys/caps.h>
73 #include <sys/malloc.h>
74 #include <sys/mbuf.h>
75 #include <sys/protosw.h>
76 #include <sys/socket.h>
77 #include <sys/socketvar.h>
78 #include <sys/domain.h>
79 #include <sys/jail.h>
80
81 #include <sys/thread2.h>
82 #include <sys/socketvar2.h>
83
84 #include <net/if.h>
85 #include <net/if_var.h>
86 #include <net/route.h>
87 #include <net/raw_cb.h>
88 #include <net/netmsg2.h>
89 #include <net/netisr2.h>
90
91 #ifdef INET6
92 #include <netinet/in_var.h>
93 #endif
94
95 /* sa_family is after sa_len, rest is data */
96 #define _SA_MINSIZE     (offsetof(struct sockaddr, sa_family) + \
97                          sizeof(((struct sockaddr *)0)->sa_family))
98
99 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
100
101 static struct route_cb {
102         int     ip_count;
103         int     ip6_count;
104         int     any_count;
105 } route_cb;
106
107 static const struct sockaddr route_src = { 2, PF_ROUTE, };
108
109 struct walkarg {
110         int     w_tmemsize;
111         int     w_op, w_arg;
112         void    *w_tmem;
113         struct sysctl_req *w_req;
114 };
115
116 #ifndef RTTABLE_DUMP_MSGCNT_MAX
117 /* Should be large enough for dupkeys */
118 #define RTTABLE_DUMP_MSGCNT_MAX         64
119 #endif
120
121 struct rttable_walkarg {
122         int     w_op;
123         int     w_arg;
124         int     w_bufsz;
125         void    *w_buf;
126
127         int     w_buflen;
128
129         const char *w_key;
130         const char *w_mask;
131
132         struct sockaddr_storage w_key0;
133         struct sockaddr_storage w_mask0;
134 };
135
136 struct netmsg_rttable_walk {
137         struct netmsg_base      base;
138         int                     af;
139         struct rttable_walkarg  *w;
140 };
141
142 struct routecb {
143         struct rawcb    rocb_rcb;
144         unsigned int    rocb_msgfilter;
145         char            *rocb_missfilter;
146         size_t          rocb_missfilterlen;
147 };
148 #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb)
149
150 static struct mbuf *
151                 rt_msg_mbuf (int, struct rt_addrinfo *);
152 static void     rt_msg_buffer (int, struct rt_addrinfo *, void *buf, int len);
153 static int      rt_msgsize(int type, const struct rt_addrinfo *rtinfo);
154 static int      rt_xaddrs (char *, char *, struct rt_addrinfo *);
155 static int      sysctl_rttable(int af, struct sysctl_req *req, int op, int arg);
156 static int      if_addrflags(const struct ifaddr *ifa);
157 static int      sysctl_iflist (int af, struct walkarg *w);
158 static int      route_output(struct mbuf *, struct socket *, ...);
159 static void     rt_setmetrics (u_long, struct rt_metrics *,
160                                struct rt_metrics *);
161
162 /*
163  * It really doesn't make any sense at all for this code to share much
164  * with raw_usrreq.c, since its functionality is so restricted.  XXX
165  */
166 static void
167 rts_abort(netmsg_t msg)
168 {
169         crit_enter();
170         raw_usrreqs.pru_abort(msg);
171         /* msg invalid now */
172         crit_exit();
173 }
174
175 static int
176 rts_filter(struct mbuf *m, const struct sockproto *proto,
177         const struct rawcb *rp)
178 {
179         const struct routecb *rop = (const struct routecb *)rp;
180         const struct rt_msghdr *rtm;
181
182         KKASSERT(m != NULL);
183         KKASSERT(proto != NULL);
184         KKASSERT(rp != NULL);
185
186         /* Wrong family for this socket. */
187         if (proto->sp_family != PF_ROUTE)
188                 return ENOPROTOOPT;
189
190         /* If no filter set, just return. */
191         if (rop->rocb_msgfilter == 0 && rop->rocb_missfilterlen == 0)
192                 return 0;
193
194         /* Ensure we can access rtm_type */
195         if (m->m_len <
196             offsetof(struct rt_msghdr, rtm_type) + sizeof(rtm->rtm_type))
197                 return EINVAL;
198
199         rtm = mtod(m, const struct rt_msghdr *);
200         /* If the rtm type is filtered out, return a positive. */
201         if (rop->rocb_msgfilter != 0 &&
202             !(rop->rocb_msgfilter & ROUTE_FILTER(rtm->rtm_type)))
203                 return EEXIST;
204
205         if (rop->rocb_missfilterlen != 0 && rtm->rtm_type == RTM_MISS) {
206                 CTASSERT(RTAX_DST == 0);
207                 struct sockaddr *sa;
208                 struct sockaddr_storage ss;
209                 struct sockaddr *dst = (struct sockaddr *)&ss;
210                 char *cp = rop->rocb_missfilter;
211                 char *ep = cp + rop->rocb_missfilterlen;
212
213                 /* Ensure we can access sa_len */
214                 if (m->m_pkthdr.len < sizeof(*rtm) + _SA_MINSIZE)
215                         return EINVAL;
216                 m_copydata(m, sizeof(*rtm) + offsetof(struct sockaddr, sa_len),
217                     sizeof(ss.ss_len), &ss);
218                 if (ss.ss_len < _SA_MINSIZE ||
219                     ss.ss_len > sizeof(ss) ||
220                     m->m_pkthdr.len < sizeof(*rtm) + ss.ss_len)
221                         return EINVAL;
222                 /* Copy out the destination sockaddr */
223                 m_copydata(m, sizeof(*rtm), ss.ss_len, &ss);
224
225                 /* Find a matching sockaddr in the filter */
226                 while (cp < ep) {
227                         sa = (struct sockaddr *)cp;
228                         if (sa->sa_len == dst->sa_len &&
229                             memcmp(sa, dst, sa->sa_len) == 0)
230                                 break;
231                         cp += RT_ROUNDUP(sa->sa_len);
232                 }
233                 if (cp == ep)
234                         return EEXIST;
235         }
236
237         /* Passed the filter. */
238         return 0;
239 }
240
241
242 /* pru_accept is EOPNOTSUPP */
243
244 static void
245 rts_attach(netmsg_t msg)
246 {
247         struct socket *so = msg->base.nm_so;
248         struct pru_attach_info *ai = msg->attach.nm_ai;
249         struct rawcb *rp;
250         struct routecb *rop;
251         int proto = msg->attach.nm_proto;
252         int error;
253
254         crit_enter();
255         if (sotorawcb(so) != NULL) {
256                 error = EISCONN;
257                 goto done;
258         }
259
260         rop = kmalloc(sizeof *rop, M_PCB, M_WAITOK | M_ZERO);
261         rp = &rop->rocb_rcb;
262
263         /*
264          * The critical section is necessary to block protocols from sending
265          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
266          * this PCB is extant but incompletely initialized.
267          * Probably we should try to do more of this work beforehand and
268          * eliminate the critical section.
269          */
270         so->so_pcb = rp;
271         soreference(so);        /* so_pcb assignment */
272         error = raw_attach(so, proto, ai->sb_rlimit);
273         rp = sotorawcb(so);
274         if (error) {
275                 kfree(rop, M_PCB);
276                 goto done;
277         }
278         switch(rp->rcb_proto.sp_protocol) {
279         case AF_INET:
280                 route_cb.ip_count++;
281                 break;
282         case AF_INET6:
283                 route_cb.ip6_count++;
284                 break;
285         }
286         rp->rcb_faddr = &route_src;
287         rp->rcb_filter = rts_filter;
288         route_cb.any_count++;
289         soisconnected(so);
290         so->so_options |= SO_USELOOPBACK;
291         error = 0;
292 done:
293         crit_exit();
294         lwkt_replymsg(&msg->lmsg, error);
295 }
296
297 static void
298 rts_bind(netmsg_t msg)
299 {
300         crit_enter();
301         raw_usrreqs.pru_bind(msg); /* xxx just EINVAL */
302         /* msg invalid now */
303         crit_exit();
304 }
305
306 static void
307 rts_connect(netmsg_t msg)
308 {
309         crit_enter();
310         raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */
311         /* msg invalid now */
312         crit_exit();
313 }
314
315 /* pru_connect2 is EOPNOTSUPP */
316 /* pru_control is EOPNOTSUPP */
317
318 static void
319 rts_detach(netmsg_t msg)
320 {
321         struct socket *so = msg->base.nm_so;
322         struct rawcb *rp = sotorawcb(so);
323         struct routecb *rop = (struct routecb *)rp;
324
325         crit_enter();
326         if (rop->rocb_missfilterlen != 0)
327                 kfree(rop->rocb_missfilter, M_PCB);
328         if (rp != NULL) {
329                 switch(rp->rcb_proto.sp_protocol) {
330                 case AF_INET:
331                         route_cb.ip_count--;
332                         break;
333                 case AF_INET6:
334                         route_cb.ip6_count--;
335                         break;
336                 }
337                 route_cb.any_count--;
338         }
339         raw_usrreqs.pru_detach(msg);
340         /* msg invalid now */
341         crit_exit();
342 }
343
344 static void
345 rts_disconnect(netmsg_t msg)
346 {
347         crit_enter();
348         raw_usrreqs.pru_disconnect(msg);
349         /* msg invalid now */
350         crit_exit();
351 }
352
353 /* pru_listen is EOPNOTSUPP */
354
355 static void
356 rts_peeraddr(netmsg_t msg)
357 {
358         crit_enter();
359         raw_usrreqs.pru_peeraddr(msg);
360         /* msg invalid now */
361         crit_exit();
362 }
363
364 /* pru_rcvd is EOPNOTSUPP */
365 /* pru_rcvoob is EOPNOTSUPP */
366
367 static void
368 rts_send(netmsg_t msg)
369 {
370         crit_enter();
371         raw_usrreqs.pru_send(msg);
372         /* msg invalid now */
373         crit_exit();
374 }
375
376 /* pru_sense is null */
377
378 static void
379 rts_shutdown(netmsg_t msg)
380 {
381         crit_enter();
382         raw_usrreqs.pru_shutdown(msg);
383         /* msg invalid now */
384         crit_exit();
385 }
386
387 static void
388 rts_sockaddr(netmsg_t msg)
389 {
390         crit_enter();
391         raw_usrreqs.pru_sockaddr(msg);
392         /* msg invalid now */
393         crit_exit();
394 }
395
396 static struct pr_usrreqs route_usrreqs = {
397         .pru_abort = rts_abort,
398         .pru_accept = pr_generic_notsupp,
399         .pru_attach = rts_attach,
400         .pru_bind = rts_bind,
401         .pru_connect = rts_connect,
402         .pru_connect2 = pr_generic_notsupp,
403         .pru_control = pr_generic_notsupp,
404         .pru_detach = rts_detach,
405         .pru_disconnect = rts_disconnect,
406         .pru_listen = pr_generic_notsupp,
407         .pru_peeraddr = rts_peeraddr,
408         .pru_rcvd = pr_generic_notsupp,
409         .pru_rcvoob = pr_generic_notsupp,
410         .pru_send = rts_send,
411         .pru_sense = pru_sense_null,
412         .pru_shutdown = rts_shutdown,
413         .pru_sockaddr = rts_sockaddr,
414         .pru_sosend = sosend,
415         .pru_soreceive = soreceive
416 };
417
418 static __inline sa_family_t
419 familyof(struct sockaddr *sa)
420 {
421         return (sa != NULL ? sa->sa_family : 0);
422 }
423
424 /*
425  * Routing socket input function.  The packet must be serialized onto cpu 0.
426  * We use the cpu0_soport() netisr processing loop to handle it.
427  *
428  * This looks messy but it means that anyone, including interrupt code,
429  * can send a message to the routing socket.
430  */
431 static void
432 rts_input_handler(netmsg_t msg)
433 {
434         static const struct sockaddr route_dst = { 2, PF_ROUTE, };
435         struct sockproto route_proto;
436         struct netmsg_packet *pmsg = &msg->packet;
437         struct mbuf *m;
438         sa_family_t family;
439         struct rawcb *skip;
440
441         family = pmsg->base.lmsg.u.ms_result;
442         route_proto.sp_family = PF_ROUTE;
443         route_proto.sp_protocol = family;
444
445         m = pmsg->nm_packet;
446         M_ASSERTPKTHDR(m);
447
448         skip = m->m_pkthdr.header;
449         m->m_pkthdr.header = NULL;
450
451         raw_input(m, &route_proto, &route_src, &route_dst, skip);
452 }
453
454 static void
455 rts_input_skip(struct mbuf *m, sa_family_t family, struct rawcb *skip)
456 {
457         struct netmsg_packet *pmsg;
458         lwkt_port_t port;
459
460         M_ASSERTPKTHDR(m);
461
462         port = netisr_cpuport(0);       /* XXX same as for routing socket */
463         pmsg = &m->m_hdr.mh_netmsg;
464         netmsg_init(&pmsg->base, NULL, &netisr_apanic_rport,
465                     0, rts_input_handler);
466         pmsg->nm_packet = m;
467         pmsg->base.lmsg.u.ms_result = family;
468         m->m_pkthdr.header = skip; /* XXX steal field in pkthdr */
469         lwkt_sendmsg(port, &pmsg->base.lmsg);
470 }
471
472 static __inline void
473 rts_input(struct mbuf *m, sa_family_t family)
474 {
475         rts_input_skip(m, family, NULL);
476 }
477
478 static void
479 route_ctloutput(netmsg_t msg)
480 {
481         struct socket *so = msg->ctloutput.base.nm_so;
482         struct sockopt *sopt = msg->ctloutput.nm_sopt;
483         struct routecb *rop = sotoroutecb(so);
484         int error;
485         unsigned int msgfilter;
486         unsigned char *cp, *ep;
487         size_t len;
488         struct sockaddr *sa;
489
490         if (sopt->sopt_level != AF_ROUTE) {
491                 error = EINVAL;
492                 goto out;
493         }
494
495         error = 0;
496
497         switch (sopt->sopt_dir) {
498         case SOPT_SET:
499                 switch (sopt->sopt_name) {
500                 case ROUTE_MSGFILTER:
501                         error = soopt_to_kbuf(sopt, &msgfilter,
502                             sizeof(msgfilter), sizeof(msgfilter));
503                         if (error == 0)
504                                 rop->rocb_msgfilter = msgfilter;
505                         break;
506                 case RO_MISSFILTER:
507                         /* Validate the data */
508                         len = 0;
509                         cp = sopt->sopt_val;
510                         ep = cp + sopt->sopt_valsize;
511                         while (cp < ep) {
512                                 if (ep - cp <
513                                     offsetof(struct sockaddr, sa_len) +
514                                     sizeof(sa->sa_len))
515                                         break;
516                                 if (++len > RO_FILTSA_MAX) {
517                                         error = ENOBUFS;
518                                         break;
519                                 }
520                                 sa = (struct sockaddr *)cp;
521                                 if (sa->sa_len < _SA_MINSIZE ||
522                                     sa->sa_len > sizeof(struct sockaddr_storage))
523                                         break;
524                                 cp += RT_ROUNDUP(sa->sa_len);
525                         }
526                         if (cp != ep) {
527                                 if (error == 0)
528                                         error = EINVAL;
529                                 break;
530                         }
531                         if (rop->rocb_missfilterlen != 0)
532                                 kfree(rop->rocb_missfilter, M_PCB);
533                         if (sopt->sopt_valsize != 0) {
534                                 rop->rocb_missfilter =
535                                     kmalloc(sopt->sopt_valsize,
536                                             M_PCB, M_WAITOK | M_NULLOK);
537                                 if (rop->rocb_missfilter == NULL) {
538                                         rop->rocb_missfilterlen = 0;
539                                         error = ENOBUFS;
540                                         break;
541                                 }
542                         } else
543                                 rop->rocb_missfilter = NULL;
544                         rop->rocb_missfilterlen = sopt->sopt_valsize;
545                         if (rop->rocb_missfilterlen != 0)
546                                 memcpy(rop->rocb_missfilter, sopt->sopt_val,
547                                     rop->rocb_missfilterlen);
548                         break;
549                 default:
550                         error = ENOPROTOOPT;
551                         break;
552                 }
553                 break;
554         case SOPT_GET:
555                 switch (sopt->sopt_name) {
556                 case ROUTE_MSGFILTER:
557                         msgfilter = rop->rocb_msgfilter;
558                         soopt_from_kbuf(sopt, &msgfilter, sizeof(msgfilter));
559                         break;
560                 case RO_MISSFILTER:
561                         soopt_from_kbuf(sopt, rop->rocb_missfilter,
562                             rop->rocb_missfilterlen);
563                         break;
564                 default:
565                         error = ENOPROTOOPT;
566                         break;
567                 }
568         }
569 out:
570         lwkt_replymsg(&msg->ctloutput.base.lmsg, error);
571 }
572
573
574
575 static void *
576 reallocbuf_nofree(void *ptr, size_t len, size_t olen)
577 {
578         void *newptr;
579
580         newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
581         if (newptr == NULL)
582                 return NULL;
583         bcopy(ptr, newptr, olen);
584         if (olen < len)
585                 bzero((char *)newptr + olen, len - olen);
586
587         return (newptr);
588 }
589
590 /*
591  * Internal helper routine for route_output().
592  */
593 static int
594 _fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt,
595            struct rt_addrinfo *rtinfo)
596 {
597         int msglen;
598         struct rt_msghdr *rtm = *prtm;
599
600         /* Fill in rt_addrinfo for call to rt_msg_buffer(). */
601         rtinfo->rti_dst = rt_key(rt);
602         rtinfo->rti_gateway = rt->rt_gateway;
603         rtinfo->rti_netmask = rt_mask(rt);              /* might be NULL */
604         rtinfo->rti_genmask = rt->rt_genmask;           /* might be NULL */
605         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
606                 if (rt->rt_ifp != NULL) {
607                         rtinfo->rti_ifpaddr =
608                             TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])
609                             ->ifa->ifa_addr;
610                         rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr;
611                         if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
612                                 rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
613                         rtm->rtm_index = rt->rt_ifp->if_index;
614                 } else {
615                         rtinfo->rti_ifpaddr = NULL;
616                         rtinfo->rti_ifaaddr = NULL;
617                 }
618         } else if (rt->rt_ifp != NULL) {
619                 rtm->rtm_index = rt->rt_ifp->if_index;
620         }
621
622         msglen = rt_msgsize(rtm->rtm_type, rtinfo);
623         if (rtm->rtm_msglen < msglen) {
624                 /* NOTE: Caller will free the old rtm accordingly */
625                 rtm = reallocbuf_nofree(rtm, msglen, rtm->rtm_msglen);
626                 if (rtm == NULL)
627                         return (ENOBUFS);
628                 *prtm = rtm;
629         }
630         rt_msg_buffer(rtm->rtm_type, rtinfo, rtm, msglen);
631
632         rtm->rtm_flags = rt->rt_flags;
633         rtm->rtm_rmx = rt->rt_rmx;
634         rtm->rtm_addrs = rtinfo->rti_addrs;
635
636         return (0);
637 }
638
639 struct rtm_arg {
640         struct rt_msghdr        *bak_rtm;
641         struct rt_msghdr        *new_rtm;
642 };
643
644 static int
645 fillrtmsg(struct rtm_arg *arg, struct rtentry *rt,
646           struct rt_addrinfo *rtinfo)
647 {
648         struct rt_msghdr *rtm = arg->new_rtm;
649         int error;
650
651         error = _fillrtmsg(&rtm, rt, rtinfo);
652         if (!error) {
653                 if (arg->new_rtm != rtm) {
654                         /*
655                          * _fillrtmsg() just allocated a new rtm;
656                          * if the previously allocated rtm is not
657                          * the backing rtm, it should be freed.
658                          */
659                         if (arg->new_rtm != arg->bak_rtm)
660                                 kfree(arg->new_rtm, M_RTABLE);
661                         arg->new_rtm = rtm;
662                 }
663         }
664         return error;
665 }
666
667 static void route_output_add_callback(int, int, struct rt_addrinfo *,
668                                         struct rtentry *, void *);
669 static void route_output_delete_callback(int, int, struct rt_addrinfo *,
670                                         struct rtentry *, void *);
671 static int route_output_get_callback(int, struct rt_addrinfo *,
672                                      struct rtentry *, void *, int);
673 static int route_output_change_callback(int, struct rt_addrinfo *,
674                                         struct rtentry *, void *, int);
675 static int route_output_lock_callback(int, struct rt_addrinfo *,
676                                       struct rtentry *, void *, int);
677
678 /*ARGSUSED*/
679 static int
680 route_output(struct mbuf *m, struct socket *so, ...)
681 {
682         struct rtm_arg arg;
683         struct rt_msghdr *rtm = NULL;
684         struct rawcb *rp = NULL;
685         struct pr_output_info *oi;
686         struct rt_addrinfo rtinfo;
687         sa_family_t family;
688         int len, error = 0;
689         __va_list ap;
690
691         M_ASSERTPKTHDR(m);
692
693         __va_start(ap, so);
694         oi = __va_arg(ap, struct pr_output_info *);
695         __va_end(ap);
696
697         family = familyof(NULL);
698
699         if (m == NULL ||
700             (m->m_len < sizeof(long) &&
701              (m = m_pullup(m, sizeof(long))) == NULL))
702                 return (ENOBUFS);
703
704 #define gotoerr(e) { error = e; goto flush; }
705
706         len = m->m_pkthdr.len;
707         if (len < sizeof(struct rt_msghdr) ||
708             len != mtod(m, struct rt_msghdr *)->rtm_msglen)
709                 gotoerr(EINVAL);
710
711         rtm = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
712         if (rtm == NULL)
713                 gotoerr(ENOBUFS);
714
715         m_copydata(m, 0, len, rtm);
716         if (rtm->rtm_version != RTM_VERSION)
717                 gotoerr(EPROTONOSUPPORT);
718
719         rtm->rtm_pid = oi->p_pid;
720         bzero(&rtinfo, sizeof(struct rt_addrinfo));
721         rtinfo.rti_addrs = rtm->rtm_addrs;
722         if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0)
723                 gotoerr(EINVAL);
724
725         rtinfo.rti_flags = rtm->rtm_flags;
726         if (rtinfo.rti_dst == NULL || rtinfo.rti_dst->sa_family >= AF_MAX ||
727             (rtinfo.rti_gateway && rtinfo.rti_gateway->sa_family >= AF_MAX))
728                 gotoerr(EINVAL);
729
730         family = familyof(rtinfo.rti_dst);
731
732         /*
733          * Verify that the caller has the appropriate privilege; RTM_GET
734          * is the only operation the non-superuser is allowed.
735          */
736         if (rtm->rtm_type != RTM_GET &&
737             caps_priv_check(so->so_cred, SYSCAP_RESTRICTEDROOT) != 0)
738                 gotoerr(EPERM);
739
740         if (rtinfo.rti_genmask != NULL) {
741                 error = rtmask_add_global(rtinfo.rti_genmask,
742                     rtm->rtm_type != RTM_GET ?
743                     RTREQ_PRIO_HIGH : RTREQ_PRIO_NORM);
744                 if (error)
745                         goto flush;
746         }
747
748         switch (rtm->rtm_type) {
749         case RTM_ADD:
750                 if (rtinfo.rti_gateway == NULL) {
751                         error = EINVAL;
752                 } else {
753                         error = rtrequest1_global(RTM_ADD, &rtinfo,
754                             route_output_add_callback, rtm, RTREQ_PRIO_HIGH);
755                 }
756                 break;
757         case RTM_DELETE:
758                 /*
759                  * Backing rtm (bak_rtm) could _not_ be freed during
760                  * rtrequest1_global or rtsearch_global, even if the
761                  * callback reallocates the rtm due to its size changes,
762                  * since rtinfo points to the backing rtm's memory area.
763                  * After rtrequest1_global or rtsearch_global returns,
764                  * it is safe to free the backing rtm, since rtinfo will
765                  * not be used anymore.
766                  *
767                  * new_rtm will be used to save the new rtm allocated
768                  * by rtrequest1_global or rtsearch_global.
769                  */
770                 arg.bak_rtm = rtm;
771                 arg.new_rtm = rtm;
772                 error = rtrequest1_global(RTM_DELETE, &rtinfo,
773                     route_output_delete_callback, &arg, RTREQ_PRIO_HIGH);
774                 rtm = arg.new_rtm;
775                 if (rtm != arg.bak_rtm)
776                         kfree(arg.bak_rtm, M_RTABLE);
777                 break;
778         case RTM_GET:
779                 /* See the comment in RTM_DELETE */
780                 arg.bak_rtm = rtm;
781                 arg.new_rtm = rtm;
782                 error = rtsearch_global(RTM_GET, &rtinfo,
783                     route_output_get_callback, &arg, RTS_NOEXACTMATCH,
784                     RTREQ_PRIO_NORM);
785                 rtm = arg.new_rtm;
786                 if (rtm != arg.bak_rtm)
787                         kfree(arg.bak_rtm, M_RTABLE);
788                 break;
789         case RTM_CHANGE:
790                 error = rtsearch_global(RTM_CHANGE, &rtinfo,
791                     route_output_change_callback, rtm, RTS_EXACTMATCH,
792                     RTREQ_PRIO_HIGH);
793                 break;
794         case RTM_LOCK:
795                 error = rtsearch_global(RTM_LOCK, &rtinfo,
796                     route_output_lock_callback, rtm, RTS_EXACTMATCH,
797                     RTREQ_PRIO_HIGH);
798                 break;
799         default:
800                 error = EOPNOTSUPP;
801                 break;
802         }
803
804 #undef gotoerr
805
806 flush:
807         if (rtm != NULL) {
808                 if (error != 0)
809                         rtm->rtm_errno = error;
810                 else
811                         rtm->rtm_flags |= RTF_DONE;
812         }
813
814         /*
815          * Check to see if we don't want our own messages.
816          */
817         if (!(so->so_options & SO_USELOOPBACK)) {
818                 if (route_cb.any_count <= 1) {
819                         if (rtm != NULL)
820                                 kfree(rtm, M_RTABLE);
821                         m_freem(m);
822                         return (error);
823                 }
824                 /* There is another listener, so construct message */
825                 rp = sotorawcb(so);
826         }
827         if (rtm != NULL) {
828                 if (m_copyback2(m, 0, rtm->rtm_msglen, rtm, M_NOWAIT) != 0) {
829                         m_freem(m);
830                         m = NULL;
831                 } else if (m->m_pkthdr.len > rtm->rtm_msglen) {
832                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
833                 }
834                 kfree(rtm, M_RTABLE);
835         }
836         if (m != NULL)
837                 rts_input_skip(m, family, rp);
838         return (error);
839 }
840
841 static void
842 route_output_add_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
843                           struct rtentry *rt, void *arg)
844 {
845         struct rt_msghdr *rtm = arg;
846
847         if (error == 0 && rt != NULL) {
848                 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
849                     &rt->rt_rmx);
850                 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
851                 rt->rt_rmx.rmx_locks |=
852                     (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
853                 if (rtinfo->rti_genmask != NULL) {
854                         rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask);
855                         if (rt->rt_genmask == NULL) {
856                                 /*
857                                  * This should not happen, since we
858                                  * have already installed genmask
859                                  * on each CPU before we reach here.
860                                  */
861                                 panic("genmask is gone!?");
862                         }
863                 } else {
864                         rt->rt_genmask = NULL;
865                 }
866                 rtm->rtm_index = rt->rt_ifp->if_index;
867         }
868 }
869
870 static void
871 route_output_delete_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
872                           struct rtentry *rt, void *arg)
873 {
874         if (error == 0 && rt) {
875                 ++rt->rt_refcnt;
876                 if (fillrtmsg(arg, rt, rtinfo) != 0) {
877                         error = ENOBUFS;
878                         /* XXX no way to return the error */
879                 }
880                 --rt->rt_refcnt;
881         }
882         if (rt && rt->rt_refcnt == 0) {
883                 ++rt->rt_refcnt;
884                 rtfree(rt);
885         }
886 }
887
888 static int
889 route_output_get_callback(int cmd, struct rt_addrinfo *rtinfo,
890                           struct rtentry *rt, void *arg, int found_cnt)
891 {
892         int error, found = 0;
893
894         if (((rtinfo->rti_flags ^ rt->rt_flags) & RTF_HOST) == 0)
895                 found = 1;
896
897         error = fillrtmsg(arg, rt, rtinfo);
898         if (!error && found) {
899                 /* Got the exact match, we could return now! */
900                 error = EJUSTRETURN;
901         }
902         return error;
903 }
904
905 static int
906 route_output_change_callback(int cmd, struct rt_addrinfo *rtinfo,
907                              struct rtentry *rt, void *arg, int found_cnt)
908 {
909         struct rt_msghdr *rtm = arg;
910         struct ifaddr *ifa;
911         int error = 0;
912
913         /*
914          * new gateway could require new ifaddr, ifp;
915          * flags may also be different; ifp may be specified
916          * by ll sockaddr when protocol address is ambiguous
917          */
918         if (((rt->rt_flags & RTF_GATEWAY) && rtinfo->rti_gateway != NULL) ||
919             rtinfo->rti_ifpaddr != NULL ||
920             (rtinfo->rti_ifaaddr != NULL &&
921              !sa_equal(rtinfo->rti_ifaaddr, rt->rt_ifa->ifa_addr))) {
922                 error = rt_getifa(rtinfo);
923                 if (error != 0)
924                         goto done;
925         }
926         if (rtinfo->rti_gateway != NULL) {
927                 /*
928                  * We only need to generate rtmsg upon the
929                  * first route to be changed.
930                  */
931                 error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway);
932                 if (error != 0)
933                         goto done;
934         }
935         if ((ifa = rtinfo->rti_ifa) != NULL) {
936                 struct ifaddr *oifa = rt->rt_ifa;
937
938                 if (oifa != ifa) {
939                         if (oifa && oifa->ifa_rtrequest)
940                                 oifa->ifa_rtrequest(RTM_DELETE, rt);
941                         IFAFREE(rt->rt_ifa);
942                         IFAREF(ifa);
943                         rt->rt_ifa = ifa;
944                         rt->rt_ifp = rtinfo->rti_ifp;
945                 }
946         }
947         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
948         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
949                 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt);
950         if (rtinfo->rti_genmask != NULL) {
951                 rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask);
952                 if (rt->rt_genmask == NULL) {
953                         /*
954                          * This should not happen, since we
955                          * have already installed genmask
956                          * on each CPU before we reach here.
957                          */
958                         panic("genmask is gone!?");
959                 }
960         }
961         rtm->rtm_index = rt->rt_ifp->if_index;
962         if (found_cnt == 1)
963                 rt_rtmsg(RTM_CHANGE, rt, rt->rt_ifp, 0);
964 done:
965         return error;
966 }
967
968 static int
969 route_output_lock_callback(int cmd, struct rt_addrinfo *rtinfo,
970                            struct rtentry *rt, void *arg,
971                            int found_cnt __unused)
972 {
973         struct rt_msghdr *rtm = arg;
974
975         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
976         rt->rt_rmx.rmx_locks |=
977                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
978         return 0;
979 }
980
981 static void
982 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
983 {
984 #define setmetric(flag, elt) if (which & (flag)) out->elt = in->elt;
985         setmetric(RTV_RPIPE, rmx_recvpipe);
986         setmetric(RTV_SPIPE, rmx_sendpipe);
987         setmetric(RTV_SSTHRESH, rmx_ssthresh);
988         setmetric(RTV_RTT, rmx_rtt);
989         setmetric(RTV_RTTVAR, rmx_rttvar);
990         setmetric(RTV_HOPCOUNT, rmx_hopcount);
991         setmetric(RTV_MTU, rmx_mtu);
992         setmetric(RTV_EXPIRE, rmx_expire);
993         setmetric(RTV_MSL, rmx_msl);
994         setmetric(RTV_IWMAXSEGS, rmx_iwmaxsegs);
995         setmetric(RTV_IWCAPSEGS, rmx_iwcapsegs);
996 #undef setmetric
997 }
998
999 /*
1000  * Extract the addresses of the passed sockaddrs.
1001  * Do a little sanity checking so as to avoid bad memory references.
1002  * This data is derived straight from userland.
1003  */
1004 static int
1005 rt_xaddrs(char *cp, char *cplim, struct rt_addrinfo *rtinfo)
1006 {
1007         struct sockaddr *sa;
1008         int i;
1009
1010         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
1011                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
1012                         continue;
1013                 sa = (struct sockaddr *)cp;
1014                 /*
1015                  * It won't fit.
1016                  */
1017                 if ((cp + sa->sa_len) > cplim) {
1018                         return (EINVAL);
1019                 }
1020
1021                 /*
1022                  * There are no more...  Quit now.
1023                  * If there are more bits, they are in error.
1024                  * I've seen this.  route(1) can evidently generate these.
1025                  * This causes kernel to core dump.
1026                  * For compatibility, if we see this, point to a safe address.
1027                  */
1028                 if (sa->sa_len == 0) {
1029                         static struct sockaddr sa_zero = {
1030                                 sizeof sa_zero, AF_INET,
1031                         };
1032
1033                         rtinfo->rti_info[i] = &sa_zero;
1034                         kprintf("rtsock: received more addr bits than sockaddrs.\n");
1035                         return (0); /* should be EINVAL but for compat */
1036                 }
1037
1038                 /* Accept the sockaddr. */
1039                 rtinfo->rti_info[i] = sa;
1040                 cp += RT_ROUNDUP(sa->sa_len);
1041         }
1042         return (0);
1043 }
1044
1045 static int
1046 rt_msghdrsize(int type)
1047 {
1048         switch (type) {
1049         case RTM_DELADDR:
1050         case RTM_NEWADDR:
1051                 return sizeof(struct ifa_msghdr);
1052         case RTM_DELMADDR:
1053         case RTM_NEWMADDR:
1054                 return sizeof(struct ifma_msghdr);
1055         case RTM_IFINFO:
1056                 return sizeof(struct if_msghdr);
1057         case RTM_IFANNOUNCE:
1058         case RTM_IEEE80211:
1059                 return sizeof(struct if_announcemsghdr);
1060         default:
1061                 return sizeof(struct rt_msghdr);
1062         }
1063 }
1064
1065 static int
1066 rt_msgsize(int type, const struct rt_addrinfo *rtinfo)
1067 {
1068         int len, i;
1069
1070         len = rt_msghdrsize(type);
1071         for (i = 0; i < RTAX_MAX; i++) {
1072                 if (rtinfo->rti_info[i] != NULL)
1073                         len += RT_ROUNDUP(rtinfo->rti_info[i]->sa_len);
1074         }
1075         len = ALIGN(len);
1076         return len;
1077 }
1078
1079 /*
1080  * Build a routing message in a buffer.
1081  * Copy the addresses in the rtinfo->rti_info[] sockaddr array
1082  * to the end of the buffer after the message header.
1083  *
1084  * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
1085  * This side-effect can be avoided if we reorder the addrs bitmask field in all
1086  * the route messages to line up so we can set it here instead of back in the
1087  * calling routine.
1088  *
1089  * NOTE! The buffer may already contain a partially filled-out rtm via
1090  *       _fillrtmsg().
1091  */
1092 static void
1093 rt_msg_buffer(int type, struct rt_addrinfo *rtinfo, void *buf, int msglen)
1094 {
1095         struct rt_msghdr *rtm;
1096         char *cp;
1097         int dlen, i;
1098
1099         rtm = (struct rt_msghdr *) buf;
1100         rtm->rtm_version = RTM_VERSION;
1101         rtm->rtm_type = type;
1102         rtm->rtm_msglen = msglen;
1103
1104         cp = (char *)buf + rt_msghdrsize(type);
1105         rtinfo->rti_addrs = 0;
1106         for (i = 0; i < RTAX_MAX; i++) {
1107                 struct sockaddr *sa;
1108
1109                 if ((sa = rtinfo->rti_info[i]) == NULL)
1110                         continue;
1111                 rtinfo->rti_addrs |= (1 << i);
1112                 dlen = RT_ROUNDUP(sa->sa_len);
1113                 bcopy(sa, cp, dlen);
1114                 cp += dlen;
1115         }
1116 }
1117
1118 /*
1119  * Build a routing message in a mbuf chain.
1120  * Copy the addresses in the rtinfo->rti_info[] sockaddr array
1121  * to the end of the mbuf after the message header.
1122  *
1123  * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
1124  * This side-effect can be avoided if we reorder the addrs bitmask field in all
1125  * the route messages to line up so we can set it here instead of back in the
1126  * calling routine.
1127  */
1128 static struct mbuf *
1129 rt_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
1130 {
1131         struct mbuf *m, *n;
1132         struct rt_msghdr *rtm;
1133         struct sockaddr *sa;
1134         int hlen, dlen, len, i;
1135
1136         hlen = rt_msghdrsize(type);
1137         KASSERT(hlen <= MCLBYTES, ("rt_msg_mbuf: hlen %d doesn't fit", hlen));
1138
1139         /* Determine the required mbuf (chain) length. */
1140         len = hlen;
1141         for (i = 0; i < RTAX_MAX; i++) {
1142                 if ((sa = rtinfo->rti_info[i]) == NULL)
1143                         continue;
1144                 len += RT_ROUNDUP(sa->sa_len);
1145         }
1146
1147         /* Allocate the mbuf header and possible chain. */
1148         m = m_getl(len, M_NOWAIT, MT_DATA, M_PKTHDR, &dlen);
1149         if (m == NULL)
1150                 return (NULL);
1151         if (len > dlen) {
1152                 n = m_getc(len - dlen, M_NOWAIT, MT_DATA);
1153                 if (n == NULL) {
1154                         m_freem(m);
1155                         return (NULL);
1156                 }
1157                 m_cat(m, n);
1158         }
1159         mbuftrackid(m, 32);
1160
1161         m->m_pkthdr.len = m->m_len = hlen; /* rtinfo->rti_info[] can be empty */
1162         m->m_pkthdr.rcvif = NULL;
1163         rtinfo->rti_addrs = 0;
1164         len = hlen;
1165         for (i = 0; i < RTAX_MAX; i++) {
1166                 if ((sa = rtinfo->rti_info[i]) == NULL)
1167                         continue;
1168                 rtinfo->rti_addrs |= (1 << i);
1169                 dlen = RT_ROUNDUP(sa->sa_len);
1170                 m_copyback(m, len, dlen, sa);
1171                 len += dlen;
1172         }
1173         rtm = mtod(m, struct rt_msghdr *);
1174         bzero(rtm, hlen);
1175         rtm->rtm_msglen = len;
1176         rtm->rtm_version = RTM_VERSION;
1177         rtm->rtm_type = type;
1178         return (m);
1179 }
1180
1181 /*
1182  * This routine is called to generate a message from the routing
1183  * socket indicating that a redirect has occurred, a routing lookup
1184  * has failed, or that a protocol has detected timeouts to a particular
1185  * destination.
1186  */
1187 void
1188 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
1189 {
1190         struct sockaddr *dst = rtinfo->rti_info[RTAX_DST];
1191         struct rt_msghdr *rtm;
1192         struct mbuf *m;
1193
1194         if (route_cb.any_count == 0)
1195                 return;
1196         m = rt_msg_mbuf(type, rtinfo);
1197         if (m == NULL)
1198                 return;
1199         rtm = mtod(m, struct rt_msghdr *);
1200         rtm->rtm_flags = RTF_DONE | flags;
1201         rtm->rtm_errno = error;
1202         rtm->rtm_addrs = rtinfo->rti_addrs;
1203         rts_input(m, familyof(dst));
1204 }
1205
1206 void
1207 rt_dstmsg(int type, struct sockaddr *dst, int error)
1208 {
1209         struct rt_msghdr *rtm;
1210         struct rt_addrinfo addrs;
1211         struct mbuf *m;
1212
1213         if (route_cb.any_count == 0)
1214                 return;
1215         bzero(&addrs, sizeof(struct rt_addrinfo));
1216         addrs.rti_info[RTAX_DST] = dst;
1217         m = rt_msg_mbuf(type, &addrs);
1218         if (m == NULL)
1219                 return;
1220         rtm = mtod(m, struct rt_msghdr *);
1221         rtm->rtm_flags = RTF_DONE;
1222         rtm->rtm_errno = error;
1223         rtm->rtm_addrs = addrs.rti_addrs;
1224         rts_input(m, familyof(dst));
1225 }
1226
1227 /*
1228  * This routine is called to generate a message from the routing
1229  * socket indicating that the status of a network interface has changed.
1230  */
1231 void
1232 rt_ifmsg(struct ifnet *ifp)
1233 {
1234         struct if_msghdr *ifm;
1235         struct mbuf *m;
1236         struct rt_addrinfo rtinfo;
1237
1238         if (route_cb.any_count == 0)
1239                 return;
1240         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1241         m = rt_msg_mbuf(RTM_IFINFO, &rtinfo);
1242         if (m == NULL)
1243                 return;
1244         ifm = mtod(m, struct if_msghdr *);
1245         ifm->ifm_index = ifp->if_index;
1246         ifm->ifm_flags = ifp->if_flags;
1247         ifm->ifm_data = ifp->if_data;
1248         ifm->ifm_addrs = 0;
1249         rts_input(m, 0);
1250 }
1251
1252 static void
1253 rt_ifamsg(int cmd, struct ifaddr *ifa)
1254 {
1255         struct ifa_msghdr *ifam;
1256         struct rt_addrinfo rtinfo;
1257         struct mbuf *m;
1258         struct ifnet *ifp = ifa->ifa_ifp;
1259
1260         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1261         rtinfo.rti_ifaaddr = ifa->ifa_addr;
1262         rtinfo.rti_ifpaddr =
1263                 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1264         rtinfo.rti_netmask = ifa->ifa_netmask;
1265         rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1266
1267         m = rt_msg_mbuf(cmd, &rtinfo);
1268         if (m == NULL)
1269                 return;
1270
1271         ifam = mtod(m, struct ifa_msghdr *);
1272         ifam->ifam_index = ifp->if_index;
1273         ifam->ifam_flags = ifa->ifa_flags;
1274         ifam->ifam_addrs = rtinfo.rti_addrs;
1275         ifam->ifam_addrflags = if_addrflags(ifa);
1276         ifam->ifam_metric = ifa->ifa_metric;
1277
1278         rts_input(m, familyof(ifa->ifa_addr));
1279 }
1280
1281 void
1282 rt_rtmsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int error)
1283 {
1284         struct rt_msghdr *rtm;
1285         struct rt_addrinfo rtinfo;
1286         struct mbuf *m;
1287         struct sockaddr *dst;
1288
1289         if (rt == NULL)
1290                 return;
1291
1292         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1293         rtinfo.rti_dst = dst = rt_key(rt);
1294         rtinfo.rti_gateway = rt->rt_gateway;
1295         rtinfo.rti_netmask = rt_mask(rt);
1296         if (ifp != NULL) {
1297                 rtinfo.rti_ifpaddr =
1298                 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1299         }
1300         if (rt->rt_ifa != NULL)
1301                 rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr;
1302
1303         m = rt_msg_mbuf(cmd, &rtinfo);
1304         if (m == NULL)
1305                 return;
1306
1307         rtm = mtod(m, struct rt_msghdr *);
1308         if (ifp != NULL)
1309                 rtm->rtm_index = ifp->if_index;
1310         rtm->rtm_flags |= rt->rt_flags;
1311         rtm->rtm_errno = error;
1312         rtm->rtm_addrs = rtinfo.rti_addrs;
1313
1314         rts_input(m, familyof(dst));
1315 }
1316
1317 /*
1318  * This is called to generate messages from the routing socket
1319  * indicating a network interface has had addresses associated with it.
1320  * if we ever reverse the logic and replace messages TO the routing
1321  * socket indicate a request to configure interfaces, then it will
1322  * be unnecessary as the routing socket will automatically generate
1323  * copies of it.
1324  */
1325 void
1326 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1327 {
1328         if (route_cb.any_count == 0)
1329                 return;
1330
1331         if (cmd == RTM_ADD) {
1332                 rt_ifamsg(RTM_NEWADDR, ifa);
1333                 rt_rtmsg(RTM_ADD, rt, ifa->ifa_ifp, error);
1334         } else {
1335                 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
1336                 rt_rtmsg(RTM_DELETE, rt, ifa->ifa_ifp, error);
1337                 rt_ifamsg(RTM_DELADDR, ifa);
1338         }
1339 }
1340
1341 /*
1342  * This is the analogue to the rt_newaddrmsg which performs the same
1343  * function but for multicast group memberhips.  This is easier since
1344  * there is no route state to worry about.
1345  */
1346 void
1347 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1348 {
1349         struct rt_addrinfo rtinfo;
1350         struct mbuf *m = NULL;
1351         struct ifnet *ifp = ifma->ifma_ifp;
1352         struct ifma_msghdr *ifmam;
1353
1354         if (route_cb.any_count == 0)
1355                 return;
1356
1357         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1358         rtinfo.rti_ifaaddr = ifma->ifma_addr;
1359         if (ifp != NULL && !TAILQ_EMPTY(&ifp->if_addrheads[mycpuid])) {
1360                 rtinfo.rti_ifpaddr =
1361                 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1362         }
1363         /*
1364          * If a link-layer address is present, present it as a ``gateway''
1365          * (similarly to how ARP entries, e.g., are presented).
1366          */
1367         rtinfo.rti_gateway = ifma->ifma_lladdr;
1368
1369         m = rt_msg_mbuf(cmd, &rtinfo);
1370         if (m == NULL)
1371                 return;
1372
1373         ifmam = mtod(m, struct ifma_msghdr *);
1374         ifmam->ifmam_index = ifp->if_index;
1375         ifmam->ifmam_addrs = rtinfo.rti_addrs;
1376
1377         rts_input(m, familyof(ifma->ifma_addr));
1378 }
1379
1380 static struct mbuf *
1381 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
1382                      struct rt_addrinfo *info)
1383 {
1384         struct if_announcemsghdr *ifan;
1385         struct mbuf *m;
1386
1387         if (route_cb.any_count == 0)
1388                 return NULL;
1389
1390         bzero(info, sizeof(*info));
1391         m = rt_msg_mbuf(type, info);
1392         if (m == NULL)
1393                 return NULL;
1394
1395         ifan = mtod(m, struct if_announcemsghdr *);
1396         ifan->ifan_index = ifp->if_index;
1397         strlcpy(ifan->ifan_name, ifp->if_xname, sizeof ifan->ifan_name);
1398         ifan->ifan_what = what;
1399         return m;
1400 }
1401
1402 /*
1403  * This is called to generate routing socket messages indicating
1404  * IEEE80211 wireless events.
1405  * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
1406  */
1407 void
1408 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
1409 {
1410         struct rt_addrinfo info;
1411         struct mbuf *m;
1412
1413         m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
1414         if (m == NULL)
1415                 return;
1416
1417         /*
1418          * Append the ieee80211 data.  Try to stick it in the
1419          * mbuf containing the ifannounce msg; otherwise allocate
1420          * a new mbuf and append.
1421          *
1422          * NB: we assume m is a single mbuf.
1423          */
1424         if (data_len > M_TRAILINGSPACE(m)) {
1425                 /* XXX use m_getb(data_len, M_NOWAIT, MT_DATA, 0); */
1426                 struct mbuf *n = m_get(M_NOWAIT, MT_DATA);
1427                 if (n == NULL) {
1428                         m_freem(m);
1429                         return;
1430                 }
1431                 KKASSERT(data_len <= M_TRAILINGSPACE(n));
1432                 bcopy(data, mtod(n, void *), data_len);
1433                 n->m_len = data_len;
1434                 m->m_next = n;
1435         } else if (data_len > 0) {
1436                 bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len);
1437                 m->m_len += data_len;
1438         }
1439         mbuftrackid(m, 33);
1440         if (m->m_flags & M_PKTHDR)
1441                 m->m_pkthdr.len += data_len;
1442         mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
1443         rts_input(m, 0);
1444 }
1445
1446 /*
1447  * This is called to generate routing socket messages indicating
1448  * network interface arrival and departure.
1449  */
1450 void
1451 rt_ifannouncemsg(struct ifnet *ifp, int what)
1452 {
1453         struct rt_addrinfo addrinfo;
1454         struct mbuf *m;
1455
1456         m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &addrinfo);
1457         if (m != NULL)
1458                 rts_input(m, 0);
1459 }
1460
1461 static int
1462 resizewalkarg(struct walkarg *w, int len)
1463 {
1464         void *newptr;
1465
1466         newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
1467         if (newptr == NULL)
1468                 return (ENOMEM);
1469         if (w->w_tmem != NULL)
1470                 kfree(w->w_tmem, M_RTABLE);
1471         w->w_tmem = newptr;
1472         w->w_tmemsize = len;
1473         bzero(newptr, len);
1474
1475         return (0);
1476 }
1477
1478 static void
1479 ifnet_compute_stats(struct ifnet *ifp)
1480 {
1481         IFNET_STAT_GET(ifp, ipackets, ifp->if_ipackets);
1482         IFNET_STAT_GET(ifp, ierrors, ifp->if_ierrors);
1483         IFNET_STAT_GET(ifp, opackets, ifp->if_opackets);
1484         IFNET_STAT_GET(ifp, collisions, ifp->if_collisions);
1485         IFNET_STAT_GET(ifp, ibytes, ifp->if_ibytes);
1486         IFNET_STAT_GET(ifp, obytes, ifp->if_obytes);
1487         IFNET_STAT_GET(ifp, imcasts, ifp->if_imcasts);
1488         IFNET_STAT_GET(ifp, omcasts, ifp->if_omcasts);
1489         IFNET_STAT_GET(ifp, iqdrops, ifp->if_iqdrops);
1490         IFNET_STAT_GET(ifp, noproto, ifp->if_noproto);
1491         IFNET_STAT_GET(ifp, oqdrops, ifp->if_oqdrops);
1492 }
1493
1494 static int
1495 if_addrflags(const struct ifaddr *ifa)
1496 {
1497         switch (ifa->ifa_addr->sa_family) {
1498 #ifdef INET6
1499         case AF_INET6:
1500                 return ((const struct in6_ifaddr *)ifa)->ia6_flags;
1501 #endif
1502         default:
1503                 return 0;
1504         }
1505 }
1506
1507 static int
1508 sysctl_iflist(int af, struct walkarg *w)
1509 {
1510         struct ifnet *ifp;
1511         struct rt_addrinfo rtinfo;
1512         int msglen, error;
1513
1514         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1515
1516         ifnet_lock();
1517         TAILQ_FOREACH(ifp, &ifnetlist, if_link) {
1518                 struct ifaddr_container *ifac, *ifac_mark;
1519                 struct ifaddr_marker mark;
1520                 struct ifaddrhead *head;
1521                 struct ifaddr *ifa;
1522
1523                 if (w->w_arg && w->w_arg != ifp->if_index)
1524                         continue;
1525                 head = &ifp->if_addrheads[mycpuid];
1526                 /*
1527                  * There is no need to reference the first ifaddr
1528                  * even if the following resizewalkarg() blocks,
1529                  * since the first ifaddr will not be destroyed
1530                  * when the ifnet lock is held.
1531                  */
1532                 ifac = TAILQ_FIRST(head);
1533                 ifa = ifac->ifa;
1534                 rtinfo.rti_ifpaddr = ifa->ifa_addr;
1535                 msglen = rt_msgsize(RTM_IFINFO, &rtinfo);
1536                 if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0) {
1537                         ifnet_unlock();
1538                         return (ENOMEM);
1539                 }
1540                 rt_msg_buffer(RTM_IFINFO, &rtinfo, w->w_tmem, msglen);
1541                 rtinfo.rti_ifpaddr = NULL;
1542                 if (w->w_req != NULL && w->w_tmem != NULL) {
1543                         struct if_msghdr *ifm = w->w_tmem;
1544
1545                         ifm->ifm_index = ifp->if_index;
1546                         ifm->ifm_flags = ifp->if_flags;
1547                         ifnet_compute_stats(ifp);
1548                         ifm->ifm_data = ifp->if_data;
1549                         ifm->ifm_addrs = rtinfo.rti_addrs;
1550                         error = SYSCTL_OUT(w->w_req, ifm, msglen);
1551                         if (error) {
1552                                 ifnet_unlock();
1553                                 return (error);
1554                         }
1555                 }
1556                 /*
1557                  * Add a marker, since SYSCTL_OUT() could block and during
1558                  * that period the list could be changed.
1559                  */
1560                 ifa_marker_init(&mark, ifp);
1561                 ifac_mark = &mark.ifac;
1562                 TAILQ_INSERT_AFTER(head, ifac, ifac_mark, ifa_link);
1563                 while ((ifac = TAILQ_NEXT(ifac_mark, ifa_link)) != NULL) {
1564                         TAILQ_REMOVE(head, ifac_mark, ifa_link);
1565                         TAILQ_INSERT_AFTER(head, ifac, ifac_mark, ifa_link);
1566
1567                         ifa = ifac->ifa;
1568
1569                         /* Ignore marker */
1570                         if (ifa->ifa_addr->sa_family == AF_UNSPEC)
1571                                 continue;
1572
1573                         if (af && af != ifa->ifa_addr->sa_family)
1574                                 continue;
1575                         if (curproc->p_ucred->cr_prison &&
1576                             prison_if(curproc->p_ucred, ifa->ifa_addr))
1577                                 continue;
1578                         rtinfo.rti_ifaaddr = ifa->ifa_addr;
1579                         rtinfo.rti_netmask = ifa->ifa_netmask;
1580                         rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1581                         msglen = rt_msgsize(RTM_NEWADDR, &rtinfo);
1582                         /*
1583                          * Keep a reference on this ifaddr, so that it will
1584                          * not be destroyed if the following resizewalkarg()
1585                          * blocks.
1586                          */
1587                         IFAREF(ifa);
1588                         if (w->w_tmemsize < msglen &&
1589                             resizewalkarg(w, msglen) != 0) {
1590                                 IFAFREE(ifa);
1591                                 TAILQ_REMOVE(head, ifac_mark, ifa_link);
1592                                 ifnet_unlock();
1593                                 return (ENOMEM);
1594                         }
1595                         rt_msg_buffer(RTM_NEWADDR, &rtinfo, w->w_tmem, msglen);
1596                         if (w->w_req != NULL) {
1597                                 struct ifa_msghdr *ifam = w->w_tmem;
1598
1599                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
1600                                 ifam->ifam_flags = ifa->ifa_flags;
1601                                 ifam->ifam_addrs = rtinfo.rti_addrs;
1602                                 ifam->ifam_addrflags = if_addrflags(ifa);
1603                                 ifam->ifam_metric = ifa->ifa_metric;
1604                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, msglen);
1605                                 if (error) {
1606                                         IFAFREE(ifa);
1607                                         TAILQ_REMOVE(head, ifac_mark, ifa_link);
1608                                         ifnet_unlock();
1609                                         return (error);
1610                                 }
1611                         }
1612                         IFAFREE(ifa);
1613                 }
1614                 TAILQ_REMOVE(head, ifac_mark, ifa_link);
1615                 rtinfo.rti_netmask = NULL;
1616                 rtinfo.rti_ifaaddr = NULL;
1617                 rtinfo.rti_bcastaddr = NULL;
1618         }
1619         ifnet_unlock();
1620         return (0);
1621 }
1622
1623 static int
1624 rttable_walkarg_create(struct rttable_walkarg *w, int op, int arg)
1625 {
1626         struct rt_addrinfo rtinfo;
1627         struct sockaddr_storage ss;
1628         int i, msglen;
1629
1630         memset(w, 0, sizeof(*w));
1631         w->w_op = op;
1632         w->w_arg = arg;
1633
1634         memset(&ss, 0, sizeof(ss));
1635         ss.ss_len = sizeof(ss);
1636
1637         memset(&rtinfo, 0, sizeof(rtinfo));
1638         for (i = 0; i < RTAX_MAX; ++i)
1639                 rtinfo.rti_info[i] = (struct sockaddr *)&ss;
1640         msglen = rt_msgsize(RTM_GET, &rtinfo);
1641
1642         w->w_bufsz = msglen * RTTABLE_DUMP_MSGCNT_MAX;
1643         w->w_buf = kmalloc(w->w_bufsz, M_TEMP, M_WAITOK | M_NULLOK);
1644         if (w->w_buf == NULL)
1645                 return ENOMEM;
1646         return 0;
1647 }
1648
1649 static void
1650 rttable_walkarg_destroy(struct rttable_walkarg *w)
1651 {
1652         kfree(w->w_buf, M_TEMP);
1653 }
1654
1655 static void
1656 rttable_entry_rtinfo(struct rt_addrinfo *rtinfo, struct radix_node *rn)
1657 {
1658         struct rtentry *rt = (struct rtentry *)rn;
1659
1660         bzero(rtinfo, sizeof(*rtinfo));
1661         rtinfo->rti_dst = rt_key(rt);
1662         rtinfo->rti_gateway = rt->rt_gateway;
1663         rtinfo->rti_netmask = rt_mask(rt);
1664         rtinfo->rti_genmask = rt->rt_genmask;
1665         if (rt->rt_ifp != NULL) {
1666                 rtinfo->rti_ifpaddr =
1667                 TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1668                 rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr;
1669                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1670                         rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
1671         }
1672 }
1673
1674 static int
1675 rttable_walk_entry(struct radix_node *rn, void *xw)
1676 {
1677         struct rttable_walkarg *w = xw;
1678         struct rtentry *rt = (struct rtentry *)rn;
1679         struct rt_addrinfo rtinfo;
1680         struct rt_msghdr *rtm;
1681         boolean_t save = FALSE;
1682         int msglen, w_bufleft;
1683         void *ptr;
1684
1685         rttable_entry_rtinfo(&rtinfo, rn);
1686         msglen = rt_msgsize(RTM_GET, &rtinfo);
1687
1688         w_bufleft = w->w_bufsz - w->w_buflen;
1689
1690         if (rn->rn_dupedkey != NULL) {
1691                 struct radix_node *rn1 = rn;
1692                 int total_msglen = msglen;
1693
1694                 /*
1695                  * Make sure that we have enough space left for all
1696                  * dupedkeys, since rn_walktree_at always starts
1697                  * from the first dupedkey.
1698                  */
1699                 while ((rn1 = rn1->rn_dupedkey) != NULL) {
1700                         struct rt_addrinfo rtinfo1;
1701                         int msglen1;
1702
1703                         if (rn1->rn_flags & RNF_ROOT)
1704                                 continue;
1705
1706                         rttable_entry_rtinfo(&rtinfo1, rn1);
1707                         msglen1 = rt_msgsize(RTM_GET, &rtinfo1);
1708                         total_msglen += msglen1;
1709                 }
1710
1711                 if (total_msglen > w_bufleft) {
1712                         if (total_msglen > w->w_bufsz) {
1713                                 static int logged = 0;
1714
1715                                 if (!logged) {
1716                                         kprintf("buffer is too small for "
1717                                             "all dupedkeys, increase "
1718                                             "RTTABLE_DUMP_MSGCNT_MAX\n");
1719                                         logged = 1;
1720                                 }
1721                                 return ENOMEM;
1722                         }
1723                         save = TRUE;
1724                 }
1725         } else if (msglen > w_bufleft) {
1726                 save = TRUE;
1727         }
1728
1729         if (save) {
1730                 /*
1731                  * Not enough buffer left; remember the position
1732                  * to start from upon next round.
1733                  */
1734                 KASSERT(msglen <= w->w_bufsz, ("msg too long %d", msglen));
1735
1736                 KASSERT(rtinfo.rti_dst->sa_len <= sizeof(w->w_key0),
1737                     ("key too long %d", rtinfo.rti_dst->sa_len));
1738                 memset(&w->w_key0, 0, sizeof(w->w_key0));
1739                 memcpy(&w->w_key0, rtinfo.rti_dst, rtinfo.rti_dst->sa_len);
1740                 w->w_key = (const char *)&w->w_key0;
1741
1742                 if (rtinfo.rti_netmask != NULL) {
1743                         KASSERT(
1744                             rtinfo.rti_netmask->sa_len <= sizeof(w->w_mask0),
1745                             ("mask too long %d", rtinfo.rti_netmask->sa_len));
1746                         memset(&w->w_mask0, 0, sizeof(w->w_mask0));
1747                         memcpy(&w->w_mask0, rtinfo.rti_netmask,
1748                             rtinfo.rti_netmask->sa_len);
1749                         w->w_mask = (const char *)&w->w_mask0;
1750                 } else {
1751                         w->w_mask = NULL;
1752                 }
1753                 return EJUSTRETURN;
1754         }
1755
1756         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1757                 return 0;
1758
1759         ptr = ((uint8_t *)w->w_buf) + w->w_buflen;
1760         rt_msg_buffer(RTM_GET, &rtinfo, ptr, msglen);
1761
1762         rtm = (struct rt_msghdr *)ptr;
1763         rtm->rtm_flags = rt->rt_flags;
1764         rtm->rtm_use = rt->rt_use;
1765         rtm->rtm_rmx = rt->rt_rmx;
1766         rtm->rtm_index = rt->rt_ifp->if_index;
1767         rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1768         rtm->rtm_addrs = rtinfo.rti_addrs;
1769
1770         w->w_buflen += msglen;
1771
1772         return 0;
1773 }
1774
1775 static void
1776 rttable_walk_dispatch(netmsg_t msg)
1777 {
1778         struct netmsg_rttable_walk *nmsg = (struct netmsg_rttable_walk *)msg;
1779         struct radix_node_head *rnh = rt_tables[mycpuid][nmsg->af];
1780         struct rttable_walkarg *w = nmsg->w;
1781         int error;
1782
1783         error = rnh->rnh_walktree_at(rnh, w->w_key, w->w_mask,
1784             rttable_walk_entry, w);
1785         lwkt_replymsg(&nmsg->base.lmsg, error);
1786 }
1787
1788 static int
1789 sysctl_rttable(int af, struct sysctl_req *req, int op, int arg)
1790 {
1791         struct rttable_walkarg w;
1792         int error, i;
1793
1794         error = rttable_walkarg_create(&w, op, arg);
1795         if (error)
1796                 return error;
1797
1798         error = EINVAL;
1799         for (i = 1; i <= AF_MAX; i++) {
1800                 if (rt_tables[mycpuid][i] != NULL && (af == 0 || af == i)) {
1801                         w.w_key = NULL;
1802                         w.w_mask = NULL;
1803                         for (;;) {
1804                                 struct netmsg_rttable_walk nmsg;
1805
1806                                 netmsg_init(&nmsg.base, NULL,
1807                                     &curthread->td_msgport, 0,
1808                                     rttable_walk_dispatch);
1809                                 nmsg.af = i;
1810                                 nmsg.w = &w;
1811
1812                                 w.w_buflen = 0;
1813
1814                                 error = lwkt_domsg(netisr_cpuport(mycpuid),
1815                                     &nmsg.base.lmsg, 0);
1816                                 if (error && error != EJUSTRETURN)
1817                                         goto done;
1818
1819                                 if (req != NULL && w.w_buflen > 0) {
1820                                         int error1;
1821
1822                                         error1 = SYSCTL_OUT(req, w.w_buf,
1823                                             w.w_buflen);
1824                                         if (error1) {
1825                                                 error = error1;
1826                                                 goto done;
1827                                         }
1828                                 }
1829                                 if (error == 0) /* done */
1830                                         break;
1831                         }
1832                 }
1833         }
1834 done:
1835         rttable_walkarg_destroy(&w);
1836         return error;
1837 }
1838
1839 static int
1840 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1841 {
1842         int     *name = (int *)arg1;
1843         u_int   namelen = arg2;
1844         int     error = EINVAL;
1845         int     origcpu, cpu;
1846         u_char  af;
1847         struct  walkarg w;
1848
1849         name ++;
1850         namelen--;
1851         if (req->newptr)
1852                 return (EPERM);
1853         if (namelen != 3 && namelen != 4)
1854                 return (EINVAL);
1855         af = name[0];
1856         bzero(&w, sizeof w);
1857         w.w_op = name[1];
1858         w.w_arg = name[2];
1859         w.w_req = req;
1860
1861         /*
1862          * Optional third argument specifies cpu, used primarily for
1863          * debugging the route table.
1864          */
1865         if (namelen == 4) {
1866                 if (name[3] < 0 || name[3] >= netisr_ncpus)
1867                         return (EINVAL);
1868                 cpu = name[3];
1869         } else {
1870                 /*
1871                  * Target cpu is not specified, use cpu0 then, so that
1872                  * the result set will be relatively stable.
1873                  */
1874                 cpu = 0;
1875         }
1876         origcpu = mycpuid;
1877         lwkt_migratecpu(cpu);
1878
1879         switch (w.w_op) {
1880         case NET_RT_DUMP:
1881         case NET_RT_FLAGS:
1882                 error = sysctl_rttable(af, w.w_req, w.w_op, w.w_arg);
1883                 break;
1884         case NET_RT_IFLIST:
1885                 error = sysctl_iflist(af, &w);
1886                 break;
1887         }
1888         if (w.w_tmem != NULL)
1889                 kfree(w.w_tmem, M_RTABLE);
1890
1891         lwkt_migratecpu(origcpu);
1892         return (error);
1893 }
1894
1895 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1896
1897 /*
1898  * Definitions of protocols supported in the ROUTE domain.
1899  */
1900
1901 static struct domain routedomain;               /* or at least forward */
1902
1903 static struct protosw routesw[] = {
1904     {
1905         .pr_type = SOCK_RAW,
1906         .pr_domain = &routedomain,
1907         .pr_protocol = 0,
1908         .pr_flags = PR_ATOMIC|PR_ADDR,
1909         .pr_input = NULL,
1910         .pr_output = route_output,
1911         .pr_ctlinput = raw_ctlinput,
1912         .pr_ctloutput = route_ctloutput,
1913         .pr_ctlport = cpu0_ctlport,
1914
1915         .pr_init = raw_init,
1916         .pr_usrreqs = &route_usrreqs
1917     }
1918 };
1919
1920 static struct domain routedomain = {
1921         .dom_family             = AF_ROUTE,
1922         .dom_name               = "route",
1923         .dom_init               = NULL,
1924         .dom_externalize        = NULL,
1925         .dom_dispose            = NULL,
1926         .dom_protosw            = routesw,
1927         .dom_protoswNPROTOSW    = &routesw[NELEM(routesw)],
1928         .dom_next               = SLIST_ENTRY_INITIALIZER,
1929         .dom_rtattach           = NULL,
1930         .dom_rtoffset           = 0,
1931         .dom_maxrtkey           = 0,
1932         .dom_ifattach           = NULL,
1933         .dom_ifdetach           = NULL
1934 };
1935
1936 DOMAIN_SET(route);
1937