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

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) {
1.1.1.2 ! root      223:                        rt = saved_nrt;
        !           224:                        RTHOLD(rt);
1.1       root      225:                        goto report;
                    226:                }
                    227:                break;
                    228: 
                    229:        case RTM_GET:
                    230:        case RTM_CHANGE:
                    231:        case RTM_LOCK:
                    232:                if ((rnh = rt_tables[dst->sa_family]) == 0) {
                    233:                        senderr(EAFNOSUPPORT);
                    234:                } else if (rt = (struct rtentry *)
                    235:                                rnh->rnh_lookup(dst, netmask, rnh))
1.1.1.2 ! root      236:                        RTHOLD(rt)
1.1       root      237:                else
                    238:                        senderr(ESRCH);
                    239:                switch(rtm->rtm_type) {
                    240: 
                    241:                case RTM_GET:
                    242:                report:
                    243:                        dst = rt_key(rt);
                    244:                        gate = rt->rt_gateway;
                    245:                        netmask = rt_mask(rt);
                    246:                        genmask = rt->rt_genmask;
                    247:                        if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
                    248:                                if (ifp = rt->rt_ifp) {
                    249:                                        ifpaddr = ifp->if_addrlist->ifa_addr;
                    250:                                        ifaaddr = rt->rt_ifa->ifa_addr;
                    251:                                        if (ifp->if_flags & IFF_POINTOPOINT)
                    252:                                                brdaddr = rt->rt_ifa->ifa_dstaddr;
                    253:                                        else
                    254:                                                brdaddr = 0;
                    255:                                        rtm->rtm_index = ifp->if_index;
                    256:                                } else {
                    257:                                        ifpaddr = 0;
                    258:                                        ifaaddr = 0;
                    259:                            }
                    260:                        }
                    261:                        len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
                    262:                                (struct walkarg *)0);
                    263:                        if (len > rtm->rtm_msglen) {
                    264:                                struct rt_msghdr *new_rtm;
                    265:                                R_Malloc(new_rtm, struct rt_msghdr *, len);
                    266:                                if (new_rtm == 0)
                    267:                                        senderr(ENOBUFS);
                    268:                                Bcopy(rtm, new_rtm, rtm->rtm_msglen);
                    269:                                Free(rtm); rtm = new_rtm;
                    270:                        }
                    271:                        (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
                    272:                                (struct walkarg *)0);
                    273:                        rtm->rtm_flags = rt->rt_flags;
                    274:                        rtm->rtm_rmx = rt->rt_rmx;
                    275:                        rtm->rtm_addrs = info.rti_addrs;
                    276:                        break;
                    277: 
                    278:                case RTM_CHANGE:
                    279:                        if (gate && rt_setgate(rt, rt_key(rt), gate))
                    280:                                senderr(EDQUOT);
                    281:                        /* new gateway could require new ifaddr, ifp;
                    282:                           flags may also be different; ifp may be specified
                    283:                           by ll sockaddr when protocol address is ambiguous */
                    284:                        if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
                    285:                            (ifp = ifa->ifa_ifp))
                    286:                                ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
                    287:                                                        ifp);
                    288:                        else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
                    289:                                 (ifa = ifa_ifwithroute(rt->rt_flags,
                    290:                                                        rt_key(rt), gate)))
                    291:                                ifp = ifa->ifa_ifp;
                    292:                        if (ifa) {
                    293:                                register struct ifaddr *oifa = rt->rt_ifa;
                    294:                                if (oifa != ifa) {
                    295:                                    if (oifa && oifa->ifa_rtrequest)
                    296:                                        oifa->ifa_rtrequest(RTM_DELETE,
                    297:                                                                rt, gate);
                    298:                                    IFAFREE(rt->rt_ifa);
                    299:                                    rt->rt_ifa = ifa;
1.1.1.2 ! root      300:                                    if (++ifa->ifa_refcnt <= 0)
        !           301:                                        panic("route_output ifa_refcnt");
1.1       root      302:                                    rt->rt_ifp = ifp;
                    303:                                }
                    304:                        }
                    305:                        rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
                    306:                                        &rt->rt_rmx);
                    307:                        if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
                    308:                               rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
                    309:                        if (genmask)
                    310:                                rt->rt_genmask = genmask;
                    311:                        /*
                    312:                         * Fall into
                    313:                         */
                    314:                case RTM_LOCK:
                    315:                        rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
                    316:                        rt->rt_rmx.rmx_locks |=
                    317:                                (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
                    318:                        break;
                    319:                }
                    320:                break;
                    321: 
                    322:        default:
                    323:                senderr(EOPNOTSUPP);
                    324:        }
                    325: 
                    326: flush:
                    327:        if (rtm) {
                    328:                if (error)
                    329:                        rtm->rtm_errno = error;
                    330:                else 
                    331:                        rtm->rtm_flags |= RTF_DONE;
                    332:        }
                    333:        if (rt)
                    334:                rtfree(rt);
                    335:     {
                    336:        register struct rawcb *rp = 0;
                    337:        /*
                    338:         * Check to see if we don't want our own messages.
                    339:         */
                    340:        if ((so->so_options & SO_USELOOPBACK) == 0) {
                    341:                if (route_cb.any_count <= 1) {
                    342:                        if (rtm)
                    343:                                Free(rtm);
                    344:                        m_freem(m);
                    345:                        return (error);
                    346:                }
                    347:                /* There is another listener, so construct message */
                    348:                rp = sotorawcb(so);
                    349:        }
                    350:        if (rtm) {
                    351:                m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
                    352:                Free(rtm);
                    353:        }
                    354:        if (rp)
                    355:                rp->rcb_proto.sp_family = 0; /* Avoid us */
                    356:        if (dst)
                    357:                route_proto.sp_protocol = dst->sa_family;
                    358:        raw_input(m, &route_proto, &route_src, &route_dst);
                    359:        if (rp)
                    360:                rp->rcb_proto.sp_family = PF_ROUTE;
                    361:     }
                    362:        return (error);
                    363: }
                    364: 
                    365: void
                    366: rt_setmetrics(which, in, out)
                    367:        u_long which;
                    368:        register struct rt_metrics *in, *out;
                    369: {
                    370: #define metric(f, e) if (which & (f)) out->e = in->e;
                    371:        metric(RTV_RPIPE, rmx_recvpipe);
                    372:        metric(RTV_SPIPE, rmx_sendpipe);
                    373:        metric(RTV_SSTHRESH, rmx_ssthresh);
                    374:        metric(RTV_RTT, rmx_rtt);
                    375:        metric(RTV_RTTVAR, rmx_rttvar);
                    376:        metric(RTV_HOPCOUNT, rmx_hopcount);
                    377:        metric(RTV_MTU, rmx_mtu);
                    378:        metric(RTV_EXPIRE, rmx_expire);
                    379: #undef metric
                    380: }
                    381: 
                    382: #define ROUNDUP(a) \
                    383:        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
                    384: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
                    385: 
                    386: static void
                    387: rt_xaddrs(cp, cplim, rtinfo)
                    388:        register caddr_t cp, cplim;
                    389:        register struct rt_addrinfo *rtinfo;
                    390: {
                    391:        register struct sockaddr *sa;
                    392:        register int i;
                    393: 
                    394:        bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
                    395:        for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
                    396:                if ((rtinfo->rti_addrs & (1 << i)) == 0)
                    397:                        continue;
                    398:                rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
                    399:                ADVANCE(cp, sa);
                    400:        }
                    401: }
                    402: 
                    403: /*
                    404:  * Copy data from a buffer back into the indicated mbuf chain,
                    405:  * starting "off" bytes from the beginning, extending the mbuf
                    406:  * chain if necessary.
                    407:  */
                    408: void
                    409: m_copyback(m0, off, len, cp)
                    410:        struct  mbuf *m0;
                    411:        register int off;
                    412:        register int len;
                    413:        caddr_t cp;
                    414: {
                    415:        register int mlen;
                    416:        register struct mbuf *m = m0, *n;
                    417:        int totlen = 0;
                    418: 
                    419:        if (m0 == 0)
                    420:                return;
                    421:        while (off > (mlen = m->m_len)) {
                    422:                off -= mlen;
                    423:                totlen += mlen;
                    424:                if (m->m_next == 0) {
                    425:                        n = m_getclr(M_DONTWAIT, m->m_type);
                    426:                        if (n == 0)
                    427:                                goto out;
                    428:                        n->m_len = min(MLEN, len + off);
                    429:                        m->m_next = n;
                    430:                }
                    431:                m = m->m_next;
                    432:        }
                    433:        while (len > 0) {
                    434:                mlen = min (m->m_len - off, len);
                    435:                bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
                    436:                cp += mlen;
                    437:                len -= mlen;
                    438:                mlen += off;
                    439:                off = 0;
                    440:                totlen += mlen;
                    441:                if (len == 0)
                    442:                        break;
                    443:                if (m->m_next == 0) {
                    444:                        n = m_get(M_DONTWAIT, m->m_type);
                    445:                        if (n == 0)
                    446:                                break;
                    447:                        n->m_len = min(MLEN, len);
                    448:                        m->m_next = n;
                    449:                }
                    450:                m = m->m_next;
                    451:        }
                    452: out:   if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
                    453:                m->m_pkthdr.len = totlen;
                    454: }
                    455: 
                    456: static struct mbuf *
                    457: rt_msg1(type, rtinfo)
                    458:        int type;
                    459:        register struct rt_addrinfo *rtinfo;
                    460: {
                    461:        register struct rt_msghdr *rtm;
                    462:        register struct mbuf *m;
                    463:        register int i;
                    464:        register struct sockaddr *sa;
                    465:        int len, dlen;
                    466: 
                    467:        m = m_gethdr(M_DONTWAIT, MT_DATA);
                    468:        if (m == 0)
                    469:                return (m);
                    470:        switch (type) {
                    471: 
                    472:        case RTM_DELADDR:
                    473:        case RTM_NEWADDR:
                    474:                len = sizeof(struct ifa_msghdr);
                    475:                break;
                    476: 
                    477:        case RTM_IFINFO:
                    478:                len = sizeof(struct if_msghdr);
                    479:                break;
                    480: 
                    481:        default:
                    482:                len = sizeof(struct rt_msghdr);
                    483:        }
                    484:        if (len > MHLEN)
                    485:                panic("rt_msg1");
                    486:        m->m_pkthdr.len = m->m_len = len;
                    487:        m->m_pkthdr.rcvif = 0;
                    488:        rtm = mtod(m, struct rt_msghdr *);
                    489:        bzero((caddr_t)rtm, len);
                    490:        for (i = 0; i < RTAX_MAX; i++) {
                    491:                if ((sa = rtinfo->rti_info[i]) == NULL)
                    492:                        continue;
                    493:                rtinfo->rti_addrs |= (1 << i);
                    494:                dlen = ROUNDUP(sa->sa_len);
                    495:                m_copyback(m, len, dlen, (caddr_t)sa);
                    496:                len += dlen;
                    497:        }
                    498:        if (m->m_pkthdr.len != len) {
                    499:                m_freem(m);
                    500:                return (NULL);
                    501:        }
                    502:        rtm->rtm_msglen = len;
                    503:        rtm->rtm_version = RTM_VERSION;
                    504:        rtm->rtm_type = type;
                    505:        return (m);
                    506: }
                    507: 
                    508: static int
                    509: rt_msg2(type, rtinfo, cp, w)
                    510:        int type;
                    511:        register struct rt_addrinfo *rtinfo;
                    512:        caddr_t cp;
                    513:        struct walkarg *w;
                    514: {
                    515:        register int i;
                    516:        int len, dlen, second_time = 0;
                    517:        caddr_t cp0;
                    518: 
                    519:        rtinfo->rti_addrs = 0;
                    520: again:
                    521:        switch (type) {
                    522: 
                    523:        case RTM_DELADDR:
                    524:        case RTM_NEWADDR:
                    525:                len = sizeof(struct ifa_msghdr);
                    526:                break;
                    527: 
                    528:        case RTM_IFINFO:
                    529:                len = sizeof(struct if_msghdr);
                    530:                break;
                    531: 
                    532:        default:
                    533:                len = sizeof(struct rt_msghdr);
                    534:        }
                    535:        if (cp0 = cp)
                    536:                cp += len;
                    537:        for (i = 0; i < RTAX_MAX; i++) {
                    538:                register struct sockaddr *sa;
                    539: 
                    540:                if ((sa = rtinfo->rti_info[i]) == 0)
                    541:                        continue;
                    542:                rtinfo->rti_addrs |= (1 << i);
                    543:                dlen = ROUNDUP(sa->sa_len);
                    544:                if (cp) {
                    545:                        bcopy((caddr_t)sa, cp, (unsigned)dlen);
                    546:                        cp += dlen;
                    547:                }
                    548:                len += dlen;
                    549:        }
                    550:        if (cp == 0 && w != NULL && !second_time) {
                    551:                register struct walkarg *rw = w;
                    552: 
                    553:                rw->w_needed += len;
                    554:                if (rw->w_needed <= 0 && rw->w_where) {
                    555:                        if (rw->w_tmemsize < len) {
                    556:                                if (rw->w_tmem)
                    557:                                        _FREE(rw->w_tmem, M_RTABLE);
                    558:                                if (rw->w_tmem = (caddr_t)
                    559:                                                _MALLOC(len, M_RTABLE, M_NOWAIT))
                    560:                                        rw->w_tmemsize = len;
                    561:                        }
                    562:                        if (rw->w_tmem) {
                    563:                                cp = rw->w_tmem;
                    564:                                second_time = 1;
                    565:                                goto again;
                    566:                        } else
                    567:                                rw->w_where = 0;
                    568:                }
                    569:        }
                    570:        if (cp) {
                    571:                register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
                    572: 
                    573:                rtm->rtm_version = RTM_VERSION;
                    574:                rtm->rtm_type = type;
                    575:                rtm->rtm_msglen = len;
                    576:        }
                    577:        return (len);
                    578: }
                    579: 
                    580: /*
                    581:  * This routine is called to generate a message from the routing
                    582:  * socket indicating that a redirect has occured, a routing lookup
                    583:  * has failed, or that a protocol has detected timeouts to a particular
                    584:  * destination.
                    585:  */
                    586: void
                    587: rt_missmsg(type, rtinfo, flags, error)
                    588:        int type, flags, error;
                    589:        register struct rt_addrinfo *rtinfo;
                    590: {
                    591:        register struct rt_msghdr *rtm;
                    592:        register struct mbuf *m;
                    593:        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
                    594: 
                    595:        if (route_cb.any_count == 0)
                    596:                return;
                    597:        m = rt_msg1(type, rtinfo);
                    598:        if (m == 0)
                    599:                return;
                    600:        rtm = mtod(m, struct rt_msghdr *);
                    601:        rtm->rtm_flags = RTF_DONE | flags;
                    602:        rtm->rtm_errno = error;
                    603:        rtm->rtm_addrs = rtinfo->rti_addrs;
                    604:        route_proto.sp_protocol = sa ? sa->sa_family : 0;
                    605:        raw_input(m, &route_proto, &route_src, &route_dst);
                    606: }
                    607: 
                    608: /*
                    609:  * This routine is called to generate a message from the routing
                    610:  * socket indicating that the status of a network interface has changed.
                    611:  */
                    612: void
                    613: rt_ifmsg(ifp)
                    614:        register struct ifnet *ifp;
                    615: {
                    616:        register struct if_msghdr *ifm;
                    617:        struct mbuf *m;
                    618:        struct rt_addrinfo info;
                    619: 
                    620:        if (route_cb.any_count == 0)
                    621:                return;
                    622:        bzero((caddr_t)&info, sizeof(info));
                    623:        m = rt_msg1(RTM_IFINFO, &info);
                    624:        if (m == 0)
                    625:                return;
                    626:        ifm = mtod(m, struct if_msghdr *);
                    627:        ifm->ifm_index = ifp->if_index;
                    628:        ifm->ifm_flags = ifp->if_flags;
                    629:        ifm->ifm_data = ifp->if_data;
                    630:        ifm->ifm_addrs = 0;
                    631:        route_proto.sp_protocol = 0;
                    632:        raw_input(m, &route_proto, &route_src, &route_dst);
                    633: }
                    634: 
                    635: /*
                    636:  * This is called to generate messages from the routing socket
                    637:  * indicating a network interface has had addresses associated with it.
                    638:  * if we ever reverse the logic and replace messages TO the routing
                    639:  * socket indicate a request to configure interfaces, then it will
                    640:  * be unnecessary as the routing socket will automatically generate
                    641:  * copies of it.
                    642:  */
                    643: void
                    644: rt_newaddrmsg(cmd, ifa, error, rt)
                    645:        int cmd, error;
                    646:        register struct ifaddr *ifa;
                    647:        register struct rtentry *rt;
                    648: {
                    649:        struct rt_addrinfo info;
                    650:        struct sockaddr *sa;
                    651:        int pass;
                    652:        struct mbuf *m;
                    653:        struct ifnet *ifp = ifa->ifa_ifp;
                    654: 
                    655:        if (route_cb.any_count == 0)
                    656:                return;
                    657:        for (pass = 1; pass < 3; pass++) {
                    658:                bzero((caddr_t)&info, sizeof(info));
                    659:                if ((cmd == RTM_ADD && pass == 1) ||
                    660:                    (cmd == RTM_DELETE && pass == 2)) {
                    661:                        register struct ifa_msghdr *ifam;
                    662:                        int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
                    663: 
                    664:                        ifaaddr = sa = ifa->ifa_addr;
                    665:                        ifpaddr = ifp->if_addrlist->ifa_addr;
                    666:                        netmask = ifa->ifa_netmask;
                    667:                        brdaddr = ifa->ifa_dstaddr;
                    668:                        if ((m = rt_msg1(ncmd, &info)) == NULL)
                    669:                                continue;
                    670:                        ifam = mtod(m, struct ifa_msghdr *);
                    671:                        ifam->ifam_index = ifp->if_index;
                    672:                        ifam->ifam_metric = ifa->ifa_metric;
                    673:                        ifam->ifam_flags = ifa->ifa_flags;
                    674:                        ifam->ifam_addrs = info.rti_addrs;
                    675:                }
                    676:                if ((cmd == RTM_ADD && pass == 2) ||
                    677:                    (cmd == RTM_DELETE && pass == 1)) {
                    678:                        register struct rt_msghdr *rtm;
                    679:                        
                    680:                        if (rt == 0)
                    681:                                continue;
                    682:                        netmask = rt_mask(rt);
                    683:                        dst = sa = rt_key(rt);
                    684:                        gate = rt->rt_gateway;
                    685:                        if ((m = rt_msg1(cmd, &info)) == NULL)
                    686:                                continue;
                    687:                        rtm = mtod(m, struct rt_msghdr *);
                    688:                        rtm->rtm_index = ifp->if_index;
                    689:                        rtm->rtm_flags |= rt->rt_flags;
                    690:                        rtm->rtm_errno = error;
                    691:                        rtm->rtm_addrs = info.rti_addrs;
                    692:                }
                    693:                route_proto.sp_protocol = sa ? sa->sa_family : 0;
                    694:                raw_input(m, &route_proto, &route_src, &route_dst);
                    695:        }
                    696: }
                    697: 
                    698: /*
                    699:  * This is used in dumping the kernel table via sysctl().
                    700:  */
                    701: int
                    702: sysctl_dumpentry(rn, w)
                    703:        struct radix_node *rn;
                    704:        register struct walkarg *w;
                    705: {
                    706:        register struct rtentry *rt = (struct rtentry *)rn;
                    707:        int error = 0, size;
                    708:        struct rt_addrinfo info;
                    709: 
                    710:        if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
                    711:                return 0;
                    712:        bzero((caddr_t)&info, sizeof(info));
                    713:        dst = rt_key(rt);
                    714:        gate = rt->rt_gateway;
                    715:        netmask = rt_mask(rt);
                    716:        genmask = rt->rt_genmask;
                    717:        if (rt->rt_ifp) {
                    718:                ifpaddr = rt->rt_ifp->if_addrlist->ifa_addr;
                    719:                ifaaddr = rt->rt_ifa->ifa_addr;
                    720:                if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
                    721:                        brdaddr = rt->rt_ifa->ifa_dstaddr;
                    722:        }
                    723:        size = rt_msg2(RTM_GET, &info, 0, w);
                    724:        if (w->w_where && w->w_tmem) {
                    725:                register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
                    726: 
                    727:                rtm->rtm_flags = rt->rt_flags;
                    728:                rtm->rtm_use = rt->rt_use;
                    729:                rtm->rtm_rmx = rt->rt_rmx;
                    730:                rtm->rtm_index = rt->rt_ifp->if_index;
                    731:                rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
                    732:                rtm->rtm_addrs = info.rti_addrs;
                    733:                if (error = copyout((caddr_t)rtm, w->w_where, size))
                    734:                        w->w_where = NULL;
                    735:                else
                    736:                        w->w_where += size;
                    737:        }
                    738:        return (error);
                    739: }
                    740: 
                    741: int
                    742: sysctl_iflist(af, w)
                    743:        int     af;
                    744:        register struct walkarg *w;
                    745: {
                    746:        register struct ifnet *ifp;
                    747:        register struct ifaddr *ifa;
                    748:        struct  rt_addrinfo info;
                    749:        int     len, error = 0;
                    750: 
                    751:        bzero((caddr_t)&info, sizeof(info));
                    752:        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
                    753:                if (w->w_arg && w->w_arg != ifp->if_index)
                    754:                        continue;
                    755:                ifa = ifp->if_addrlist;
                    756:                ifpaddr = ifa->ifa_addr;
                    757:                len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
                    758:                ifpaddr = 0;
                    759:                if (w->w_where && w->w_tmem) {
                    760:                        register struct if_msghdr *ifm;
                    761: 
                    762:                        ifm = (struct if_msghdr *)w->w_tmem;
                    763:                        ifm->ifm_index = ifp->if_index;
                    764:                        ifm->ifm_flags = ifp->if_flags;
                    765:                        ifm->ifm_data = ifp->if_data;
                    766:                        ifm->ifm_addrs = info.rti_addrs;
                    767:                        if (error = copyout((caddr_t)ifm, w->w_where, len))
                    768:                                return (error);
                    769:                        w->w_where += len;
                    770:                }
                    771:                while (ifa = ifa->ifa_next) {
                    772:                        if (af && af != ifa->ifa_addr->sa_family)
                    773:                                continue;
                    774:                        ifaaddr = ifa->ifa_addr;
                    775:                        netmask = ifa->ifa_netmask;
                    776:                        brdaddr = ifa->ifa_dstaddr;
                    777:                        len = rt_msg2(RTM_NEWADDR, &info, 0, w);
                    778:                        if (w->w_where && w->w_tmem) {
                    779:                                register struct ifa_msghdr *ifam;
                    780: 
                    781:                                ifam = (struct ifa_msghdr *)w->w_tmem;
                    782:                                ifam->ifam_index = ifa->ifa_ifp->if_index;
                    783:                                ifam->ifam_flags = ifa->ifa_flags;
                    784:                                ifam->ifam_metric = ifa->ifa_metric;
                    785:                                ifam->ifam_addrs = info.rti_addrs;
                    786:                                if (error = copyout(w->w_tmem, w->w_where, len))
                    787:                                        return (error);
                    788:                                w->w_where += len;
                    789:                        }
                    790:                }
                    791:                ifaaddr = netmask = brdaddr = 0;
                    792:        }
                    793:        return (0);
                    794: }
                    795: 
                    796: int
                    797: sysctl_rtable(name, namelen, where, given, new, newlen)
                    798:        int     *name;
                    799:        int     namelen;
                    800:        caddr_t where;
                    801:        size_t  *given;
                    802:        caddr_t *new;
                    803:        size_t  newlen;
                    804: {
                    805:        register struct radix_node_head *rnh;
                    806:        int     i, s, error = EINVAL;
                    807:        u_char  af;
                    808:        struct  walkarg w;
                    809: 
                    810:        if (new)
                    811:                return (EPERM);
                    812:        if (namelen != 3)
                    813:                return (EINVAL);
                    814:        af = name[0];
                    815:        Bzero(&w, sizeof(w));
                    816:        w.w_where = where;
                    817:        w.w_given = *given;
                    818:        w.w_needed = 0 - w.w_given;
                    819:        w.w_op = name[1];
                    820:        w.w_arg = name[2];
                    821: 
                    822:        s = splnet();
                    823:        switch (w.w_op) {
                    824: 
                    825:        case NET_RT_DUMP:
                    826:        case NET_RT_FLAGS:
                    827:                for (i = 1; i <= AF_MAX; i++)
                    828:                        if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
                    829:                            (error = rnh->rnh_walktree(rnh,
                    830:                                                        sysctl_dumpentry, &w)))
                    831:                                break;
                    832:                break;
                    833: 
                    834:        case NET_RT_IFLIST:
                    835:                error = sysctl_iflist(af, &w);
                    836:        }
                    837:        splx(s);
                    838:        if (w.w_tmem)
                    839:                _FREE(w.w_tmem, M_RTABLE);
                    840:        w.w_needed += w.w_given;
                    841:        if (where) {
                    842:                *given = w.w_where - where;
                    843:                if (*given < w.w_needed)
                    844:                        return (ENOMEM);
                    845:        } else {
                    846:                *given = (11 * w.w_needed) / 10;
                    847:        }
                    848:        return (error);
                    849: }
                    850: 
                    851: /*
                    852:  * Definitions of protocols supported in the ROUTE domain.
                    853:  */
                    854: 
                    855: extern struct domain routedomain;              /* or at least forward */
                    856: 
                    857: struct protosw routesw[] = {
                    858: { SOCK_RAW,    &routedomain,   0,              PR_ATOMIC|PR_ADDR,
                    859:   raw_input,   route_output,   raw_ctlinput,   0,
                    860:   route_usrreq,
                    861:   raw_init,    0,              0,              0,
                    862:   sysctl_rtable,
                    863: }
                    864: };
                    865: 
                    866: struct domain routedomain =
                    867:     { PF_ROUTE, "route", route_init, 0, 0,
                    868:       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.