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:  *      @(#)idp_usrreq.c	7.2 (Berkeley) 1/20/88
  13:  */
  14: 
  15: #include "param.h"
  16: #ifdef  NS
  17: #include "user.h"
  18: #include "mbuf.h"
  19: #include "protosw.h"
  20: #include "socket.h"
  21: #include "socketvar.h"
  22: #include "errno.h"
  23: #include "stat.h"
  24: 
  25: #include "../net/if.h"
  26: #include "../net/route.h"
  27: 
  28: #include "ns.h"
  29: #include "ns_pcb.h"
  30: #include "ns_if.h"
  31: #include "idp.h"
  32: #include "idp_var.h"
  33: #include "ns_error.h"
  34: 
  35: /*
  36:  * IDP protocol implementation.
  37:  */
  38: 
  39: struct  sockaddr_ns idp_ns = { AF_NS };
  40: 
  41: /*
  42:  *  This may also be called for raw listeners.
  43:  */
  44: idp_input(m, nsp, ifp)
  45:     struct mbuf *m;
  46:     register struct nspcb *nsp;
  47:     struct ifnet *ifp;
  48: {
  49:     register struct idp *idp = mtod(m, struct idp *);
  50: 
  51:     if (nsp==0)
  52:         panic("No nspcb");
  53:     /*
  54: 	 * Construct sockaddr format source address.
  55: 	 * Stuff source address and datagram in user buffer.
  56: 	 */
  57:     idp_ns.sns_addr = idp->idp_sna;
  58:     if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
  59:         register struct ifaddr *ia;
  60: 
  61:         for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) {
  62:             if (ia->ifa_addr.sa_family == AF_NS) {
  63:                 idp_ns.sns_addr.x_net =
  64:                     IA_SNS(ia)->sns_addr.x_net;
  65:                 break;
  66:             }
  67:         }
  68:     }
  69:     nsp->nsp_rpt = idp->idp_pt;
  70:     if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
  71:         m->m_len -= sizeof (struct idp);
  72:         m->m_off += sizeof (struct idp);
  73:     }
  74:     if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
  75:         m, (struct mbuf *)0) == 0)
  76:         goto bad;
  77:     sorwakeup(nsp->nsp_socket);
  78:     return;
  79: bad:
  80:     m_freem(m);
  81: }
  82: 
  83: idp_abort(nsp)
  84:     struct nspcb *nsp;
  85: {
  86:     struct socket *so = nsp->nsp_socket;
  87: 
  88:     ns_pcbdisconnect(nsp);
  89:     soisdisconnected(so);
  90: }
  91: /*
  92:  * Drop connection, reporting
  93:  * the specified error.
  94:  */
  95: struct nspcb *
  96: idp_drop(nsp, errno)
  97:     register struct nspcb *nsp;
  98:     int errno;
  99: {
 100:     struct socket *so = nsp->nsp_socket;
 101: 
 102:     /*
 103: 	 * someday, in the xerox world
 104: 	 * we will generate error protocol packets
 105: 	 * announcing that the socket has gone away.
 106: 	 */
 107:     /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
 108: 		tp->t_state = TCPS_CLOSED;
 109: 		(void) tcp_output(tp);
 110: 	}*/
 111:     so->so_error = errno;
 112:     ns_pcbdisconnect(nsp);
 113:     soisdisconnected(so);
 114: }
 115: 
 116: int noIdpRoute;
 117: idp_output(nsp, m0)
 118:     struct nspcb *nsp;
 119:     struct mbuf *m0;
 120: {
 121:     register struct mbuf *m;
 122:     register struct idp *idp;
 123:     register struct socket *so;
 124:     register int len = 0;
 125:     register struct route *ro;
 126:     struct mbuf *mprev;
 127:     extern int idpcksum;
 128: 
 129:     /*
 130: 	 * Calculate data length.
 131: 	 */
 132:     for (m = m0; m; m = m->m_next) {
 133:         mprev = m;
 134:         len += m->m_len;
 135:     }
 136:     /*
 137: 	 * Make sure packet is actually of even length.
 138: 	 */
 139: 
 140:     if (len & 1) {
 141:         m = mprev;
 142:         if (m->m_len + m->m_off < MMAXOFF) {
 143:             m->m_len++;
 144:         } else {
 145:             struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
 146: 
 147:             if (m1 == 0) {
 148:                 m_freem(m0);
 149:                 return (ENOBUFS);
 150:             }
 151:             m1->m_len = 1;
 152:             m1->m_off = MMAXOFF - 1;
 153:             * mtod(m1, char *) = 0;
 154:             m->m_next = m1;
 155:         }
 156:     }
 157: 
 158:     /*
 159: 	 * Fill in mbuf with extended IDP header
 160: 	 * and addresses and length put into network format.
 161: 	 */
 162:     if (nsp->nsp_flags & NSP_RAWOUT) {
 163:         m = m0;
 164:         idp = mtod(m, struct idp *);
 165:     } else {
 166:         m = m_get(M_DONTWAIT, MT_HEADER);
 167:         if (m == 0) {
 168:             m_freem(m0);
 169:             return (ENOBUFS);
 170:         }
 171:         m->m_off = MMAXOFF - sizeof (struct idp) - 2;
 172:                 /* adjust to start on longword bdry
 173: 				   for NSIP on gould */
 174:         m->m_len = sizeof (struct idp);
 175:         m->m_next = m0;
 176:         idp = mtod(m, struct idp *);
 177:         idp->idp_tc = 0;
 178:         idp->idp_pt = nsp->nsp_dpt;
 179:         idp->idp_sna = nsp->nsp_laddr;
 180:         idp->idp_dna = nsp->nsp_faddr;
 181:         len += sizeof (struct idp);
 182:     }
 183: 
 184:     idp->idp_len = htons((u_short)len);
 185: 
 186:     if (idpcksum) {
 187:         idp->idp_sum = 0;
 188:         len = ((len - 1) | 1) + 1;
 189:         idp->idp_sum = ns_cksum(m, len);
 190:     } else
 191:         idp->idp_sum = 0xffff;
 192: 
 193:     /*
 194: 	 * Output datagram.
 195: 	 */
 196:     so = nsp->nsp_socket;
 197:     if (so->so_options & SO_DONTROUTE)
 198:         return (ns_output(m, (struct route *)0,
 199:             (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
 200:     /*
 201: 	 * Use cached route for previous datagram if
 202: 	 * possible.  If the previous net was the same
 203: 	 * and the interface was a broadcast medium, or
 204: 	 * if the previous destination was identical,
 205: 	 * then we are ok.
 206: 	 *
 207: 	 * NB: We don't handle broadcasts because that
 208: 	 *     would require 3 subroutine calls.
 209: 	 */
 210:     ro = &nsp->nsp_route;
 211: #ifdef ancient_history
 212:     /*
 213: 	 * I think that this will all be handled in ns_pcbconnect!
 214: 	 */
 215:     if (ro->ro_rt) {
 216:         if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) {
 217:             /*
 218: 			 * This assumes we have no GH type routes
 219: 			 */
 220:             if (ro->ro_rt->rt_flags & RTF_HOST) {
 221:                 if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna))
 222:                     goto re_route;
 223: 
 224:             }
 225:             if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
 226:                 register struct ns_addr *dst =
 227:                         &satons_addr(ro->ro_dst);
 228:                 dst->x_host = idp->idp_dna.x_host;
 229:             }
 230:             /*
 231: 			 * Otherwise, we go through the same gateway
 232: 			 * and dst is already set up.
 233: 			 */
 234:         } else {
 235:         re_route:
 236:             RTFREE(ro->ro_rt);
 237:             ro->ro_rt = (struct rtentry *)0;
 238:         }
 239:     }
 240:     nsp->nsp_lastdst = idp->idp_dna;
 241: #endif ancient_history
 242:     if (noIdpRoute) ro = 0;
 243:     return (ns_output(m, ro, so->so_options & SO_BROADCAST));
 244: }
 245: /* ARGSUSED */
 246: idp_ctloutput(req, so, level, name, value)
 247:     int req, level;
 248:     struct socket *so;
 249:     int name;
 250:     struct mbuf **value;
 251: {
 252:     register struct mbuf *m;
 253:     struct nspcb *nsp = sotonspcb(so);
 254:     int mask, error = 0;
 255:     extern long ns_pexseq;
 256: 
 257:     if (nsp == NULL)
 258:         return (EINVAL);
 259: 
 260:     switch (req) {
 261: 
 262:     case PRCO_GETOPT:
 263:         if (value==NULL)
 264:             return (EINVAL);
 265:         m = m_get(M_DONTWAIT, MT_DATA);
 266:         if (m==NULL)
 267:             return (ENOBUFS);
 268:         switch (name) {
 269: 
 270:         case SO_ALL_PACKETS:
 271:             mask = NSP_ALL_PACKETS;
 272:             goto get_flags;
 273: 
 274:         case SO_HEADERS_ON_INPUT:
 275:             mask = NSP_RAWIN;
 276:             goto get_flags;
 277: 
 278:         case SO_HEADERS_ON_OUTPUT:
 279:             mask = NSP_RAWOUT;
 280:         get_flags:
 281:             m->m_len = sizeof(short);
 282:             m->m_off = MMAXOFF - sizeof(short);
 283:             *mtod(m, short *) = nsp->nsp_flags & mask;
 284:             break;
 285: 
 286:         case SO_DEFAULT_HEADERS:
 287:             m->m_len = sizeof(struct idp);
 288:             m->m_off = MMAXOFF - sizeof(struct idp);
 289:             {
 290:                 register struct idp *idp = mtod(m, struct idp *);
 291:                 idp->idp_len = 0;
 292:                 idp->idp_sum = 0;
 293:                 idp->idp_tc = 0;
 294:                 idp->idp_pt = nsp->nsp_dpt;
 295:                 idp->idp_dna = nsp->nsp_faddr;
 296:                 idp->idp_sna = nsp->nsp_laddr;
 297:             }
 298:             break;
 299: 
 300:         case SO_SEQNO:
 301:             m->m_len = sizeof(long);
 302:             m->m_off = MMAXOFF - sizeof(long);
 303:             *mtod(m, long *) = ns_pexseq++;
 304:             break;
 305: 
 306:         default:
 307:             error = EINVAL;
 308:         }
 309:         *value = m;
 310:         break;
 311: 
 312:     case PRCO_SETOPT:
 313:         switch (name) {
 314:             int *ok;
 315: 
 316:         case SO_ALL_PACKETS:
 317:             mask = NSP_ALL_PACKETS;
 318:             goto set_head;
 319: 
 320:         case SO_HEADERS_ON_INPUT:
 321:             mask = NSP_RAWIN;
 322:             goto set_head;
 323: 
 324:         case SO_HEADERS_ON_OUTPUT:
 325:             mask = NSP_RAWOUT;
 326:         set_head:
 327:             if (value && *value) {
 328:                 ok = mtod(*value, int *);
 329:                 if (*ok)
 330:                     nsp->nsp_flags |= mask;
 331:                 else
 332:                     nsp->nsp_flags &= ~mask;
 333:             } else error = EINVAL;
 334:             break;
 335: 
 336:         case SO_DEFAULT_HEADERS:
 337:             {
 338:                 register struct idp *idp
 339:                     = mtod(*value, struct idp *);
 340:                 nsp->nsp_dpt = idp->idp_pt;
 341:             }
 342:             break;
 343: #ifdef NSIP
 344: 
 345:         case SO_NSIP_ROUTE:
 346:             error = nsip_route(*value);
 347:             break;
 348: #endif NSIP
 349:         default:
 350:             error = EINVAL;
 351:         }
 352:         if (value && *value)
 353:             m_freem(*value);
 354:         break;
 355:     }
 356:     return (error);
 357: }
 358: 
 359: /*ARGSUSED*/
 360: idp_usrreq(so, req, m, nam, rights)
 361:     struct socket *so;
 362:     int req;
 363:     struct mbuf *m, *nam, *rights;
 364: {
 365:     struct nspcb *nsp = sotonspcb(so);
 366:     int error = 0;
 367: 
 368:     if (req == PRU_CONTROL)
 369:                 return (ns_control(so, (int)m, (caddr_t)nam,
 370:             (struct ifnet *)rights));
 371:     if (rights && rights->m_len) {
 372:         error = EINVAL;
 373:         goto release;
 374:     }
 375:     if (nsp == NULL && req != PRU_ATTACH) {
 376:         error = EINVAL;
 377:         goto release;
 378:     }
 379:     switch (req) {
 380: 
 381:     case PRU_ATTACH:
 382:         if (nsp != NULL) {
 383:             error = EINVAL;
 384:             break;
 385:         }
 386:         error = ns_pcballoc(so, &nspcb);
 387:         if (error)
 388:             break;
 389:         error = soreserve(so, 2048, 2048);
 390:         if (error)
 391:             break;
 392:         break;
 393: 
 394:     case PRU_DETACH:
 395:         if (nsp == NULL) {
 396:             error = ENOTCONN;
 397:             break;
 398:         }
 399:         ns_pcbdetach(nsp);
 400:         break;
 401: 
 402:     case PRU_BIND:
 403:         error = ns_pcbbind(nsp, nam);
 404:         break;
 405: 
 406:     case PRU_LISTEN:
 407:         error = EOPNOTSUPP;
 408:         break;
 409: 
 410:     case PRU_CONNECT:
 411:         if (!ns_nullhost(nsp->nsp_faddr)) {
 412:             error = EISCONN;
 413:             break;
 414:         }
 415:         error = ns_pcbconnect(nsp, nam);
 416:         if (error == 0)
 417:             soisconnected(so);
 418:         break;
 419: 
 420:     case PRU_CONNECT2:
 421:         error = EOPNOTSUPP;
 422:         break;
 423: 
 424:     case PRU_ACCEPT:
 425:         error = EOPNOTSUPP;
 426:         break;
 427: 
 428:     case PRU_DISCONNECT:
 429:         if (ns_nullhost(nsp->nsp_faddr)) {
 430:             error = ENOTCONN;
 431:             break;
 432:         }
 433:         ns_pcbdisconnect(nsp);
 434:         soisdisconnected(so);
 435:         break;
 436: 
 437:     case PRU_SHUTDOWN:
 438:         socantsendmore(so);
 439:         break;
 440: 
 441:     case PRU_SEND:
 442:     {
 443:         struct ns_addr laddr;
 444:         int s;
 445: 
 446:         if (nam) {
 447:             laddr = nsp->nsp_laddr;
 448:             if (!ns_nullhost(nsp->nsp_faddr)) {
 449:                 error = EISCONN;
 450:                 break;
 451:             }
 452:             /*
 453: 			 * Must block input while temporarily connected.
 454: 			 */
 455:             s = splnet();
 456:             error = ns_pcbconnect(nsp, nam);
 457:             if (error) {
 458:                 splx(s);
 459:                 break;
 460:             }
 461:         } else {
 462:             if (ns_nullhost(nsp->nsp_faddr)) {
 463:                 error = ENOTCONN;
 464:                 break;
 465:             }
 466:         }
 467:         error = idp_output(nsp, m);
 468:         m = NULL;
 469:         if (nam) {
 470:             ns_pcbdisconnect(nsp);
 471:             splx(s);
 472:             nsp->nsp_laddr.x_host = laddr.x_host;
 473:             nsp->nsp_laddr.x_port = laddr.x_port;
 474:         }
 475:     }
 476:         break;
 477: 
 478:     case PRU_ABORT:
 479:         ns_pcbdetach(nsp);
 480:         sofree(so);
 481:         soisdisconnected(so);
 482:         break;
 483: 
 484:     case PRU_SOCKADDR:
 485:         ns_setsockaddr(nsp, nam);
 486:         break;
 487: 
 488:     case PRU_PEERADDR:
 489:         ns_setpeeraddr(nsp, nam);
 490:         break;
 491: 
 492:     case PRU_SENSE:
 493:         /*
 494: 		 * stat: don't bother with a blocksize.
 495: 		 */
 496:         return (0);
 497: 
 498:     case PRU_SENDOOB:
 499:     case PRU_FASTTIMO:
 500:     case PRU_SLOWTIMO:
 501:     case PRU_PROTORCV:
 502:     case PRU_PROTOSEND:
 503:         error =  EOPNOTSUPP;
 504:         break;
 505: 
 506:     case PRU_CONTROL:
 507:     case PRU_RCVD:
 508:     case PRU_RCVOOB:
 509:         return (EOPNOTSUPP);    /* do not free mbuf's */
 510: 
 511:     default:
 512:         panic("idp_usrreq");
 513:     }
 514: release:
 515:     if (m != NULL)
 516:         m_freem(m);
 517:     return (error);
 518: }
 519: /*ARGSUSED*/
 520: idp_raw_usrreq(so, req, m, nam, rights)
 521:     struct socket *so;
 522:     int req;
 523:     struct mbuf *m, *nam, *rights;
 524: {
 525:     int error = 0;
 526:     struct nspcb *nsp = sotonspcb(so);
 527:     extern struct nspcb nsrawpcb;
 528: 
 529:     switch (req) {
 530: 
 531:     case PRU_ATTACH:
 532: 
 533:         if (!suser() || (nsp != NULL)) {
 534:             error = EINVAL;
 535:             break;
 536:         }
 537:         error = ns_pcballoc(so, &nsrawpcb);
 538:         if (error)
 539:             break;
 540:         error = soreserve(so, 2048, 2048);
 541:         if (error)
 542:             break;
 543:         nsp = sotonspcb(so);
 544:         nsp->nsp_faddr.x_host = ns_broadhost;
 545:         nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
 546:         break;
 547:     default:
 548:         error = idp_usrreq(so, req, m, nam, rights);
 549:     }
 550:     return (error);
 551: }
 552: #endif

Defined functions

idp_abort defined in line 83; never used
idp_ctloutput defined in line 246; never used
idp_drop defined in line 95; never used
idp_input defined in line 44; never used
idp_output defined in line 117; used 1 times
idp_raw_usrreq defined in line 520; never used
idp_usrreq defined in line 360; used 1 times

Defined variables

idp_ns defined in line 39; used 3 times
noIdpRoute defined in line 116; used 1 times
Last modified: 1988-04-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3886
Valid CSS Valid XHTML 1.0 Strict