Annotation of kernel/bsd/net/rtsock.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
        !            26: /*
        !            27:  * Copyright (c) 1988, 1991, 1993
        !            28:  *     The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * Redistribution and use in source and binary forms, with or without
        !            31:  * modification, are permitted provided that the following conditions
        !            32:  * are met:
        !            33:  * 1. Redistributions of source code must retain the above copyright
        !            34:  *    notice, this list of conditions and the following disclaimer.
        !            35:  * 2. Redistributions in binary form must reproduce the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer in the
        !            37:  *    documentation and/or other materials provided with the distribution.
        !            38:  * 3. All advertising materials mentioning features or use of this software
        !            39:  *    must display the following acknowledgement:
        !            40:  *     This product includes software developed by the University of
        !            41:  *     California, Berkeley and its contributors.
        !            42:  * 4. Neither the name of the University nor the names of its contributors
        !            43:  *    may be used to endorse or promote products derived from this software
        !            44:  *    without specific prior written permission.
        !            45:  *
        !            46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            56:  * SUCH DAMAGE.
        !            57:  *
        !            58:  *     @(#)rtsock.c    8.6 (Berkeley) 2/11/95
        !            59:  */
        !            60: 
        !            61: #include <sys/param.h>
        !            62: #include <sys/systm.h>
        !            63: #include <sys/proc.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: #include <sys/malloc.h>
        !            70: 
        !            71: #include <net/if.h>
        !            72: #include <net/route.h>
        !            73: #include <net/raw_cb.h>
        !            74: 
        !            75: struct route_cb route_cb;
        !            76: struct sockaddr route_dst = { 2, PF_ROUTE, };
        !            77: struct sockaddr route_src = { 2, PF_ROUTE, };
        !            78: struct sockproto route_proto = { PF_ROUTE, };
        !            79: 
        !            80: struct walkarg {
        !            81:        int     w_op, w_arg, w_given, w_needed, w_tmemsize;
        !            82:        caddr_t w_where, w_tmem;
        !            83: };
        !            84: 
        !            85: static struct mbuf *
        !            86:                rt_msg1 __P((int, struct rt_addrinfo *));
        !            87: static int     rt_msg2 __P((int,
        !            88:                    struct rt_addrinfo *, caddr_t, struct walkarg *));
        !            89: static void    rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
        !            90: 
        !            91: /* Sleazy use of local variables throughout file, warning!!!! */
        !            92: #define dst    info.rti_info[RTAX_DST]
        !            93: #define gate   info.rti_info[RTAX_GATEWAY]
        !            94: #define netmask        info.rti_info[RTAX_NETMASK]
        !            95: #define genmask        info.rti_info[RTAX_GENMASK]
        !            96: #define ifpaddr        info.rti_info[RTAX_IFP]
        !            97: #define ifaaddr        info.rti_info[RTAX_IFA]
        !            98: #define brdaddr        info.rti_info[RTAX_BRD]
        !            99: 
        !           100: /*ARGSUSED*/
        !           101: int
        !           102: route_usrreq(so, req, m, nam, control)
        !           103:        register struct socket *so;
        !           104:        int req;
        !           105:        struct mbuf *m, *nam, *control;
        !           106: {
        !           107:        register int error = 0;
        !           108:        register struct rawcb *rp = sotorawcb(so);
        !           109:        int s;
        !           110: 
        !           111:        if (req == PRU_ATTACH) {
        !           112:                MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
        !           113:                if (so->so_pcb = (caddr_t)rp)
        !           114:                        bzero(so->so_pcb, sizeof(*rp));
        !           115: 
        !           116:        }
        !           117:        if (req == PRU_DETACH && rp) {
        !           118:                int af = rp->rcb_proto.sp_protocol;
        !           119:                if (af == AF_INET)
        !           120:                        route_cb.ip_count--;
        !           121:                else if (af == AF_NS)
        !           122:                        route_cb.ns_count--;
        !           123:                else if (af == AF_ISO)
        !           124:                        route_cb.iso_count--;
        !           125:                route_cb.any_count--;
        !           126:        }
        !           127:        s = splnet();
        !           128:        error = raw_usrreq(so, req, m, nam, control);
        !           129:        rp = sotorawcb(so);
        !           130:        if (req == PRU_ATTACH && rp) {
        !           131:                int af = rp->rcb_proto.sp_protocol;
        !           132:                if (error) {
        !           133:                        _FREE((caddr_t)rp, M_PCB);
        !           134:                        splx(s);
        !           135:                        return (error);
        !           136:                }
        !           137:                if (af == AF_INET)
        !           138:                        route_cb.ip_count++;
        !           139:                else if (af == AF_NS)
        !           140:                        route_cb.ns_count++;
        !           141:                else if (af == AF_ISO)
        !           142:                        route_cb.iso_count++;
        !           143:                rp->rcb_faddr = &route_src;
        !           144:                route_cb.any_count++;
        !           145:                soisconnected(so);
        !           146:                so->so_options |= SO_USELOOPBACK;
        !           147:        }
        !           148:        splx(s);
        !           149:        return (error);
        !           150: }
        !           151: 
        !           152: void m_copyback(struct mbuf *, int, int, caddr_t);
        !           153: 
        !           154: /*ARGSUSED*/
        !           155: int
        !           156: route_output(m, so)
        !           157:        register struct mbuf *m;
        !           158:        struct socket *so;
        !           159: {
        !           160:        register struct rt_msghdr *rtm = 0;
        !           161:        register struct rtentry *rt = 0;
        !           162:        struct rtentry *saved_nrt = 0;
        !           163:        struct radix_node_head *rnh;
        !           164:        struct rt_addrinfo info;
        !           165:        int len, error = 0;
        !           166:        struct ifnet *ifp = 0;
        !           167:        struct ifaddr *ifa = 0;
        !           168: 
        !           169: #define senderr(e) { error = e; goto flush;}
        !           170:        if (m == 0 || ((m->m_len < sizeof(int32_t)) &&
        !           171:                       (m = m_pullup(m, sizeof(int32_t))) == 0))
        !           172:                return (ENOBUFS);
        !           173:        if ((m->m_flags & M_PKTHDR) == 0)
        !           174:                panic("route_output");
        !           175:        len = m->m_pkthdr.len;
        !           176:        if (len < sizeof(*rtm) ||
        !           177:            len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
        !           178:                dst = 0;
        !           179:                senderr(EINVAL);
        !           180:        }
        !           181:        R_Malloc(rtm, struct rt_msghdr *, len);
        !           182:        if (rtm == 0) {
        !           183:                dst = 0;
        !           184:                senderr(ENOBUFS);
        !           185:        }
        !           186:        m_copydata(m, 0, len, (caddr_t)rtm);
        !           187:        if (rtm->rtm_version != RTM_VERSION) {
        !           188:                dst = 0;
        !           189:                senderr(EPROTONOSUPPORT);
        !           190:        }
        !           191:        rtm->rtm_pid = current_proc()->p_pid;
        !           192:        info.rti_addrs = rtm->rtm_addrs;
        !           193:        rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info);
        !           194:        if (dst == 0)
        !           195:                senderr(EINVAL);
        !           196:        if (genmask) {
        !           197:                struct radix_node *t;
        !           198:                t = rn_addmask((caddr_t)genmask, 0, 1);
        !           199:                if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
        !           200:                        genmask = (struct sockaddr *)(t->rn_key);
        !           201:                else
        !           202:                        senderr(ENOBUFS);
        !           203:        }
        !           204:        switch (rtm->rtm_type) {
        !           205: 
        !           206:        case RTM_ADD:
        !           207:                if (gate == 0)
        !           208:                        senderr(EINVAL);
        !           209:                error = rtrequest(RTM_ADD, dst, gate, netmask,
        !           210:                                        rtm->rtm_flags, &saved_nrt);
        !           211:                if (error == 0 && saved_nrt) {
        !           212:                        rt_setmetrics(rtm->rtm_inits,
        !           213:                                &rtm->rtm_rmx, &saved_nrt->rt_rmx);
        !           214:                        saved_nrt->rt_refcnt--;
        !           215:                        saved_nrt->rt_genmask = genmask;
        !           216:                }
        !           217:                break;
        !           218: 
        !           219:        case RTM_DELETE:
        !           220:                error = rtrequest(RTM_DELETE, dst, gate, netmask,
        !           221:                                rtm->rtm_flags, &saved_nrt);
        !           222:                if (error == 0) {
        !           223:                        (rt = saved_nrt)->rt_refcnt++;
        !           224:                        goto report;
        !           225:                }
        !           226:                break;
        !           227: 
        !           228:        case RTM_GET:
        !           229:        case RTM_CHANGE:
        !           230:        case RTM_LOCK:
        !           231:                if ((rnh = rt_tables[dst->sa_family]) == 0) {
        !           232:                        senderr(EAFNOSUPPORT);
        !           233:                } else if (rt = (struct rtentry *)
        !           234:                                rnh->rnh_lookup(dst, netmask, rnh))
        !           235:                        rt->rt_refcnt++;
        !           236:                else
        !           237:                        senderr(ESRCH);
        !           238:                switch(rtm->rtm_type) {
        !           239: 
        !           240:                case RTM_GET:
        !           241:                report:
        !           242:                        dst = rt_key(rt);
        !           243:                        gate = rt->rt_gateway;
        !           244:                        netmask = rt_mask(rt);
        !           245:                        genmask = rt->rt_genmask;
        !           246:                        if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
        !           247:                                if (ifp = rt->rt_ifp) {
        !           248:                                        ifpaddr = ifp->if_addrlist->ifa_addr;
        !           249:                                        ifaaddr = rt->rt_ifa->ifa_addr;
        !           250:                                        if (ifp->if_flags & IFF_POINTOPOINT)
        !           251:                                                brdaddr = rt->rt_ifa->ifa_dstaddr;
        !           252:                                        else
        !           253:                                                brdaddr = 0;
        !           254:                                        rtm->rtm_index = ifp->if_index;
        !           255:                                } else {
        !           256:                                        ifpaddr = 0;
        !           257:                                        ifaaddr = 0;
        !           258:                            }
        !           259:                        }
        !           260:                        len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
        !           261:                                (struct walkarg *)0);
        !           262:                        if (len > rtm->rtm_msglen) {
        !           263:                                struct rt_msghdr *new_rtm;
        !           264:                                R_Malloc(new_rtm, struct rt_msghdr *, len);
        !           265:                                if (new_rtm == 0)
        !           266:                                        senderr(ENOBUFS);
        !           267:                                Bcopy(rtm, new_rtm, rtm->rtm_msglen);
        !           268:                                Free(rtm); rtm = new_rtm;
        !           269:                        }
        !           270:                        (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
        !           271:                                (struct walkarg *)0);
        !           272:                        rtm->rtm_flags = rt->rt_flags;
        !           273:                        rtm->rtm_rmx = rt->rt_rmx;
        !           274:                        rtm->rtm_addrs = info.rti_addrs;
        !           275:                        break;
        !           276: 
        !           277:                case RTM_CHANGE:
        !           278:                        if (gate && rt_setgate(rt, rt_key(rt), gate))
        !           279:                                senderr(EDQUOT);
        !           280:                        /* new gateway could require new ifaddr, ifp;
        !           281:                           flags may also be different; ifp may be specified
        !           282:                           by ll sockaddr when protocol address is ambiguous */
        !           283:                        if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
        !           284:                            (ifp = ifa->ifa_ifp))
        !           285:                                ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
        !           286:                                                        ifp);
        !           287:                        else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
        !           288:                                 (ifa = ifa_ifwithroute(rt->rt_flags,
        !           289:                                                        rt_key(rt), gate)))
        !           290:                                ifp = ifa->ifa_ifp;
        !           291:                        if (ifa) {
        !           292:                                register struct ifaddr *oifa = rt->rt_ifa;
        !           293:                                if (oifa != ifa) {
        !           294:                                    if (oifa && oifa->ifa_rtrequest)
        !           295:                                        oifa->ifa_rtrequest(RTM_DELETE,
        !           296:                                                                rt, gate);
        !           297:                                    IFAFREE(rt->rt_ifa);
        !           298:                                    rt->rt_ifa = ifa;
        !           299:                                    ifa->ifa_refcnt++;
        !           300:                                    rt->rt_ifp = ifp;
        !           301:                                }
        !           302:                        }
        !           303:                        rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
        !           304:                                        &rt->rt_rmx);
        !           305:                        if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
        !           306:                               rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
        !           307:                        if (genmask)
        !           308:                                rt->rt_genmask = genmask;
        !           309:                        /*
        !           310:                         * Fall into
        !           311:                         */
        !           312:                case RTM_LOCK:
        !           313:                        rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
        !           314:                        rt->rt_rmx.rmx_locks |=
        !           315:                                (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
        !           316:                        break;
        !           317:                }
        !           318:                break;
        !           319: 
        !           320:        default:
        !           321:                senderr(EOPNOTSUPP);
        !           322:        }
        !           323: 
        !           324: flush:
        !           325:        if (rtm) {
        !           326:                if (error)
        !           327:                        rtm->rtm_errno = error;
        !           328:                else 
        !           329:                        rtm->rtm_flags |= RTF_DONE;
        !           330:        }
        !           331:        if (rt)
        !           332:                rtfree(rt);
        !           333:     {
        !           334:        register struct rawcb *rp = 0;
        !           335:        /*
        !           336:         * Check to see if we don't want our own messages.
        !           337:         */
        !           338:        if ((so->so_options & SO_USELOOPBACK) == 0) {
        !           339:                if (route_cb.any_count <= 1) {
        !           340:                        if (rtm)
        !           341:                                Free(rtm);
        !           342:                        m_freem(m);
        !           343:                        return (error);
        !           344:                }
        !           345:                /* There is another listener, so construct message */
        !           346:                rp = sotorawcb(so);
        !           347:        }
        !           348:        if (rtm) {
        !           349:                m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
        !           350:                Free(rtm);
        !           351:        }
        !           352:        if (rp)
        !           353:                rp->rcb_proto.sp_family = 0; /* Avoid us */
        !           354:        if (dst)
        !           355:                route_proto.sp_protocol = dst->sa_family;
        !           356:        raw_input(m, &route_proto, &route_src, &route_dst);
        !           357:        if (rp)
        !           358:                rp->rcb_proto.sp_family = PF_ROUTE;
        !           359:     }
        !           360:        return (error);
        !           361: }
        !           362: 
        !           363: void
        !           364: rt_setmetrics(which, in, out)
        !           365:        u_long which;
        !           366:        register struct rt_metrics *in, *out;
        !           367: {
        !           368: #define metric(f, e) if (which & (f)) out->e = in->e;
        !           369:        metric(RTV_RPIPE, rmx_recvpipe);
        !           370:        metric(RTV_SPIPE, rmx_sendpipe);
        !           371:        metric(RTV_SSTHRESH, rmx_ssthresh);
        !           372:        metric(RTV_RTT, rmx_rtt);
        !           373:        metric(RTV_RTTVAR, rmx_rttvar);
        !           374:        metric(RTV_HOPCOUNT, rmx_hopcount);
        !           375:        metric(RTV_MTU, rmx_mtu);
        !           376:        metric(RTV_EXPIRE, rmx_expire);
        !           377: #undef metric
        !           378: }
        !           379: 
        !           380: #define ROUNDUP(a) \
        !           381:        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
        !           382: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
        !           383: 
        !           384: static void
        !           385: rt_xaddrs(cp, cplim, rtinfo)
        !           386:        register caddr_t cp, cplim;
        !           387:        register struct rt_addrinfo *rtinfo;
        !           388: {
        !           389:        register struct sockaddr *sa;
        !           390:        register int i;
        !           391: 
        !           392:        bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
        !           393:        for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
        !           394:                if ((rtinfo->rti_addrs & (1 << i)) == 0)
        !           395:                        continue;
        !           396:                rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
        !           397:                ADVANCE(cp, sa);
        !           398:        }
        !           399: }
        !           400: 
        !           401: /*
        !           402:  * Copy data from a buffer back into the indicated mbuf chain,
        !           403:  * starting "off" bytes from the beginning, extending the mbuf
        !           404:  * chain if necessary.
        !           405:  */
        !           406: void
        !           407: m_copyback(m0, off, len, cp)
        !           408:        struct  mbuf *m0;
        !           409:        register int off;
        !           410:        register int len;
        !           411:        caddr_t cp;
        !           412: {
        !           413:        register int mlen;
        !           414:        register struct mbuf *m = m0, *n;
        !           415:        int totlen = 0;
        !           416: 
        !           417:        if (m0 == 0)
        !           418:                return;
        !           419:        while (off > (mlen = m->m_len)) {
        !           420:                off -= mlen;
        !           421:                totlen += mlen;
        !           422:                if (m->m_next == 0) {
        !           423:                        n = m_getclr(M_DONTWAIT, m->m_type);
        !           424:                        if (n == 0)
        !           425:                                goto out;
        !           426:                        n->m_len = min(MLEN, len + off);
        !           427:                        m->m_next = n;
        !           428:                }
        !           429:                m = m->m_next;
        !           430:        }
        !           431:        while (len > 0) {
        !           432:                mlen = min (m->m_len - off, len);
        !           433:                bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
        !           434:                cp += mlen;
        !           435:                len -= mlen;
        !           436:                mlen += off;
        !           437:                off = 0;
        !           438:                totlen += mlen;
        !           439:                if (len == 0)
        !           440:                        break;
        !           441:                if (m->m_next == 0) {
        !           442:                        n = m_get(M_DONTWAIT, m->m_type);
        !           443:                        if (n == 0)
        !           444:                                break;
        !           445:                        n->m_len = min(MLEN, len);
        !           446:                        m->m_next = n;
        !           447:                }
        !           448:                m = m->m_next;
        !           449:        }
        !           450: out:   if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
        !           451:                m->m_pkthdr.len = totlen;
        !           452: }
        !           453: 
        !           454: static struct mbuf *
        !           455: rt_msg1(type, rtinfo)
        !           456:        int type;
        !           457:        register struct rt_addrinfo *rtinfo;
        !           458: {
        !           459:        register struct rt_msghdr *rtm;
        !           460:        register struct mbuf *m;
        !           461:        register int i;
        !           462:        register struct sockaddr *sa;
        !           463:        int len, dlen;
        !           464: 
        !           465:        m = m_gethdr(M_DONTWAIT, MT_DATA);
        !           466:        if (m == 0)
        !           467:                return (m);
        !           468:        switch (type) {
        !           469: 
        !           470:        case RTM_DELADDR:
        !           471:        case RTM_NEWADDR:
        !           472:                len = sizeof(struct ifa_msghdr);
        !           473:                break;
        !           474: 
        !           475:        case RTM_IFINFO:
        !           476:                len = sizeof(struct if_msghdr);
        !           477:                break;
        !           478: 
        !           479:        default:
        !           480:                len = sizeof(struct rt_msghdr);
        !           481:        }
        !           482:        if (len > MHLEN)
        !           483:                panic("rt_msg1");
        !           484:        m->m_pkthdr.len = m->m_len = len;
        !           485:        m->m_pkthdr.rcvif = 0;
        !           486:        rtm = mtod(m, struct rt_msghdr *);
        !           487:        bzero((caddr_t)rtm, len);
        !           488:        for (i = 0; i < RTAX_MAX; i++) {
        !           489:                if ((sa = rtinfo->rti_info[i]) == NULL)
        !           490:                        continue;
        !           491:                rtinfo->rti_addrs |= (1 << i);
        !           492:                dlen = ROUNDUP(sa->sa_len);
        !           493:                m_copyback(m, len, dlen, (caddr_t)sa);
        !           494:                len += dlen;
        !           495:        }
        !           496:        if (m->m_pkthdr.len != len) {
        !           497:                m_freem(m);
        !           498:                return (NULL);
        !           499:        }
        !           500:        rtm->rtm_msglen = len;
        !           501:        rtm->rtm_version = RTM_VERSION;
        !           502:        rtm->rtm_type = type;
        !           503:        return (m);
        !           504: }
        !           505: 
        !           506: static int
        !           507: rt_msg2(type, rtinfo, cp, w)
        !           508:        int type;
        !           509:        register struct rt_addrinfo *rtinfo;
        !           510:        caddr_t cp;
        !           511:        struct walkarg *w;
        !           512: {
        !           513:        register int i;
        !           514:        int len, dlen, second_time = 0;
        !           515:        caddr_t cp0;
        !           516: 
        !           517:        rtinfo->rti_addrs = 0;
        !           518: again:
        !           519:        switch (type) {
        !           520: 
        !           521:        case RTM_DELADDR:
        !           522:        case RTM_NEWADDR:
        !           523:                len = sizeof(struct ifa_msghdr);
        !           524:                break;
        !           525: 
        !           526:        case RTM_IFINFO:
        !           527:                len = sizeof(struct if_msghdr);
        !           528:                break;
        !           529: 
        !           530:        default:
        !           531:                len = sizeof(struct rt_msghdr);
        !           532:        }
        !           533:        if (cp0 = cp)
        !           534:                cp += len;
        !           535:        for (i = 0; i < RTAX_MAX; i++) {
        !           536:                register struct sockaddr *sa;
        !           537: 
        !           538:                if ((sa = rtinfo->rti_info[i]) == 0)
        !           539:                        continue;
        !           540:                rtinfo->rti_addrs |= (1 << i);
        !           541:                dlen = ROUNDUP(sa->sa_len);
        !           542:                if (cp) {
        !           543:                        bcopy((caddr_t)sa, cp, (unsigned)dlen);
        !           544:                        cp += dlen;
        !           545:                }
        !           546:                len += dlen;
        !           547:        }
        !           548:        if (cp == 0 && w != NULL && !second_time) {
        !           549:                register struct walkarg *rw = w;
        !           550: 
        !           551:                rw->w_needed += len;
        !           552:                if (rw->w_needed <= 0 && rw->w_where) {
        !           553:                        if (rw->w_tmemsize < len) {
        !           554:                                if (rw->w_tmem)
        !           555:                                        _FREE(rw->w_tmem, M_RTABLE);
        !           556:                                if (rw->w_tmem = (caddr_t)
        !           557:                                                _MALLOC(len, M_RTABLE, M_NOWAIT))
        !           558:                                        rw->w_tmemsize = len;
        !           559:                        }
        !           560:                        if (rw->w_tmem) {
        !           561:                                cp = rw->w_tmem;
        !           562:                                second_time = 1;
        !           563:                                goto again;
        !           564:                        } else
        !           565:                                rw->w_where = 0;
        !           566:                }
        !           567:        }
        !           568:        if (cp) {
        !           569:                register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
        !           570: 
        !           571:                rtm->rtm_version = RTM_VERSION;
        !           572:                rtm->rtm_type = type;
        !           573:                rtm->rtm_msglen = len;
        !           574:        }
        !           575:        return (len);
        !           576: }
        !           577: 
        !           578: /*
        !           579:  * This routine is called to generate a message from the routing
        !           580:  * socket indicating that a redirect has occured, a routing lookup
        !           581:  * has failed, or that a protocol has detected timeouts to a particular
        !           582:  * destination.
        !           583:  */
        !           584: void
        !           585: rt_missmsg(type, rtinfo, flags, error)
        !           586:        int type, flags, error;
        !           587:        register struct rt_addrinfo *rtinfo;
        !           588: {
        !           589:        register struct rt_msghdr *rtm;
        !           590:        register struct mbuf *m;
        !           591:        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
        !           592: 
        !           593:        if (route_cb.any_count == 0)
        !           594:                return;
        !           595:        m = rt_msg1(type, rtinfo);
        !           596:        if (m == 0)
        !           597:                return;
        !           598:        rtm = mtod(m, struct rt_msghdr *);
        !           599:        rtm->rtm_flags = RTF_DONE | flags;
        !           600:        rtm->rtm_errno = error;
        !           601:        rtm->rtm_addrs = rtinfo->rti_addrs;
        !           602:        route_proto.sp_protocol = sa ? sa->sa_family : 0;
        !           603:        raw_input(m, &route_proto, &route_src, &route_dst);
        !           604: }
        !           605: 
        !           606: /*
        !           607:  * This routine is called to generate a message from the routing
        !           608:  * socket indicating that the status of a network interface has changed.
        !           609:  */
        !           610: void
        !           611: rt_ifmsg(ifp)
        !           612:        register struct ifnet *ifp;
        !           613: {
        !           614:        register struct if_msghdr *ifm;
        !           615:        struct mbuf *m;
        !           616:        struct rt_addrinfo info;
        !           617: 
        !           618:        if (route_cb.any_count == 0)
        !           619:                return;
        !           620:        bzero((caddr_t)&info, sizeof(info));
        !           621:        m = rt_msg1(RTM_IFINFO, &info);
        !           622:        if (m == 0)
        !           623:                return;
        !           624:        ifm = mtod(m, struct if_msghdr *);
        !           625:        ifm->ifm_index = ifp->if_index;
        !           626:        ifm->ifm_flags = ifp->if_flags;
        !           627:        ifm->ifm_data = ifp->if_data;
        !           628:        ifm->ifm_addrs = 0;
        !           629:        route_proto.sp_protocol = 0;
        !           630:        raw_input(m, &route_proto, &route_src, &route_dst);
        !           631: }
        !           632: 
        !           633: /*
        !           634:  * This is called to generate messages from the routing socket
        !           635:  * indicating a network interface has had addresses associated with it.
        !           636:  * if we ever reverse the logic and replace messages TO the routing
        !           637:  * socket indicate a request to configure interfaces, then it will
        !           638:  * be unnecessary as the routing socket will automatically generate
        !           639:  * copies of it.
        !           640:  */
        !           641: void
        !           642: rt_newaddrmsg(cmd, ifa, error, rt)
        !           643:        int cmd, error;
        !           644:        register struct ifaddr *ifa;
        !           645:        register struct rtentry *rt;
        !           646: {
        !           647:        struct rt_addrinfo info;
        !           648:        struct sockaddr *sa;
        !           649:        int pass;
        !           650:        struct mbuf *m;
        !           651:        struct ifnet *ifp = ifa->ifa_ifp;
        !           652: 
        !           653:        if (route_cb.any_count == 0)
        !           654:                return;
        !           655:        for (pass = 1; pass < 3; pass++) {
        !           656:                bzero((caddr_t)&info, sizeof(info));
        !           657:                if ((cmd == RTM_ADD && pass == 1) ||
        !           658:                    (cmd == RTM_DELETE && pass == 2)) {
        !           659:                        register struct ifa_msghdr *ifam;
        !           660:                        int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
        !           661: 
        !           662:                        ifaaddr = sa = ifa->ifa_addr;
        !           663:                        ifpaddr = ifp->if_addrlist->ifa_addr;
        !           664:                        netmask = ifa->ifa_netmask;
        !           665:                        brdaddr = ifa->ifa_dstaddr;
        !           666:                        if ((m = rt_msg1(ncmd, &info)) == NULL)
        !           667:                                continue;
        !           668:                        ifam = mtod(m, struct ifa_msghdr *);
        !           669:                        ifam->ifam_index = ifp->if_index;
        !           670:                        ifam->ifam_metric = ifa->ifa_metric;
        !           671:                        ifam->ifam_flags = ifa->ifa_flags;
        !           672:                        ifam->ifam_addrs = info.rti_addrs;
        !           673:                }
        !           674:                if ((cmd == RTM_ADD && pass == 2) ||
        !           675:                    (cmd == RTM_DELETE && pass == 1)) {
        !           676:                        register struct rt_msghdr *rtm;
        !           677:                        
        !           678:                        if (rt == 0)
        !           679:                                continue;
        !           680:                        netmask = rt_mask(rt);
        !           681:                        dst = sa = rt_key(rt);
        !           682:                        gate = rt->rt_gateway;
        !           683:                        if ((m = rt_msg1(cmd, &info)) == NULL)
        !           684:                                continue;
        !           685:                        rtm = mtod(m, struct rt_msghdr *);
        !           686:                        rtm->rtm_index = ifp->if_index;
        !           687:                        rtm->rtm_flags |= rt->rt_flags;
        !           688:                        rtm->rtm_errno = error;
        !           689:                        rtm->rtm_addrs = info.rti_addrs;
        !           690:                }
        !           691:                route_proto.sp_protocol = sa ? sa->sa_family : 0;
        !           692:                raw_input(m, &route_proto, &route_src, &route_dst);
        !           693:        }
        !           694: }
        !           695: 
        !           696: /*
        !           697:  * This is used in dumping the kernel table via sysctl().
        !           698:  */
        !           699: int
        !           700: sysctl_dumpentry(rn, w)
        !           701:        struct radix_node *rn;
        !           702:        register struct walkarg *w;
        !           703: {
        !           704:        register struct rtentry *rt = (struct rtentry *)rn;
        !           705:        int error = 0, size;
        !           706:        struct rt_addrinfo info;
        !           707: 
        !           708:        if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
        !           709:                return 0;
        !           710:        bzero((caddr_t)&info, sizeof(info));
        !           711:        dst = rt_key(rt);
        !           712:        gate = rt->rt_gateway;
        !           713:        netmask = rt_mask(rt);
        !           714:        genmask = rt->rt_genmask;
        !           715:        if (rt->rt_ifp) {
        !           716:                ifpaddr = rt->rt_ifp->if_addrlist->ifa_addr;
        !           717:                ifaaddr = rt->rt_ifa->ifa_addr;
        !           718:                if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
        !           719:                        brdaddr = rt->rt_ifa->ifa_dstaddr;
        !           720:        }
        !           721:        size = rt_msg2(RTM_GET, &info, 0, w);
        !           722:        if (w->w_where && w->w_tmem) {
        !           723:                register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
        !           724: 
        !           725:                rtm->rtm_flags = rt->rt_flags;
        !           726:                rtm->rtm_use = rt->rt_use;
        !           727:                rtm->rtm_rmx = rt->rt_rmx;
        !           728:                rtm->rtm_index = rt->rt_ifp->if_index;
        !           729:                rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
        !           730:                rtm->rtm_addrs = info.rti_addrs;
        !           731:                if (error = copyout((caddr_t)rtm, w->w_where, size))
        !           732:                        w->w_where = NULL;
        !           733:                else
        !           734:                        w->w_where += size;
        !           735:        }
        !           736:        return (error);
        !           737: }
        !           738: 
        !           739: int
        !           740: sysctl_iflist(af, w)
        !           741:        int     af;
        !           742:        register struct walkarg *w;
        !           743: {
        !           744:        register struct ifnet *ifp;
        !           745:        register struct ifaddr *ifa;
        !           746:        struct  rt_addrinfo info;
        !           747:        int     len, error = 0;
        !           748: 
        !           749:        bzero((caddr_t)&info, sizeof(info));
        !           750:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
        !           751:                if (w->w_arg && w->w_arg != ifp->if_index)
        !           752:                        continue;
        !           753:                ifa = ifp->if_addrlist;
        !           754:                ifpaddr = ifa->ifa_addr;
        !           755:                len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
        !           756:                ifpaddr = 0;
        !           757:                if (w->w_where && w->w_tmem) {
        !           758:                        register struct if_msghdr *ifm;
        !           759: 
        !           760:                        ifm = (struct if_msghdr *)w->w_tmem;
        !           761:                        ifm->ifm_index = ifp->if_index;
        !           762:                        ifm->ifm_flags = ifp->if_flags;
        !           763:                        ifm->ifm_data = ifp->if_data;
        !           764:                        ifm->ifm_addrs = info.rti_addrs;
        !           765:                        if (error = copyout((caddr_t)ifm, w->w_where, len))
        !           766:                                return (error);
        !           767:                        w->w_where += len;
        !           768:                }
        !           769:                while (ifa = ifa->ifa_next) {
        !           770:                        if (af && af != ifa->ifa_addr->sa_family)
        !           771:                                continue;
        !           772:                        ifaaddr = ifa->ifa_addr;
        !           773:                        netmask = ifa->ifa_netmask;
        !           774:                        brdaddr = ifa->ifa_dstaddr;
        !           775:                        len = rt_msg2(RTM_NEWADDR, &info, 0, w);
        !           776:                        if (w->w_where && w->w_tmem) {
        !           777:                                register struct ifa_msghdr *ifam;
        !           778: 
        !           779:                                ifam = (struct ifa_msghdr *)w->w_tmem;
        !           780:                                ifam->ifam_index = ifa->ifa_ifp->if_index;
        !           781:                                ifam->ifam_flags = ifa->ifa_flags;
        !           782:                                ifam->ifam_metric = ifa->ifa_metric;
        !           783:                                ifam->ifam_addrs = info.rti_addrs;
        !           784:                                if (error = copyout(w->w_tmem, w->w_where, len))
        !           785:                                        return (error);
        !           786:                                w->w_where += len;
        !           787:                        }
        !           788:                }
        !           789:                ifaaddr = netmask = brdaddr = 0;
        !           790:        }
        !           791:        return (0);
        !           792: }
        !           793: 
        !           794: int
        !           795: sysctl_rtable(name, namelen, where, given, new, newlen)
        !           796:        int     *name;
        !           797:        int     namelen;
        !           798:        caddr_t where;
        !           799:        size_t  *given;
        !           800:        caddr_t *new;
        !           801:        size_t  newlen;
        !           802: {
        !           803:        register struct radix_node_head *rnh;
        !           804:        int     i, s, error = EINVAL;
        !           805:        u_char  af;
        !           806:        struct  walkarg w;
        !           807: 
        !           808:        if (new)
        !           809:                return (EPERM);
        !           810:        if (namelen != 3)
        !           811:                return (EINVAL);
        !           812:        af = name[0];
        !           813:        Bzero(&w, sizeof(w));
        !           814:        w.w_where = where;
        !           815:        w.w_given = *given;
        !           816:        w.w_needed = 0 - w.w_given;
        !           817:        w.w_op = name[1];
        !           818:        w.w_arg = name[2];
        !           819: 
        !           820:        s = splnet();
        !           821:        switch (w.w_op) {
        !           822: 
        !           823:        case NET_RT_DUMP:
        !           824:        case NET_RT_FLAGS:
        !           825:                for (i = 1; i <= AF_MAX; i++)
        !           826:                        if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
        !           827:                            (error = rnh->rnh_walktree(rnh,
        !           828:                                                        sysctl_dumpentry, &w)))
        !           829:                                break;
        !           830:                break;
        !           831: 
        !           832:        case NET_RT_IFLIST:
        !           833:                error = sysctl_iflist(af, &w);
        !           834:        }
        !           835:        splx(s);
        !           836:        if (w.w_tmem)
        !           837:                _FREE(w.w_tmem, M_RTABLE);
        !           838:        w.w_needed += w.w_given;
        !           839:        if (where) {
        !           840:                *given = w.w_where - where;
        !           841:                if (*given < w.w_needed)
        !           842:                        return (ENOMEM);
        !           843:        } else {
        !           844:                *given = (11 * w.w_needed) / 10;
        !           845:        }
        !           846:        return (error);
        !           847: }
        !           848: 
        !           849: /*
        !           850:  * Definitions of protocols supported in the ROUTE domain.
        !           851:  */
        !           852: 
        !           853: extern struct domain routedomain;              /* or at least forward */
        !           854: 
        !           855: struct protosw routesw[] = {
        !           856: { SOCK_RAW,    &routedomain,   0,              PR_ATOMIC|PR_ADDR,
        !           857:   raw_input,   route_output,   raw_ctlinput,   0,
        !           858:   route_usrreq,
        !           859:   raw_init,    0,              0,              0,
        !           860:   sysctl_rtable,
        !           861: }
        !           862: };
        !           863: 
        !           864: struct domain routedomain =
        !           865:     { PF_ROUTE, "route", route_init, 0, 0,
        !           866:       routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };

unix.superglobalmegacorp.com

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