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

Defined functions

idp_abort defined in line 77; used 2 times
idp_ctloutput defined in line 240; used 5 times
idp_drop defined in line 89; used 4 times
idp_input defined in line 38; used 5 times
idp_output defined in line 111; used 5 times
idp_raw_usrreq defined in line 514; used 3 times
idp_usrreq defined in line 354; used 3 times

Defined variables

idp_ns defined in line 33; used 3 times
noIdpRoute defined in line 110; used 1 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1776
Valid CSS Valid XHTML 1.0 Strict