]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/rtsock.c
o Move per-process jail pointer (p->pr_prison) to inside of the subject
[FreeBSD/FreeBSD.git] / sys / net / rtsock.c
1 /*
2  * Copyright (c) 1988, 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      @(#)rtsock.c    8.5 (Berkeley) 11/2/94
34  * $FreeBSD$
35  */
36
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/sysctl.h>
42 #include <sys/proc.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/domain.h>
48 #include <sys/protosw.h>
49 #include <sys/jail.h>
50
51 #include <net/if.h>
52 #include <net/route.h>
53 #include <net/raw_cb.h>
54
55 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
56
57 static struct   sockaddr route_dst = { 2, PF_ROUTE, };
58 static struct   sockaddr route_src = { 2, PF_ROUTE, };
59 static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
60 static struct   sockproto route_proto = { PF_ROUTE, };
61
62 struct walkarg {
63         int     w_tmemsize;
64         int     w_op, w_arg;
65         caddr_t w_tmem;
66         struct sysctl_req *w_req;
67 };
68
69 static struct mbuf *
70                 rt_msg1 __P((int, struct rt_addrinfo *));
71 static int      rt_msg2 __P((int,
72                     struct rt_addrinfo *, caddr_t, struct walkarg *));
73 static int      rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
74 static int      sysctl_dumpentry __P((struct radix_node *rn, void *vw));
75 static int      sysctl_iflist __P((int af, struct walkarg *w));
76 static int       route_output __P((struct mbuf *, struct socket *));
77 static void      rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
78
79 /* Sleazy use of local variables throughout file, warning!!!! */
80 #define dst     info.rti_info[RTAX_DST]
81 #define gate    info.rti_info[RTAX_GATEWAY]
82 #define netmask info.rti_info[RTAX_NETMASK]
83 #define genmask info.rti_info[RTAX_GENMASK]
84 #define ifpaddr info.rti_info[RTAX_IFP]
85 #define ifaaddr info.rti_info[RTAX_IFA]
86 #define brdaddr info.rti_info[RTAX_BRD]
87
88 /*
89  * It really doesn't make any sense at all for this code to share much
90  * with raw_usrreq.c, since its functionality is so restricted.  XXX
91  */
92 static int
93 rts_abort(struct socket *so)
94 {
95         int s, error;
96         s = splnet();
97         error = raw_usrreqs.pru_abort(so);
98         splx(s);
99         return error;
100 }
101
102 /* pru_accept is EOPNOTSUPP */
103
104 static int
105 rts_attach(struct socket *so, int proto, struct proc *p)
106 {
107         struct rawcb *rp;
108         int s, error;
109
110         if (sotorawcb(so) != 0)
111                 return EISCONN; /* XXX panic? */
112         /* XXX */
113         MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
114         if (rp == 0)
115                 return ENOBUFS;
116
117         /*
118          * The splnet() is necessary to block protocols from sending
119          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
120          * this PCB is extant but incompletely initialized.
121          * Probably we should try to do more of this work beforehand and
122          * eliminate the spl.
123          */
124         s = splnet();
125         so->so_pcb = (caddr_t)rp;
126         error = raw_usrreqs.pru_attach(so, proto, p);
127         rp = sotorawcb(so);
128         if (error) {
129                 splx(s);
130                 free(rp, M_PCB);
131                 return error;
132         }
133         switch(rp->rcb_proto.sp_protocol) {
134         case AF_INET:
135                 route_cb.ip_count++;
136                 break;
137         case AF_INET6:
138                 route_cb.ip6_count++;
139                 break;
140         case AF_IPX:
141                 route_cb.ipx_count++;
142                 break;
143         case AF_NS:
144                 route_cb.ns_count++;
145                 break;
146         }
147         rp->rcb_faddr = &route_src;
148         route_cb.any_count++;
149         soisconnected(so);
150         so->so_options |= SO_USELOOPBACK;
151         splx(s);
152         return 0;
153 }
154
155 static int
156 rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
157 {
158         int s, error;
159         s = splnet();
160         error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
161         splx(s);
162         return error;
163 }
164
165 static int
166 rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
167 {
168         int s, error;
169         s = splnet();
170         error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
171         splx(s);
172         return error;
173 }
174
175 /* pru_connect2 is EOPNOTSUPP */
176 /* pru_control is EOPNOTSUPP */
177
178 static int
179 rts_detach(struct socket *so)
180 {
181         struct rawcb *rp = sotorawcb(so);
182         int s, error;
183
184         s = splnet();
185         if (rp != 0) {
186                 switch(rp->rcb_proto.sp_protocol) {
187                 case AF_INET:
188                         route_cb.ip_count--;
189                         break;
190                 case AF_INET6:
191                         route_cb.ip6_count--;
192                         break;
193                 case AF_IPX:
194                         route_cb.ipx_count--;
195                         break;
196                 case AF_NS:
197                         route_cb.ns_count--;
198                         break;
199                 }
200                 route_cb.any_count--;
201         }
202         error = raw_usrreqs.pru_detach(so);
203         splx(s);
204         return error;
205 }
206
207 static int
208 rts_disconnect(struct socket *so)
209 {
210         int s, error;
211         s = splnet();
212         error = raw_usrreqs.pru_disconnect(so);
213         splx(s);
214         return error;
215 }
216
217 /* pru_listen is EOPNOTSUPP */
218
219 static int
220 rts_peeraddr(struct socket *so, struct sockaddr **nam)
221 {
222         int s, error;
223         s = splnet();
224         error = raw_usrreqs.pru_peeraddr(so, nam);
225         splx(s);
226         return error;
227 }
228
229 /* pru_rcvd is EOPNOTSUPP */
230 /* pru_rcvoob is EOPNOTSUPP */
231
232 static int
233 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
234          struct mbuf *control, struct proc *p)
235 {
236         int s, error;
237         s = splnet();
238         error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
239         splx(s);
240         return error;
241 }
242
243 /* pru_sense is null */
244
245 static int
246 rts_shutdown(struct socket *so)
247 {
248         int s, error;
249         s = splnet();
250         error = raw_usrreqs.pru_shutdown(so);
251         splx(s);
252         return error;
253 }
254
255 static int
256 rts_sockaddr(struct socket *so, struct sockaddr **nam)
257 {
258         int s, error;
259         s = splnet();
260         error = raw_usrreqs.pru_sockaddr(so, nam);
261         splx(s);
262         return error;
263 }
264
265 static struct pr_usrreqs route_usrreqs = {
266         rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
267         pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
268         pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
269         rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
270         sosend, soreceive, sopoll
271 };
272
273 /*ARGSUSED*/
274 static int
275 route_output(m, so)
276         register struct mbuf *m;
277         struct socket *so;
278 {
279         register struct rt_msghdr *rtm = 0;
280         register struct rtentry *rt = 0;
281         struct rtentry *saved_nrt = 0;
282         struct radix_node_head *rnh;
283         struct rt_addrinfo info;
284         int len, error = 0;
285         struct ifnet *ifp = 0;
286         struct ifaddr *ifa = 0;
287
288 #define senderr(e) { error = e; goto flush;}
289         if (m == 0 || ((m->m_len < sizeof(long)) &&
290                        (m = m_pullup(m, sizeof(long))) == 0))
291                 return (ENOBUFS);
292         if ((m->m_flags & M_PKTHDR) == 0)
293                 panic("route_output");
294         len = m->m_pkthdr.len;
295         if (len < sizeof(*rtm) ||
296             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
297                 dst = 0;
298                 senderr(EINVAL);
299         }
300         R_Malloc(rtm, struct rt_msghdr *, len);
301         if (rtm == 0) {
302                 dst = 0;
303                 senderr(ENOBUFS);
304         }
305         m_copydata(m, 0, len, (caddr_t)rtm);
306         if (rtm->rtm_version != RTM_VERSION) {
307                 dst = 0;
308                 senderr(EPROTONOSUPPORT);
309         }
310         rtm->rtm_pid = curproc->p_pid;
311         info.rti_addrs = rtm->rtm_addrs;
312         if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
313                 dst = 0;
314                 senderr(EINVAL);
315         }
316         if (dst == 0 || (dst->sa_family >= AF_MAX)
317             || (gate != 0 && (gate->sa_family >= AF_MAX)))
318                 senderr(EINVAL);
319         if (genmask) {
320                 struct radix_node *t;
321                 t = rn_addmask((caddr_t)genmask, 0, 1);
322                 if (t && Bcmp((caddr_t *)genmask + 1, (caddr_t *)t->rn_key + 1,
323                               *(u_char *)t->rn_key - 1) == 0)
324                         genmask = (struct sockaddr *)(t->rn_key);
325                 else
326                         senderr(ENOBUFS);
327         }
328         switch (rtm->rtm_type) {
329
330         case RTM_ADD:
331                 if (gate == 0)
332                         senderr(EINVAL);
333                 error = rtrequest(RTM_ADD, dst, gate, netmask,
334                                         rtm->rtm_flags, &saved_nrt);
335                 if (error == 0 && saved_nrt) {
336                         rt_setmetrics(rtm->rtm_inits,
337                                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
338                         saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
339                         saved_nrt->rt_rmx.rmx_locks |=
340                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
341                         saved_nrt->rt_refcnt--;
342                         saved_nrt->rt_genmask = genmask;
343                 }
344                 break;
345
346         case RTM_DELETE:
347                 error = rtrequest(RTM_DELETE, dst, gate, netmask,
348                                 rtm->rtm_flags, &saved_nrt);
349                 if (error == 0) {
350                         if ((rt = saved_nrt))
351                                 rt->rt_refcnt++;
352                         goto report;
353                 }
354                 break;
355
356         case RTM_GET:
357         case RTM_CHANGE:
358         case RTM_LOCK:
359                 if ((rnh = rt_tables[dst->sa_family]) == 0) {
360                         senderr(EAFNOSUPPORT);
361                 } else if ((rt = (struct rtentry *)
362                                 rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
363                         rt->rt_refcnt++;
364                 else
365                         senderr(ESRCH);
366                 switch(rtm->rtm_type) {
367
368                 case RTM_GET:
369                 report:
370                         dst = rt_key(rt);
371                         gate = rt->rt_gateway;
372                         netmask = rt_mask(rt);
373                         genmask = rt->rt_genmask;
374                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
375                                 ifp = rt->rt_ifp;
376                                 if (ifp) {
377                                         ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
378                                         ifaaddr = rt->rt_ifa->ifa_addr;
379                                         rtm->rtm_index = ifp->if_index;
380                                 } else {
381                                         ifpaddr = 0;
382                                         ifaaddr = 0;
383                             }
384                         }
385                         len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
386                                 (struct walkarg *)0);
387                         if (len > rtm->rtm_msglen) {
388                                 struct rt_msghdr *new_rtm;
389                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
390                                 if (new_rtm == 0)
391                                         senderr(ENOBUFS);
392                                 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
393                                 Free(rtm); rtm = new_rtm;
394                         }
395                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
396                                 (struct walkarg *)0);
397                         rtm->rtm_flags = rt->rt_flags;
398                         rtm->rtm_rmx = rt->rt_rmx;
399                         rtm->rtm_addrs = info.rti_addrs;
400                         break;
401
402                 case RTM_CHANGE:
403                         if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
404                                 senderr(error);
405
406                         /*
407                          * If they tried to change things but didn't specify
408                          * the required gateway, then just use the old one.
409                          * This can happen if the user tries to change the
410                          * flags on the default route without changing the
411                          * default gateway.  Changing flags still doesn't work.
412                          */
413                         if ((rt->rt_flags & RTF_GATEWAY) && !gate)
414                                 gate = rt->rt_gateway;
415
416                         /* new gateway could require new ifaddr, ifp;
417                            flags may also be different; ifp may be specified
418                            by ll sockaddr when protocol address is ambiguous */
419                         if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
420                             (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
421                                 ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
422                                                         ifp);
423                         else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
424                                  (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
425                                                         rt_key(rt), gate))))
426                                 ifp = ifa->ifa_ifp;
427                         if (ifa) {
428                                 register struct ifaddr *oifa = rt->rt_ifa;
429                                 if (oifa != ifa) {
430                                     if (oifa && oifa->ifa_rtrequest)
431                                         oifa->ifa_rtrequest(RTM_DELETE,
432                                                                 rt, gate);
433                                     IFAFREE(rt->rt_ifa);
434                                     rt->rt_ifa = ifa;
435                                     ifa->ifa_refcnt++;
436                                     rt->rt_ifp = ifp;
437                                 }
438                         }
439                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
440                                         &rt->rt_rmx);
441                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
442                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
443                         if (genmask)
444                                 rt->rt_genmask = genmask;
445                         /*
446                          * Fall into
447                          */
448                 case RTM_LOCK:
449                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
450                         rt->rt_rmx.rmx_locks |=
451                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
452                         break;
453                 }
454                 break;
455
456         default:
457                 senderr(EOPNOTSUPP);
458         }
459
460 flush:
461         if (rtm) {
462                 if (error)
463                         rtm->rtm_errno = error;
464                 else
465                         rtm->rtm_flags |= RTF_DONE;
466         }
467         if (rt)
468                 rtfree(rt);
469     {
470         register struct rawcb *rp = 0;
471         /*
472          * Check to see if we don't want our own messages.
473          */
474         if ((so->so_options & SO_USELOOPBACK) == 0) {
475                 if (route_cb.any_count <= 1) {
476                         if (rtm)
477                                 Free(rtm);
478                         m_freem(m);
479                         return (error);
480                 }
481                 /* There is another listener, so construct message */
482                 rp = sotorawcb(so);
483         }
484         if (rtm) {
485                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
486                 Free(rtm);
487         }
488         if (rp)
489                 rp->rcb_proto.sp_family = 0; /* Avoid us */
490         if (dst)
491                 route_proto.sp_protocol = dst->sa_family;
492         raw_input(m, &route_proto, &route_src, &route_dst);
493         if (rp)
494                 rp->rcb_proto.sp_family = PF_ROUTE;
495     }
496         return (error);
497 }
498
499 static void
500 rt_setmetrics(which, in, out)
501         u_long which;
502         register struct rt_metrics *in, *out;
503 {
504 #define metric(f, e) if (which & (f)) out->e = in->e;
505         metric(RTV_RPIPE, rmx_recvpipe);
506         metric(RTV_SPIPE, rmx_sendpipe);
507         metric(RTV_SSTHRESH, rmx_ssthresh);
508         metric(RTV_RTT, rmx_rtt);
509         metric(RTV_RTTVAR, rmx_rttvar);
510         metric(RTV_HOPCOUNT, rmx_hopcount);
511         metric(RTV_MTU, rmx_mtu);
512         metric(RTV_EXPIRE, rmx_expire);
513 #undef metric
514 }
515
516 #define ROUNDUP(a) \
517         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
518 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
519
520
521 /*
522  * Extract the addresses of the passed sockaddrs.
523  * Do a little sanity checking so as to avoid bad memory references.
524  * This data is derived straight from userland.
525  */
526 static int
527 rt_xaddrs(cp, cplim, rtinfo)
528         register caddr_t cp, cplim;
529         register struct rt_addrinfo *rtinfo;
530 {
531         register struct sockaddr *sa;
532         register int i;
533
534         bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
535         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
536                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
537                         continue;
538                 sa = (struct sockaddr *)cp;
539                 /*
540                  * It won't fit.
541                  */
542                 if ( (cp + sa->sa_len) > cplim ) {
543                         return (EINVAL);
544                 }
545
546                 /*
547                  * there are no more.. quit now
548                  * If there are more bits, they are in error.
549                  * I've seen this. route(1) can evidently generate these. 
550                  * This causes kernel to core dump.
551                  * for compatibility, If we see this, point to a safe address.
552                  */
553                 if (sa->sa_len == 0) {
554                         rtinfo->rti_info[i] = &sa_zero;
555                         return (0); /* should be EINVAL but for compat */
556                 }
557
558                 /* accept it */
559                 rtinfo->rti_info[i] = sa;
560                 ADVANCE(cp, sa);
561         }
562         return (0);
563 }
564
565 static struct mbuf *
566 rt_msg1(type, rtinfo)
567         int type;
568         register struct rt_addrinfo *rtinfo;
569 {
570         register struct rt_msghdr *rtm;
571         register struct mbuf *m;
572         register int i;
573         register struct sockaddr *sa;
574         int len, dlen;
575
576         m = m_gethdr(M_DONTWAIT, MT_DATA);
577         if (m == 0)
578                 return (m);
579         switch (type) {
580
581         case RTM_DELADDR:
582         case RTM_NEWADDR:
583                 len = sizeof(struct ifa_msghdr);
584                 break;
585
586         case RTM_DELMADDR:
587         case RTM_NEWMADDR:
588                 len = sizeof(struct ifma_msghdr);
589                 break;
590
591         case RTM_IFINFO:
592                 len = sizeof(struct if_msghdr);
593                 break;
594
595         default:
596                 len = sizeof(struct rt_msghdr);
597         }
598         if (len > MHLEN)
599                 panic("rt_msg1");
600         m->m_pkthdr.len = m->m_len = len;
601         m->m_pkthdr.rcvif = 0;
602         rtm = mtod(m, struct rt_msghdr *);
603         bzero((caddr_t)rtm, len);
604         for (i = 0; i < RTAX_MAX; i++) {
605                 if ((sa = rtinfo->rti_info[i]) == NULL)
606                         continue;
607                 rtinfo->rti_addrs |= (1 << i);
608                 dlen = ROUNDUP(sa->sa_len);
609                 m_copyback(m, len, dlen, (caddr_t)sa);
610                 len += dlen;
611         }
612         if (m->m_pkthdr.len != len) {
613                 m_freem(m);
614                 return (NULL);
615         }
616         rtm->rtm_msglen = len;
617         rtm->rtm_version = RTM_VERSION;
618         rtm->rtm_type = type;
619         return (m);
620 }
621
622 static int
623 rt_msg2(type, rtinfo, cp, w)
624         int type;
625         register struct rt_addrinfo *rtinfo;
626         caddr_t cp;
627         struct walkarg *w;
628 {
629         register int i;
630         int len, dlen, second_time = 0;
631         caddr_t cp0;
632
633         rtinfo->rti_addrs = 0;
634 again:
635         switch (type) {
636
637         case RTM_DELADDR:
638         case RTM_NEWADDR:
639                 len = sizeof(struct ifa_msghdr);
640                 break;
641
642         case RTM_IFINFO:
643                 len = sizeof(struct if_msghdr);
644                 break;
645
646         default:
647                 len = sizeof(struct rt_msghdr);
648         }
649         cp0 = cp;
650         if (cp0)
651                 cp += len;
652         for (i = 0; i < RTAX_MAX; i++) {
653                 register struct sockaddr *sa;
654
655                 if ((sa = rtinfo->rti_info[i]) == 0)
656                         continue;
657                 rtinfo->rti_addrs |= (1 << i);
658                 dlen = ROUNDUP(sa->sa_len);
659                 if (cp) {
660                         bcopy((caddr_t)sa, cp, (unsigned)dlen);
661                         cp += dlen;
662                 }
663                 len += dlen;
664         }
665         if (cp == 0 && w != NULL && !second_time) {
666                 register struct walkarg *rw = w;
667
668                 if (rw->w_req) {
669                         if (rw->w_tmemsize < len) {
670                                 if (rw->w_tmem)
671                                         free(rw->w_tmem, M_RTABLE);
672                                 rw->w_tmem = (caddr_t)
673                                         malloc(len, M_RTABLE, M_NOWAIT);
674                                 if (rw->w_tmem)
675                                         rw->w_tmemsize = len;
676                         }
677                         if (rw->w_tmem) {
678                                 cp = rw->w_tmem;
679                                 second_time = 1;
680                                 goto again;
681                         }
682                 }
683         }
684         if (cp) {
685                 register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
686
687                 rtm->rtm_version = RTM_VERSION;
688                 rtm->rtm_type = type;
689                 rtm->rtm_msglen = len;
690         }
691         return (len);
692 }
693
694 /*
695  * This routine is called to generate a message from the routing
696  * socket indicating that a redirect has occured, a routing lookup
697  * has failed, or that a protocol has detected timeouts to a particular
698  * destination.
699  */
700 void
701 rt_missmsg(type, rtinfo, flags, error)
702         int type, flags, error;
703         register struct rt_addrinfo *rtinfo;
704 {
705         register struct rt_msghdr *rtm;
706         register struct mbuf *m;
707         struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
708
709         if (route_cb.any_count == 0)
710                 return;
711         m = rt_msg1(type, rtinfo);
712         if (m == 0)
713                 return;
714         rtm = mtod(m, struct rt_msghdr *);
715         rtm->rtm_flags = RTF_DONE | flags;
716         rtm->rtm_errno = error;
717         rtm->rtm_addrs = rtinfo->rti_addrs;
718         route_proto.sp_protocol = sa ? sa->sa_family : 0;
719         raw_input(m, &route_proto, &route_src, &route_dst);
720 }
721
722 /*
723  * This routine is called to generate a message from the routing
724  * socket indicating that the status of a network interface has changed.
725  */
726 void
727 rt_ifmsg(ifp)
728         register struct ifnet *ifp;
729 {
730         register struct if_msghdr *ifm;
731         struct mbuf *m;
732         struct rt_addrinfo info;
733
734         if (route_cb.any_count == 0)
735                 return;
736         bzero((caddr_t)&info, sizeof(info));
737         m = rt_msg1(RTM_IFINFO, &info);
738         if (m == 0)
739                 return;
740         ifm = mtod(m, struct if_msghdr *);
741         ifm->ifm_index = ifp->if_index;
742         ifm->ifm_flags = (u_short)ifp->if_flags;
743         ifm->ifm_data = ifp->if_data;
744         ifm->ifm_addrs = 0;
745         route_proto.sp_protocol = 0;
746         raw_input(m, &route_proto, &route_src, &route_dst);
747 }
748
749 /*
750  * This is called to generate messages from the routing socket
751  * indicating a network interface has had addresses associated with it.
752  * if we ever reverse the logic and replace messages TO the routing
753  * socket indicate a request to configure interfaces, then it will
754  * be unnecessary as the routing socket will automatically generate
755  * copies of it.
756  */
757 void
758 rt_newaddrmsg(cmd, ifa, error, rt)
759         int cmd, error;
760         register struct ifaddr *ifa;
761         register struct rtentry *rt;
762 {
763         struct rt_addrinfo info;
764         struct sockaddr *sa = 0;
765         int pass;
766         struct mbuf *m = 0;
767         struct ifnet *ifp = ifa->ifa_ifp;
768
769         if (route_cb.any_count == 0)
770                 return;
771         for (pass = 1; pass < 3; pass++) {
772                 bzero((caddr_t)&info, sizeof(info));
773                 if ((cmd == RTM_ADD && pass == 1) ||
774                     (cmd == RTM_DELETE && pass == 2)) {
775                         register struct ifa_msghdr *ifam;
776                         int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
777
778                         ifaaddr = sa = ifa->ifa_addr;
779                         ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
780                         netmask = ifa->ifa_netmask;
781                         brdaddr = ifa->ifa_dstaddr;
782                         if ((m = rt_msg1(ncmd, &info)) == NULL)
783                                 continue;
784                         ifam = mtod(m, struct ifa_msghdr *);
785                         ifam->ifam_index = ifp->if_index;
786                         ifam->ifam_metric = ifa->ifa_metric;
787                         ifam->ifam_flags = ifa->ifa_flags;
788                         ifam->ifam_addrs = info.rti_addrs;
789                 }
790                 if ((cmd == RTM_ADD && pass == 2) ||
791                     (cmd == RTM_DELETE && pass == 1)) {
792                         register struct rt_msghdr *rtm;
793
794                         if (rt == 0)
795                                 continue;
796                         netmask = rt_mask(rt);
797                         dst = sa = rt_key(rt);
798                         gate = rt->rt_gateway;
799                         if ((m = rt_msg1(cmd, &info)) == NULL)
800                                 continue;
801                         rtm = mtod(m, struct rt_msghdr *);
802                         rtm->rtm_index = ifp->if_index;
803                         rtm->rtm_flags |= rt->rt_flags;
804                         rtm->rtm_errno = error;
805                         rtm->rtm_addrs = info.rti_addrs;
806                 }
807                 route_proto.sp_protocol = sa ? sa->sa_family : 0;
808                 raw_input(m, &route_proto, &route_src, &route_dst);
809         }
810 }
811
812 /*
813  * This is the analogue to the rt_newaddrmsg which performs the same
814  * function but for multicast group memberhips.  This is easier since
815  * there is no route state to worry about.
816  */
817 void
818 rt_newmaddrmsg(cmd, ifma)
819         int cmd;
820         struct ifmultiaddr *ifma;
821 {
822         struct rt_addrinfo info;
823         struct mbuf *m = 0;
824         struct ifnet *ifp = ifma->ifma_ifp;
825         struct ifma_msghdr *ifmam;
826
827         if (route_cb.any_count == 0)
828                 return;
829
830         bzero((caddr_t)&info, sizeof(info));
831         ifaaddr = ifma->ifma_addr;
832         if (ifp && TAILQ_FIRST(&ifp->if_addrhead))
833                 ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
834         else
835                 ifpaddr = NULL;
836         /*
837          * If a link-layer address is present, present it as a ``gateway''
838          * (similarly to how ARP entries, e.g., are presented).
839          */
840         gate = ifma->ifma_lladdr;
841         if ((m = rt_msg1(cmd, &info)) == NULL)
842                 return;
843         ifmam = mtod(m, struct ifma_msghdr *);
844         ifmam->ifmam_index = ifp->if_index;
845         ifmam->ifmam_addrs = info.rti_addrs;
846         route_proto.sp_protocol = ifma->ifma_addr->sa_family;
847         raw_input(m, &route_proto, &route_src, &route_dst);
848 }
849
850 /*
851  * This is used in dumping the kernel table via sysctl().
852  */
853 int
854 sysctl_dumpentry(rn, vw)
855         struct radix_node *rn;
856         void *vw;
857 {
858         register struct walkarg *w = vw;
859         register struct rtentry *rt = (struct rtentry *)rn;
860         int error = 0, size;
861         struct rt_addrinfo info;
862
863         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
864                 return 0;
865         bzero((caddr_t)&info, sizeof(info));
866         dst = rt_key(rt);
867         gate = rt->rt_gateway;
868         netmask = rt_mask(rt);
869         genmask = rt->rt_genmask;
870         size = rt_msg2(RTM_GET, &info, 0, w);
871         if (w->w_req && w->w_tmem) {
872                 register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
873
874                 rtm->rtm_flags = rt->rt_flags;
875                 rtm->rtm_use = rt->rt_use;
876                 rtm->rtm_rmx = rt->rt_rmx;
877                 rtm->rtm_index = rt->rt_ifp->if_index;
878                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
879                 rtm->rtm_addrs = info.rti_addrs;
880                 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
881                 return (error);
882         }
883         return (error);
884 }
885
886 int
887 sysctl_iflist(af, w)
888         int     af;
889         register struct walkarg *w;
890 {
891         register struct ifnet *ifp;
892         register struct ifaddr *ifa;
893         struct  rt_addrinfo info;
894         int     len, error = 0;
895
896         bzero((caddr_t)&info, sizeof(info));
897         TAILQ_FOREACH(ifp, &ifnet, if_link) {
898                 if (w->w_arg && w->w_arg != ifp->if_index)
899                         continue;
900                 ifa = TAILQ_FIRST(&ifp->if_addrhead);
901                 ifpaddr = ifa->ifa_addr;
902                 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
903                 ifpaddr = 0;
904                 if (w->w_req && w->w_tmem) {
905                         register struct if_msghdr *ifm;
906
907                         ifm = (struct if_msghdr *)w->w_tmem;
908                         ifm->ifm_index = ifp->if_index;
909                         ifm->ifm_flags = (u_short)ifp->if_flags;
910                         ifm->ifm_data = ifp->if_data;
911                         ifm->ifm_addrs = info.rti_addrs;
912                         error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
913                         if (error)
914                                 return (error);
915                 }
916                 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != 0) {
917                         if (af && af != ifa->ifa_addr->sa_family)
918                                 continue;
919                         if (jailed(curproc->p_ucred) &&
920                             prison_if(curproc->p_ucred, ifa->ifa_addr))
921                                 continue;
922                         ifaaddr = ifa->ifa_addr;
923                         netmask = ifa->ifa_netmask;
924                         brdaddr = ifa->ifa_dstaddr;
925                         len = rt_msg2(RTM_NEWADDR, &info, 0, w);
926                         if (w->w_req && w->w_tmem) {
927                                 register struct ifa_msghdr *ifam;
928
929                                 ifam = (struct ifa_msghdr *)w->w_tmem;
930                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
931                                 ifam->ifam_flags = ifa->ifa_flags;
932                                 ifam->ifam_metric = ifa->ifa_metric;
933                                 ifam->ifam_addrs = info.rti_addrs;
934                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
935                                 if (error)
936                                         return (error);
937                         }
938                 }
939                 ifaaddr = netmask = brdaddr = 0;
940         }
941         return (0);
942 }
943
944 static int
945 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
946 {
947         int     *name = (int *)arg1;
948         u_int   namelen = arg2;
949         register struct radix_node_head *rnh;
950         int     i, s, error = EINVAL;
951         u_char  af;
952         struct  walkarg w;
953
954         name ++;
955         namelen--;
956         if (req->newptr)
957                 return (EPERM);
958         if (namelen != 3)
959                 return (EINVAL);
960         af = name[0];
961         Bzero(&w, sizeof(w));
962         w.w_op = name[1];
963         w.w_arg = name[2];
964         w.w_req = req;
965
966         s = splnet();
967         switch (w.w_op) {
968
969         case NET_RT_DUMP:
970         case NET_RT_FLAGS:
971                 for (i = 1; i <= AF_MAX; i++)
972                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
973                             (error = rnh->rnh_walktree(rnh,
974                                                         sysctl_dumpentry, &w)))
975                                 break;
976                 break;
977
978         case NET_RT_IFLIST:
979                 error = sysctl_iflist(af, &w);
980         }
981         splx(s);
982         if (w.w_tmem)
983                 free(w.w_tmem, M_RTABLE);
984         return (error);
985 }
986
987 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
988
989 /*
990  * Definitions of protocols supported in the ROUTE domain.
991  */
992
993 extern struct domain routedomain;               /* or at least forward */
994
995 static struct protosw routesw[] = {
996 { SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
997   0,            route_output,   raw_ctlinput,   0,
998   0,
999   raw_init,     0,              0,              0,
1000   &route_usrreqs
1001 }
1002 };
1003
1004 static struct domain routedomain =
1005     { PF_ROUTE, "route", 0, 0, 0,
1006       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
1007
1008 DOMAIN_SET(route);