# 2.11BSD#431 - /usr/src/sys/netns/ns_ip.c

##### Functions

    idpip_input       X
    nsip_ctlinput     X
    nsip_free         X
    nsip_route        X
    nsip_rtchange     X
    nsipattach        X
    nsipioctl         X
    nsipoutput        X

##### Variables

    ifr               X
    nsip_badlen       X
    nsip_hold_input   X
    nsip_lastin       X
    nsip_list         X
    nsipif            X

##### Macros

    LOMTU             X

##### struct's

    ifnet_en          X

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

#### Defined functions

idpip_input defined in line 125; never used
nsip_ctlinput defined in line 378; never used
nsip_free defined in line 364; used 1 times

- in line 112

nsip_route defined in line 287; never used
nsip_rtchange defined in line 406; used 1 times

- in line 401

nsipattach defined in line 61; used 1 times

- in line 341

nsipioctl defined in line 89; used 2 times

- in line 54, 76

nsipoutput defined in line 219; used 2 times

- in line 54, 77

#### Defined variables

ifr defined in line 285; used 8 times

- in line 95, 110-111(2), 355-360(5)

nsip_badlen defined in line 121; used 3 times

- in line 174-175(3)

nsip_hold_input defined in line 123; used 1 times

- in line 134

nsip_lastin defined in line 122; used 3 times

- in line 135-138(3)

nsip_list defined in line 58; used 4 times

- in line 70-71(2), 335, 412

nsipif defined in line 57; used 7 times

- in line 79, 143-147(2), 155, 173, 237, 355

#### Defined struct's

ifnet_en defined in line 47; used 18 times

- in line 69(2), 220(2), 232(2), 294(2), 346(2), 367(4), 410-413(4)

#### Defined macros

LOMTU defined in line 55; used 1 times

- in line 75

Last modified: 1988-04-29 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1257 |