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