Cosmetic cleanups.
[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.19 2005/01/06 09:14:13 hsu Exp $
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/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/domain.h>
49
50 #include <machine/stdarg.h>
51
52 #include <net/if.h>
53 #include <net/route.h>
54 #include <net/raw_cb.h>
55
56 MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
57
58 static struct route_cb {
59         int     ip_count;
60         int     ip6_count;
61         int     ipx_count;
62         int     ns_count;
63         int     any_count;
64 } route_cb;
65
66 static struct   sockaddr route_dst = { 2, PF_ROUTE, };
67 static struct   sockaddr route_src = { 2, PF_ROUTE, };
68 static struct   sockaddr sa_zero   = { sizeof sa_zero, AF_INET, };
69 static struct   sockproto route_proto = { PF_ROUTE, };
70
71 struct walkarg {
72         int     w_tmemsize;
73         int     w_op, w_arg;
74         caddr_t w_tmem;
75         struct sysctl_req *w_req;
76 };
77
78 static struct mbuf *
79                 rt_msg1 (int, struct rt_addrinfo *);
80 static int      rt_msg2 (int, struct rt_addrinfo *, caddr_t, struct walkarg *);
81 static int      rt_xaddrs (char *, char *, struct rt_addrinfo *);
82 static int      sysctl_dumpentry (struct radix_node *rn, void *vw);
83 static int      sysctl_iflist (int af, struct walkarg *w);
84 static int      route_output(struct mbuf *, struct socket *, ...);
85 static void     rt_setmetrics (u_long, struct rt_metrics *,
86                                struct rt_metrics *);
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
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) != NULL)
112                 return EISCONN; /* XXX panic? */
113
114         MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK|M_ZERO);
115         if (rp == NULL)
116                 return ENOBUFS;
117
118         /*
119          * The splnet() is necessary to block protocols from sending
120          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
121          * this PCB is extant but incompletely initialized.
122          * Probably we should try to do more of this work beforehand and
123          * eliminate the spl.
124          */
125         s = splnet();
126         so->so_pcb = rp;
127         error = raw_attach(so, proto, ai->sb_rlimit);
128         rp = sotorawcb(so);
129         if (error) {
130                 splx(s);
131                 free(rp, M_PCB);
132                 return error;
133         }
134         switch(rp->rcb_proto.sp_protocol) {
135         case AF_INET:
136                 route_cb.ip_count++;
137                 break;
138         case AF_INET6:
139                 route_cb.ip6_count++;
140                 break;
141         case AF_IPX:
142                 route_cb.ipx_count++;
143                 break;
144         case AF_NS:
145                 route_cb.ns_count++;
146                 break;
147         }
148         rp->rcb_faddr = &route_src;
149         route_cb.any_count++;
150         soisconnected(so);
151         so->so_options |= SO_USELOOPBACK;
152         splx(s);
153         return 0;
154 }
155
156 static int
157 rts_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
158 {
159         int s, error;
160
161         s = splnet();
162         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
163         splx(s);
164         return error;
165 }
166
167 static int
168 rts_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
169 {
170         int s, error;
171
172         s = splnet();
173         error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
174         splx(s);
175         return error;
176 }
177
178 /* pru_connect2 is EOPNOTSUPP */
179 /* pru_control is EOPNOTSUPP */
180
181 static int
182 rts_detach(struct socket *so)
183 {
184         struct rawcb *rp = sotorawcb(so);
185         int s, error;
186
187         s = splnet();
188         if (rp != NULL) {
189                 switch(rp->rcb_proto.sp_protocol) {
190                 case AF_INET:
191                         route_cb.ip_count--;
192                         break;
193                 case AF_INET6:
194                         route_cb.ip6_count--;
195                         break;
196                 case AF_IPX:
197                         route_cb.ipx_count--;
198                         break;
199                 case AF_NS:
200                         route_cb.ns_count--;
201                         break;
202                 }
203                 route_cb.any_count--;
204         }
205         error = raw_usrreqs.pru_detach(so);
206         splx(s);
207         return error;
208 }
209
210 static int
211 rts_disconnect(struct socket *so)
212 {
213         int s, error;
214
215         s = splnet();
216         error = raw_usrreqs.pru_disconnect(so);
217         splx(s);
218         return error;
219 }
220
221 /* pru_listen is EOPNOTSUPP */
222
223 static int
224 rts_peeraddr(struct socket *so, struct sockaddr **nam)
225 {
226         int s, error;
227
228         s = splnet();
229         error = raw_usrreqs.pru_peeraddr(so, nam);
230         splx(s);
231         return error;
232 }
233
234 /* pru_rcvd is EOPNOTSUPP */
235 /* pru_rcvoob is EOPNOTSUPP */
236
237 static int
238 rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
239          struct mbuf *control, struct thread *td)
240 {
241         int s, error;
242
243         s = splnet();
244         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
245         splx(s);
246         return error;
247 }
248
249 /* pru_sense is null */
250
251 static int
252 rts_shutdown(struct socket *so)
253 {
254         int s, error;
255
256         s = splnet();
257         error = raw_usrreqs.pru_shutdown(so);
258         splx(s);
259         return error;
260 }
261
262 static int
263 rts_sockaddr(struct socket *so, struct sockaddr **nam)
264 {
265         int s, error;
266
267         s = splnet();
268         error = raw_usrreqs.pru_sockaddr(so, nam);
269         splx(s);
270         return error;
271 }
272
273 static struct pr_usrreqs route_usrreqs = {
274         rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
275         pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
276         pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
277         rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
278         sosend, soreceive, sopoll
279 };
280
281 /*ARGSUSED*/
282 static int
283 route_output(struct mbuf *m, struct socket *so, ...)
284 {
285         struct rt_msghdr *rtm = NULL;
286         struct rtentry *rt = NULL;
287         struct rtentry *saved_nrt = NULL;
288         struct radix_node_head *rnh;
289         struct ifnet *ifp = NULL;
290         struct ifaddr *ifa = NULL;
291         struct rawcb *rp = NULL;
292         struct pr_output_info *oi;
293         struct rt_addrinfo info;
294         int len, error = 0;
295         __va_list ap;
296
297         __va_start(ap, so);
298         oi = __va_arg(ap, struct pr_output_info *);
299         __va_end(ap);
300
301 #define gotoerr(e) { error = e; goto flush;}
302         if (m == NULL || ((m->m_len < sizeof(long)) &&
303                        (m = m_pullup(m, sizeof(long))) == NULL))
304                 return (ENOBUFS);
305         if (!(m->m_flags & M_PKTHDR))
306                 panic("route_output");
307         len = m->m_pkthdr.len;
308         if (len < sizeof *rtm ||
309             len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
310                 info.sa_dst = NULL;
311                 gotoerr(EINVAL);
312         }
313         R_Malloc(rtm, struct rt_msghdr *, len);
314         if (rtm == NULL) {
315                 info.sa_dst = NULL;
316                 gotoerr(ENOBUFS);
317         }
318         m_copydata(m, 0, len, (caddr_t)rtm);
319         if (rtm->rtm_version != RTM_VERSION) {
320                 info.sa_dst = NULL;
321                 gotoerr(EPROTONOSUPPORT);
322         }
323         rtm->rtm_pid = oi->p_pid;
324         bzero(&info, sizeof info);
325         info.rti_addrs = rtm->rtm_addrs;
326         if (rt_xaddrs((char *)(rtm + 1), len + (char *)rtm, &info)) {
327                 info.sa_dst = NULL;
328                 gotoerr(EINVAL);
329         }
330         info.rti_flags = rtm->rtm_flags;
331         if (info.sa_dst == NULL || info.sa_dst->sa_family >= AF_MAX ||
332             (info.sa_gateway != NULL && (info.sa_gateway->sa_family >= AF_MAX)))
333                 gotoerr(EINVAL);
334
335         if (info.sa_genmask != NULL) {
336                 struct radix_node *t;
337                 int klen;
338
339                 t = rn_addmask((char *)info.sa_genmask, TRUE, 1);
340                 if (t != NULL &&
341                     info.sa_genmask->sa_len >= (klen = *(u_char *)t->rn_key) &&
342                     bcmp((char *)info.sa_genmask + 1, (char *)t->rn_key + 1,
343                          klen - 1) == 0)
344                         info.sa_genmask = (struct sockaddr *)(t->rn_key);
345                 else
346                         gotoerr(ENOBUFS);
347         }
348
349         /*
350          * Verify that the caller has the appropriate privilege; RTM_GET
351          * is the only operation the non-superuser is allowed.
352          */
353         if (rtm->rtm_type != RTM_GET && suser_cred(so->so_cred, 0) != 0)
354                 gotoerr(EPERM);
355
356         switch (rtm->rtm_type) {
357
358         case RTM_ADD:
359                 if (info.sa_gateway == NULL)
360                         gotoerr(EINVAL);
361                 error = rtrequest1(RTM_ADD, &info, &saved_nrt);
362                 if (error == 0 && saved_nrt != NULL) {
363                         rt_setmetrics(rtm->rtm_inits,
364                                 &rtm->rtm_rmx, &saved_nrt->rt_rmx);
365                         saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
366                         saved_nrt->rt_rmx.rmx_locks |=
367                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
368                         saved_nrt->rt_refcnt--;
369                         saved_nrt->rt_genmask = info.sa_genmask;
370                 }
371                 break;
372
373         case RTM_DELETE:
374                 error = rtrequest1(RTM_DELETE, &info, &saved_nrt);
375                 if (error == 0) {
376                         if ((rt = saved_nrt))
377                                 rt->rt_refcnt++;
378                         goto report;
379                 }
380                 break;
381
382         case RTM_GET:
383         case RTM_CHANGE:
384         case RTM_LOCK:
385                 if ((rnh = rt_tables[info.sa_dst->sa_family]) == NULL) {
386                         gotoerr(EAFNOSUPPORT);
387                 } else if ((rt = (struct rtentry *) rnh->rnh_lookup(
388                     (char *)info.sa_dst, (char *)info.sa_netmask, rnh)) != NULL)
389                         rt->rt_refcnt++;
390                 else
391                         gotoerr(ESRCH);
392                 switch(rtm->rtm_type) {
393
394                 case RTM_GET:
395                 report:
396                         info.sa_dst = rt_key(rt);
397                         info.sa_gateway = rt->rt_gateway;
398                         info.sa_netmask = rt_mask(rt);
399                         info.sa_genmask = rt->rt_genmask;
400                         if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
401                                 ifp = rt->rt_ifp;
402                                 if (ifp) {
403                                         info.sa_ifpaddr =
404                                             TAILQ_FIRST(&ifp->if_addrhead)->
405                                                 ifa_addr;
406                                         info.sa_ifaaddr = rt->rt_ifa->ifa_addr;
407                                         if (ifp->if_flags & IFF_POINTOPOINT)
408                                                 info.sa_bcastaddr =
409                                                     rt->rt_ifa->ifa_dstaddr;
410                                         rtm->rtm_index = ifp->if_index;
411                                 } else {
412                                         info.sa_ifpaddr = NULL;
413                                         info.sa_ifaaddr = NULL;
414                             }
415                         }
416                         len = rt_msg2(rtm->rtm_type, &info, NULL, NULL);
417                         if (len > rtm->rtm_msglen) {
418                                 struct rt_msghdr *new_rtm;
419                                 R_Malloc(new_rtm, struct rt_msghdr *, len);
420                                 if (new_rtm == NULL)
421                                         gotoerr(ENOBUFS);
422                                 bcopy(rtm, new_rtm, rtm->rtm_msglen);
423                                 Free(rtm); rtm = new_rtm;
424                         }
425                         rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm, NULL);
426                         rtm->rtm_flags = rt->rt_flags;
427                         rtm->rtm_rmx = rt->rt_rmx;
428                         rtm->rtm_addrs = info.rti_addrs;
429                         break;
430
431                 case RTM_CHANGE:
432                         /*
433                          * new gateway could require new ifaddr, ifp;
434                          * flags may also be different; ifp may be specified
435                          * by ll sockaddr when protocol address is ambiguous
436                          */
437                         if (((rt->rt_flags & RTF_GATEWAY) &&
438                              info.sa_gateway != NULL) ||
439                             info.sa_ifpaddr != NULL ||
440                             (info.sa_ifaaddr != NULL &&
441                              sa_equal(info.sa_ifaaddr, rt->rt_ifa->ifa_addr))) {
442                                 if ((error = rt_getifa(&info)) != 0)
443                                         gotoerr(error);
444                         }
445                         if (info.sa_gateway != NULL &&
446                             (error = rt_setgate(rt, rt_key(rt),
447                                                 info.sa_gateway)) != 0)
448                                 gotoerr(error);
449                         if ((ifa = info.rti_ifa) != NULL) {
450                                 struct ifaddr *oifa = rt->rt_ifa;
451
452                                 if (oifa != ifa) {
453                                         if (oifa && oifa->ifa_rtrequest)
454                                                 oifa->ifa_rtrequest(RTM_DELETE,
455                                                                     rt, &info);
456                                         IFAFREE(rt->rt_ifa);
457                                         rt->rt_ifa = ifa;
458                                         IFAREF(ifa);
459                                         rt->rt_ifp = info.rti_ifp;
460                                 }
461                         }
462                         rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
463                             &rt->rt_rmx);
464                         if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
465                                rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
466                         if (info.sa_genmask != NULL)
467                                 rt->rt_genmask = info.sa_genmask;
468                         /*
469                          * Fall into
470                          */
471                 case RTM_LOCK:
472                         rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
473                         rt->rt_rmx.rmx_locks |=
474                                 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
475                         break;
476                 }
477                 break;
478
479         default:
480                 gotoerr(EOPNOTSUPP);
481         }
482
483 flush:
484         if (rtm) {
485                 if (error)
486                         rtm->rtm_errno = error;
487                 else
488                         rtm->rtm_flags |= RTF_DONE;
489         }
490         if (rt)
491                 rtfree(rt);
492         /*
493          * Check to see if we don't want our own messages.
494          */
495         if (!(so->so_options & SO_USELOOPBACK)) {
496                 if (route_cb.any_count <= 1) {
497                         if (rtm)
498                                 Free(rtm);
499                         m_freem(m);
500                         return (error);
501                 }
502                 /* There is another listener, so construct message */
503                 rp = sotorawcb(so);
504         }
505         if (rtm) {
506                 m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
507                 if (m->m_pkthdr.len < rtm->rtm_msglen) {
508                         m_freem(m);
509                         m = NULL;
510                 } else if (m->m_pkthdr.len > rtm->rtm_msglen)
511                         m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
512                 Free(rtm);
513         }
514         if (rp != NULL)
515                 rp->rcb_proto.sp_family = 0; /* Avoid us */
516         if (info.sa_dst != NULL)
517                 route_proto.sp_protocol = info.sa_dst->sa_family;
518         if (m != NULL)
519                 raw_input(m, &route_proto, &route_src, &route_dst);
520         if (rp != NULL)
521                 rp->rcb_proto.sp_family = PF_ROUTE;
522         return (error);
523 }
524
525 static void
526 rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_metrics *out)
527 {
528 #define setmetric(flag, elt) if (which & (flag)) out->elt = in->elt;
529         setmetric(RTV_RPIPE, rmx_recvpipe);
530         setmetric(RTV_SPIPE, rmx_sendpipe);
531         setmetric(RTV_SSTHRESH, rmx_ssthresh);
532         setmetric(RTV_RTT, rmx_rtt);
533         setmetric(RTV_RTTVAR, rmx_rttvar);
534         setmetric(RTV_HOPCOUNT, rmx_hopcount);
535         setmetric(RTV_MTU, rmx_mtu);
536         setmetric(RTV_EXPIRE, rmx_expire);
537 #undef setmetric
538 }
539
540 #define ROUNDUP(a) \
541         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
542 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
543
544 /*
545  * Extract the addresses of the passed sockaddrs.
546  * Do a little sanity checking so as to avoid bad memory references.
547  * This data is derived straight from userland.
548  */
549 static int
550 rt_xaddrs(char *cp, char *cplim, struct rt_addrinfo *rtinfo)
551 {
552         struct sockaddr *sa;
553         int i;
554
555         for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
556                 if ((rtinfo->rti_addrs & (1 << i)) == 0)
557                         continue;
558                 sa = (struct sockaddr *)cp;
559                 /*
560                  * It won't fit.
561                  */
562                 if ((cp + sa->sa_len) > cplim) {
563                         return (EINVAL);
564                 }
565
566                 /*
567                  * There are no more...  Quit now.
568                  * If there are more bits, they are in error.
569                  * I've seen this.  route(1) can evidently generate these. 
570                  * This causes kernel to core dump.
571                  * For compatibility, if we see this, point to a safe address.
572                  */
573                 if (sa->sa_len == 0) {
574                         rtinfo->rti_info[i] = &sa_zero;
575                         return (0); /* should be EINVAL but for compat */
576                 }
577
578                 /* Accept the sockaddr. */
579                 rtinfo->rti_info[i] = sa;
580                 ADVANCE(cp, sa);
581         }
582         return (0);
583 }
584
585 static struct mbuf *
586 rt_msg1(int type, struct rt_addrinfo *rtinfo)
587 {
588         struct rt_msghdr *rtm;
589         struct mbuf *m;
590         int i;
591         struct sockaddr *sa;
592         int len, dlen;
593
594         switch (type) {
595
596         case RTM_DELADDR:
597         case RTM_NEWADDR:
598                 len = sizeof(struct ifa_msghdr);
599                 break;
600
601         case RTM_DELMADDR:
602         case RTM_NEWMADDR:
603                 len = sizeof(struct ifma_msghdr);
604                 break;
605
606         case RTM_IFINFO:
607                 len = sizeof(struct if_msghdr);
608                 break;
609
610         case RTM_IFANNOUNCE:
611                 len = sizeof(struct if_announcemsghdr);
612                 break;
613
614         default:
615                 len = sizeof(struct rt_msghdr);
616         }
617         if (len > MCLBYTES)
618                 panic("rt_msg1");
619         m = m_gethdr(MB_DONTWAIT, MT_DATA);
620         if (m && len > MHLEN) {
621                 MCLGET(m, MB_DONTWAIT);
622                 if (!(m->m_flags & M_EXT)) {
623                         m_free(m);
624                         m = NULL;
625                 }
626         }
627         if (m == NULL)
628                 return (m);
629         m->m_pkthdr.len = m->m_len = len;
630         m->m_pkthdr.rcvif = NULL;
631         rtm = mtod(m, struct rt_msghdr *);
632         bzero(rtm, len);
633         for (i = 0; i < RTAX_MAX; i++) {
634                 if ((sa = rtinfo->rti_info[i]) == NULL)
635                         continue;
636                 rtinfo->rti_addrs |= (1 << i);
637                 dlen = ROUNDUP(sa->sa_len);
638                 m_copyback(m, len, dlen, (caddr_t)sa);
639                 len += dlen;
640         }
641         if (m->m_pkthdr.len != len) {
642                 m_freem(m);
643                 return (NULL);
644         }
645         rtm->rtm_msglen = len;
646         rtm->rtm_version = RTM_VERSION;
647         rtm->rtm_type = type;
648         return (m);
649 }
650
651 static int
652 rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
653 {
654         int i;
655         int len, dlen;
656         boolean_t second_time = FALSE;
657         caddr_t cp0;
658
659         rtinfo->rti_addrs = NULL;
660 again:
661         switch (type) {
662
663         case RTM_DELADDR:
664         case RTM_NEWADDR:
665                 len = sizeof(struct ifa_msghdr);
666                 break;
667
668         case RTM_IFINFO:
669                 len = sizeof(struct if_msghdr);
670                 break;
671
672         default:
673                 len = sizeof(struct rt_msghdr);
674         }
675         cp0 = cp;
676         if (cp != NULL)
677                 cp += len;
678
679         for (i = 0; i < RTAX_MAX; i++) {
680                 struct sockaddr *sa;
681
682                 if ((sa = rtinfo->rti_info[i]) == NULL)
683                         continue;
684                 rtinfo->rti_addrs |= (1 << i);
685                 dlen = ROUNDUP(sa->sa_len);
686                 if (cp != NULL) {
687                         bcopy(sa, cp, dlen);
688                         cp += dlen;
689                 }
690                 len += dlen;
691         }
692         len = ALIGN(len);
693         if (cp == NULL && w != NULL && !second_time) {
694                 struct walkarg *rw = w;
695
696                 if (rw->w_req != NULL) {
697                         if (rw->w_tmemsize < len) {
698                                 if (rw->w_tmem)
699                                         free(rw->w_tmem, M_RTABLE);
700                                 rw->w_tmem = malloc(len, M_RTABLE,
701                                                     M_INTWAIT | M_NULLOK);
702                                 if (rw->w_tmem)
703                                         rw->w_tmemsize = len;
704                         }
705                         if (rw->w_tmem != NULL) {
706                                 cp = rw->w_tmem;
707                                 second_time = TRUE;
708                                 goto again;
709                         }
710                 }
711         }
712         if (cp != NULL) {
713                 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
714
715                 rtm->rtm_version = RTM_VERSION;
716                 rtm->rtm_type = type;
717                 rtm->rtm_msglen = len;
718         }
719         return (len);
720 }
721
722 /*
723  * This routine is called to generate a message from the routing
724  * socket indicating that a redirect has occurred, a routing lookup
725  * has failed, or that a protocol has detected timeouts to a particular
726  * destination.
727  */
728 void
729 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
730 {
731         struct sockaddr *dst = rtinfo->rti_info[RTAX_DST];
732         struct rt_msghdr *rtm;
733         struct mbuf *m;
734
735         if (route_cb.any_count == 0)
736                 return;
737         m = rt_msg1(type, rtinfo);
738         if (m == NULL)
739                 return;
740         rtm = mtod(m, struct rt_msghdr *);
741         rtm->rtm_flags = RTF_DONE | flags;
742         rtm->rtm_errno = error;
743         rtm->rtm_addrs = rtinfo->rti_addrs;
744         route_proto.sp_protocol = (dst != NULL) ? dst->sa_family : 0;
745         raw_input(m, &route_proto, &route_src, &route_dst);
746 }
747
748 /*
749  * This routine is called to generate a message from the routing
750  * socket indicating that the status of a network interface has changed.
751  */
752 void
753 rt_ifmsg(struct ifnet *ifp)
754 {
755         struct if_msghdr *ifm;
756         struct mbuf *m;
757         struct rt_addrinfo info;
758
759         if (route_cb.any_count == 0)
760                 return;
761         bzero(&info, sizeof info);
762         m = rt_msg1(RTM_IFINFO, &info);
763         if (m == NULL)
764                 return;
765         ifm = mtod(m, struct if_msghdr *);
766         ifm->ifm_index = ifp->if_index;
767         ifm->ifm_flags = (u_short)ifp->if_flags;
768         ifm->ifm_data = ifp->if_data;
769         ifm->ifm_addrs = NULL;
770         route_proto.sp_protocol = 0;
771         raw_input(m, &route_proto, &route_src, &route_dst);
772 }
773
774 static void
775 rt_ifamsg(int cmd, struct ifaddr *ifa)
776 {
777         struct ifa_msghdr *ifam;
778         struct rt_addrinfo info;
779         struct mbuf *m;
780         struct sockaddr *sa;
781         struct ifnet *ifp = ifa->ifa_ifp;
782
783         bzero(&info, sizeof info);
784         info.sa_ifaaddr = sa = ifa->ifa_addr;
785         info.sa_ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
786         info.sa_netmask = ifa->ifa_netmask;
787         info.sa_bcastaddr = ifa->ifa_dstaddr;
788
789         m = rt_msg1(cmd, &info);
790         if (m == NULL)
791                 return;
792
793         ifam = mtod(m, struct ifa_msghdr *);
794         ifam->ifam_index = ifp->if_index;
795         ifam->ifam_metric = ifa->ifa_metric;
796         ifam->ifam_flags = ifa->ifa_flags;
797         ifam->ifam_addrs = info.rti_addrs;
798
799         route_proto.sp_protocol = sa ? sa->sa_family : 0;
800
801         raw_input(m, &route_proto, &route_src, &route_dst);
802 }
803
804 static void
805 rt_rtmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
806 {
807         struct rt_msghdr *rtm;
808         struct rt_addrinfo info;
809         struct mbuf *m;
810         struct sockaddr *sa;
811         struct ifnet *ifp = ifa->ifa_ifp;
812
813         if (rt == NULL)
814                 return;
815
816         bzero(&info, sizeof info);
817         info.sa_netmask = rt_mask(rt);
818         info.sa_dst = sa = rt_key(rt);
819         info.sa_gateway = rt->rt_gateway;
820
821         m = rt_msg1(cmd, &info);
822         if (m == NULL)
823                 return;
824
825         rtm = mtod(m, struct rt_msghdr *);
826         rtm->rtm_index = ifp->if_index;
827         rtm->rtm_flags |= rt->rt_flags;
828         rtm->rtm_errno = error;
829         rtm->rtm_addrs = info.rti_addrs;
830
831         route_proto.sp_protocol = sa ? sa->sa_family : 0;
832
833         raw_input(m, &route_proto, &route_src, &route_dst);
834 }
835
836 /*
837  * This is called to generate messages from the routing socket
838  * indicating a network interface has had addresses associated with it.
839  * if we ever reverse the logic and replace messages TO the routing
840  * socket indicate a request to configure interfaces, then it will
841  * be unnecessary as the routing socket will automatically generate
842  * copies of it.
843  */
844 void
845 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
846 {
847         if (route_cb.any_count == 0)
848                 return;
849
850         if (cmd == RTM_ADD) {
851                 rt_ifamsg(RTM_NEWADDR, ifa);
852                 rt_rtmsg(RTM_ADD, ifa, error, rt);
853         } else {
854                 KASSERT((cmd == RTM_DELETE), ("unknown cmd %d", cmd));
855                 rt_rtmsg(RTM_DELETE, ifa, error, rt);
856                 rt_ifamsg(RTM_DELADDR, ifa);
857         }
858 }
859
860 /*
861  * This is the analogue to the rt_newaddrmsg which performs the same
862  * function but for multicast group memberhips.  This is easier since
863  * there is no route state to worry about.
864  */
865 void
866 rt_newmaddrmsg(int cmd, struct ifmultiaddr *ifma)
867 {
868         struct rt_addrinfo info;
869         struct mbuf *m = NULL;
870         struct ifnet *ifp = ifma->ifma_ifp;
871         struct ifma_msghdr *ifmam;
872
873         if (route_cb.any_count == 0)
874                 return;
875
876         bzero(&info, sizeof info);
877         info.sa_ifaaddr = ifma->ifma_addr;
878         if (ifp != NULL && TAILQ_FIRST(&ifp->if_addrhead) != NULL)
879                 info.sa_ifpaddr = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr;
880         else
881                 info.sa_ifpaddr = NULL;
882         /*
883          * If a link-layer address is present, present it as a ``gateway''
884          * (similarly to how ARP entries, e.g., are presented).
885          */
886         info.sa_gateway = ifma->ifma_lladdr;
887
888         m = rt_msg1(cmd, &info);
889         if (m == NULL)
890                 return;
891
892         ifmam = mtod(m, struct ifma_msghdr *);
893         ifmam->ifmam_index = ifp->if_index;
894         ifmam->ifmam_addrs = info.rti_addrs;
895         route_proto.sp_protocol = ifma->ifma_addr->sa_family;
896
897         raw_input(m, &route_proto, &route_src, &route_dst);
898 }
899
900 /*
901  * This is called to generate routing socket messages indicating
902  * network interface arrival and departure.
903  */
904 void
905 rt_ifannouncemsg(ifp, what)
906         struct ifnet *ifp;
907         int what;
908 {
909         struct if_announcemsghdr *ifan;
910         struct mbuf *m;
911         struct rt_addrinfo info;
912
913         if (route_cb.any_count == 0)
914                 return;
915
916         bzero(&info, sizeof info);
917
918         m = rt_msg1(RTM_IFANNOUNCE, &info);
919         if (m == NULL)
920                 return;
921
922         ifan = mtod(m, struct if_announcemsghdr *);
923         ifan->ifan_index = ifp->if_index;
924         strlcpy(ifan->ifan_name, ifp->if_xname, sizeof ifan->ifan_name);
925         ifan->ifan_what = what;
926
927         route_proto.sp_protocol = 0;
928
929         raw_input(m, &route_proto, &route_src, &route_dst);
930  }
931
932 /*
933  * This is used in dumping the kernel table via sysctl().
934  */
935 int
936 sysctl_dumpentry(rn, vw)
937         struct radix_node *rn;
938         void *vw;
939 {
940         struct walkarg *w = vw;
941         struct rtentry *rt = (struct rtentry *)rn;
942         int error = 0, size;
943         struct rt_addrinfo info;
944
945         if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
946                 return 0;
947
948         bzero(&info, sizeof info);
949         info.sa_dst = rt_key(rt);
950         info.sa_gateway = rt->rt_gateway;
951         info.sa_netmask = rt_mask(rt);
952         info.sa_genmask = rt->rt_genmask;
953         if (rt->rt_ifp != NULL) {
954                 info.sa_ifpaddr =
955                     TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr;
956                 info.sa_ifaaddr = rt->rt_ifa->ifa_addr;
957                 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
958                         info.sa_bcastaddr = rt->rt_ifa->ifa_dstaddr;
959         }
960         size = rt_msg2(RTM_GET, &info, NULL, w);
961         if (w->w_req != NULL && w->w_tmem != NULL) {
962                 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
963
964                 rtm->rtm_flags = rt->rt_flags;
965                 rtm->rtm_use = rt->rt_use;
966                 rtm->rtm_rmx = rt->rt_rmx;
967                 rtm->rtm_index = rt->rt_ifp->if_index;
968                 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
969                 rtm->rtm_addrs = info.rti_addrs;
970                 error = SYSCTL_OUT(w->w_req, rtm, size);
971                 return (error);
972         }
973         return (error);
974 }
975
976 int
977 sysctl_iflist(af, w)
978         int     af;
979         struct  walkarg *w;
980 {
981         struct ifnet *ifp;
982         struct ifaddr *ifa;
983         struct  rt_addrinfo info;
984         int     len, error = 0;
985
986         bzero(&info, sizeof info);
987         TAILQ_FOREACH(ifp, &ifnet, if_link) {
988                 if (w->w_arg && w->w_arg != ifp->if_index)
989                         continue;
990                 ifa = TAILQ_FIRST(&ifp->if_addrhead);
991                 info.sa_ifpaddr = ifa->ifa_addr;
992                 len = rt_msg2(RTM_IFINFO, &info, NULL, w);
993                 info.sa_ifpaddr = NULL;
994                 if (w->w_req != NULL && w->w_tmem != NULL) {
995                         struct if_msghdr *ifm;
996
997                         ifm = (struct if_msghdr *)w->w_tmem;
998                         ifm->ifm_index = ifp->if_index;
999                         ifm->ifm_flags = (u_short)ifp->if_flags;
1000                         ifm->ifm_data = ifp->if_data;
1001                         ifm->ifm_addrs = info.rti_addrs;
1002                         error = SYSCTL_OUT(w->w_req, ifm, len);
1003                         if (error)
1004                                 return (error);
1005                 }
1006                 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) {
1007                         if (af && af != ifa->ifa_addr->sa_family)
1008                                 continue;
1009                         if (curproc->p_ucred->cr_prison && prison_if(curthread, ifa->ifa_addr))
1010                                 continue;
1011                         info.sa_ifaaddr = ifa->ifa_addr;
1012                         info.sa_netmask = ifa->ifa_netmask;
1013                         info.sa_bcastaddr = ifa->ifa_dstaddr;
1014                         len = rt_msg2(RTM_NEWADDR, &info, NULL, w);
1015                         if (w->w_req && w->w_tmem) {
1016                                 struct ifa_msghdr *ifam;
1017
1018                                 ifam = (struct ifa_msghdr *)w->w_tmem;
1019                                 ifam->ifam_index = ifa->ifa_ifp->if_index;
1020                                 ifam->ifam_flags = ifa->ifa_flags;
1021                                 ifam->ifam_metric = ifa->ifa_metric;
1022                                 ifam->ifam_addrs = info.rti_addrs;
1023                                 error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
1024                                 if (error)
1025                                         return (error);
1026                         }
1027                 }
1028                 info.sa_netmask = info.sa_ifaaddr = info.sa_bcastaddr = NULL;
1029         }
1030         return (0);
1031 }
1032
1033 static int
1034 sysctl_rtsock(SYSCTL_HANDLER_ARGS)
1035 {
1036         int     *name = (int *)arg1;
1037         u_int   namelen = arg2;
1038         struct radix_node_head *rnh;
1039         int     i, s, error = EINVAL;
1040         u_char  af;
1041         struct  walkarg w;
1042
1043         name ++;
1044         namelen--;
1045         if (req->newptr)
1046                 return (EPERM);
1047         if (namelen != 3)
1048                 return (EINVAL);
1049         af = name[0];
1050         bzero(&w, sizeof w);
1051         w.w_op = name[1];
1052         w.w_arg = name[2];
1053         w.w_req = req;
1054
1055         s = splnet();
1056         switch (w.w_op) {
1057
1058         case NET_RT_DUMP:
1059         case NET_RT_FLAGS:
1060                 for (i = 1; i <= AF_MAX; i++)
1061                         if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
1062                             (error = rnh->rnh_walktree(rnh,
1063                                                        sysctl_dumpentry, &w)))
1064                                 break;
1065                 break;
1066
1067         case NET_RT_IFLIST:
1068                 error = sysctl_iflist(af, &w);
1069         }
1070         splx(s);
1071         if (w.w_tmem)
1072                 free(w.w_tmem, M_RTABLE);
1073         return (error);
1074 }
1075
1076 SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, "");
1077
1078 /*
1079  * Definitions of protocols supported in the ROUTE domain.
1080  */
1081
1082 extern struct domain routedomain;               /* or at least forward */
1083
1084 static struct protosw routesw[] = {
1085 { SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
1086   0,            route_output,   raw_ctlinput,   0,
1087   cpu0_soport,
1088   raw_init,     0,              0,              0,
1089   &route_usrreqs
1090 }
1091 };
1092
1093 static struct domain routedomain =
1094     { PF_ROUTE, "route", 0, 0, 0,
1095       routesw, &routesw[(sizeof routesw)/(sizeof routesw[0])] };
1096
1097 DOMAIN_SET(route);