Annotation of 43BSDReno/sys/netns/ns_ip.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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