Annotation of XNU/bsd/net/rtsock.c, revision 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.