Remove some duplicate FreeBSD CVS IDs, move some IDs to better places.
[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) 2004, 2005 Jeffrey M. Hsu.  All rights reserved.
35  *
36  * License terms: all terms for the DragonFly license above plus the following:
37  *
38  * 4. All advertising materials mentioning features or use of this software
39  *    must display the following acknowledgement:
40  *
41  *      This product includes software developed by Jeffrey M. Hsu
42  *      for the DragonFly Project.
43  *
44  *    This requirement may be waived with permission from Jeffrey Hsu.
45  *    Permission will be granted to any DragonFly user for free.
46  *    This requirement will sunset and may be removed on Jan 31, 2006,
47  *    after which the standard DragonFly license (as shown above) will
48  *    apply.
49  */
50
51 /*
52  * Copyright (c) 1988, 1991, 1993
53  *      The Regents of the University of California.  All rights reserved.
54  *
55  * Redistribution and use in source and binary forms, with or without
56  * modification, are permitted provided that the following conditions
57  * are met:
58  * 1. Redistributions of source code must retain the above copyright
59  *    notice, this list of conditions and the following disclaimer.
60  * 2. Redistributions in binary form must reproduce the above copyright
61  *    notice, this list of conditions and the following disclaimer in the
62  *    documentation and/or other materials provided with the distribution.
63  * 3. All advertising materials mentioning features or use of this software
64  *    must display the following acknowledgement:
65  *      This product includes software developed by the University of
66  *      California, Berkeley and its contributors.
67  * 4. Neither the name of the University nor the names of its contributors
68  *    may be used to endorse or promote products derived from this software
69  *    without specific prior written permission.
70  *
71  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
72  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
75  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
77  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
78  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
79  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
80  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
81  * SUCH DAMAGE.
82  *
83  *      @(#)rtsock.c    8.7 (Berkeley) 10/12/95
84  * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $
85  * $DragonFly: src/sys/net/rtsock.c,v 1.21 2005/01/26 23:09:57 hsu Exp $
86  */
87
88 #include <sys/param.h>
89 #include <sys/systm.h>
90 #include <sys/kernel.h>
91 #include <sys/sysctl.h>
92 #include <sys/proc.h>
93 #include <sys/malloc.h>
94 #include <sys/mbuf.h>
95 #include <sys/protosw.h>
96 #include <sys/socket.h>
97 #include <sys/socketvar.h>
98 #include <sys/domain.h>
99
100 #include <machine/stdarg.h>
101
102 #include <net/if.h>
103 #include <net/route.h>
104 #include <net/raw_cb.h>
105
106 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
107
108 static struct route_cb {
109         int     ip_count;
110         int     ip6_count;
111         int     ipx_count;
112         int     ns_count;
113         int     any_count;
114 } route_cb;
115
116 static const struct sockaddr route_src = { 2, PF_ROUTE, };
117
118 struct walkarg {
119         int     w_tmemsize;
120         int     w_op, w_arg;
121         char    *w_tmem;
122         struct sysctl_req *w_req;
123 };
124
125 static struct mbuf *
126                 rt_msg_mbuf (int, struct rt_addrinfo *);
127 static void     rt_msg_buffer (int, struct rt_addrinfo *, void *buf, int len);
128 static int      rt_msgsize (int type, struct rt_addrinfo *rtinfo);
129 static int      rt_xaddrs (char *, char *, struct rt_addrinfo *);
130 static int      sysctl_dumpentry (struct radix_node *rn, void *vw);
131 static int      sysctl_iflist (int af, struct walkarg *w);
132 static int      route_output(struct mbuf *, struct socket *, ...);
133 static void     rt_setmetrics (u_long, struct rt_metrics *,
134                                struct rt_metrics *);
135
136 /*
137  * It really doesn't make any sense at all for this code to share much
138  * with raw_usrreq.c, since its functionality is so restricted.  XXX
139  */
140 static int
141 rts_abort(struct socket *so)
142 {
143         int s, error;
144
145         s = splnet();
146         error = raw_usrreqs.pru_abort(so);
147         splx(s);
148         return error;
149 }
150
151 /* pru_accept is EOPNOTSUPP */
152
153 static int
154 rts_attach(struct socket *so, int proto, struct pru_attach_info *ai)
155 {
156         struct rawcb *rp;
157         int s, error;
158
159         if (sotorawcb(so) != NULL)
160                 return EISCONN; /* XXX panic? */
161
162         rp = malloc(sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
163         if (rp == NULL)
164                 return ENOBUFS;
165
166         /*
167          * The splnet() is necessary to block protocols from sending
168          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
169          * this PCB is extant but incompletely initialized.
170          * Probably we should try to do more of this work beforehand and
171          * eliminate the spl.
172          */
173         s = splnet();
174         so->so_pcb = rp;
175         error = raw_attach(so, proto, ai->sb_rlimit);
176         rp = sotorawcb(so);
177         if (error) {
178                 splx(s);
179                 free(rp, M_PCB);
180                 return error;
181         }
182         switch(rp->rcb_proto.sp_protocol) {
183         case AF_INET:
184                 route_cb.ip_count++;
185                 break;
186         case AF_INET6:
187                 route_cb.ip6_count++;
188                 break;
189         case AF_IPX:
190                 route_cb.ipx_count++;
191                 break;
192         case AF_NS:
193                 route_cb.ns_count++;
194                 break;
195         }
196         rp->rcb_faddr = &route_src;
197         route_cb.any_count++;
198         soisconnected(so);
199         so->so_options |= SO_USELOOPBACK;
200         splx(s);
201         return 0;
202 }
203
204 static int
205 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
206 {
207         int s, error;
208
209         s = splnet();
210         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
211         splx(s);
212         return error;
213 }
214
215 static int
216 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
217 {
218         int s, error;
219
220         s = splnet();
221         error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
222         splx(s);
223         return error;
224 }
225
226 /* pru_connect2 is EOPNOTSUPP */
227 /* pru_control is EOPNOTSUPP */
228
229 static int
230 rts_detach(struct socket *so)
231 {
232         struct rawcb *rp = sotorawcb(so);
233         int s, error;
234
235         s = splnet();
236         if (rp != NULL) {
237                 switch(rp->rcb_proto.sp_protocol) {
238                 case AF_INET:
239                         route_cb.ip_count--;
240                         break;
241                 case AF_INET6:
242                         route_cb.ip6_count--;
243                         break;
244                 case AF_IPX:
245                         route_cb.ipx_count--;
246                         break;
247                 case AF_NS:
248                         route_cb.ns_count--;
249                         break;
250                 }
251                 route_cb.any_count--;
252         }
253         error = raw_usrreqs.pru_detach(so);
254         splx(s);
255         return error;
256 }
257
258 static int
259 rts_disconnect(struct socket *so)
260 {
261         int s, error;
262
263         s = splnet();
264         error = raw_usrreqs.pru_disconnect(so);
265         splx(s);
266         return error;
267 }
268
269 /* pru_listen is EOPNOTSUPP */
270
271 static int
272 rts_peeraddr(struct socket *so, struct sockaddr **nam)
273 {
274         int s, error;
275
276         s = splnet();
277         error = raw_usrreqs.pru_peeraddr(so, nam);
278         splx(s);
279         return error;
280 }
281
282 /* pru_rcvd is EOPNOTSUPP */
283 /* pru_rcvoob is EOPNOTSUPP */
284
285 static int
286 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
287          struct mbuf *control, struct thread *td)
288 {
289         int s, error;
290
291         s = splnet();
292         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
293         splx(s);
294         return error;
295 }
296
297 /* pru_sense is null */
298
299 static int
300 rts_shutdown(struct socket *so)
301 {
302         int s, error;
303
304         s = splnet();
305         error = raw_usrreqs.pru_shutdown(so);
306         splx(s);
307         return error;
308 }
309
310 static int
311 rts_sockaddr(struct socket *so, struct sockaddr **nam)
312 {
313         int s, error;
314
315         s = splnet();
316         error = raw_usrreqs.pru_sockaddr(so, nam);
317         splx(s);
318         return error;
319 }
320
321 static struct pr_usrreqs route_usrreqs = {
322         rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
323         pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
324         pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
325         rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
326         sosend, soreceive, sopoll
327 };
328
329 static __inline sa_family_t
330 familyof(struct sockaddr *sa)
331 {
332         return (sa != NULL ? sa->sa_family : 0);
333 }
334
335 static void
336 rts_input(struct mbuf *m, sa_family_t family)
337 {
338         static const struct sockaddr route_dst = { 2, PF_ROUTE, };
339         struct sockproto route_proto = { PF_ROUTE, family };
340
341         raw_input(m, &route_proto, &route_src, &route_dst);
342 }
343
344 static void *
345 reallocbuf(void *ptr, size_t len, size_t olen)
346 {
347         void *newptr;
348
349         newptr = malloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
350         if (newptr == NULL)
351                 return NULL;
352         bcopy(ptr, newptr, olen);
353         free(ptr, M_RTABLE);
354         return (newptr);
355 }
356
357 static int
358 fillrtmsg(struct rt_msghdr **prtm, struct rtentry *rt,
359           struct rt_addrinfo *rtinfo)
360 {
361         int msglen;
362         struct rt_msghdr *rtm = *prtm;
363
364         /* Fill in rt_addrinfo for call to rt_msg_buffer(). */
365         rtinfo->rti_dst = rt_key(rt);
366         rtinfo->rti_gateway = rt->rt_gateway;
367         rtinfo->rti_netmask = rt_mask(rt);              /* might be NULL */
368         rtinfo->rti_genmask = rt->rt_genmask;           /* might be NULL */
369         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
370                 if (rt->rt_ifp != NULL) {
371                         rtinfo->rti_ifpaddr =
372                             TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
373                         rtinfo->rti_ifaaddr = rt->rt_ifa->ifa_addr;
374                         if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
375                                 rtinfo->rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
376                         rtm->rtm_index = rt->rt_ifp->if_index;
377                 } else {
378                         rtinfo->rti_ifpaddr = NULL;
379                         rtinfo->rti_ifaaddr = NULL;
380             }
381         }
382
383         msglen = rt_msgsize(rtm->rtm_type, rtinfo);
384         if (rtm->rtm_msglen < msglen) {
385                 rtm = reallocbuf(rtm, msglen, rtm->rtm_msglen);
386                 if (rtm == NULL)
387                         return (ENOBUFS);
388                 *prtm = rtm;
389         }
390         rt_msg_buffer(rtm->rtm_type, rtinfo, rtm, msglen);
391
392         rtm->rtm_flags = rt->rt_flags;
393         rtm->rtm_rmx = rt->rt_rmx;
394         rtm->rtm_addrs = rtinfo->rti_addrs;
395
396         return (0);
397 }
398
399 /*ARGSUSED*/
400 static int
401 route_output(struct mbuf *m, struct socket *so, ...)
402 {
403         struct rt_msghdr *rtm = NULL;
404         struct rtentry *rt = NULL;
405         struct rtentry *saved_nrt = NULL;
406         struct radix_node_head *rnh;
407         struct ifaddr *ifa = NULL;
408         struct rawcb *rp = NULL;
409         struct pr_output_info *oi;
410         struct rt_addrinfo rtinfo;
411         int len, error = 0;
412         __va_list ap;
413
414         __va_start(ap, so);
415         oi = __va_arg(ap, struct pr_output_info *);
416         __va_end(ap);
417
418 #define gotoerr(e) { error = e; goto flush;}
419
420         if (m == NULL ||
421             (m->m_len < sizeof(long) &&
422              (m = m_pullup(m, sizeof(long))) == NULL))
423                 return (ENOBUFS);
424         if (!(m->m_flags & M_PKTHDR))
425                 panic("route_output");
426         len = m->m_pkthdr.len;
427         if (len < sizeof(struct rt_msghdr) ||
428             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
429                 rtinfo.rti_dst = NULL;
430                 gotoerr(EINVAL);
431         }
432         rtm = malloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
433         if (rtm == NULL) {
434                 rtinfo.rti_dst = NULL;
435                 gotoerr(ENOBUFS);
436         }
437         m_copydata(m, 0, len, (caddr_t)rtm);
438         if (rtm->rtm_version != RTM_VERSION) {
439                 rtinfo.rti_dst = NULL;
440                 gotoerr(EPROTONOSUPPORT);
441         }
442         rtm->rtm_pid = oi->p_pid;
443         bzero(&rtinfo, sizeof(struct rt_addrinfo));
444         rtinfo.rti_addrs = rtm->rtm_addrs;
445         if (rt_xaddrs((char *)(rtm + 1), (char *)rtm + len, &rtinfo) != 0) {
446                 rtinfo.rti_dst = NULL;
447                 gotoerr(EINVAL);
448         }
449         rtinfo.rti_flags = rtm->rtm_flags;
450         if (rtinfo.rti_dst == NULL || rtinfo.rti_dst->sa_family >= AF_MAX ||
451             (rtinfo.rti_gateway && rtinfo.rti_gateway->sa_family >= AF_MAX))
452                 gotoerr(EINVAL);
453
454         if (rtinfo.rti_genmask != NULL) {
455                 struct radix_node *n;
456
457 #define clen(s) (*(u_char *)(s))
458                 n = rn_addmask((char *)rtinfo.rti_genmask, TRUE, 1);
459                 if (n != NULL &&
460                     rtinfo.rti_genmask->sa_len >= clen(n->rn_key) &&
461                     bcmp((char *)rtinfo.rti_genmask + 1,
462                          (char *)n->rn_key + 1, clen(n->rn_key) - 1) == 0)
463                         rtinfo.rti_genmask = (struct sockaddr *)n->rn_key;
464                 else
465                         gotoerr(ENOBUFS);
466         }
467
468         /*
469          * Verify that the caller has the appropriate privilege; RTM_GET
470          * is the only operation the non-superuser is allowed.
471          */
472         if (rtm->rtm_type != RTM_GET && suser_cred(so->so_cred, 0) != 0)
473                 gotoerr(EPERM);
474
475         switch (rtm->rtm_type) {
476         case RTM_ADD:
477                 if (rtinfo.rti_gateway == NULL)
478                         gotoerr(EINVAL);
479                 error = rtrequest1(RTM_ADD, &rtinfo, &saved_nrt);
480                 if (error == 0 && saved_nrt != NULL) {
481                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
482                             &saved_nrt->rt_rmx);
483                         saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
484                         saved_nrt->rt_rmx.rmx_locks |=
485                             (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
486                         --saved_nrt->rt_refcnt;
487                         saved_nrt->rt_genmask = rtinfo.rti_genmask;
488                 }
489                 break;
490         case RTM_DELETE:
491                 error = rtrequest1(RTM_DELETE, &rtinfo, &saved_nrt);
492                 if (error == 0) {
493                         if ((rt = saved_nrt))
494                                 rt->rt_refcnt++;
495                         if (fillrtmsg(&rtm, rt, &rtinfo) != 0)
496                                 gotoerr(ENOBUFS);
497                 }
498                 break;
499         case RTM_GET:
500         case RTM_CHANGE:
501         case RTM_LOCK:
502                 if ((rnh = rt_tables[rtinfo.rti_dst->sa_family]) == NULL)
503                         gotoerr(EAFNOSUPPORT);
504                 rt = (struct rtentry *)
505                     rnh->rnh_lookup((char *)rtinfo.rti_dst,
506                                     (char *)rtinfo.rti_netmask, rnh);
507                 if (rt == NULL)
508                         gotoerr(ESRCH);
509                 rt->rt_refcnt++;
510
511                 switch(rtm->rtm_type) {
512                 case RTM_GET:
513                         if (fillrtmsg(&rtm, rt, &rtinfo) != 0)
514                                 gotoerr(ENOBUFS);
515                         break;
516                 case RTM_CHANGE:
517                         /*
518                          * new gateway could require new ifaddr, ifp;
519                          * flags may also be different; ifp may be specified
520                          * by ll sockaddr when protocol address is ambiguous
521                          */
522                         if (((rt->rt_flags & RTF_GATEWAY) &&
523                              rtinfo.rti_gateway != NULL) ||
524                             rtinfo.rti_ifpaddr != NULL ||
525                             (rtinfo.rti_ifaaddr != NULL &&
526                              sa_equal(rtinfo.rti_ifaaddr,
527                                       rt->rt_ifa->ifa_addr))) {
528                                 error = rt_getifa(&rtinfo);
529                                 if (error != 0)
530                                         gotoerr(error);
531                         }
532                         if (rtinfo.rti_gateway != NULL) {
533                                 error = rt_setgate(rt, rt_key(rt),
534                                                    rtinfo.rti_gateway);
535                                 if (error != 0)
536                                         gotoerr(error);
537                         }
538                         if ((ifa = rtinfo.rti_ifa) != NULL) {
539                                 struct ifaddr *oifa = rt->rt_ifa;
540
541                                 if (oifa != ifa) {
542                                         if (oifa && oifa->ifa_rtrequest)
543                                                 oifa->ifa_rtrequest(RTM_DELETE,
544                                                     rt, &rtinfo);
545                                         IFAFREE(rt->rt_ifa);
546                                         IFAREF(ifa);
547                                         rt->rt_ifa = ifa;
548                                         rt->rt_ifp = rtinfo.rti_ifp;
549                                 }
550                         }
551                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
552                                       &rt->rt_rmx);
553                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
554                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &rtinfo);
555                         if (rtinfo.rti_genmask != NULL)
556                                 rt->rt_genmask = rtinfo.rti_genmask;
557                         /*
558                          * Fall into
559                          */
560                 case RTM_LOCK:
561                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
562                         rt->rt_rmx.rmx_locks |=
563                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
564                         break;
565                 }
566
567                 break;
568         default:
569                 gotoerr(EOPNOTSUPP);
570         }
571
572 flush:
573         if (rtm != NULL) {
574                 if (error != 0)
575                         rtm->rtm_errno = error;
576                 else
577                         rtm->rtm_flags |= RTF_DONE;
578         }
579         if (rt != NULL)
580                 rtfree(rt);
581         /*
582          * Check to see if we don't want our own messages.
583          */
584         if (!(so->so_options & SO_USELOOPBACK)) {
585                 if (route_cb.any_count <= 1) {
586                         if (rtm != NULL)
587                                 free(rtm, M_RTABLE);
588                         m_freem(m);
589                         return (error);
590                 }
591                 /* There is another listener, so construct message */
592                 rp = sotorawcb(so);
593         }
594         if (rtm != NULL) {
595                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
596                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
597                         m_freem(m);
598                         m = NULL;
599                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
600                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
601                 free(rtm, M_RTABLE);
602         }
603         if (rp != NULL)
604                 rp->rcb_proto.sp_family = 0; /* Avoid us */
605         if (m != NULL)
606                 rts_input(m, familyof(rtinfo.rti_dst));
607         if (rp != NULL)
608                 rp->rcb_proto.sp_family = PF_ROUTE;
609         return (error);
610 }
611
612 static void
613 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
614 {
615 #define setmetric(flag, elt) if (which & (flag)) out->elt = in->elt;
616         setmetric(RTV_RPIPE, rmx_recvpipe);
617         setmetric(RTV_SPIPE, rmx_sendpipe);
618         setmetric(RTV_SSTHRESH, rmx_ssthresh);
619         setmetric(RTV_RTT, rmx_rtt);
620         setmetric(RTV_RTTVAR, rmx_rttvar);
621         setmetric(RTV_HOPCOUNT, rmx_hopcount);
622         setmetric(RTV_MTU, rmx_mtu);
623         setmetric(RTV_EXPIRE, rmx_expire);
624 #undef setmetric
625 }
626
627 #define ROUNDUP(a) \
628         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
629
630 /*
631  * Extract the addresses of the passed sockaddrs.
632  * Do a little sanity checking so as to avoid bad memory references.
633  * This data is derived straight from userland.
634  */
635 static int
636 rt_xaddrs(char *cp, char *cplim, struct rt_addrinfo *rtinfo)
637 {
638         struct sockaddr *sa;
639         int i;
640
641         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
642                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
643                         continue;
644                 sa = (struct sockaddr *)cp;
645                 /*
646                  * It won't fit.
647                  */
648                 if ((cp + sa->sa_len) > cplim) {
649                         return (EINVAL);
650                 }
651
652                 /*
653                  * There are no more...  Quit now.
654                  * If there are more bits, they are in error.
655                  * I've seen this.  route(1) can evidently generate these. 
656                  * This causes kernel to core dump.
657                  * For compatibility, if we see this, point to a safe address.
658                  */
659                 if (sa->sa_len == 0) {
660                         static struct sockaddr sa_zero = {
661                                 sizeof sa_zero, AF_INET,
662                         };
663
664                         rtinfo->rti_info[i] = &sa_zero;
665                         return (0); /* should be EINVAL but for compat */
666                 }
667
668                 /* Accept the sockaddr. */
669                 rtinfo->rti_info[i] = sa;
670                 cp += ROUNDUP(sa->sa_len);
671         }
672         return (0);
673 }
674
675 static int
676 rt_msghdrsize(int type)
677 {
678         switch (type) {
679         case RTM_DELADDR:
680         case RTM_NEWADDR:
681                 return sizeof(struct ifa_msghdr);
682         case RTM_DELMADDR:
683         case RTM_NEWMADDR:
684                 return sizeof(struct ifma_msghdr);
685         case RTM_IFINFO:
686                 return sizeof(struct if_msghdr);
687         case RTM_IFANNOUNCE:
688                 return sizeof(struct if_announcemsghdr);
689         default:
690                 return sizeof(struct rt_msghdr);
691         }
692 }
693
694 static int
695 rt_msgsize(int type, struct rt_addrinfo *rtinfo)
696 {
697         int len, i;
698
699         len = rt_msghdrsize(type);
700         for (i = 0; i < RTAX_MAX; i++) {
701                 if (rtinfo->rti_info[i] != NULL)
702                         len += ROUNDUP(rtinfo->rti_info[i]->sa_len);
703         }
704         len = ALIGN(len);
705         return len;
706 }
707
708 /*
709  * Build a routing message in a buffer.
710  * Copy the addresses in the rtinfo->rti_info[] sockaddr array
711  * to the end of the buffer after the message header.
712  *
713  * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
714  * This side-effect can be avoided if we reorder the addrs bitmask field in all
715  * the route messages to line up so we can set it here instead of back in the
716  * calling routine.
717  */
718 static void
719 rt_msg_buffer(int type, struct rt_addrinfo *rtinfo, void *buf, int msglen)
720 {
721         struct rt_msghdr *rtm;
722         char *cp;
723         int dlen, i;
724
725         rtm = (struct rt_msghdr *) buf;
726         rtm->rtm_version = RTM_VERSION;
727         rtm->rtm_type = type;
728         rtm->rtm_msglen = msglen;
729
730         cp = (char *)buf + rt_msghdrsize(type);
731         rtinfo->rti_addrs = 0;
732         for (i = 0; i < RTAX_MAX; i++) {
733                 struct sockaddr *sa;
734
735                 if ((sa = rtinfo->rti_info[i]) == NULL)
736                         continue;
737                 rtinfo->rti_addrs |= (1 << i);
738                 dlen = ROUNDUP(sa->sa_len);
739                 bcopy(sa, cp, dlen);
740                 cp += dlen;
741         }
742 }
743
744 /*
745  * Build a routing message in a mbuf chain.
746  * Copy the addresses in the rtinfo->rti_info[] sockaddr array
747  * to the end of the mbuf after the message header.
748  *
749  * Set the rtinfo->rti_addrs bitmask of addresses present in rtinfo->rti_info[].
750  * This side-effect can be avoided if we reorder the addrs bitmask field in all
751  * the route messages to line up so we can set it here instead of back in the
752  * calling routine.
753  */
754 static struct mbuf *
755 rt_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
756 {
757         struct mbuf *m;
758         struct rt_msghdr *rtm;
759         int hlen, len;
760         int i;
761
762         hlen = rt_msghdrsize(type);
763         KASSERT(hlen <= MCLBYTES, ("rt_msg_mbuf: hlen %d doesn't fit", hlen));
764
765         m = m_gethdr(MB_DONTWAIT, MT_DATA);
766         if (m == NULL)
767                 return (NULL);
768         if (hlen > MHLEN) {
769                 MCLGET(m, MB_DONTWAIT);
770                 if (!(m->m_flags & M_EXT)) {
771                         m_free(m);
772                         return (NULL);
773                 }
774         }
775         m->m_pkthdr.len = m->m_len = hlen;
776         m->m_pkthdr.rcvif = NULL;
777         rtinfo->rti_addrs = 0;
778         len = hlen;
779         for (i = 0; i < RTAX_MAX; i++) {
780                 struct sockaddr *sa;
781                 int dlen;
782
783                 if ((sa = rtinfo->rti_info[i]) == NULL)
784                         continue;
785                 rtinfo->rti_addrs |= (1 << i);
786                 dlen = ROUNDUP(sa->sa_len);
787                 m_copyback(m, len, dlen, (caddr_t)sa); /* can grow mbuf chain */
788                 len += dlen;
789         }
790         if (m->m_pkthdr.len != len) { /* one of the m_copyback() calls failed */
791                 m_freem(m);
792                 return (NULL);
793         }
794         rtm = mtod(m, struct rt_msghdr *);
795         bzero(rtm, hlen);
796         rtm->rtm_msglen = len;
797         rtm->rtm_version = RTM_VERSION;
798         rtm->rtm_type = type;
799         return (m);
800 }
801
802 /*
803  * This routine is called to generate a message from the routing
804  * socket indicating that a redirect has occurred, a routing lookup
805  * has failed, or that a protocol has detected timeouts to a particular
806  * destination.
807  */
808 void
809 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
810 {
811         struct sockaddr *dst = rtinfo->rti_info[RTAX_DST];
812         struct rt_msghdr *rtm;
813         struct mbuf *m;
814
815         if (route_cb.any_count == 0)
816                 return;
817         m = rt_msg_mbuf(type, rtinfo);
818         if (m == NULL)
819                 return;
820         rtm = mtod(m, struct rt_msghdr *);
821         rtm->rtm_flags = RTF_DONE | flags;
822         rtm->rtm_errno = error;
823         rtm->rtm_addrs = rtinfo->rti_addrs;
824         rts_input(m, familyof(dst));
825 }
826
827 void
828 rt_dstmsg(int type, struct sockaddr *dst, int error)
829 {
830         struct rt_msghdr *rtm;
831         struct rt_addrinfo addrs;
832         struct mbuf *m;
833
834         if (route_cb.any_count == 0)
835                 return;
836         bzero(&addrs, sizeof(struct rt_addrinfo));
837         addrs.rti_info[RTAX_DST] = dst;
838         m = rt_msg_mbuf(type, &addrs);
839         if (m == NULL)
840                 return;
841         rtm = mtod(m, struct rt_msghdr *);
842         rtm->rtm_flags = RTF_DONE;
843         rtm->rtm_errno = error;
844         rtm->rtm_addrs = addrs.rti_addrs;
845         rts_input(m, familyof(dst));
846 }
847
848 /*
849  * This routine is called to generate a message from the routing
850  * socket indicating that the status of a network interface has changed.
851  */
852 void
853 rt_ifmsg(struct ifnet *ifp)
854 {
855         struct if_msghdr *ifm;
856         struct mbuf *m;
857         struct rt_addrinfo rtinfo;
858
859         if (route_cb.any_count == 0)
860                 return;
861         bzero(&rtinfo, sizeof(struct rt_addrinfo));
862         m = rt_msg_mbuf(RTM_IFINFO, &rtinfo);
863         if (m == NULL)
864                 return;
865         ifm = mtod(m, struct if_msghdr *);
866         ifm->ifm_index = ifp->if_index;
867         ifm->ifm_flags = (u_short)ifp->if_flags;
868         ifm->ifm_data = ifp->if_data;
869         ifm->ifm_addrs = 0;
870         rts_input(m, 0);
871 }
872
873 static void
874 rt_ifamsg(int cmd, struct ifaddr *ifa)
875 {
876         struct ifa_msghdr *ifam;
877         struct rt_addrinfo rtinfo;
878         struct mbuf *m;
879         struct ifnet *ifp = ifa->ifa_ifp;
880
881         bzero(&rtinfo, sizeof(struct rt_addrinfo));
882         rtinfo.rti_ifaaddr = ifa->ifa_addr;
883         rtinfo.rti_ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
884         rtinfo.rti_netmask = ifa->ifa_netmask;
885         rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
886
887         m = rt_msg_mbuf(cmd, &rtinfo);
888         if (m == NULL)
889                 return;
890
891         ifam = mtod(m, struct ifa_msghdr *);
892         ifam->ifam_index = ifp->if_index;
893         ifam->ifam_metric = ifa->ifa_metric;
894         ifam->ifam_flags = ifa->ifa_flags;
895         ifam->ifam_addrs = rtinfo.rti_addrs;
896
897         rts_input(m, familyof(ifa->ifa_addr));
898 }
899
900 void
901 rt_rtmsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int error)
902 {
903         struct rt_msghdr *rtm;
904         struct rt_addrinfo rtinfo;
905         struct mbuf *m;
906         struct sockaddr *dst;
907
908         if (rt == NULL)
909                 return;
910
911         bzero(&rtinfo, sizeof(struct rt_addrinfo));
912         rtinfo.rti_dst = dst = rt_key(rt);
913         rtinfo.rti_gateway = rt->rt_gateway;
914         rtinfo.rti_netmask = rt_mask(rt);
915         if (ifp != NULL)
916                 rtinfo.rti_ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
917         rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr;
918
919         m = rt_msg_mbuf(cmd, &rtinfo);
920         if (m == NULL)
921                 return;
922
923         rtm = mtod(m, struct rt_msghdr *);
924         if (ifp != NULL)
925                 rtm->rtm_index = ifp->if_index;
926         rtm->rtm_flags |= rt->rt_flags;
927         rtm->rtm_errno = error;
928         rtm->rtm_addrs = rtinfo.rti_addrs;
929
930         rts_input(m, familyof(dst));
931 }
932
933 /*
934  * This is called to generate messages from the routing socket
935  * indicating a network interface has had addresses associated with it.
936  * if we ever reverse the logic and replace messages TO the routing
937  * socket indicate a request to configure interfaces, then it will
938  * be unnecessary as the routing socket will automatically generate
939  * copies of it.
940  */
941 void
942 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
943 {
944         if (route_cb.any_count == 0)
945                 return;
946
947         if (cmd == RTM_ADD) {
948                 rt_ifamsg(RTM_NEWADDR, ifa);
949                 rt_rtmsg(RTM_ADD, rt, ifa->ifa_ifp, error);
950         } else {
951                 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
952                 rt_rtmsg(RTM_DELETE, rt, ifa->ifa_ifp, error);
953                 rt_ifamsg(RTM_DELADDR, ifa);
954         }
955 }
956
957 /*
958  * This is the analogue to the rt_newaddrmsg which performs the same
959  * function but for multicast group memberhips.  This is easier since
960  * there is no route state to worry about.
961  */
962 void
963 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
964 {
965         struct rt_addrinfo rtinfo;
966         struct mbuf *m = NULL;
967         struct ifnet *ifp = ifma->ifma_ifp;
968         struct ifma_msghdr *ifmam;
969
970         if (route_cb.any_count == 0)
971                 return;
972
973         bzero(&rtinfo, sizeof(struct rt_addrinfo));
974         rtinfo.rti_ifaaddr = ifma->ifma_addr;
975         if (ifp != NULL)
976                 rtinfo.rti_ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
977         else
978                 rtinfo.rti_ifpaddr = NULL;
979         /*
980          * If a link-layer address is present, present it as a ``gateway''
981          * (similarly to how ARP entries, e.g., are presented).
982          */
983         rtinfo.rti_gateway = ifma->ifma_lladdr;
984
985         m = rt_msg_mbuf(cmd, &rtinfo);
986         if (m == NULL)
987                 return;
988
989         ifmam = mtod(m, struct ifma_msghdr *);
990         ifmam->ifmam_index = ifp->if_index;
991         ifmam->ifmam_addrs = rtinfo.rti_addrs;
992
993         rts_input(m, familyof(ifma->ifma_addr));
994 }
995
996 /*
997  * This is called to generate routing socket messages indicating
998  * network interface arrival and departure.
999  */
1000 void
1001 rt_ifannouncemsg(struct ifnet *ifp, int what)
1002 {
1003         struct rt_addrinfo addrinfo;
1004         struct mbuf *m;
1005         struct if_announcemsghdr *ifan;
1006
1007         if (route_cb.any_count == 0)
1008                 return;
1009
1010         bzero(&addrinfo, sizeof addrinfo);
1011         m = rt_msg_mbuf(RTM_IFANNOUNCE, &addrinfo);
1012         if (m == NULL)
1013                 return;
1014
1015         ifan = mtod(m, struct if_announcemsghdr *);
1016         ifan->ifan_index = ifp->if_index;
1017         strlcpy(ifan->ifan_name, ifp->if_xname, sizeof ifan->ifan_name);
1018         ifan->ifan_what = what;
1019
1020         rts_input(m, 0);
1021 }
1022
1023 static int
1024 resizewalkarg(struct walkarg *w, int len)
1025 {
1026         void *newptr;
1027
1028         newptr = malloc(len, M_RTABLE, M_INTWAIT | M_NULLOK);
1029         if (newptr == NULL)
1030                 return (ENOMEM);
1031         if (w->w_tmem != NULL)
1032                 free(w->w_tmem, M_RTABLE);
1033         w->w_tmem = newptr;
1034         w->w_tmemsize = len;
1035         return (0);
1036 }
1037
1038 /*
1039  * This is used in dumping the kernel table via sysctl().
1040  */
1041 int
1042 sysctl_dumpentry(struct radix_node *rn, void *vw)
1043 {
1044         struct walkarg *w = vw;
1045         struct rtentry *rt = (struct rtentry *)rn;
1046         struct rt_addrinfo rtinfo;
1047         int error, msglen;
1048
1049         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
1050                 return 0;
1051
1052         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1053         rtinfo.rti_dst = rt_key(rt);
1054         rtinfo.rti_gateway = rt->rt_gateway;
1055         rtinfo.rti_netmask = rt_mask(rt);
1056         rtinfo.rti_genmask = rt->rt_genmask;
1057         if (rt->rt_ifp != NULL) {
1058                 rtinfo.rti_ifpaddr =
1059                     TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
1060                 rtinfo.rti_ifaaddr = rt->rt_ifa->ifa_addr;
1061                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
1062                         rtinfo.rti_bcastaddr = rt->rt_ifa->ifa_dstaddr;
1063         }
1064         msglen = rt_msgsize(RTM_GET, &rtinfo);
1065         if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0)
1066                 return (ENOMEM);
1067         rt_msg_buffer(RTM_GET, &rtinfo, w->w_tmem, msglen);
1068         if (w->w_req != NULL) {
1069                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
1070
1071                 rtm->rtm_flags = rt->rt_flags;
1072                 rtm->rtm_use = rt->rt_use;
1073                 rtm->rtm_rmx = rt->rt_rmx;
1074                 rtm->rtm_index = rt->rt_ifp->if_index;
1075                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
1076                 rtm->rtm_addrs = rtinfo.rti_addrs;
1077                 error = SYSCTL_OUT(w->w_req, rtm, msglen);
1078                 return (error);
1079         }
1080         return (0);
1081 }
1082
1083 static int
1084 sysctl_iflist(int af, struct walkarg *w)
1085 {
1086         struct ifnet *ifp;
1087         struct ifaddr *ifa;
1088         struct rt_addrinfo rtinfo;
1089         int msglen, error;
1090
1091         bzero(&rtinfo, sizeof(struct rt_addrinfo));
1092         TAILQ_FOREACH(ifp, &ifnet, if_link) {
1093                 if (w->w_arg && w->w_arg != ifp->if_index)
1094                         continue;
1095                 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1096                 rtinfo.rti_ifpaddr = ifa->ifa_addr;
1097                 msglen = rt_msgsize(RTM_IFINFO, &rtinfo);
1098                 if (w->w_tmemsize < msglen && resizewalkarg(w, msglen) != 0)
1099                         return (ENOMEM);
1100                 rt_msg_buffer(RTM_IFINFO, &rtinfo, w->w_tmem, msglen);
1101                 rtinfo.rti_ifpaddr = NULL;
1102                 if (w->w_req != NULL && w->w_tmem != NULL) {
1103                         struct if_msghdr *ifm;
1104
1105                         ifm = (struct if_msghdr *)w->w_tmem;
1106                         ifm->ifm_index = ifp->if_index;
1107                         ifm->ifm_flags = (u_short)ifp->if_flags;
1108                         ifm->ifm_data = ifp->if_data;
1109                         ifm->ifm_addrs = rtinfo.rti_addrs;
1110                         error = SYSCTL_OUT(w->w_req, ifm, msglen);
1111                         if (error)
1112                                 return (error);
1113                 }
1114                 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
1115                         if (af && af != ifa->ifa_addr->sa_family)
1116                                 continue;
1117                         if (curproc->p_ucred->cr_prison &&
1118                             prison_if(curthread, ifa->ifa_addr))
1119                                 continue;
1120                         rtinfo.rti_ifaaddr = ifa->ifa_addr;
1121                         rtinfo.rti_netmask = ifa->ifa_netmask;
1122                         rtinfo.rti_bcastaddr = ifa->ifa_dstaddr;
1123                         msglen = rt_msgsize(RTM_NEWADDR, &rtinfo);
1124                         if (w->w_tmemsize < msglen &&
1125                             resizewalkarg(w, msglen) != 0)
1126                                 return (ENOMEM);
1127                         rt_msg_buffer(RTM_NEWADDR, &rtinfo, w->w_tmem, msglen);
1128                         if (w->w_req != NULL) {
1129                                 struct ifa_msghdr *ifam;
1130
1131                                 ifam = (struct ifa_msghdr *)w->w_tmem;
1132                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
1133                                 ifam->ifam_flags = ifa->ifa_flags;
1134                                 ifam->ifam_metric = ifa->ifa_metric;
1135                                 ifam->ifam_addrs = rtinfo.rti_addrs;
1136                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, msglen);
1137                                 if (error)
1138                                         return (error);
1139                         }
1140                 }
1141                 rtinfo.rti_netmask = NULL;
1142                 rtinfo.rti_ifaaddr = NULL;
1143                 rtinfo.rti_bcastaddr = NULL;
1144         }
1145         return (0);
1146 }
1147
1148 static int
1149 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1150 {
1151         int     *name = (int *)arg1;
1152         u_int   namelen = arg2;
1153         struct radix_node_head *rnh;
1154         int     i, s, error = EINVAL;
1155         u_char  af;
1156         struct  walkarg w;
1157
1158         name ++;
1159         namelen--;
1160         if (req->newptr)
1161                 return (EPERM);
1162         if (namelen != 3)
1163                 return (EINVAL);
1164         af = name[0];
1165         bzero(&w, sizeof w);
1166         w.w_op = name[1];
1167         w.w_arg = name[2];
1168         w.w_req = req;
1169
1170         s = splnet();
1171         switch (w.w_op) {
1172
1173         case NET_RT_DUMP:
1174         case NET_RT_FLAGS:
1175                 for (i = 1; i <= AF_MAX; i++)
1176                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
1177                             (error = rnh->rnh_walktree(rnh,
1178                                                        sysctl_dumpentry, &w)))
1179                                 break;
1180                 break;
1181
1182         case NET_RT_IFLIST:
1183                 error = sysctl_iflist(af, &w);
1184         }
1185         splx(s);
1186         if (w.w_tmem != NULL)
1187                 free(w.w_tmem, M_RTABLE);
1188         return (error);
1189 }
1190
1191 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1192
1193 /*
1194  * Definitions of protocols supported in the ROUTE domain.
1195  */
1196
1197 extern struct domain routedomain;               /* or at least forward */
1198
1199 static struct protosw routesw[] = {
1200 { SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
1201   0,            route_output,   raw_ctlinput,   0,
1202   cpu0_soport,
1203   raw_init,     0,              0,              0,
1204   &route_usrreqs
1205 }
1206 };
1207
1208 static struct domain routedomain =
1209     { PF_ROUTE, "route", 0, 0, 0,
1210       routesw, &routesw[(sizeof routesw)/(sizeof routesw[0])] };
1211
1212 DOMAIN_SET(route);