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

Defined functions

idpip_input defined in line 119; used 2 times
nsip_ctlinput defined in line 372; used 2 times
nsip_free defined in line 358; used 1 times
nsip_route defined in line 281; used 1 times
nsip_rtchange defined in line 400; used 1 times
nsipattach defined in line 55; used 1 times
nsipioctl defined in line 83; used 2 times
nsipoutput defined in line 213; used 2 times

Defined variables

ifr defined in line 279; used 8 times
nsip_badlen defined in line 115; used 3 times
nsip_hold_input defined in line 117; used 1 times
nsip_lastin defined in line 116; used 3 times
nsip_list defined in line 52; used 4 times
nsipif defined in line 51; used 7 times

Defined struct's

ifnet_en defined in line 41; used 18 times

Defined macros

LOMTU defined in line 49; used 1 times
  • in line 69
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1530
Valid CSS Valid XHTML 1.0 Strict