netisr: rename cpu_portfn() to netisr_portfn().
[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. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *      This product includes software developed by the University of
48  *      California, Berkeley and its contributors.
49  * 4. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  *      @(#)rtsock.c    8.7 (Berkeley) 10/12/95
66  * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $
67  */
68
69 #include "opt_sctp.h"
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/kernel.h>
74 #include <sys/sysctl.h>
75 #include <sys/proc.h>
76 #include <sys/priv.h>
77 #include <sys/malloc.h>
78 #include <sys/mbuf.h>
79 #include <sys/protosw.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
82 #include <sys/domain.h>
83
84 #include <sys/thread2.h>
85 #include <sys/socketvar2.h>
86
87 #include <net/if.h>
88 #include <net/route.h>
89 #include <net/raw_cb.h>
90 #include <net/netmsg2.h>
91
92 #ifdef SCTP
93 extern void sctp_add_ip_address(struct ifaddr *ifa);
94 extern void sctp_delete_ip_address(struct ifaddr *ifa);
95 #endif /* SCTP */
96
97 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
98
99 static struct route_cb {
100         int     ip_count;
101         int     ip6_count;
102         int     ipx_count;
103         int     ns_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 static struct mbuf *
117                 rt_msg_mbuf (int, struct rt_addrinfo *);
118 static void     rt_msg_buffer (int, struct rt_addrinfo *, void *buf, int len);
119 static int      rt_msgsize (int type, struct rt_addrinfo *rtinfo);
120 static int      rt_xaddrs (char *, char *, struct rt_addrinfo *);
121 static int      sysctl_dumpentry (struct radix_node *rn, void *vw);
122 static int      sysctl_iflist (int af, struct walkarg *w);
123 static int      route_output(struct mbuf *, struct socket *, ...);
124 static void     rt_setmetrics (u_long, struct rt_metrics *,
125                                struct rt_metrics *);
126
127 /*
128  * It really doesn't make any sense at all for this code to share much
129  * with raw_usrreq.c, since its functionality is so restricted.  XXX
130  */
131 static void
132 rts_abort(netmsg_t msg)
133 {
134         crit_enter();
135         raw_usrreqs.pru_abort(msg);
136         /* msg invalid now */
137         crit_exit();
138 }
139
140 /* pru_accept is EOPNOTSUPP */
141
142 static void
143 rts_attach(netmsg_t msg)
144 {
145         struct socket *so = msg->base.nm_so;
146         struct pru_attach_info *ai = msg->attach.nm_ai;
147         struct rawcb *rp;
148         int proto = msg->attach.nm_proto;
149         int error;
150
151         crit_enter();
152         if (sotorawcb(so) != NULL) {
153                 error = EISCONN;
154                 goto done;
155         }
156
157         rp = kmalloc(sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
158
159         /*
160          * The critical section is necessary to block protocols from sending
161          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
162          * this PCB is extant but incompletely initialized.
163          * Probably we should try to do more of this work beforehand and
164          * eliminate the critical section.
165          */
166         so->so_pcb = rp;
167         soreference(so);        /* so_pcb assignment */
168         error = raw_attach(so, proto, ai->sb_rlimit);
169         rp = sotorawcb(so);
170         if (error) {
171                 kfree(rp, M_PCB);
172                 goto done;
173         }
174         switch(rp->rcb_proto.sp_protocol) {
175         case AF_INET:
176                 route_cb.ip_count++;
177                 break;
178         case AF_INET6:
179                 route_cb.ip6_count++;
180                 break;
181         case AF_IPX:
182                 route_cb.ipx_count++;
183                 break;
184         case AF_NS:
185                 route_cb.ns_count++;
186                 break;
187         }
188         rp->rcb_faddr = &route_src;
189         route_cb.any_count++;
190         soisconnected(so);
191         so->so_options |= SO_USELOOPBACK;
192         error = 0;
193 done:
194         crit_exit();
195         lwkt_replymsg(&msg->lmsg, error);
196 }
197
198 static void
199 rts_bind(netmsg_t msg)
200 {
201         crit_enter();
202         raw_usrreqs.pru_bind(msg); /* xxx just EINVAL */
203         /* msg invalid now */
204         crit_exit();
205 }
206
207 static void
208 rts_connect(netmsg_t msg)
209 {
210         crit_enter();
211         raw_usrreqs.pru_connect(msg); /* XXX just EINVAL */
212         /* msg invalid now */
213         crit_exit();
214 }
215
216 /* pru_connect2 is EOPNOTSUPP */
217 /* pru_control is EOPNOTSUPP */
218
219 static void
220 rts_detach(netmsg_t msg)
221 {
222         struct socket *so = msg->base.nm_so;
223         struct rawcb *rp = sotorawcb(so);
224
225         crit_enter();
226         if (rp != NULL) {
227                 switch(rp->rcb_proto.sp_protocol) {
228                 case AF_INET:
229                         route_cb.ip_count--;
230                         break;
231                 case AF_INET6:
232                         route_cb.ip6_count--;
233                         break;
234                 case AF_IPX:
235                         route_cb.ipx_count--;
236                         break;
237                 case AF_NS:
238                         route_cb.ns_count--;
239                         break;
240                 }
241                 route_cb.any_count--;
242         }
243         raw_usrreqs.pru_detach(msg);
244         /* msg invalid now */
245         crit_exit();
246 }
247
248 static void
249 rts_disconnect(netmsg_t msg)
250 {
251         crit_enter();
252         raw_usrreqs.pru_disconnect(msg);
253         /* msg invalid now */
254         crit_exit();
255 }
256
257 /* pru_listen is EOPNOTSUPP */
258
259 static void
260 rts_peeraddr(netmsg_t msg)
261 {
262         crit_enter();
263         raw_usrreqs.pru_peeraddr(msg);
264         /* msg invalid now */
265         crit_exit();
266 }
267
268 /* pru_rcvd is EOPNOTSUPP */
269 /* pru_rcvoob is EOPNOTSUPP */
270
271 static void
272 rts_send(netmsg_t msg)
273 {
274         crit_enter();
275         raw_usrreqs.pru_send(msg);
276         /* msg invalid now */
277         crit_exit();
278 }
279
280 /* pru_sense is null */
281
282 static void
283 rts_shutdown(netmsg_t msg)
284 {
285         crit_enter();
286         raw_usrreqs.pru_shutdown(msg);
287         /* msg invalid now */
288         crit_exit();
289 }
290
291 static void
292 rts_sockaddr(netmsg_t msg)
293 {
294         crit_enter();
295         raw_usrreqs.pru_sockaddr(msg);
296         /* msg invalid now */
297         crit_exit();
298 }
299
300 static struct pr_usrreqs route_usrreqs = {
301         .pru_abort = rts_abort,
302         .pru_accept = pr_generic_notsupp,
303         .pru_attach = rts_attach,
304         .pru_bind = rts_bind,
305         .pru_connect = rts_connect,
306         .pru_connect2 = pr_generic_notsupp,
307         .pru_control = pr_generic_notsupp,
308         .pru_detach = rts_detach,
309         .pru_disconnect = rts_disconnect,
310         .pru_listen = pr_generic_notsupp,
311         .pru_peeraddr = rts_peeraddr,
312         .pru_rcvd = pr_generic_notsupp,
313         .pru_rcvoob = pr_generic_notsupp,
314         .pru_send = rts_send,
315         .pru_sense = pru_sense_null,
316         .pru_shutdown = rts_shutdown,
317         .pru_sockaddr = rts_sockaddr,
318         .pru_sosend = sosend,
319         .pru_soreceive = soreceive
320 };
321
322 static __inline sa_family_t
323 familyof(struct sockaddr *sa)
324 {
325         return (sa != NULL ? sa->sa_family : 0);
326 }
327
328 /*
329  * Routing socket input function.  The packet must be serialized onto cpu 0.
330  * We use the cpu0_soport() netisr processing loop to handle it.
331  *
332  * This looks messy but it means that anyone, including interrupt code,
333  * can send a message to the routing socket.
334  */
335 static void
336 rts_input_handler(netmsg_t msg)
337 {
338         static const struct sockaddr route_dst = { 2, PF_ROUTE, };
339         struct sockproto route_proto;
340         struct netmsg_packet *pmsg = &msg->packet;
341         struct mbuf *m;
342         sa_family_t family;
343         struct rawcb *skip;
344
345         family = pmsg->base.lmsg.u.ms_result;
346         route_proto.sp_family = PF_ROUTE;
347         route_proto.sp_protocol = family;
348
349         m = pmsg->nm_packet;
350         M_ASSERTPKTHDR(m);
351
352         skip = m->m_pkthdr.header;
353         m->m_pkthdr.header = NULL;
354
355         raw_input(m, &route_proto, &route_src, &route_dst, skip);
356 }
357
358 static void
359 rts_input_skip(struct mbuf *m, sa_family_t family, struct rawcb *skip)
360 {
361         struct netmsg_packet *pmsg;
362         lwkt_port_t port;
363
364         M_ASSERTPKTHDR(m);
365
366         port = netisr_portfn(0);        /* XXX same as for routing socket */
367         pmsg = &m->m_hdr.mh_netmsg;
368         netmsg_init(&pmsg->base, NULL, &netisr_apanic_rport,
369                     0, rts_input_handler);
370         pmsg->nm_packet = m;
371         pmsg->base.lmsg.u.ms_result = family;
372         m->m_pkthdr.header = skip; /* XXX steal field in pkthdr */
373         lwkt_sendmsg(port, &pmsg->base.lmsg);
374 }
375
376 static __inline void
377 rts_input(struct mbuf *m, sa_family_t family)
378 {
379         rts_input_skip(m, family, NULL);
380 }
381
382 static void *
383 reallocbuf_nofree(void *ptr, size_t len, size_t olen)
384 {
385         void *newptr;
386
387         newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
388         if (newptr == NULL)
389                 return NULL;
390         bcopy(ptr, newptr, olen);
391         return (newptr);
392 }
393
394 /*
395  * Internal helper routine for route_output().
396  */
397 static int
398 _fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt,
399            struct rt_addrinfo *rtinfo)
400 {
401         int msglen;
402         struct rt_msghdr *rtm = *prtm;
403
404         /* Fill in rt_addrinfo for call to rt_msg_buffer(). */
405         rtinfo->rti_dst = rt_key(rt);
406         rtinfo->rti_gateway = rt->rt_gateway;
407         rtinfo->rti_netmask = rt_mask(rt);              /* might be NULL */
408         rtinfo->rti_genmask = rt->rt_genmask;           /* might be NULL */
409         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
410                 if (rt->rt_ifp != NULL) {
411                         rtinfo->rti_ifpaddr =
412                             TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])
413                             ->ifa->ifa_addr;
414                         rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr;
415                         if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
416                                 rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
417                         rtm->rtm_index = rt->rt_ifp->if_index;
418                 } else {
419                         rtinfo->rti_ifpaddr = NULL;
420                         rtinfo->rti_ifaaddr = NULL;
421                 }
422         } else if (rt->rt_ifp != NULL) {
423                 rtm->rtm_index = rt->rt_ifp->if_index;
424         }
425
426         msglen = rt_msgsize(rtm->rtm_type, rtinfo);
427         if (rtm->rtm_msglen < msglen) {
428                 /* NOTE: Caller will free the old rtm accordingly */
429                 rtm = reallocbuf_nofree(rtm, msglen, rtm->rtm_msglen);
430                 if (rtm == NULL)
431                         return (ENOBUFS);
432                 *prtm = rtm;
433         }
434         rt_msg_buffer(rtm->rtm_type, rtinfo, rtm, msglen);
435
436         rtm->rtm_flags = rt->rt_flags;
437         rtm->rtm_rmx = rt->rt_rmx;
438         rtm->rtm_addrs = rtinfo->rti_addrs;
439
440         return (0);
441 }
442
443 struct rtm_arg {
444         struct rt_msghdr        *bak_rtm;
445         struct rt_msghdr        *new_rtm;
446 };
447
448 static int
449 fillrtmsg(struct rtm_arg *arg, struct rtentry *rt,
450           struct rt_addrinfo *rtinfo)
451 {
452         struct rt_msghdr *rtm = arg->new_rtm;
453         int error;
454
455         error = _fillrtmsg(&rtm, rt, rtinfo);
456         if (!error) {
457                 if (arg->new_rtm != rtm) {
458                         /*
459                          * _fillrtmsg() just allocated a new rtm;
460                          * if the previously allocated rtm is not
461                          * the backing rtm, it should be freed.
462                          */
463                         if (arg->new_rtm != arg->bak_rtm)
464                                 kfree(arg->new_rtm, M_RTABLE);
465                         arg->new_rtm = rtm;
466                 }
467         }
468         return error;
469 }
470
471 static void route_output_add_callback(int, int, struct rt_addrinfo *,
472                                         struct rtentry *, void *);
473 static void route_output_delete_callback(int, int, struct rt_addrinfo *,
474                                         struct rtentry *, void *);
475 static int route_output_get_callback(int, struct rt_addrinfo *,
476                                      struct rtentry *, void *, int);
477 static int route_output_change_callback(int, struct rt_addrinfo *,
478                                         struct rtentry *, void *, int);
479 static int route_output_lock_callback(int, struct rt_addrinfo *,
480                                       struct rtentry *, void *, int);
481
482 /*ARGSUSED*/
483 static int
484 route_output(struct mbuf *m, struct socket *so, ...)
485 {
486         struct rtm_arg arg;
487         struct rt_msghdr *rtm = NULL;
488         struct rawcb *rp = NULL;
489         struct pr_output_info *oi;
490         struct rt_addrinfo rtinfo;
491         sa_family_t family;
492         int len, error = 0;
493         __va_list ap;
494
495         M_ASSERTPKTHDR(m);
496
497         __va_start(ap, so);
498         oi = __va_arg(ap, struct pr_output_info *);
499         __va_end(ap);
500
501         family = familyof(NULL);
502
503 #define gotoerr(e) { error = e; goto flush;}
504
505         if (m == NULL ||
506             (m->m_len < sizeof(long) &&
507              (m = m_pullup(m, sizeof(long))) == NULL))
508                 return (ENOBUFS);
509         len = m->m_pkthdr.len;
510         if (len < sizeof(struct rt_msghdr) ||
511             len != mtod(m, struct rt_msghdr *)->rtm_msglen)
512                 gotoerr(EINVAL);
513
514         rtm = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
515         if (rtm == NULL)
516                 gotoerr(ENOBUFS);
517
518         m_copydata(m, 0, len, (caddr_t)rtm);
519         if (rtm->rtm_version != RTM_VERSION)
520                 gotoerr(EPROTONOSUPPORT);
521
522         rtm->rtm_pid = oi->p_pid;
523         bzero(&rtinfo, sizeof(struct rt_addrinfo));
524         rtinfo.rti_addrs = rtm->rtm_addrs;
525         if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0)
526                 gotoerr(EINVAL);
527
528         rtinfo.rti_flags = rtm->rtm_flags;
529         if (rtinfo.rti_dst == NULL || rtinfo.rti_dst->sa_family >= AF_MAX ||
530             (rtinfo.rti_gateway && rtinfo.rti_gateway->sa_family >= AF_MAX))
531                 gotoerr(EINVAL);
532
533         family = familyof(rtinfo.rti_dst);
534
535         if (rtinfo.rti_genmask != NULL) {
536                 error = rtmask_add_global(rtinfo.rti_genmask);
537                 if (error)
538                         goto flush;
539         }
540
541         /*
542          * Verify that the caller has the appropriate privilege; RTM_GET
543          * is the only operation the non-superuser is allowed.
544          */
545         if (rtm->rtm_type != RTM_GET &&
546             priv_check_cred(so->so_cred, PRIV_ROOT, 0) != 0)
547                 gotoerr(EPERM);
548
549         switch (rtm->rtm_type) {
550         case RTM_ADD:
551                 if (rtinfo.rti_gateway == NULL) {
552                         error = EINVAL;
553                 } else {
554                         error = rtrequest1_global(RTM_ADD, &rtinfo, 
555                                           route_output_add_callback, rtm);
556                 }
557                 break;
558         case RTM_DELETE:
559                 /*
560                  * Backing rtm (bak_rtm) could _not_ be freed during
561                  * rtrequest1_global or rtsearch_global, even if the
562                  * callback reallocates the rtm due to its size changes,
563                  * since rtinfo points to the backing rtm's memory area.
564                  * After rtrequest1_global or rtsearch_global returns,
565                  * it is safe to free the backing rtm, since rtinfo will
566                  * not be used anymore.
567                  *
568                  * new_rtm will be used to save the new rtm allocated
569                  * by rtrequest1_global or rtsearch_global.
570                  */
571                 arg.bak_rtm = rtm;
572                 arg.new_rtm = rtm;
573                 error = rtrequest1_global(RTM_DELETE, &rtinfo,
574                                           route_output_delete_callback, &arg);
575                 rtm = arg.new_rtm;
576                 if (rtm != arg.bak_rtm)
577                         kfree(arg.bak_rtm, M_RTABLE);
578                 break;
579         case RTM_GET:
580                 /* See the comment in RTM_DELETE */
581                 arg.bak_rtm = rtm;
582                 arg.new_rtm = rtm;
583                 error = rtsearch_global(RTM_GET, &rtinfo,
584                                         route_output_get_callback, &arg,
585                                         RTS_NOEXACTMATCH);
586                 rtm = arg.new_rtm;
587                 if (rtm != arg.bak_rtm)
588                         kfree(arg.bak_rtm, M_RTABLE);
589                 break;
590         case RTM_CHANGE:
591                 error = rtsearch_global(RTM_CHANGE, &rtinfo,
592                                         route_output_change_callback, rtm,
593                                         RTS_EXACTMATCH);
594                 break;
595         case RTM_LOCK:
596                 error = rtsearch_global(RTM_LOCK, &rtinfo,
597                                         route_output_lock_callback, rtm,
598                                         RTS_EXACTMATCH);
599                 break;
600         default:
601                 error = EOPNOTSUPP;
602                 break;
603         }
604 flush:
605         if (rtm != NULL) {
606                 if (error != 0)
607                         rtm->rtm_errno = error;
608                 else
609                         rtm->rtm_flags |= RTF_DONE;
610         }
611
612         /*
613          * Check to see if we don't want our own messages.
614          */
615         if (!(so->so_options & SO_USELOOPBACK)) {
616                 if (route_cb.any_count <= 1) {
617                         if (rtm != NULL)
618                                 kfree(rtm, M_RTABLE);
619                         m_freem(m);
620                         return (error);
621                 }
622                 /* There is another listener, so construct message */
623                 rp = sotorawcb(so);
624         }
625         if (rtm != NULL) {
626                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
627                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
628                         m_freem(m);
629                         m = NULL;
630                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
631                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
632                 kfree(rtm, M_RTABLE);
633         }
634         if (m != NULL)
635                 rts_input_skip(m, family, rp);
636         return (error);
637 }
638
639 static void
640 route_output_add_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
641                           struct rtentry *rt, void *arg)
642 {
643         struct rt_msghdr *rtm = arg;
644
645         if (error == 0 && rt != NULL) {
646                 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
647                     &rt->rt_rmx);
648                 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
649                 rt->rt_rmx.rmx_locks |=
650                     (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
651                 if (rtinfo->rti_genmask != NULL) {
652                         rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask);
653                         if (rt->rt_genmask == NULL) {
654                                 /*
655                                  * This should not happen, since we
656                                  * have already installed genmask
657                                  * on each CPU before we reach here.
658                                  */
659                                 panic("genmask is gone!?");
660                         }
661                 } else {
662                         rt->rt_genmask = NULL;
663                 }
664                 rtm->rtm_index = rt->rt_ifp->if_index;
665         }
666 }
667
668 static void
669 route_output_delete_callback(int cmd, int error, struct rt_addrinfo *rtinfo,
670                           struct rtentry *rt, void *arg)
671 {
672         if (error == 0 && rt) {
673                 ++rt->rt_refcnt;
674                 if (fillrtmsg(arg, rt, rtinfo) != 0) {
675                         error = ENOBUFS;
676                         /* XXX no way to return the error */
677                 }
678                 --rt->rt_refcnt;
679         }
680         if (rt && rt->rt_refcnt == 0) {
681                 ++rt->rt_refcnt;
682                 rtfree(rt);
683         }
684 }
685
686 static int
687 route_output_get_callback(int cmd, struct rt_addrinfo *rtinfo,
688                           struct rtentry *rt, void *arg, int found_cnt)
689 {
690         int error, found = 0;
691
692         if (((rtinfo->rti_flags ^ rt->rt_flags) & RTF_HOST) == 0)
693                 found = 1;
694
695         error = fillrtmsg(arg, rt, rtinfo);
696         if (!error && found) {
697                 /* Got the exact match, we could return now! */
698                 error = EJUSTRETURN;
699         }
700         return error;
701 }
702
703 static int
704 route_output_change_callback(int cmd, struct rt_addrinfo *rtinfo,
705                              struct rtentry *rt, void *arg, int found_cnt)
706 {
707         struct rt_msghdr *rtm = arg;
708         struct ifaddr *ifa;
709         int error = 0;
710
711         /*
712          * new gateway could require new ifaddr, ifp;
713          * flags may also be different; ifp may be specified
714          * by ll sockaddr when protocol address is ambiguous
715          */
716         if (((rt->rt_flags & RTF_GATEWAY) && rtinfo->rti_gateway != NULL) ||
717             rtinfo->rti_ifpaddr != NULL ||
718             (rtinfo->rti_ifaaddr != NULL &&
719              !sa_equal(rtinfo->rti_ifaaddr, rt->rt_ifa->ifa_addr))) {
720                 error = rt_getifa(rtinfo);
721                 if (error != 0)
722                         goto done;
723         }
724         if (rtinfo->rti_gateway != NULL) {
725                 /*
726                  * We only need to generate rtmsg upon the
727                  * first route to be changed.
728                  */
729                 error = rt_setgate(rt, rt_key(rt), rtinfo->rti_gateway,
730                         found_cnt == 1 ? RTL_REPORTMSG : RTL_DONTREPORT);
731                 if (error != 0)
732                         goto done;
733         }
734         if ((ifa = rtinfo->rti_ifa) != NULL) {
735                 struct ifaddr *oifa = rt->rt_ifa;
736
737                 if (oifa != ifa) {
738                         if (oifa && oifa->ifa_rtrequest)
739                                 oifa->ifa_rtrequest(RTM_DELETE, rt, rtinfo);
740                         IFAFREE(rt->rt_ifa);
741                         IFAREF(ifa);
742                         rt->rt_ifa = ifa;
743                         rt->rt_ifp = rtinfo->rti_ifp;
744                 }
745         }
746         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, &rt->rt_rmx);
747         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
748                 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, rtinfo);
749         if (rtinfo->rti_genmask != NULL) {
750                 rt->rt_genmask = rtmask_purelookup(rtinfo->rti_genmask);
751                 if (rt->rt_genmask == NULL) {
752                         /*
753                          * This should not happen, since we
754                          * have already installed genmask
755                          * on each CPU before we reach here.
756                          */
757                         panic("genmask is gone!?");
758                 }
759         }
760         rtm->rtm_index = rt->rt_ifp->if_index;
761 done:
762         return error;
763 }
764
765 static int
766 route_output_lock_callback(int cmd, struct rt_addrinfo *rtinfo,
767                            struct rtentry *rt, void *arg,
768                            int found_cnt __unused)
769 {
770         struct rt_msghdr *rtm = arg;
771
772         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
773         rt->rt_rmx.rmx_locks |=
774                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
775         return 0;
776 }
777
778 static void
779 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
780 {
781 #define setmetric(flag, elt) if (which & (flag)) out->elt = in->elt;
782         setmetric(RTV_RPIPE, rmx_recvpipe);
783         setmetric(RTV_SPIPE, rmx_sendpipe);
784         setmetric(RTV_SSTHRESH, rmx_ssthresh);
785         setmetric(RTV_RTT, rmx_rtt);
786         setmetric(RTV_RTTVAR, rmx_rttvar);
787         setmetric(RTV_HOPCOUNT, rmx_hopcount);
788         setmetric(RTV_MTU, rmx_mtu);
789         setmetric(RTV_EXPIRE, rmx_expire);
790         setmetric(RTV_MSL, rmx_msl);
791         setmetric(RTV_IWMAXSEGS, rmx_iwmaxsegs);
792         setmetric(RTV_IWCAPSEGS, rmx_iwcapsegs);
793 #undef setmetric
794 }
795
796 #define ROUNDUP(a) \
797         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
798
799 /*
800  * Extract the addresses of the passed sockaddrs.
801  * Do a little sanity checking so as to avoid bad memory references.
802  * This data is derived straight from userland.
803  */
804 static int
805 rt_xaddrs(char *cp, char *cplim, struct rt_addrinfo *rtinfo)
806 {
807         struct sockaddr *sa;
808         int i;
809
810         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
811                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
812                         continue;
813                 sa = (struct sockaddr *)cp;
814                 /*
815                  * It won't fit.
816                  */
817                 if ((cp + sa->sa_len) > cplim) {
818                         return (EINVAL);
819                 }
820
821                 /*
822                  * There are no more...  Quit now.
823                  * If there are more bits, they are in error.
824                  * I've seen this.  route(1) can evidently generate these. 
825                  * This causes kernel to core dump.
826                  * For compatibility, if we see this, point to a safe address.
827                  */
828                 if (sa->sa_len == 0) {
829                         static struct sockaddr sa_zero = {
830                                 sizeof sa_zero, AF_INET,
831                         };
832
833                         rtinfo->rti_info[i] = &sa_zero;
834                         kprintf("rtsock: received more addr bits than sockaddrs.\n");
835                         return (0); /* should be EINVAL but for compat */
836                 }
837
838                 /* Accept the sockaddr. */
839                 rtinfo->rti_info[i] = sa;
840                 cp += ROUNDUP(sa->sa_len);
841         }
842         return (0);
843 }
844
845 static int
846 rt_msghdrsize(int type)
847 {
848         switch (type) {
849         case RTM_DELADDR:
850         case RTM_NEWADDR:
851                 return sizeof(struct ifa_msghdr);
852         case RTM_DELMADDR:
853         case RTM_NEWMADDR:
854                 return sizeof(struct ifma_msghdr);
855         case RTM_IFINFO:
856                 return sizeof(struct if_msghdr);
857         case RTM_IFANNOUNCE:
858         case RTM_IEEE80211:
859                 return sizeof(struct if_announcemsghdr);
860         default:
861                 return sizeof(struct rt_msghdr);
862         }
863 }
864
865 static int
866 rt_msgsize(int type, struct rt_addrinfo *rtinfo)
867 {
868         int len, i;
869
870         len = rt_msghdrsize(type);
871         for (i = 0; i < RTAX_MAX; i++) {
872                 if (rtinfo->rti_info[i] != NULL)
873                         len += ROUNDUP(rtinfo->rti_info[i]->sa_len);
874         }
875         len = ALIGN(len);
876         return len;
877 }
878
879 /*
880  * Build a routing message in a buffer.
881  * Copy the addresses in the rtinfo->rti_info[] sockaddr array
882  * to the end of the buffer after the message header.
883  *
884  * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
885  * This side-effect can be avoided if we reorder the addrs bitmask field in all
886  * the route messages to line up so we can set it here instead of back in the
887  * calling routine.
888  */
889 static void
890 rt_msg_buffer(int type, struct rt_addrinfo *rtinfo, void *buf, int msglen)
891 {
892         struct rt_msghdr *rtm;
893         char *cp;
894         int dlen, i;
895
896         rtm = (struct rt_msghdr *) buf;
897         rtm->rtm_version = RTM_VERSION;
898         rtm->rtm_type = type;
899         rtm->rtm_msglen = msglen;
900
901         cp = (char *)buf + rt_msghdrsize(type);
902         rtinfo->rti_addrs = 0;
903         for (i = 0; i < RTAX_MAX; i++) {
904                 struct sockaddr *sa;
905
906                 if ((sa = rtinfo->rti_info[i]) == NULL)
907                         continue;
908                 rtinfo->rti_addrs |= (1 << i);
909                 dlen = ROUNDUP(sa->sa_len);
910                 bcopy(sa, cp, dlen);
911                 cp += dlen;
912         }
913 }
914
915 /*
916  * Build a routing message in a mbuf chain.
917  * Copy the addresses in the rtinfo->rti_info[] sockaddr array
918  * to the end of the mbuf after the message header.
919  *
920  * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
921  * This side-effect can be avoided if we reorder the addrs bitmask field in all
922  * the route messages to line up so we can set it here instead of back in the
923  * calling routine.
924  */
925 static struct mbuf *
926 rt_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
927 {
928         struct mbuf *m;
929         struct rt_msghdr *rtm;
930         int hlen, len;
931         int i;
932
933         hlen = rt_msghdrsize(type);
934         KASSERT(hlen <= MCLBYTES, ("rt_msg_mbuf: hlen %d doesn't fit", hlen));
935
936         m = m_getl(hlen, MB_DONTWAIT, MT_DATA, M_PKTHDR, NULL);
937         if (m == NULL)
938                 return (NULL);
939         mbuftrackid(m, 32);
940         m->m_pkthdr.len = m->m_len = hlen;
941         m->m_pkthdr.rcvif = NULL;
942         rtinfo->rti_addrs = 0;
943         len = hlen;
944         for (i = 0; i < RTAX_MAX; i++) {
945                 struct sockaddr *sa;
946                 int dlen;
947
948                 if ((sa = rtinfo->rti_info[i]) == NULL)
949                         continue;
950                 rtinfo->rti_addrs |= (1 << i);
951                 dlen = ROUNDUP(sa->sa_len);
952                 m_copyback(m, len, dlen, (caddr_t)sa); /* can grow mbuf chain */
953                 len += dlen;
954         }
955         if (m->m_pkthdr.len != len) { /* one of the m_copyback() calls failed */
956                 m_freem(m);
957                 return (NULL);
958         }
959         rtm = mtod(m, struct rt_msghdr *);
960         bzero(rtm, hlen);
961         rtm->rtm_msglen = len;
962         rtm->rtm_version = RTM_VERSION;
963         rtm->rtm_type = type;
964         return (m);
965 }
966
967 /*
968  * This routine is called to generate a message from the routing
969  * socket indicating that a redirect has occurred, a routing lookup
970  * has failed, or that a protocol has detected timeouts to a particular
971  * destination.
972  */
973 void
974 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
975 {
976         struct sockaddr *dst = rtinfo->rti_info[RTAX_DST];
977         struct rt_msghdr *rtm;
978         struct mbuf *m;
979
980         if (route_cb.any_count == 0)
981                 return;
982         m = rt_msg_mbuf(type, rtinfo);
983         if (m == NULL)
984                 return;
985         rtm = mtod(m, struct rt_msghdr *);
986         rtm->rtm_flags = RTF_DONE | flags;
987         rtm->rtm_errno = error;
988         rtm->rtm_addrs = rtinfo->rti_addrs;
989         rts_input(m, familyof(dst));
990 }
991
992 void
993 rt_dstmsg(int type, struct sockaddr *dst, int error)
994 {
995         struct rt_msghdr *rtm;
996         struct rt_addrinfo addrs;
997         struct mbuf *m;
998
999         if (route_cb.any_count == 0)
1000                 return;
1001         bzero(&addrs, sizeof(struct rt_addrinfo));
1002         addrs.rti_info[RTAX_DST] = dst;
1003         m = rt_msg_mbuf(type, &addrs);
1004         if (m == NULL)
1005                 return;
1006         rtm = mtod(m, struct rt_msghdr *);
1007         rtm->rtm_flags = RTF_DONE;
1008         rtm->rtm_errno = error;
1009         rtm->rtm_addrs = addrs.rti_addrs;
1010         rts_input(m, familyof(dst));
1011 }
1012
1013 /*
1014  * This routine is called to generate a message from the routing
1015  * socket indicating that the status of a network interface has changed.
1016  */
1017 void
1018 rt_ifmsg(struct ifnet *ifp)
1019 {
1020         struct if_msghdr *ifm;
1021         struct mbuf *m;
1022         struct rt_addrinfo rtinfo;
1023
1024         if (route_cb.any_count == 0)
1025                 return;
1026         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1027         m = rt_msg_mbuf(RTM_IFINFO, &rtinfo);
1028         if (m == NULL)
1029                 return;
1030         ifm = mtod(m, struct if_msghdr *);
1031         ifm->ifm_index = ifp->if_index;
1032         ifm->ifm_flags = ifp->if_flags;
1033         ifm->ifm_data = ifp->if_data;
1034         ifm->ifm_addrs = 0;
1035         rts_input(m, 0);
1036 }
1037
1038 static void
1039 rt_ifamsg(int cmd, struct ifaddr *ifa)
1040 {
1041         struct ifa_msghdr *ifam;
1042         struct rt_addrinfo rtinfo;
1043         struct mbuf *m;
1044         struct ifnet *ifp = ifa->ifa_ifp;
1045
1046         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1047         rtinfo.rti_ifaaddr = ifa->ifa_addr;
1048         rtinfo.rti_ifpaddr =
1049                 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1050         rtinfo.rti_netmask = ifa->ifa_netmask;
1051         rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1052
1053         m = rt_msg_mbuf(cmd, &rtinfo);
1054         if (m == NULL)
1055                 return;
1056
1057         ifam = mtod(m, struct ifa_msghdr *);
1058         ifam->ifam_index = ifp->if_index;
1059         ifam->ifam_metric = ifa->ifa_metric;
1060         ifam->ifam_flags = ifa->ifa_flags;
1061         ifam->ifam_addrs = rtinfo.rti_addrs;
1062
1063         rts_input(m, familyof(ifa->ifa_addr));
1064 }
1065
1066 void
1067 rt_rtmsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int error)
1068 {
1069         struct rt_msghdr *rtm;
1070         struct rt_addrinfo rtinfo;
1071         struct mbuf *m;
1072         struct sockaddr *dst;
1073
1074         if (rt == NULL)
1075                 return;
1076
1077         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1078         rtinfo.rti_dst = dst = rt_key(rt);
1079         rtinfo.rti_gateway = rt->rt_gateway;
1080         rtinfo.rti_netmask = rt_mask(rt);
1081         if (ifp != NULL) {
1082                 rtinfo.rti_ifpaddr =
1083                 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1084         }
1085         rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr;
1086
1087         m = rt_msg_mbuf(cmd, &rtinfo);
1088         if (m == NULL)
1089                 return;
1090
1091         rtm = mtod(m, struct rt_msghdr *);
1092         if (ifp != NULL)
1093                 rtm->rtm_index = ifp->if_index;
1094         rtm->rtm_flags |= rt->rt_flags;
1095         rtm->rtm_errno = error;
1096         rtm->rtm_addrs = rtinfo.rti_addrs;
1097
1098         rts_input(m, familyof(dst));
1099 }
1100
1101 /*
1102  * This is called to generate messages from the routing socket
1103  * indicating a network interface has had addresses associated with it.
1104  * if we ever reverse the logic and replace messages TO the routing
1105  * socket indicate a request to configure interfaces, then it will
1106  * be unnecessary as the routing socket will automatically generate
1107  * copies of it.
1108  */
1109 void
1110 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
1111 {
1112 #ifdef SCTP
1113         /*
1114          * notify the SCTP stack
1115          * this will only get called when an address is added/deleted
1116          * XXX pass the ifaddr struct instead if ifa->ifa_addr...
1117          */
1118         if (cmd == RTM_ADD)
1119                 sctp_add_ip_address(ifa);
1120         else if (cmd == RTM_DELETE)
1121                 sctp_delete_ip_address(ifa);
1122 #endif /* SCTP */
1123
1124         if (route_cb.any_count == 0)
1125                 return;
1126
1127         if (cmd == RTM_ADD) {
1128                 rt_ifamsg(RTM_NEWADDR, ifa);
1129                 rt_rtmsg(RTM_ADD, rt, ifa->ifa_ifp, error);
1130         } else {
1131                 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
1132                 rt_rtmsg(RTM_DELETE, rt, ifa->ifa_ifp, error);
1133                 rt_ifamsg(RTM_DELADDR, ifa);
1134         }
1135 }
1136
1137 /*
1138  * This is the analogue to the rt_newaddrmsg which performs the same
1139  * function but for multicast group memberhips.  This is easier since
1140  * there is no route state to worry about.
1141  */
1142 void
1143 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
1144 {
1145         struct rt_addrinfo rtinfo;
1146         struct mbuf *m = NULL;
1147         struct ifnet *ifp = ifma->ifma_ifp;
1148         struct ifma_msghdr *ifmam;
1149
1150         if (route_cb.any_count == 0)
1151                 return;
1152
1153         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1154         rtinfo.rti_ifaaddr = ifma->ifma_addr;
1155         if (ifp != NULL && !TAILQ_EMPTY(&ifp->if_addrheads[mycpuid])) {
1156                 rtinfo.rti_ifpaddr =
1157                 TAILQ_FIRST(&ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1158         }
1159         /*
1160          * If a link-layer address is present, present it as a ``gateway''
1161          * (similarly to how ARP entries, e.g., are presented).
1162          */
1163         rtinfo.rti_gateway = ifma->ifma_lladdr;
1164
1165         m = rt_msg_mbuf(cmd, &rtinfo);
1166         if (m == NULL)
1167                 return;
1168
1169         ifmam = mtod(m, struct ifma_msghdr *);
1170         ifmam->ifmam_index = ifp->if_index;
1171         ifmam->ifmam_addrs = rtinfo.rti_addrs;
1172
1173         rts_input(m, familyof(ifma->ifma_addr));
1174 }
1175
1176 static struct mbuf *
1177 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what,
1178                      struct rt_addrinfo *info)
1179 {
1180         struct if_announcemsghdr *ifan;
1181         struct mbuf *m;
1182
1183         if (route_cb.any_count == 0)
1184                 return NULL;
1185
1186         bzero(info, sizeof(*info));
1187         m = rt_msg_mbuf(type, info);
1188         if (m == NULL)
1189                 return NULL;
1190
1191         ifan = mtod(m, struct if_announcemsghdr *);
1192         ifan->ifan_index = ifp->if_index;
1193         strlcpy(ifan->ifan_name, ifp->if_xname, sizeof ifan->ifan_name);
1194         ifan->ifan_what = what;
1195         return m;
1196 }
1197
1198 /*
1199  * This is called to generate routing socket messages indicating
1200  * IEEE80211 wireless events.
1201  * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way.
1202  */
1203 void
1204 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len)
1205 {
1206         struct rt_addrinfo info;
1207         struct mbuf *m;
1208
1209         m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info);
1210         if (m == NULL)
1211                 return;
1212
1213         /*
1214          * Append the ieee80211 data.  Try to stick it in the
1215          * mbuf containing the ifannounce msg; otherwise allocate
1216          * a new mbuf and append.
1217          *
1218          * NB: we assume m is a single mbuf.
1219          */
1220         if (data_len > M_TRAILINGSPACE(m)) {
1221                 /* XXX use m_getb(data_len, MB_DONTWAIT, MT_DATA, 0); */
1222                 struct mbuf *n = m_get(MB_DONTWAIT, MT_DATA);
1223                 if (n == NULL) {
1224                         m_freem(m);
1225                         return;
1226                 }
1227                 KKASSERT(data_len <= M_TRAILINGSPACE(n));
1228                 bcopy(data, mtod(n, void *), data_len);
1229                 n->m_len = data_len;
1230                 m->m_next = n;
1231         } else if (data_len > 0) {
1232                 bcopy(data, mtod(m, u_int8_t *) + m->m_len, data_len);
1233                 m->m_len += data_len;
1234         }
1235         mbuftrackid(m, 33);
1236         if (m->m_flags & M_PKTHDR)
1237                 m->m_pkthdr.len += data_len;
1238         mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
1239         rts_input(m, 0);
1240 }
1241
1242 /*
1243  * This is called to generate routing socket messages indicating
1244  * network interface arrival and departure.
1245  */
1246 void
1247 rt_ifannouncemsg(struct ifnet *ifp, int what)
1248 {
1249         struct rt_addrinfo addrinfo;
1250         struct mbuf *m;
1251
1252         m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &addrinfo);
1253         if (m != NULL)
1254                 rts_input(m, 0);
1255 }
1256
1257 static int
1258 resizewalkarg(struct walkarg *w, int len)
1259 {
1260         void *newptr;
1261
1262         newptr = kmalloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
1263         if (newptr == NULL)
1264                 return (ENOMEM);
1265         if (w->w_tmem != NULL)
1266                 kfree(w->w_tmem, M_RTABLE);
1267         w->w_tmem = newptr;
1268         w->w_tmemsize = len;
1269         return (0);
1270 }
1271
1272 /*
1273  * This is used in dumping the kernel table via sysctl().
1274  */
1275 int
1276 sysctl_dumpentry(struct radix_node *rn, void *vw)
1277 {
1278         struct walkarg *w = vw;
1279         struct rtentry *rt = (struct rtentry *)rn;
1280         struct rt_addrinfo rtinfo;
1281         int error, msglen;
1282
1283         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1284                 return 0;
1285
1286         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1287         rtinfo.rti_dst = rt_key(rt);
1288         rtinfo.rti_gateway = rt->rt_gateway;
1289         rtinfo.rti_netmask = rt_mask(rt);
1290         rtinfo.rti_genmask = rt->rt_genmask;
1291         if (rt->rt_ifp != NULL) {
1292                 rtinfo.rti_ifpaddr =
1293                 TAILQ_FIRST(&rt->rt_ifp->if_addrheads[mycpuid])->ifa->ifa_addr;
1294                 rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr;
1295                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1296                         rtinfo.rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
1297         }
1298         msglen = rt_msgsize(RTM_GET, &rtinfo);
1299         if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0)
1300                 return (ENOMEM);
1301         rt_msg_buffer(RTM_GET, &rtinfo, w->w_tmem, msglen);
1302         if (w->w_req != NULL) {
1303                 struct rt_msghdr *rtm = w->w_tmem;
1304
1305                 rtm->rtm_flags = rt->rt_flags;
1306                 rtm->rtm_use = rt->rt_use;
1307                 rtm->rtm_rmx = rt->rt_rmx;
1308                 rtm->rtm_index = rt->rt_ifp->if_index;
1309                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1310                 rtm->rtm_addrs = rtinfo.rti_addrs;
1311                 error = SYSCTL_OUT(w->w_req, rtm, msglen);
1312                 return (error);
1313         }
1314         return (0);
1315 }
1316
1317 static int
1318 sysctl_iflist(int af, struct walkarg *w)
1319 {
1320         struct ifnet *ifp;
1321         struct rt_addrinfo rtinfo;
1322         int msglen, error;
1323
1324         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1325         TAILQ_FOREACH(ifp, &ifnet, if_link) {
1326                 struct ifaddr_container *ifac;
1327                 struct ifaddr *ifa;
1328
1329                 if (w->w_arg && w->w_arg != ifp->if_index)
1330                         continue;
1331                 ifac = TAILQ_FIRST(&ifp->if_addrheads[mycpuid]);
1332                 ifa = ifac->ifa;
1333                 rtinfo.rti_ifpaddr = ifa->ifa_addr;
1334                 msglen = rt_msgsize(RTM_IFINFO, &rtinfo);
1335                 if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0)
1336                         return (ENOMEM);
1337                 rt_msg_buffer(RTM_IFINFO, &rtinfo, w->w_tmem, msglen);
1338                 rtinfo.rti_ifpaddr = NULL;
1339                 if (w->w_req != NULL && w->w_tmem != NULL) {
1340                         struct if_msghdr *ifm = w->w_tmem;
1341
1342                         ifm->ifm_index = ifp->if_index;
1343                         ifm->ifm_flags = ifp->if_flags;
1344                         ifm->ifm_data = ifp->if_data;
1345                         ifm->ifm_addrs = rtinfo.rti_addrs;
1346                         error = SYSCTL_OUT(w->w_req, ifm, msglen);
1347                         if (error)
1348                                 return (error);
1349                 }
1350                 while ((ifac = TAILQ_NEXT(ifac, ifa_link)) != NULL) {
1351                         ifa = ifac->ifa;
1352
1353                         if (af && af != ifa->ifa_addr->sa_family)
1354                                 continue;
1355                         if (curproc->p_ucred->cr_prison &&
1356                             prison_if(curproc->p_ucred, ifa->ifa_addr))
1357                                 continue;
1358                         rtinfo.rti_ifaaddr = ifa->ifa_addr;
1359                         rtinfo.rti_netmask = ifa->ifa_netmask;
1360                         rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1361                         msglen = rt_msgsize(RTM_NEWADDR, &rtinfo);
1362                         if (w->w_tmemsize < msglen &&
1363                             resizewalkarg(w, msglen) != 0)
1364                                 return (ENOMEM);
1365                         rt_msg_buffer(RTM_NEWADDR, &rtinfo, w->w_tmem, msglen);
1366                         if (w->w_req != NULL) {
1367                                 struct ifa_msghdr *ifam = w->w_tmem;
1368
1369                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
1370                                 ifam->ifam_flags = ifa->ifa_flags;
1371                                 ifam->ifam_metric = ifa->ifa_metric;
1372                                 ifam->ifam_addrs = rtinfo.rti_addrs;
1373                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, msglen);
1374                                 if (error)
1375                                         return (error);
1376                         }
1377                 }
1378                 rtinfo.rti_netmask = NULL;
1379                 rtinfo.rti_ifaaddr = NULL;
1380                 rtinfo.rti_bcastaddr = NULL;
1381         }
1382         return (0);
1383 }
1384
1385 static int
1386 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1387 {
1388         int     *name = (int *)arg1;
1389         u_int   namelen = arg2;
1390         struct radix_node_head *rnh;
1391         int     i, error = EINVAL;
1392         int     origcpu;
1393         u_char  af;
1394         struct  walkarg w;
1395
1396         name ++;
1397         namelen--;
1398         if (req->newptr)
1399                 return (EPERM);
1400         if (namelen != 3 && namelen != 4)
1401                 return (EINVAL);
1402         af = name[0];
1403         bzero(&w, sizeof w);
1404         w.w_op = name[1];
1405         w.w_arg = name[2];
1406         w.w_req = req;
1407
1408         /*
1409          * Optional third argument specifies cpu, used primarily for
1410          * debugging the route table.
1411          */
1412         if (namelen == 4) {
1413                 if (name[3] < 0 || name[3] >= ncpus)
1414                         return (EINVAL);
1415                 origcpu = mycpuid;
1416                 lwkt_migratecpu(name[3]);
1417         } else {
1418                 origcpu = -1;
1419         }
1420         crit_enter();
1421         switch (w.w_op) {
1422         case NET_RT_DUMP:
1423         case NET_RT_FLAGS:
1424                 for (i = 1; i <= AF_MAX; i++)
1425                         if ((rnh = rt_tables[mycpuid][i]) &&
1426                             (af == 0 || af == i) &&
1427                             (error = rnh->rnh_walktree(rnh,
1428                                                        sysctl_dumpentry, &w)))
1429                                 break;
1430                 break;
1431
1432         case NET_RT_IFLIST:
1433                 error = sysctl_iflist(af, &w);
1434         }
1435         crit_exit();
1436         if (w.w_tmem != NULL)
1437                 kfree(w.w_tmem, M_RTABLE);
1438         if (origcpu >= 0)
1439                 lwkt_migratecpu(origcpu);
1440         return (error);
1441 }
1442
1443 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1444
1445 /*
1446  * Definitions of protocols supported in the ROUTE domain.
1447  */
1448
1449 static struct domain routedomain;               /* or at least forward */
1450
1451 static struct protosw routesw[] = {
1452     {
1453         .pr_type = SOCK_RAW,
1454         .pr_domain = &routedomain,
1455         .pr_protocol = 0,
1456         .pr_flags = PR_ATOMIC|PR_ADDR,
1457         .pr_input = NULL,
1458         .pr_output = route_output,
1459         .pr_ctlinput = raw_ctlinput,
1460         .pr_ctloutput = NULL,
1461         .pr_ctlport = cpu0_ctlport,
1462
1463         .pr_init = raw_init,
1464         .pr_usrreqs = &route_usrreqs
1465     }
1466 };
1467
1468 static struct domain routedomain = {
1469         PF_ROUTE, "route", NULL, NULL, NULL,
1470         routesw, &routesw[(sizeof routesw)/(sizeof routesw[0])],
1471 };
1472
1473 DOMAIN_SET(route);
1474