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
nsip_route defined in line 287; never used
nsip_rtchange defined in line 406; used 1 times
nsipattach defined in line 61; used 1 times
nsipioctl defined in line 89; used 2 times
nsipoutput defined in line 219; used 2 times

Defined variables

ifr defined in line 285; used 8 times
nsip_badlen defined in line 121; used 3 times
nsip_hold_input defined in line 123; used 1 times
nsip_lastin defined in line 122; used 3 times
nsip_list defined in line 58; used 4 times
nsipif defined in line 57; used 7 times

Defined struct's

ifnet_en defined in line 47; used 18 times

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: 3916
Valid CSS Valid XHTML 1.0 Strict