1: /*
   2:  * Copyright (c) 1982, 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:  *	@(#)uipc_usrreq.c	7.1.2 (2.11BSD GTE) 1997/1/18
   7:  */
   8: 
   9: #include "param.h"
  10: #include "user.h"
  11: #include "mbuf.h"
  12: #include "domain.h"
  13: #include "protosw.h"
  14: #include "socket.h"
  15: #include "socketvar.h"
  16: #include "unpcb.h"
  17: #include "un.h"
  18: #include "inode.h"
  19: #include "file.h"
  20: #include "stat.h"
  21: 
  22: /*
  23:  * Unix communications domain.
  24:  *
  25:  * TODO:
  26:  *	SEQPACKET, RDM
  27:  *	rethink name space problems
  28:  *	need a proper out-of-band
  29:  */
  30: struct sockaddr sun_noname = { AF_UNIX };
  31: ino_t unp_ino;          /* prototype for fake inode numbers */
  32: 
  33: extern void unpdisc(), unpgc1();
  34: extern int fadjust();
  35: 
  36: /*ARGSUSED*/
  37: uipc_usrreq(so, req, m, nam, rights)
  38:     struct socket *so;
  39:     int req;
  40:     struct mbuf *m, *nam, *rights;
  41: {
  42:     struct unpcb *unp = sotounpcb(so);
  43:     register struct socket *so2;
  44:     int error = 0;
  45: 
  46:     if (req == PRU_CONTROL)
  47:         return (EOPNOTSUPP);
  48:     if (req != PRU_SEND && rights && rights->m_len) {
  49:         error = EOPNOTSUPP;
  50:         goto release;
  51:     }
  52:     if (unp == 0 && req != PRU_ATTACH) {
  53:         error = EINVAL;
  54:         goto release;
  55:     }
  56:     switch (req) {
  57: 
  58:     case PRU_ATTACH:
  59:         if (unp) {
  60:             error = EISCONN;
  61:             break;
  62:         }
  63:         error = unp_attach(so);
  64:         break;
  65: 
  66:     case PRU_DETACH:
  67:         unp_detach(unp);
  68:         break;
  69: 
  70:     case PRU_BIND:
  71:         error = unp_bind(unp, nam);
  72:         break;
  73: 
  74:     case PRU_LISTEN:
  75:         if (unp->unp_inode == 0)
  76:             error = EINVAL;
  77:         break;
  78: 
  79:     case PRU_CONNECT:
  80:         error = unp_connect(so, nam);
  81:         break;
  82: 
  83:     case PRU_CONNECT2:
  84:         error = unp_connect2(so, (struct socket *)nam);
  85:         break;
  86: 
  87:     case PRU_DISCONNECT:
  88:         unp_disconnect(unp);
  89:         break;
  90: 
  91:     case PRU_ACCEPT:
  92:         /*
  93: 		 * Pass back name of connected socket,
  94: 		 * if it was bound and we are still connected
  95: 		 * (our peer may have closed already!).
  96: 		 */
  97:         if (unp->unp_conn && unp->unp_conn->unp_addr) {
  98:             nam->m_len = unp->unp_conn->unp_addr->m_len;
  99:             bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
 100:                 mtod(nam, caddr_t), (unsigned)nam->m_len);
 101:         } else {
 102:             nam->m_len = sizeof(sun_noname);
 103:             *(mtod(nam, struct sockaddr *)) = sun_noname;
 104:         }
 105:         break;
 106: 
 107:     case PRU_SHUTDOWN:
 108:         socantsendmore(so);
 109:         unp_usrclosed(unp);
 110:         break;
 111: 
 112:     case PRU_RCVD:
 113:         switch (so->so_type) {
 114: 
 115:         case SOCK_DGRAM:
 116:             panic("uipc 1");
 117:             /*NOTREACHED*/
 118: 
 119:         case SOCK_STREAM:
 120: #define rcv (&so->so_rcv)
 121: #define snd (&so2->so_snd)
 122:             if (unp->unp_conn == 0)
 123:                 break;
 124:             so2 = unp->unp_conn->unp_socket;
 125:             /*
 126: 			 * Adjust backpressure on sender
 127: 			 * and wakeup any waiting to write.
 128: 			 */
 129:             snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt;
 130:             unp->unp_mbcnt = rcv->sb_mbcnt;
 131:             snd->sb_hiwat += unp->unp_cc - rcv->sb_cc;
 132:             unp->unp_cc = rcv->sb_cc;
 133:             sowwakeup(so2);
 134: #undef snd
 135: #undef rcv
 136:             break;
 137: 
 138:         default:
 139:             panic("uipc 2");
 140:         }
 141:         break;
 142: 
 143:     case PRU_SEND:
 144:         if (rights) {
 145:             error = unp_internalize(rights);
 146:             if (error)
 147:                 break;
 148:         }
 149:         switch (so->so_type) {
 150: 
 151:         case SOCK_DGRAM: {
 152:             struct sockaddr *from;
 153: 
 154:             if (nam) {
 155:                 if (unp->unp_conn) {
 156:                     error = EISCONN;
 157:                     break;
 158:                 }
 159:                 error = unp_connect(so, nam);
 160:                 if (error)
 161:                     break;
 162:             } else {
 163:                 if (unp->unp_conn == 0) {
 164:                     error = ENOTCONN;
 165:                     break;
 166:                 }
 167:             }
 168:             so2 = unp->unp_conn->unp_socket;
 169:             if (unp->unp_addr)
 170:                 from = mtod(unp->unp_addr, struct sockaddr *);
 171:             else
 172:                 from = &sun_noname;
 173:             if (sbspace(&so2->so_rcv) > 0 &&
 174:                 sbappendaddr(&so2->so_rcv, from, m, rights)) {
 175:                 sorwakeup(so2);
 176:                 m = 0;
 177:             } else
 178:                 error = ENOBUFS;
 179:             if (nam)
 180:                 unp_disconnect(unp);
 181:             break;
 182:         }
 183: 
 184:         case SOCK_STREAM:
 185: #define rcv (&so2->so_rcv)
 186: #define snd (&so->so_snd)
 187:             if (so->so_state & SS_CANTSENDMORE) {
 188:                 error = EPIPE;
 189:                 break;
 190:             }
 191:             if (unp->unp_conn == 0)
 192:                 panic("uipc 3");
 193:             so2 = unp->unp_conn->unp_socket;
 194:             /*
 195: 			 * Send to paired receive port, and then reduce
 196: 			 * send buffer hiwater marks to maintain backpressure.
 197: 			 * Wake up readers.
 198: 			 */
 199:             if (rights)
 200:                 (void)sbappendrights(rcv, m, rights);
 201:             else
 202:                 sbappend(rcv, m);
 203:             snd->sb_mbmax -=
 204:                 rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt;
 205:             unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt;
 206:             snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc;
 207:             unp->unp_conn->unp_cc = rcv->sb_cc;
 208:             sorwakeup(so2);
 209:             m = 0;
 210: #undef snd
 211: #undef rcv
 212:             break;
 213: 
 214:         default:
 215:             panic("uipc 4");
 216:         }
 217:         break;
 218: 
 219:     case PRU_ABORT:
 220:         unp_drop(unp, ECONNABORTED);
 221:         break;
 222: 
 223:     case PRU_SENSE:
 224:         ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
 225:         if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) {
 226:             so2 = unp->unp_conn->unp_socket;
 227:             ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc;
 228:         }
 229:         ((struct stat *) m)->st_dev = NODEV;
 230:         if (unp->unp_ino == 0)
 231:             unp->unp_ino = unp_ino++;
 232:         ((struct stat *) m)->st_ino = unp->unp_ino;
 233:         return (0);
 234: 
 235:     case PRU_RCVOOB:
 236:         return (EOPNOTSUPP);
 237: 
 238:     case PRU_SENDOOB:
 239:         error = EOPNOTSUPP;
 240:         break;
 241: 
 242:     case PRU_SOCKADDR:
 243:         break;
 244: 
 245:     case PRU_PEERADDR:
 246:         if (unp->unp_conn && unp->unp_conn->unp_addr) {
 247:             nam->m_len = unp->unp_conn->unp_addr->m_len;
 248:             bcopy(mtod(unp->unp_conn->unp_addr, caddr_t),
 249:                 mtod(nam, caddr_t), (unsigned)nam->m_len);
 250:         }
 251:         break;
 252: 
 253:     case PRU_SLOWTIMO:
 254:         break;
 255: 
 256:     default:
 257:         panic("piusrreq");
 258:     }
 259: release:
 260:     if (m)
 261:         m_freem(m);
 262:     return (error);
 263: }
 264: 
 265: /*
 266:  * Both send and receive buffers are allocated PIPSIZ bytes of buffering
 267:  * for stream sockets, although the total for sender and receiver is
 268:  * actually only PIPSIZ.
 269:  * Datagram sockets really use the sendspace as the maximum datagram size,
 270:  * and don't really want to reserve the sendspace.  Their recvspace should
 271:  * be large enough for at least one max-size datagram plus address.
 272:  */
 273: #define PIPSIZ  4096
 274: int unpst_sendspace = PIPSIZ;
 275: int unpst_recvspace = PIPSIZ;
 276: int unpdg_sendspace = 2*1024;   /* really max datagram size */
 277: int unpdg_recvspace = 4*1024;
 278: 
 279: int unp_rights;         /* file descriptors in flight */
 280: 
 281: unp_attach(so)
 282:     struct socket *so;
 283: {
 284:     register struct mbuf *m;
 285:     register struct unpcb *unp;
 286:     int error;
 287: 
 288:     switch (so->so_type) {
 289: 
 290:     case SOCK_STREAM:
 291:         error = soreserve(so, unpst_sendspace, unpst_recvspace);
 292:         break;
 293: 
 294:     case SOCK_DGRAM:
 295:         error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
 296:         break;
 297:     }
 298:     if (error)
 299:         return (error);
 300:     m = m_getclr(M_DONTWAIT, MT_PCB);
 301:     if (m == NULL)
 302:         return (ENOBUFS);
 303:     unp = mtod(m, struct unpcb *);
 304:     so->so_pcb = (caddr_t)unp;
 305:     unp->unp_socket = so;
 306:     return (0);
 307: }
 308: 
 309: unp_detach(unp)
 310:     register struct unpcb *unp;
 311: {
 312: 
 313:     if (unp->unp_inode) {
 314:         UNPDET(unp->unp_inode);
 315:         unp->unp_inode = 0;
 316:     }
 317:     if (unp->unp_conn)
 318:         unp_disconnect(unp);
 319:     while (unp->unp_refs)
 320:         unp_drop(unp->unp_refs, ECONNRESET);
 321:     soisdisconnected(unp->unp_socket);
 322:     unp->unp_socket->so_pcb = 0;
 323:     m_freem(unp->unp_addr);
 324:     (void) m_free(dtom(unp));
 325:     if (unp_rights)
 326:         unp_gc();
 327: }
 328: 
 329: unp_bind(unp, nam)
 330:     struct unpcb *unp;
 331:     struct mbuf *nam;
 332: {
 333:     struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
 334:     struct inode *ip;
 335:     int error;
 336: 
 337:     if (unp->unp_inode != NULL || nam->m_len >= MLEN)
 338:         return (EINVAL);
 339:     *(mtod(nam, caddr_t) + nam->m_len) = 0;
 340:     error = UNPBIND(soun->sun_path, nam->m_len, &ip, unp->unp_socket);
 341:     if (error)
 342:         return(error);
 343:     if (!ip)
 344:         panic("unp_bind");
 345:     unp->unp_inode = ip;
 346:     unp->unp_addr = m_copy(nam, 0, M_COPYALL);
 347:     return (0);
 348: }
 349: 
 350: unp_connect(so, nam)
 351:     struct socket *so;
 352:     struct mbuf *nam;
 353: {
 354:     register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *);
 355:     struct inode *ip;
 356:     int error;
 357:     struct socket *so2;
 358: 
 359:     if (nam->m_len + (nam->m_off - MMINOFF) == MLEN)
 360:         return (EMSGSIZE);
 361:     *(mtod(nam, caddr_t) + nam->m_len) = 0;
 362: 
 363:     error = UNPCONN(soun->sun_path, nam->m_len, &so2, &ip);
 364:     if (error || !so2 || !ip)
 365:         goto bad;
 366:     if (so->so_type != so2->so_type) {
 367:         error = EPROTOTYPE;
 368:         goto bad;
 369:     }
 370:     if (so->so_proto->pr_flags & PR_CONNREQUIRED &&
 371:         ((so2->so_options&SO_ACCEPTCONN) == 0 ||
 372:         (so2 = sonewconn(so2)) == 0)) {
 373:         error = ECONNREFUSED;
 374:         goto bad;
 375:     }
 376:     error = unp_connect2(so, so2);
 377: bad:
 378:     if (ip)
 379:         IPUT(ip);
 380:     return (error);
 381: }
 382: 
 383: unp_connect2(so, so2)
 384:     register struct socket *so;
 385:     register struct socket *so2;
 386: {
 387:     register struct unpcb *unp = sotounpcb(so);
 388:     register struct unpcb *unp2;
 389: 
 390:     if (so2->so_type != so->so_type)
 391:         return (EPROTOTYPE);
 392:     unp2 = sotounpcb(so2);
 393:     unp->unp_conn = unp2;
 394:     switch (so->so_type) {
 395: 
 396:     case SOCK_DGRAM:
 397:         unp->unp_nextref = unp2->unp_refs;
 398:         unp2->unp_refs = unp;
 399:         soisconnected(so);
 400:         break;
 401: 
 402:     case SOCK_STREAM:
 403:         unp2->unp_conn = unp;
 404:         soisconnected(so2);
 405:         soisconnected(so);
 406:         break;
 407: 
 408:     default:
 409:         panic("unp_connect2");
 410:     }
 411:     return (0);
 412: }
 413: 
 414: unp_disconnect(unp)
 415:     struct unpcb *unp;
 416: {
 417:     register struct unpcb *unp2 = unp->unp_conn;
 418: 
 419:     if (unp2 == 0)
 420:         return;
 421:     unp->unp_conn = 0;
 422:     switch (unp->unp_socket->so_type) {
 423: 
 424:     case SOCK_DGRAM:
 425:         if (unp2->unp_refs == unp)
 426:             unp2->unp_refs = unp->unp_nextref;
 427:         else {
 428:             unp2 = unp2->unp_refs;
 429:             for (;;) {
 430:                 if (unp2 == 0)
 431:                     panic("unp_disconnect");
 432:                 if (unp2->unp_nextref == unp)
 433:                     break;
 434:                 unp2 = unp2->unp_nextref;
 435:             }
 436:             unp2->unp_nextref = unp->unp_nextref;
 437:         }
 438:         unp->unp_nextref = 0;
 439:         unp->unp_socket->so_state &= ~SS_ISCONNECTED;
 440:         break;
 441: 
 442:     case SOCK_STREAM:
 443:         soisdisconnected(unp->unp_socket);
 444:         unp2->unp_conn = 0;
 445:         soisdisconnected(unp2->unp_socket);
 446:         break;
 447:     }
 448: }
 449: 
 450: #ifdef notdef
 451: unp_abort(unp)
 452:     struct unpcb *unp;
 453: {
 454: 
 455:     unp_detach(unp);
 456: }
 457: #endif
 458: 
 459: /*ARGSUSED*/
 460: unp_usrclosed(unp)
 461:     struct unpcb *unp;
 462: {
 463: 
 464: }
 465: 
 466: unp_drop(unp, errno)
 467:     struct unpcb *unp;
 468:     int errno;
 469: {
 470:     struct socket *so = unp->unp_socket;
 471: 
 472:     so->so_error = errno;
 473:     unp_disconnect(unp);
 474:     if (so->so_head) {
 475:         so->so_pcb = (caddr_t) 0;
 476:         m_freem(unp->unp_addr);
 477:         (void) m_free(dtom(unp));
 478:         sofree(so);
 479:     }
 480: }
 481: 
 482: #ifdef notdef
 483: unp_drain()
 484: {
 485: 
 486: }
 487: #endif
 488: 
 489: unp_externalize(rights)
 490:     struct mbuf *rights;
 491: {
 492:     int newfds = rights->m_len / sizeof (int);
 493:     register int i;
 494:     register struct file **rp = mtod(rights, struct file **);
 495:     register struct file *fp;
 496:     int f;
 497: 
 498:     printf("unp_externalize(0%o)\n",rights);
 499:     if (newfds > ufavail()) {
 500:         for (i = 0; i < newfds; i++) {
 501:             fp = *rp;
 502:             unp_discard(fp);
 503:             *rp++ = 0;
 504:         }
 505:         return (EMSGSIZE);
 506:     }
 507:     for (i = 0; i < newfds; i++) {
 508:         f = ufalloc(0);
 509:         if (f < 0)
 510:             panic("unp_externalize");
 511:         fp = *rp;
 512:         u.u_ofile[f] = fp;
 513:         /* -1 added to msgcount, 0 to count */
 514:         SKcall(fadjust, sizeof(fp) + sizeof(int) + sizeof(int),
 515:             fp, -1, 0);
 516:         unp_rights--;
 517:         *(int *)rp++ = f;
 518:     }
 519:     return (0);
 520: }
 521: 
 522: unp_internalize(rights)
 523:     struct mbuf *rights;
 524: {
 525:     register struct file **rp;
 526:     int oldfds = rights->m_len / sizeof (int);
 527:     register int i;
 528:     register struct file *fp;
 529: 
 530:     printf("unp_internalize(0%o)\n",rights);
 531:     rp = mtod(rights, struct file **);
 532:     for (i = 0; i < oldfds; i++, rp++)
 533:         GETF(fp, *(int *)rp);
 534:     rp = mtod(rights, struct file **);
 535:     for (i = 0; i < oldfds; i++) {
 536:         GETF(fp, *(int *)rp);
 537:         *rp++ = fp;
 538:         /* bump both the message count and reference count of fp */
 539:         SKcall(fadjust, sizeof(fp) + sizeof(int) + sizeof(int),
 540:             fp, 1, 1);
 541:         unp_rights++;
 542:     }
 543:     return (0);
 544: }
 545: 
 546: int unp_defer, unp_gcing;
 547: int unp_mark();
 548: extern  struct domain unixdomain;
 549: 
 550: /*
 551:  * What I did to the next routine isn't pretty, feel free to redo it, but
 552:  * I doubt it'd be worth it since this isn't used very much.  SMS
 553:  */
 554: unp_gc()
 555: {
 556:     register struct file *fp;
 557:     register struct socket *so;
 558:     struct file *file, *fileNFILE, xf;
 559: 
 560:     if (unp_gcing)
 561:         return;
 562:     unp_gcing = 1;
 563: restart:
 564:     unp_defer = 0;
 565:     /* get limits AND clear FMARK|FDEFER in all file table entries */
 566:     SKcall(unpgc1, sizeof(file) + sizeof(fileNFILE), &file, &fileNFILE);
 567:     do {
 568:         for (fp = file; fp < fileNFILE; fp++) {
 569:             /* get file table entry, the return value is f_count */
 570:             if (FPFETCH(fp, &xf) == 0)
 571:                 continue;
 572:             if (xf.f_flag & FDEFER) {
 573:                 FPFLAGS(fp, 0, FDEFER);
 574:                 unp_defer--;
 575:             } else {
 576:                 if (xf.f_flag & FMARK)
 577:                     continue;
 578:                 if (xf.f_count == xf.f_msgcount)
 579:                     continue;
 580:                 FPFLAGS(fp, FMARK, 0);
 581:             }
 582:             if (xf.f_type != DTYPE_SOCKET)
 583:                 continue;
 584:             so = xf.f_socket;
 585:             if (so->so_proto->pr_domain != &unixdomain ||
 586:                 (so->so_proto->pr_flags&PR_RIGHTS) == 0)
 587:                 continue;
 588:             if (so->so_rcv.sb_flags & SB_LOCK) {
 589:                 sbwait(&so->so_rcv);
 590:                 goto restart;
 591:             }
 592:             unp_scan(so->so_rcv.sb_mb, unp_mark);
 593:         }
 594:     } while (unp_defer);
 595:     for (fp = file; fp < fileNFILE; fp++) {
 596:         if (FPFETCH(fp, &xf) == 0)
 597:             continue;
 598:         if (xf.f_count == xf.f_msgcount && (xf.f_flag & FMARK) == 0)
 599:             while (FPFETCH(fp, &xf) && xf.f_msgcount)
 600:                 unp_discard(fp);
 601:     }
 602:     unp_gcing = 0;
 603: }
 604: 
 605: unp_dispose(m)
 606:     struct mbuf *m;
 607: {
 608:     int unp_discard();
 609: 
 610:     if (m)
 611:         unp_scan(m, unp_discard);
 612: }
 613: 
 614: unp_scan(m0, op)
 615:     register struct mbuf *m0;
 616:     int (*op)();
 617: {
 618:     register struct mbuf *m;
 619:     register struct file **rp;
 620:     register int i;
 621:     int qfds;
 622: 
 623:     while (m0) {
 624:         for (m = m0; m; m = m->m_next)
 625:             if (m->m_type == MT_RIGHTS && m->m_len) {
 626:                 qfds = m->m_len / sizeof (struct file *);
 627:                 rp = mtod(m, struct file **);
 628:                 for (i = 0; i < qfds; i++)
 629:                     (*op)(*rp++);
 630:                 break;      /* XXX, but saves time */
 631:             }
 632:         m0 = m0->m_act;
 633:     }
 634: }
 635: 
 636: unp_mark(fp)
 637:     struct file *fp;
 638: {
 639:     struct file xf;
 640: 
 641:     FPFETCH(fp, &xf);
 642:     if (xf.f_flag & FMARK)
 643:         return;
 644:     unp_defer++;
 645:     FPFLAGS(fp, FMARK|FDEFER, 0);
 646: }
 647: 
 648: unp_discard(fp)
 649:     struct file *fp;
 650: {
 651:     unp_rights--;
 652:     SKcall(unpdisc, sizeof(fp), fp);
 653: }

Defined functions

uipc_usrreq defined in line 37; used 3 times
unp_abort defined in line 451; never used
unp_attach defined in line 281; used 1 times
  • in line 63
unp_bind defined in line 329; used 1 times
  • in line 71
unp_connect defined in line 350; used 2 times
unp_connect2 defined in line 383; used 2 times
unp_detach defined in line 309; used 2 times
unp_discard defined in line 648; used 5 times
unp_disconnect defined in line 414; used 4 times
unp_dispose defined in line 605; used 2 times
unp_drain defined in line 483; never used
unp_drop defined in line 466; used 2 times
unp_externalize defined in line 489; used 2 times
unp_gc defined in line 554; used 1 times
unp_internalize defined in line 522; used 1 times
unp_mark defined in line 636; used 2 times
unp_scan defined in line 614; used 2 times
unp_usrclosed defined in line 460; used 1 times

Defined variables

sun_noname defined in line 30; used 3 times
unp_defer defined in line 546; used 4 times
unp_gcing defined in line 546; used 3 times
unp_ino defined in line 31; used 4 times
unp_rights defined in line 279; used 4 times
unpdg_recvspace defined in line 277; used 1 times
unpdg_sendspace defined in line 276; used 1 times
unpst_recvspace defined in line 275; used 1 times
unpst_sendspace defined in line 274; used 1 times

Defined macros

PIPSIZ defined in line 273; used 2 times
rcv defined in line 185; used 12 times
snd defined in line 186; used 6 times
Last modified: 1997-01-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 116
Valid CSS Valid XHTML 1.0 Strict