Annotation of XNU/bsd/net/rtsock.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.