M_NOWAIT -> M_WAITOK or M_INTWAIT conversions. There is a whole lot of net
[dragonfly.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.7 (Berkeley) 10/12/95
34  * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.11 2002/12/04 14:05:41 ru Exp $
35  * $DragonFly: src/sys/net/rtsock.c,v 1.12 2004/04/22 04:21:29 dillon Exp $
36  */
37
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/sysctl.h>
43 #include <sys/proc.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/domain.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 (int, struct rt_addrinfo *);
71 static int      rt_msg2 (int, struct rt_addrinfo *, caddr_t, struct walkarg *);
72 static int      rt_xaddrs (caddr_t, caddr_t, struct rt_addrinfo *);
73 static int      sysctl_dumpentry (struct radix_node *rn, void *vw);
74 static int      sysctl_iflist (int af, struct walkarg *w);
75 static int      route_output (struct mbuf *, struct socket *,
76                     struct pr_output_info *);
77 static void     rt_setmetrics (u_long, struct rt_metrics *,
78                     struct rt_metrics *);
79
80 /* Sleazy use of local variables throughout file, warning!!!! */
81 #define dst     info.rti_info[RTAX_DST]
82 #define gate    info.rti_info[RTAX_GATEWAY]
83 #define netmask info.rti_info[RTAX_NETMASK]
84 #define genmask info.rti_info[RTAX_GENMASK]
85 #define ifpaddr info.rti_info[RTAX_IFP]
86 #define ifaaddr info.rti_info[RTAX_IFA]
87 #define brdaddr info.rti_info[RTAX_BRD]
88
89 /*
90  * It really doesn't make any sense at all for this code to share much
91  * with raw_usrreq.c, since its functionality is so restricted.  XXX
92  */
93 static int
94 rts_abort(struct socket *so)
95 {
96         int s, error;
97         s = splnet();
98         error = raw_usrreqs.pru_abort(so);
99         splx(s);
100         return error;
101 }
102
103 /* pru_accept is EOPNOTSUPP */
104
105 static int
106 rts_attach(struct socket *so, int proto, struct pru_attach_info *ai)
107 {
108         struct rawcb *rp;
109         int s, error;
110
111         if (sotorawcb(so) != 0)
112                 return EISCONN; /* XXX panic? */
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_attach(so, proto, ai->sb_rlimit);
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 thread *td)
157 {
158         int s, error;
159         s = splnet();
160         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
161         splx(s);
162         return error;
163 }
164
165 static int
166 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
167 {
168         int s, error;
169         s = splnet();
170         error = raw_usrreqs.pru_connect(so, nam, td); /* 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 thread *td)
235 {
236         int s, error;
237         s = splnet();
238         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
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(struct mbuf *m, struct socket *so, struct pr_output_info *oi)
276 {
277         struct rt_msghdr *rtm = 0;
278         struct rtentry *rt = 0;
279         struct rtentry *saved_nrt = 0;
280         struct radix_node_head *rnh;
281         struct rt_addrinfo info;
282         int len, error = 0;
283         struct ifnet *ifp = 0;
284         struct ifaddr *ifa = 0;
285
286 #define senderr(e) { error = e; goto flush;}
287         if (m == 0 || ((m->m_len < sizeof(long)) &&
288                        (m = m_pullup(m, sizeof(long))) == 0))
289                 return (ENOBUFS);
290         if ((m->m_flags & M_PKTHDR) == 0)
291                 panic("route_output");
292         len = m->m_pkthdr.len;
293         if (len < sizeof(*rtm) ||
294             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
295                 dst = 0;
296                 senderr(EINVAL);
297         }
298         R_Malloc(rtm, struct rt_msghdr *, len);
299         if (rtm == 0) {
300                 dst = 0;
301                 senderr(ENOBUFS);
302         }
303         m_copydata(m, 0, len, (caddr_t)rtm);
304         if (rtm->rtm_version != RTM_VERSION) {
305                 dst = 0;
306                 senderr(EPROTONOSUPPORT);
307         }
308         rtm->rtm_pid = oi->p_pid;
309         bzero(&info, sizeof(info));
310         info.rti_addrs = rtm->rtm_addrs;
311         if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
312                 dst = 0;
313                 senderr(EINVAL);
314         }
315         info.rti_flags = rtm->rtm_flags;
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
329         /*
330          * Verify that the caller has the appropriate privilege; RTM_GET
331          * is the only operation the non-superuser is allowed.
332          */
333         if (rtm->rtm_type != RTM_GET && suser_cred(so->so_cred, 0) != 0)
334                 senderr(EPERM);
335
336         switch (rtm->rtm_type) {
337
338         case RTM_ADD:
339                 if (gate == 0)
340                         senderr(EINVAL);
341                 error = rtrequest1(RTM_ADD, &info, &saved_nrt);
342                 if (error == 0 && saved_nrt) {
343                         rt_setmetrics(rtm->rtm_inits,
344                                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
345                         saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
346                         saved_nrt->rt_rmx.rmx_locks |=
347                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
348                         saved_nrt->rt_refcnt--;
349                         saved_nrt->rt_genmask = genmask;
350                 }
351                 break;
352
353         case RTM_DELETE:
354                 error = rtrequest1(RTM_DELETE, &info, &saved_nrt);
355                 if (error == 0) {
356                         if ((rt = saved_nrt))
357                                 rt->rt_refcnt++;
358                         goto report;
359                 }
360                 break;
361
362         case RTM_GET:
363         case RTM_CHANGE:
364         case RTM_LOCK:
365                 if ((rnh = rt_tables[dst->sa_family]) == 0) {
366                         senderr(EAFNOSUPPORT);
367                 } else if ((rt = (struct rtentry *)
368                                 rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
369                         rt->rt_refcnt++;
370                 else
371                         senderr(ESRCH);
372                 switch(rtm->rtm_type) {
373
374                 case RTM_GET:
375                 report:
376                         dst = rt_key(rt);
377                         gate = rt->rt_gateway;
378                         netmask = rt_mask(rt);
379                         genmask = rt->rt_genmask;
380                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
381                                 ifp = rt->rt_ifp;
382                                 if (ifp) {
383                                         ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
384                                         ifaaddr = rt->rt_ifa->ifa_addr;
385                                         if (ifp->if_flags & IFF_POINTOPOINT)
386                                                 brdaddr = rt->rt_ifa->ifa_dstaddr;
387                                         rtm->rtm_index = ifp->if_index;
388                                 } else {
389                                         ifpaddr = 0;
390                                         ifaaddr = 0;
391                             }
392                         }
393                         len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
394                                 (struct walkarg *)0);
395                         if (len > rtm->rtm_msglen) {
396                                 struct rt_msghdr *new_rtm;
397                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
398                                 if (new_rtm == 0)
399                                         senderr(ENOBUFS);
400                                 Bcopy(rtm, new_rtm, rtm->rtm_msglen);
401                                 Free(rtm); rtm = new_rtm;
402                         }
403                         (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
404                                 (struct walkarg *)0);
405                         rtm->rtm_flags = rt->rt_flags;
406                         rtm->rtm_rmx = rt->rt_rmx;
407                         rtm->rtm_addrs = info.rti_addrs;
408                         break;
409
410                 case RTM_CHANGE:
411                         /* new gateway could require new ifaddr, ifp;
412                            flags may also be different; ifp may be specified
413                            by ll sockaddr when protocol address is ambiguous */
414 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
415                         if ((rt->rt_flags & RTF_GATEWAY && gate != NULL) ||
416                             ifpaddr != NULL ||
417                             (ifaaddr != NULL &&
418                             !equal(ifaaddr, rt->rt_ifa->ifa_addr))) {
419                                 if ((error = rt_getifa(&info)) != 0)
420                                         senderr(error);
421                         }
422                         if (gate != NULL &&
423                             (error = rt_setgate(rt, rt_key(rt), gate)) != 0)
424                                 senderr(error);
425                         if ((ifa = info.rti_ifa) != NULL) {
426                                 struct ifaddr *oifa = rt->rt_ifa;
427                                 if (oifa != ifa) {
428                                     if (oifa && oifa->ifa_rtrequest)
429                                         oifa->ifa_rtrequest(RTM_DELETE, rt,
430                                             &info);
431                                     IFAFREE(rt->rt_ifa);
432                                     rt->rt_ifa = ifa;
433                                     ifa->ifa_refcnt++;
434                                     rt->rt_ifp = info.rti_ifp;
435                                 }
436                         }
437                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
438                                         &rt->rt_rmx);
439                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
440                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
441                         if (genmask)
442                                 rt->rt_genmask = genmask;
443                         /*
444                          * Fall into
445                          */
446                 case RTM_LOCK:
447                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
448                         rt->rt_rmx.rmx_locks |=
449                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
450                         break;
451                 }
452                 break;
453
454         default:
455                 senderr(EOPNOTSUPP);
456         }
457
458 flush:
459         if (rtm) {
460                 if (error)
461                         rtm->rtm_errno = error;
462                 else
463                         rtm->rtm_flags |= RTF_DONE;
464         }
465         if (rt)
466                 rtfree(rt);
467     {
468         struct rawcb *rp = 0;
469         /*
470          * Check to see if we don't want our own messages.
471          */
472         if ((so->so_options & SO_USELOOPBACK) == 0) {
473                 if (route_cb.any_count <= 1) {
474                         if (rtm)
475                                 Free(rtm);
476                         m_freem(m);
477                         return (error);
478                 }
479                 /* There is another listener, so construct message */
480                 rp = sotorawcb(so);
481         }
482         if (rtm) {
483                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
484                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
485                         m_freem(m);
486                         m = NULL;
487                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
488                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
489                 Free(rtm);
490         }
491         if (rp)
492                 rp->rcb_proto.sp_family = 0; /* Avoid us */
493         if (dst)
494                 route_proto.sp_protocol = dst->sa_family;
495         if (m)
496                 raw_input(m, &route_proto, &route_src, &route_dst);
497         if (rp)
498                 rp->rcb_proto.sp_family = PF_ROUTE;
499     }
500         return (error);
501 }
502
503 static void
504 rt_setmetrics(which, in, out)
505         u_long which;
506         struct rt_metrics *in, *out;
507 {
508 #define metric(f, e) if (which & (f)) out->e = in->e;
509         metric(RTV_RPIPE, rmx_recvpipe);
510         metric(RTV_SPIPE, rmx_sendpipe);
511         metric(RTV_SSTHRESH, rmx_ssthresh);
512         metric(RTV_RTT, rmx_rtt);
513         metric(RTV_RTTVAR, rmx_rttvar);
514         metric(RTV_HOPCOUNT, rmx_hopcount);
515         metric(RTV_MTU, rmx_mtu);
516         metric(RTV_EXPIRE, rmx_expire);
517 #undef metric
518 }
519
520 #define ROUNDUP(a) \
521         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
522 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
523
524
525 /*
526  * Extract the addresses of the passed sockaddrs.
527  * Do a little sanity checking so as to avoid bad memory references.
528  * This data is derived straight from userland.
529  */
530 static int
531 rt_xaddrs(cp, cplim, rtinfo)
532         caddr_t cp, cplim;
533         struct rt_addrinfo *rtinfo;
534 {
535         struct sockaddr *sa;
536         int i;
537
538         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
539                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
540                         continue;
541                 sa = (struct sockaddr *)cp;
542                 /*
543                  * It won't fit.
544                  */
545                 if ( (cp + sa->sa_len) > cplim ) {
546                         return (EINVAL);
547                 }
548
549                 /*
550                  * there are no more.. quit now
551                  * If there are more bits, they are in error.
552                  * I've seen this. route(1) can evidently generate these. 
553                  * This causes kernel to core dump.
554                  * for compatibility, If we see this, point to a safe address.
555                  */
556                 if (sa->sa_len == 0) {
557                         rtinfo->rti_info[i] = &sa_zero;
558                         return (0); /* should be EINVAL but for compat */
559                 }
560
561                 /* accept it */
562                 rtinfo->rti_info[i] = sa;
563                 ADVANCE(cp, sa);
564         }
565         return (0);
566 }
567
568 static struct mbuf *
569 rt_msg1(type, rtinfo)
570         int type;
571         struct rt_addrinfo *rtinfo;
572 {
573         struct rt_msghdr *rtm;
574         struct mbuf *m;
575         int i;
576         struct sockaddr *sa;
577         int len, dlen;
578
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         case RTM_IFANNOUNCE:
596                 len = sizeof(struct if_announcemsghdr);
597                 break;
598
599         default:
600                 len = sizeof(struct rt_msghdr);
601         }
602         if (len > MCLBYTES)
603                 panic("rt_msg1");
604         m = m_gethdr(M_DONTWAIT, MT_DATA);
605         if (m && len > MHLEN) {
606                 MCLGET(m, M_DONTWAIT);
607                 if ((m->m_flags & M_EXT) == 0) {
608                         m_free(m);
609                         m = NULL;
610                 }
611         }
612         if (m == 0)
613                 return (m);
614         m->m_pkthdr.len = m->m_len = len;
615         m->m_pkthdr.rcvif = 0;
616         rtm = mtod(m, struct rt_msghdr *);
617         bzero((caddr_t)rtm, len);
618         for (i = 0; i < RTAX_MAX; i++) {
619                 if ((sa = rtinfo->rti_info[i]) == NULL)
620                         continue;
621                 rtinfo->rti_addrs |= (1 << i);
622                 dlen = ROUNDUP(sa->sa_len);
623                 m_copyback(m, len, dlen, (caddr_t)sa);
624                 len += dlen;
625         }
626         if (m->m_pkthdr.len != len) {
627                 m_freem(m);
628                 return (NULL);
629         }
630         rtm->rtm_msglen = len;
631         rtm->rtm_version = RTM_VERSION;
632         rtm->rtm_type = type;
633         return (m);
634 }
635
636 static int
637 rt_msg2(type, rtinfo, cp, w)
638         int type;
639         struct rt_addrinfo *rtinfo;
640         caddr_t cp;
641         struct walkarg *w;
642 {
643         int i;
644         int len, dlen, second_time = 0;
645         caddr_t cp0;
646
647         rtinfo->rti_addrs = 0;
648 again:
649         switch (type) {
650
651         case RTM_DELADDR:
652         case RTM_NEWADDR:
653                 len = sizeof(struct ifa_msghdr);
654                 break;
655
656         case RTM_IFINFO:
657                 len = sizeof(struct if_msghdr);
658                 break;
659
660         default:
661                 len = sizeof(struct rt_msghdr);
662         }
663         cp0 = cp;
664         if (cp0)
665                 cp += len;
666         for (i = 0; i < RTAX_MAX; i++) {
667                 struct sockaddr *sa;
668
669                 if ((sa = rtinfo->rti_info[i]) == 0)
670                         continue;
671                 rtinfo->rti_addrs |= (1 << i);
672                 dlen = ROUNDUP(sa->sa_len);
673                 if (cp) {
674                         bcopy((caddr_t)sa, cp, (unsigned)dlen);
675                         cp += dlen;
676                 }
677                 len += dlen;
678         }
679         len = ALIGN(len);
680         if (cp == 0 && w != NULL && !second_time) {
681                 struct walkarg *rw = w;
682
683                 if (rw->w_req) {
684                         if (rw->w_tmemsize < len) {
685                                 if (rw->w_tmem)
686                                         free(rw->w_tmem, M_RTABLE);
687                                 rw->w_tmem = (caddr_t)malloc(len, M_RTABLE,
688                                                         M_INTWAIT | M_NULLOK);
689                                 if (rw->w_tmem)
690                                         rw->w_tmemsize = len;
691                         }
692                         if (rw->w_tmem) {
693                                 cp = rw->w_tmem;
694                                 second_time = 1;
695                                 goto again;
696                         }
697                 }
698         }
699         if (cp) {
700                 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
701
702                 rtm->rtm_version = RTM_VERSION;
703                 rtm->rtm_type = type;
704                 rtm->rtm_msglen = len;
705         }
706         return (len);
707 }
708
709 /*
710  * This routine is called to generate a message from the routing
711  * socket indicating that a redirect has occured, a routing lookup
712  * has failed, or that a protocol has detected timeouts to a particular
713  * destination.
714  */
715 void
716 rt_missmsg(type, rtinfo, flags, error)
717         int type, flags, error;
718         struct rt_addrinfo *rtinfo;
719 {
720         struct rt_msghdr *rtm;
721         struct mbuf *m;
722         struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
723
724         if (route_cb.any_count == 0)
725                 return;
726         m = rt_msg1(type, rtinfo);
727         if (m == 0)
728                 return;
729         rtm = mtod(m, struct rt_msghdr *);
730         rtm->rtm_flags = RTF_DONE | flags;
731         rtm->rtm_errno = error;
732         rtm->rtm_addrs = rtinfo->rti_addrs;
733         route_proto.sp_protocol = sa ? sa->sa_family : 0;
734         raw_input(m, &route_proto, &route_src, &route_dst);
735 }
736
737 /*
738  * This routine is called to generate a message from the routing
739  * socket indicating that the status of a network interface has changed.
740  */
741 void
742 rt_ifmsg(ifp)
743         struct ifnet *ifp;
744 {
745         struct if_msghdr *ifm;
746         struct mbuf *m;
747         struct rt_addrinfo info;
748
749         if (route_cb.any_count == 0)
750                 return;
751         bzero((caddr_t)&info, sizeof(info));
752         m = rt_msg1(RTM_IFINFO, &info);
753         if (m == 0)
754                 return;
755         ifm = mtod(m, struct if_msghdr *);
756         ifm->ifm_index = ifp->if_index;
757         ifm->ifm_flags = (u_short)ifp->if_flags;
758         ifm->ifm_data = ifp->if_data;
759         ifm->ifm_addrs = 0;
760         route_proto.sp_protocol = 0;
761         raw_input(m, &route_proto, &route_src, &route_dst);
762 }
763
764 static void
765 rt_ifamsg(int cmd, struct ifaddr *ifa)
766 {
767         struct ifa_msghdr *ifam;
768         struct rt_addrinfo info;
769         struct mbuf *m;
770         struct sockaddr *sa;
771         struct ifnet *ifp = ifa->ifa_ifp;
772
773         bzero(&info, sizeof(info));
774         ifaaddr = sa = ifa->ifa_addr;
775         ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
776         netmask = ifa->ifa_netmask;
777         brdaddr = ifa->ifa_dstaddr;
778         if ((m = rt_msg1(cmd, &info)) == NULL)
779                 return;
780         ifam = mtod(m, struct ifa_msghdr *);
781         ifam->ifam_index = ifp->if_index;
782         ifam->ifam_metric = ifa->ifa_metric;
783         ifam->ifam_flags = ifa->ifa_flags;
784         ifam->ifam_addrs = info.rti_addrs;
785
786         route_proto.sp_protocol = sa ? sa->sa_family : 0;
787         raw_input(m, &route_proto, &route_src, &route_dst);
788 }
789
790 static void
791 rt_rtmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
792 {
793         struct rt_msghdr *rtm;
794         struct rt_addrinfo info;
795         struct mbuf *m;
796         struct sockaddr *sa;
797         struct ifnet *ifp = ifa->ifa_ifp;
798
799         if (rt == NULL)
800                 return;
801         bzero(&info, sizeof(info));
802         netmask = rt_mask(rt);
803         dst = sa = rt_key(rt);
804         gate = rt->rt_gateway;
805         if ((m = rt_msg1(cmd, &info)) == NULL)
806                 return;
807         rtm = mtod(m, struct rt_msghdr *);
808         rtm->rtm_index = ifp->if_index;
809         rtm->rtm_flags |= rt->rt_flags;
810         rtm->rtm_errno = error;
811         rtm->rtm_addrs = info.rti_addrs;
812
813         route_proto.sp_protocol = sa ? sa->sa_family : 0;
814         raw_input(m, &route_proto, &route_src, &route_dst);
815 }
816
817 /*
818  * This is called to generate messages from the routing socket
819  * indicating a network interface has had addresses associated with it.
820  * if we ever reverse the logic and replace messages TO the routing
821  * socket indicate a request to configure interfaces, then it will
822  * be unnecessary as the routing socket will automatically generate
823  * copies of it.
824  */
825 void
826 rt_newaddrmsg(cmd, ifa, error, rt)
827         int cmd, error;
828         struct ifaddr *ifa;
829         struct rtentry *rt;
830 {
831         if (route_cb.any_count == 0)
832                 return;
833
834         if (cmd == RTM_ADD) {
835                 rt_ifamsg(RTM_NEWADDR, ifa);
836                 rt_rtmsg(RTM_ADD, ifa, error, rt);
837         } else {
838                 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
839                 rt_rtmsg(RTM_DELETE, ifa, error, rt);
840                 rt_ifamsg(RTM_DELADDR, ifa);
841         }
842 }
843
844 /*
845  * This is the analogue to the rt_newaddrmsg which performs the same
846  * function but for multicast group memberhips.  This is easier since
847  * there is no route state to worry about.
848  */
849 void
850 rt_newmaddrmsg(cmd, ifma)
851         int cmd;
852         struct ifmultiaddr *ifma;
853 {
854         struct rt_addrinfo info;
855         struct mbuf *m = 0;
856         struct ifnet *ifp = ifma->ifma_ifp;
857         struct ifma_msghdr *ifmam;
858
859         if (route_cb.any_count == 0)
860                 return;
861
862         bzero((caddr_t)&info, sizeof(info));
863         ifaaddr = ifma->ifma_addr;
864         if (ifp && TAILQ_FIRST(&ifp->if_addrhead))
865                 ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
866         else
867                 ifpaddr = NULL;
868         /*
869          * If a link-layer address is present, present it as a ``gateway''
870          * (similarly to how ARP entries, e.g., are presented).
871          */
872         gate = ifma->ifma_lladdr;
873         if ((m = rt_msg1(cmd, &info)) == NULL)
874                 return;
875         ifmam = mtod(m, struct ifma_msghdr *);
876         ifmam->ifmam_index = ifp->if_index;
877         ifmam->ifmam_addrs = info.rti_addrs;
878         route_proto.sp_protocol = ifma->ifma_addr->sa_family;
879         raw_input(m, &route_proto, &route_src, &route_dst);
880 }
881
882 /*
883  * This is called to generate routing socket messages indicating
884  * network interface arrival and departure.
885  */
886 void
887 rt_ifannouncemsg(ifp, what)
888         struct ifnet *ifp;
889         int what;
890 {
891         struct if_announcemsghdr *ifan;
892         struct mbuf *m;
893         struct rt_addrinfo info;
894
895         if (route_cb.any_count == 0)
896                 return;
897         bzero((caddr_t)&info, sizeof(info));
898         m = rt_msg1(RTM_IFANNOUNCE, &info);
899         if (m == NULL)
900                 return;
901         ifan = mtod(m, struct if_announcemsghdr *);
902         ifan->ifan_index = ifp->if_index;
903         strlcpy(ifan->ifan_name, ifp->if_xname, sizeof(ifan->ifan_name));
904         ifan->ifan_what = what;
905         route_proto.sp_protocol = 0;
906         raw_input(m, &route_proto, &route_src, &route_dst);
907  }
908
909 /*
910  * This is used in dumping the kernel table via sysctl().
911  */
912 int
913 sysctl_dumpentry(rn, vw)
914         struct radix_node *rn;
915         void *vw;
916 {
917         struct walkarg *w = vw;
918         struct rtentry *rt = (struct rtentry *)rn;
919         int error = 0, size;
920         struct rt_addrinfo info;
921
922         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
923                 return 0;
924         bzero((caddr_t)&info, sizeof(info));
925         dst = rt_key(rt);
926         gate = rt->rt_gateway;
927         netmask = rt_mask(rt);
928         genmask = rt->rt_genmask;
929         if (rt->rt_ifp) {
930                 ifpaddr = TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
931                 ifaaddr = rt->rt_ifa->ifa_addr;
932                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
933                         brdaddr = rt->rt_ifa->ifa_dstaddr;
934         }
935         size = rt_msg2(RTM_GET, &info, 0, w);
936         if (w->w_req && w->w_tmem) {
937                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
938
939                 rtm->rtm_flags = rt->rt_flags;
940                 rtm->rtm_use = rt->rt_use;
941                 rtm->rtm_rmx = rt->rt_rmx;
942                 rtm->rtm_index = rt->rt_ifp->if_index;
943                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
944                 rtm->rtm_addrs = info.rti_addrs;
945                 error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size);
946                 return (error);
947         }
948         return (error);
949 }
950
951 int
952 sysctl_iflist(af, w)
953         int     af;
954         struct  walkarg *w;
955 {
956         struct ifnet *ifp;
957         struct ifaddr *ifa;
958         struct  rt_addrinfo info;
959         int     len, error = 0;
960
961         bzero((caddr_t)&info, sizeof(info));
962         TAILQ_FOREACH(ifp, &ifnet, if_link) {
963                 if (w->w_arg && w->w_arg != ifp->if_index)
964                         continue;
965                 ifa = TAILQ_FIRST(&ifp->if_addrhead);
966                 ifpaddr = ifa->ifa_addr;
967                 len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
968                 ifpaddr = 0;
969                 if (w->w_req && w->w_tmem) {
970                         struct if_msghdr *ifm;
971
972                         ifm = (struct if_msghdr *)w->w_tmem;
973                         ifm->ifm_index = ifp->if_index;
974                         ifm->ifm_flags = (u_short)ifp->if_flags;
975                         ifm->ifm_data = ifp->if_data;
976                         ifm->ifm_addrs = info.rti_addrs;
977                         error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
978                         if (error)
979                                 return (error);
980                 }
981                 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != 0) {
982                         if (af && af != ifa->ifa_addr->sa_family)
983                                 continue;
984                         if (curproc->p_ucred->cr_prison && prison_if(curthread, ifa->ifa_addr))
985                                 continue;
986                         ifaaddr = ifa->ifa_addr;
987                         netmask = ifa->ifa_netmask;
988                         brdaddr = ifa->ifa_dstaddr;
989                         len = rt_msg2(RTM_NEWADDR, &info, 0, w);
990                         if (w->w_req && w->w_tmem) {
991                                 struct ifa_msghdr *ifam;
992
993                                 ifam = (struct ifa_msghdr *)w->w_tmem;
994                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
995                                 ifam->ifam_flags = ifa->ifa_flags;
996                                 ifam->ifam_metric = ifa->ifa_metric;
997                                 ifam->ifam_addrs = info.rti_addrs;
998                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
999                                 if (error)
1000                                         return (error);
1001                         }
1002                 }
1003                 ifaaddr = netmask = brdaddr = 0;
1004         }
1005         return (0);
1006 }
1007
1008 static int
1009 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1010 {
1011         int     *name = (int *)arg1;
1012         u_int   namelen = arg2;
1013         struct radix_node_head *rnh;
1014         int     i, s, error = EINVAL;
1015         u_char  af;
1016         struct  walkarg w;
1017
1018         name ++;
1019         namelen--;
1020         if (req->newptr)
1021                 return (EPERM);
1022         if (namelen != 3)
1023                 return (EINVAL);
1024         af = name[0];
1025         Bzero(&w, sizeof(w));
1026         w.w_op = name[1];
1027         w.w_arg = name[2];
1028         w.w_req = req;
1029
1030         s = splnet();
1031         switch (w.w_op) {
1032
1033         case NET_RT_DUMP:
1034         case NET_RT_FLAGS:
1035                 for (i = 1; i <= AF_MAX; i++)
1036                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
1037                             (error = rnh->rnh_walktree(rnh,
1038                                                         sysctl_dumpentry, &w)))
1039                                 break;
1040                 break;
1041
1042         case NET_RT_IFLIST:
1043                 error = sysctl_iflist(af, &w);
1044         }
1045         splx(s);
1046         if (w.w_tmem)
1047                 free(w.w_tmem, M_RTABLE);
1048         return (error);
1049 }
1050
1051 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1052
1053 /*
1054  * Definitions of protocols supported in the ROUTE domain.
1055  */
1056
1057 extern struct domain routedomain;               /* or at least forward */
1058
1059 static struct protosw routesw[] = {
1060 { SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
1061   0,            route_output,   raw_ctlinput,   0,
1062   cpu0_soport,
1063   raw_init,     0,              0,              0,
1064   &route_usrreqs
1065 }
1066 };
1067
1068 static struct domain routedomain =
1069     { PF_ROUTE, "route", 0, 0, 0,
1070       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
1071
1072 DOMAIN_SET(route);