Annotation of XNU/bsd/netns/ns_ip.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1984, 1985, 1986, 1987, 1993
                     24:  *     The Regents of the University of California.  All rights reserved.
                     25:  *
                     26:  * Redistribution and use in source and binary forms, with or without
                     27:  * modification, are permitted provided that the following conditions
                     28:  * are met:
                     29:  * 1. Redistributions of source code must retain the above copyright
                     30:  *    notice, this list of conditions and the following disclaimer.
                     31:  * 2. Redistributions in binary form must reproduce the above copyright
                     32:  *    notice, this list of conditions and the following disclaimer in the
                     33:  *    documentation and/or other materials provided with the distribution.
                     34:  * 3. All advertising materials mentioning features or use of this software
                     35:  *    must display the following acknowledgement:
                     36:  *     This product includes software developed by the University of
                     37:  *     California, Berkeley and its contributors.
                     38:  * 4. Neither the name of the University nor the names of its contributors
                     39:  *    may be used to endorse or promote products derived from this software
                     40:  *    without specific prior written permission.
                     41:  *
                     42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     52:  * SUCH DAMAGE.
                     53:  *
                     54:  *     @(#)ns_ip.c     8.1 (Berkeley) 6/10/93
                     55:  */
                     56: 
                     57: /*
                     58:  * Software interface driver for encapsulating ns in ip.
                     59:  */
                     60: 
                     61: #ifdef NSIP
                     62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/malloc.h>
                     65: #include <sys/mbuf.h>
                     66: #include <sys/socket.h>
                     67: #include <sys/socketvar.h>
                     68: #include <sys/errno.h>
                     69: #include <sys/ioctl.h>
                     70: #include <sys/protosw.h>
                     71: 
                     72: #include <net/if.h>
                     73: #include <net/netisr.h>
                     74: #include <net/route.h>
                     75: 
                     76: #include <netinet/in.h>
                     77: #include <netinet/in_systm.h>
                     78: #include <netinet/in_var.h>
                     79: #include <netinet/ip.h>
                     80: #include <netinet/ip_var.h>
                     81: 
                     82: #include <machine/mtpr.h>
                     83: 
                     84: #include <netns/ns.h>
                     85: #include <netns/ns_if.h>
                     86: #include <netns/idp.h>
                     87: 
                     88: struct ifnet_en {
                     89:        struct ifnet ifen_ifnet;
                     90:        struct route ifen_route;
                     91:        struct in_addr ifen_src;
                     92:        struct in_addr ifen_dst;
                     93:        struct ifnet_en *ifen_next;
                     94: };
                     95: 
                     96: int    nsipoutput(), nsipioctl(), nsipstart();
                     97: #define LOMTU  (1024+512);
                     98: 
                     99: struct ifnet nsipif;
                    100: struct ifnet_en *nsip_list;            /* list of all hosts and gateways or
                    101:                                        broadcast addrs */
                    102: 
                    103: struct ifnet_en *
                    104: nsipattach()
                    105: {
                    106:        register struct ifnet_en *m;
                    107:        register struct ifnet *ifp;
                    108: 
                    109:        if (nsipif.if_mtu == 0) {
                    110:                ifp = &nsipif;
                    111:                ifp->if_name = "nsip";
                    112:                ifp->if_mtu = LOMTU;
                    113:                ifp->if_ioctl = nsipioctl;
                    114:                ifp->if_output = nsipoutput;
                    115:                ifp->if_start = nsipstart;
                    116:                ifp->if_flags = IFF_POINTOPOINT;
                    117:        }
                    118: 
                    119:        MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT);
                    120:        if (m == NULL) return (NULL);
                    121:        m->ifen_next = nsip_list;
                    122:        nsip_list = m;
                    123:        ifp = &m->ifen_ifnet;
                    124: 
                    125:        ifp->if_name = "nsip";
                    126:        ifp->if_mtu = LOMTU;
                    127:        ifp->if_ioctl = nsipioctl;
                    128:        ifp->if_output = nsipoutput;
                    129:        ifp->if_start = nsipstart;
                    130:        ifp->if_flags = IFF_POINTOPOINT;
                    131:        ifp->if_unit = nsipif.if_unit++;
                    132:        if_attach(ifp);
                    133: 
                    134:        return (m);
                    135: }
                    136: 
                    137: 
                    138: /*
                    139:  * Process an ioctl request.
                    140:  */
                    141: /* ARGSUSED */
                    142: nsipioctl(ifp, cmd, data)
                    143:        register struct ifnet *ifp;
                    144:        int cmd;
                    145:        caddr_t data;
                    146: {
                    147:        int error = 0;
                    148:        struct ifreq *ifr;
                    149: 
                    150:        switch (cmd) {
                    151: 
                    152:        case SIOCSIFADDR:
                    153:                ifp->if_flags |= IFF_UP;
                    154:                /* fall into: */
                    155: 
                    156:        case SIOCSIFDSTADDR:
                    157:                /*
                    158:                 * Everything else is done at a higher level.
                    159:                 */
                    160:                break;
                    161: 
                    162:        case SIOCSIFFLAGS:
                    163:                ifr = (struct ifreq *)data;
                    164:                if ((ifr->ifr_flags & IFF_UP) == 0)
                    165:                        error = nsip_free(ifp);
                    166: 
                    167: 
                    168:        default:
                    169:                error = EINVAL;
                    170:        }
                    171:        return (error);
                    172: }
                    173: 
                    174: struct mbuf *nsip_badlen;
                    175: struct mbuf *nsip_lastin;
                    176: int nsip_hold_input;
                    177: 
                    178: idpip_input(m, ifp)
                    179:        register struct mbuf *m;
                    180:        struct ifnet *ifp;
                    181: {
                    182:        register struct ip *ip;
                    183:        register struct idp *idp;
                    184:        register struct ifqueue *ifq = &nsintrq;
                    185:        int len, s;
                    186: 
                    187:        if (nsip_hold_input) {
                    188:                if (nsip_lastin) {
                    189:                        m_freem(nsip_lastin);
                    190:                }
                    191:                nsip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);
                    192:        }
                    193:        /*
                    194:         * Get IP and IDP header together in first mbuf.
                    195:         */
                    196:        nsipif.if_ipackets++;
                    197:        s = sizeof (struct ip) + sizeof (struct idp);
                    198:        if (((m->m_flags & M_EXT) || m->m_len < s) &&
                    199:            (m = m_pullup(m, s)) == 0) {
                    200:                nsipif.if_ierrors++;
                    201:                return;
                    202:        }
                    203:        ip = mtod(m, struct ip *);
                    204:        if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
                    205:                ip_stripoptions(m, (struct mbuf *)0);
                    206:                if (m->m_len < s) {
                    207:                        if ((m = m_pullup(m, s)) == 0) {
                    208:                                nsipif.if_ierrors++;
                    209:                                return;
                    210:                        }
                    211:                        ip = mtod(m, struct ip *);
                    212:                }
                    213:        }
                    214: 
                    215:        /*
                    216:         * Make mbuf data length reflect IDP length.
                    217:         * If not enough data to reflect IDP length, drop.
                    218:         */
                    219:        m->m_data += sizeof (struct ip);
                    220:        m->m_len -= sizeof (struct ip);
                    221:        m->m_pkthdr.len -= sizeof (struct ip);
                    222:        idp = mtod(m, struct idp *);
                    223:        len = ntohs(idp->idp_len);
                    224:        if (len & 1) len++;             /* Preserve Garbage Byte */
                    225:        if (ip->ip_len != len) {
                    226:                if (len > ip->ip_len) {
                    227:                        nsipif.if_ierrors++;
                    228:                        if (nsip_badlen) m_freem(nsip_badlen);
                    229:                        nsip_badlen = m;
                    230:                        return;
                    231:                }
                    232:                /* Any extra will be trimmed off by the NS routines */
                    233:        }
                    234: 
                    235:        /*
                    236:         * Place interface pointer before the data
                    237:         * for the receiving protocol.
                    238:         */
                    239:        m->m_pkthdr.rcvif = ifp;
                    240:        /*
                    241:         * Deliver to NS
                    242:         */
                    243:        s = splimp();
                    244:        if (IF_QFULL(ifq)) {
                    245:                IF_DROP(ifq);
                    246: bad:
                    247:                m_freem(m);
                    248:                splx(s);
                    249:                return;
                    250:        }
                    251:        IF_ENQUEUE(ifq, m);
                    252:        schednetisr(NETISR_NS);
                    253:        splx(s);
                    254:        return;
                    255: }
                    256: 
                    257: /* ARGSUSED */
                    258: nsipoutput(ifn, m, dst)
                    259:        struct ifnet_en *ifn;
                    260:        register struct mbuf *m;
                    261:        struct sockaddr *dst;
                    262: {
                    263: 
                    264:        register struct ip *ip;
                    265:        register struct route *ro = &(ifn->ifen_route);
                    266:        register int len = 0;
                    267:        register struct idp *idp = mtod(m, struct idp *);
                    268:        int error;
                    269: 
                    270:        ifn->ifen_ifnet.if_opackets++;
                    271:        nsipif.if_opackets++;
                    272: 
                    273: 
                    274:        /*
                    275:         * Calculate data length and make space
                    276:         * for IP header.
                    277:         */
                    278:        len =  ntohs(idp->idp_len);
                    279:        if (len & 1) len++;             /* Preserve Garbage Byte */
                    280:        /* following clause not necessary on vax */
                    281:        if (3 & (int)m->m_data) {
                    282:                /* force longword alignment of ip hdr */
                    283:                struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);
                    284:                if (m0 == 0) {
                    285:                        m_freem(m);
                    286:                        return (ENOBUFS);
                    287:                }
                    288:                MH_ALIGN(m0, sizeof (struct ip));
                    289:                m0->m_flags = m->m_flags & M_COPYFLAGS;
                    290:                m0->m_next = m;
                    291:                m0->m_len = sizeof (struct ip);
                    292:                m0->m_pkthdr.len = m0->m_len + m->m_len;
                    293:                m->m_flags &= ~M_PKTHDR;
                    294:        } else {
                    295:                M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);
                    296:                if (m == 0)
                    297:                        return (ENOBUFS);
                    298:        }
                    299:        /*
                    300:         * Fill in IP header.
                    301:         */
                    302:        ip = mtod(m, struct ip *);
                    303:        *(long *)ip = 0;
                    304:        ip->ip_p = IPPROTO_IDP;
                    305:        ip->ip_src = ifn->ifen_src;
                    306:        ip->ip_dst = ifn->ifen_dst;
                    307:        ip->ip_len = (u_short)len + sizeof (struct ip);
                    308:        ip->ip_ttl = MAXTTL;
                    309: 
                    310:        /*
                    311:         * Output final datagram.
                    312:         */
                    313:        error =  (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST, NULL));
                    314:        if (error) {
                    315:                ifn->ifen_ifnet.if_oerrors++;
                    316:                ifn->ifen_ifnet.if_ierrors = error;
                    317:        }
                    318:        return (error);
                    319: bad:
                    320:        m_freem(m);
                    321:        return (ENETUNREACH);
                    322: }
                    323: 
                    324: nsipstart(ifp)
                    325: struct ifnet *ifp;
                    326: {
                    327:        panic("nsip_start called\n");
                    328: }
                    329: 
                    330: struct ifreq ifr = {"nsip0"};
                    331: 
                    332: nsip_route(m)
                    333:        register struct mbuf *m;
                    334: {
                    335:        register struct nsip_req *rq = mtod(m, struct nsip_req *);
                    336:        struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
                    337:        struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
                    338:        struct route ro;
                    339:        struct ifnet_en *ifn;
                    340:        struct sockaddr_in *src;
                    341: 
                    342:        /*
                    343:         * First, make sure we already have an ns address:
                    344:         */
                    345:        if (ns_hosteqnh(ns_thishost, ns_zerohost))
                    346:                return (EADDRNOTAVAIL);
                    347:        /*
                    348:         * Now, determine if we can get to the destination
                    349:         */
                    350:        bzero((caddr_t)&ro, sizeof (ro));
                    351:        ro.ro_dst = *(struct sockaddr *)ip_dst;
                    352:        rtalloc(&ro);
                    353:        if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
                    354:                return (ENETUNREACH);
                    355:        }
                    356: 
                    357:        /*
                    358:         * And see how he's going to get back to us:
                    359:         * i.e., what return ip address do we use?
                    360:         */
                    361:        {
                    362:                register struct in_ifaddr *ia;
                    363:                struct ifnet *ifp = ro.ro_rt->rt_ifp;
                    364: 
                    365:                for (ia = in_ifaddr; ia; ia = ia->ia_next)
                    366:                        if (ia->ia_ifp == ifp)
                    367:                                break;
                    368:                if (ia == 0)
                    369:                        ia = in_ifaddr;
                    370:                if (ia == 0) {
                    371:                        RTFREE(ro.ro_rt);
                    372:                        return (EADDRNOTAVAIL);
                    373:                }
                    374:                src = (struct sockaddr_in *)&ia->ia_addr;
                    375:        }
                    376: 
                    377:        /*
                    378:         * Is there a free (pseudo-)interface or space?
                    379:         */
                    380:        for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
                    381:                if ((ifn->ifen_ifnet.if_flags & IFF_UP) == 0)
                    382:                        break;
                    383:        }
                    384:        if (ifn == NULL)
                    385:                ifn = nsipattach();
                    386:        if (ifn == NULL) {
                    387:                RTFREE(ro.ro_rt);
                    388:                return (ENOBUFS);
                    389:        }
                    390:        ifn->ifen_route = ro;
                    391:        ifn->ifen_dst =  ip_dst->sin_addr;
                    392:        ifn->ifen_src = src->sin_addr;
                    393: 
                    394:        /*
                    395:         * now configure this as a point to point link
                    396:         */
                    397:        ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
                    398:        ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
                    399:        (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr,
                    400:                        (struct ifnet *)ifn);
                    401:        satons_addr(ifr.ifr_addr).x_host = ns_thishost;
                    402:        return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,
                    403:                        (struct ifnet *)ifn));
                    404: }
                    405: 
                    406: nsip_free(ifp)
                    407: struct ifnet *ifp;
                    408: {
                    409:        register struct ifnet_en *ifn = (struct ifnet_en *)ifp;
                    410:        struct route *ro = & ifn->ifen_route;
                    411: 
                    412:        if (ro->ro_rt) {
                    413:                RTFREE(ro->ro_rt);
                    414:                ro->ro_rt = 0;
                    415:        }
                    416:        ifp->if_flags &= ~IFF_UP;
                    417:        return (0);
                    418: }
                    419: 
                    420: nsip_ctlinput(cmd, sa)
                    421:        int cmd;
                    422:        struct sockaddr *sa;
                    423: {
                    424:        extern u_char inetctlerrmap[];
                    425:        struct sockaddr_in *sin;
                    426:        int in_rtchange();
                    427: 
                    428:        if ((unsigned)cmd >= PRC_NCMDS)
                    429:                return;
                    430:        if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
                    431:                return;
                    432:        sin = (struct sockaddr_in *)sa;
                    433:        if (sin->sin_addr.s_addr == INADDR_ANY)
                    434:                return;
                    435: 
                    436:        switch (cmd) {
                    437: 
                    438:        case PRC_ROUTEDEAD:
                    439:        case PRC_REDIRECT_NET:
                    440:        case PRC_REDIRECT_HOST:
                    441:        case PRC_REDIRECT_TOSNET:
                    442:        case PRC_REDIRECT_TOSHOST:
                    443:                nsip_rtchange(&sin->sin_addr);
                    444:                break;
                    445:        }
                    446: }
                    447: 
                    448: nsip_rtchange(dst)
                    449:        register struct in_addr *dst;
                    450: {
                    451:        register struct ifnet_en *ifn;
                    452: 
                    453:        for (ifn = nsip_list; ifn; ifn = ifn->ifen_next) {
                    454:                if (ifn->ifen_dst.s_addr == dst->s_addr &&
                    455:                        ifn->ifen_route.ro_rt) {
                    456:                                RTFREE(ifn->ifen_route.ro_rt);
                    457:                                ifn->ifen_route.ro_rt = 0;
                    458:                }
                    459:        }
                    460: }
                    461: #endif

unix.superglobalmegacorp.com

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