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_socket.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "param.h"
  10: #include "systm.h"
  11: #include "dir.h"
  12: #include "user.h"
  13: #include "proc.h"
  14: #include "file.h"
  15: #include "inode.h"
  16: #include "buf.h"
  17: #include "mbuf.h"
  18: #include "un.h"
  19: #include "domain.h"
  20: #include "protosw.h"
  21: #include "socket.h"
  22: #include "socketvar.h"
  23: #include "stat.h"
  24: #include "ioctl.h"
  25: #include "uio.h"
  26: #include "../net/route.h"
  27: #include "../netinet/in.h"
  28: #include "../net/if.h"
  29: 
  30: /*
  31:  * Socket operation routines.
  32:  * These routines are called by the routines in
  33:  * sys_socket.c or from a system process, and
  34:  * implement the semantics of socket operations by
  35:  * switching out to the protocol specific routines.
  36:  *
  37:  * TODO:
  38:  *	test socketpair
  39:  *	clean up async
  40:  *	out-of-band is a kludge
  41:  */
  42: /*ARGSUSED*/
  43: socreate(dom, aso, type, proto)
  44:     struct socket **aso;
  45:     register int type;
  46:     int proto;
  47: {
  48:     register struct protosw *prp;
  49:     register struct socket *so;
  50:     register struct mbuf *m;
  51:     register int error;
  52: 
  53:     if (proto)
  54:         prp = pffindproto(dom, proto, type);
  55:     else
  56:         prp = pffindtype(dom, type);
  57:     if (prp == 0)
  58:         return (EPROTONOSUPPORT);
  59:     if (prp->pr_type != type)
  60:         return (EPROTOTYPE);
  61:     m = m_getclr(M_WAIT, MT_SOCKET);
  62:     so = mtod(m, struct socket *);
  63:     so->so_options = 0;
  64:     so->so_state = 0;
  65:     so->so_type = type;
  66:     if (u.u_uid == 0)
  67:         so->so_state = SS_PRIV;
  68:     so->so_proto = prp;
  69:     error =
  70:         (*prp->pr_usrreq)(so, PRU_ATTACH,
  71:         (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
  72:     if (error) {
  73:         so->so_state |= SS_NOFDREF;
  74:         sofree(so);
  75:         return (error);
  76:     }
  77:     *aso = so;
  78:     return (0);
  79: }
  80: 
  81: sobind(so, nam)
  82:     struct socket *so;
  83:     struct mbuf *nam;
  84: {
  85:     int s = splnet();
  86:     int error;
  87: 
  88:     error =
  89:         (*so->so_proto->pr_usrreq)(so, PRU_BIND,
  90:         (struct mbuf *)0, nam, (struct mbuf *)0);
  91:     splx(s);
  92:     return (error);
  93: }
  94: 
  95: solisten(so, backlog)
  96:     register struct socket *so;
  97:     int backlog;
  98: {
  99:     int s = splnet(), error;
 100: 
 101:     error =
 102:         (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
 103:         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
 104:     if (error) {
 105:         splx(s);
 106:         return (error);
 107:     }
 108:     if (so->so_q == 0) {
 109:         so->so_q = so;
 110:         so->so_q0 = so;
 111:         so->so_options |= SO_ACCEPTCONN;
 112:     }
 113:     if (backlog < 0)
 114:         backlog = 0;
 115:     so->so_qlimit = MIN(backlog, SOMAXCONN);
 116:     splx(s);
 117:     return (0);
 118: }
 119: 
 120: sofree(so)
 121:     register struct socket *so;
 122: {
 123: 
 124:     if (so->so_head) {
 125:         if (!soqremque(so, 0) && !soqremque(so, 1))
 126:             panic("sofree dq");
 127:         so->so_head = 0;
 128:     }
 129:     if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
 130:         return;
 131:     sbrelease(&so->so_snd);
 132:     sorflush(so);
 133:     (void) m_free(dtom(so));
 134: }
 135: 
 136: /*
 137:  * Close a socket on last file table reference removal.
 138:  * Initiate disconnect if connected.
 139:  * Free socket when disconnect complete.
 140:  */
 141: soclose(so)
 142:     register struct socket *so;
 143: {
 144:     int s = splnet();       /* conservative */
 145:     int error;
 146: 
 147:     if (so->so_options & SO_ACCEPTCONN) {
 148:         while (so->so_q0 != so)
 149:             (void) soabort(so->so_q0);
 150:         while (so->so_q != so)
 151:             (void) soabort(so->so_q);
 152:     }
 153:     if (so->so_pcb == 0)
 154:         goto discard;
 155:     if (so->so_state & SS_ISCONNECTED) {
 156:         if ((so->so_state & SS_ISDISCONNECTING) == 0) {
 157:             error = sodisconnect(so);
 158:             if (error)
 159:                 goto drop;
 160:         }
 161:         if (so->so_options & SO_LINGER) {
 162:             if ((so->so_state & SS_ISDISCONNECTING) &&
 163:                 (so->so_state & SS_NBIO))
 164:                 goto drop;
 165:             while (so->so_state & SS_ISCONNECTED)
 166:                 sleep((caddr_t)&so->so_timeo, PZERO+1);
 167:         }
 168:     }
 169: drop:
 170:     if (so->so_pcb) {
 171:         int error2 =
 172:             (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
 173:             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
 174:         if (error == 0)
 175:             error = error2;
 176:     }
 177: discard:
 178:     if (so->so_state & SS_NOFDREF)
 179:         panic("soclose: NOFDREF");
 180:     so->so_state |= SS_NOFDREF;
 181:     sofree(so);
 182:     splx(s);
 183:     return (error);
 184: }
 185: 
 186: /*
 187:  * Must be called at splnet...
 188:  */
 189: soabort(so)
 190:     struct socket *so;
 191: {
 192: 
 193:     return (
 194:         (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
 195:         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
 196: }
 197: 
 198: soaccept(so, nam)
 199:     register struct socket *so;
 200:     struct mbuf *nam;
 201: {
 202:     int s = splnet();
 203:     int error;
 204: 
 205:     if ((so->so_state & SS_NOFDREF) == 0)
 206:         panic("soaccept: !NOFDREF");
 207:     so->so_state &= ~SS_NOFDREF;
 208:     error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
 209:         (struct mbuf *)0, nam, (struct mbuf *)0);
 210:     splx(s);
 211:     return (error);
 212: }
 213: 
 214: soconnect(so, nam)
 215:     register struct socket *so;
 216:     struct mbuf *nam;
 217: {
 218:     int s = splnet();
 219:     int error;
 220: 
 221:     /*
 222: 	 * If protocol is connection-based, can only connect once.
 223: 	 * Otherwise, if connected, try to disconnect first.
 224: 	 * This allows user to disconnect by connecting to, e.g.,
 225: 	 * a null address.
 226: 	 */
 227:     if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
 228:         ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
 229:         (error = sodisconnect(so))))
 230:         error = EISCONN;
 231:     else
 232:         error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
 233:             (struct mbuf *)0, nam, (struct mbuf *)0);
 234:     splx(s);
 235:     return (error);
 236: }
 237: 
 238: soconnect2(so1, so2)
 239:     register struct socket *so1;
 240:     struct socket *so2;
 241: {
 242:     int s = splnet();
 243:     int error;
 244: 
 245:     error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
 246:         (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
 247:     splx(s);
 248:     return (error);
 249: }
 250: 
 251: sodisconnect(so)
 252:     register struct socket *so;
 253: {
 254:     int s = splnet();
 255:     int error;
 256: 
 257:     if ((so->so_state & SS_ISCONNECTED) == 0) {
 258:         error = ENOTCONN;
 259:         goto bad;
 260:     }
 261:     if (so->so_state & SS_ISDISCONNECTING) {
 262:         error = EALREADY;
 263:         goto bad;
 264:     }
 265:     error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
 266:         (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
 267: bad:
 268:     splx(s);
 269:     return (error);
 270: }
 271: 
 272: /*
 273:  * Send on a socket.
 274:  * If send must go all at once and message is larger than
 275:  * send buffering, then hard error.
 276:  * Lock against other senders.
 277:  * If must go all at once and not enough room now, then
 278:  * inform user that this would block and do nothing.
 279:  * Otherwise, if nonblocking, send as much as possible.
 280:  */
 281: sosend(so, nam, uio, flags, rights)
 282:     register struct socket *so;
 283:     struct mbuf *nam;
 284:     register struct uio *uio;
 285:     int flags;
 286:     struct mbuf *rights;
 287: {
 288:     struct mbuf *top = 0;
 289:     register struct mbuf *m, **mp;
 290:     register int space;
 291:     int len, rlen = 0, error = 0, s, dontroute, first = 1;
 292: 
 293:     if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
 294:         return (EMSGSIZE);
 295:     dontroute =
 296:         (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
 297:         (so->so_proto->pr_flags & PR_ATOMIC);
 298:     u.u_ru.ru_msgsnd++;
 299:     if (rights)
 300:         rlen = rights->m_len;
 301: #define snderr(errno)   { error = errno; splx(s); goto release; }
 302: 
 303: restart:
 304:     sblock(&so->so_snd);
 305:     do {
 306:         s = splnet();
 307:         if (so->so_state & SS_CANTSENDMORE)
 308:             snderr(EPIPE);
 309:         if (so->so_error) {
 310:             error = so->so_error;
 311:             so->so_error = 0;           /* ??? */
 312:             splx(s);
 313:             goto release;
 314:         }
 315:         if ((so->so_state & SS_ISCONNECTED) == 0) {
 316:             if (so->so_proto->pr_flags & PR_CONNREQUIRED)
 317:                 snderr(ENOTCONN);
 318:             if (nam == 0)
 319:                 snderr(EDESTADDRREQ);
 320:         }
 321:         if (flags & MSG_OOB)
 322:             space = 1024;
 323:         else {
 324:             space = sbspace(&so->so_snd);
 325:             if (space <= rlen ||
 326:                (sosendallatonce(so) &&
 327:                 space < uio->uio_resid + rlen) ||
 328:                (uio->uio_resid >= CLBYTES && space < CLBYTES &&
 329:                so->so_snd.sb_cc >= CLBYTES &&
 330:                (so->so_state & SS_NBIO) == 0)) {
 331:                 if (so->so_state & SS_NBIO) {
 332:                     if (first)
 333:                         error = EWOULDBLOCK;
 334:                     splx(s);
 335:                     goto release;
 336:                 }
 337:                 sbunlock(&so->so_snd);
 338:                 sbwait(&so->so_snd);
 339:                 splx(s);
 340:                 goto restart;
 341:             }
 342:         }
 343:         splx(s);
 344:         mp = &top;
 345:         space -= rlen;
 346:         while (space > 0) {
 347:             MGET(m, M_WAIT, MT_DATA);
 348:             if (uio->uio_resid >= CLBYTES / 2 && space >= CLBYTES) {
 349:                 MCLGET(m);
 350:                 if (m->m_len != CLBYTES)
 351:                     goto nopages;
 352:                 len = MIN(CLBYTES, uio->uio_resid);
 353:                 space -= CLBYTES;
 354:             } else {
 355: nopages:
 356:                 len = MIN(MIN(MLEN, uio->uio_resid), space);
 357:                 space -= len;
 358:             }
 359:             error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
 360:             m->m_len = len;
 361:             *mp = m;
 362:             if (error)
 363:                 goto release;
 364:             mp = &m->m_next;
 365:             if (uio->uio_resid <= 0)
 366:                 break;
 367:         }
 368:         if (dontroute)
 369:             so->so_options |= SO_DONTROUTE;
 370:         s = splnet();                   /* XXX */
 371:         error = (*so->so_proto->pr_usrreq)(so,
 372:             (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
 373:             top, (caddr_t)nam, rights);
 374:         splx(s);
 375:         if (dontroute)
 376:             so->so_options &= ~SO_DONTROUTE;
 377:         rights = 0;
 378:         rlen = 0;
 379:         top = 0;
 380:         first = 0;
 381:         if (error)
 382:             break;
 383:     } while (uio->uio_resid);
 384: 
 385: release:
 386:     sbunlock(&so->so_snd);
 387:     if (top)
 388:         m_freem(top);
 389:     if (error == EPIPE)
 390:         psignal(u.u_procp, SIGPIPE);
 391:     return (error);
 392: }
 393: 
 394: /*
 395:  * Implement receive operations on a socket.
 396:  * We depend on the way that records are added to the sockbuf
 397:  * by sbappend*.  In particular, each record (mbufs linked through m_next)
 398:  * must begin with an address if the protocol so specifies,
 399:  * followed by an optional mbuf containing access rights if supported
 400:  * by the protocol, and then zero or more mbufs of data.
 401:  * In order to avoid blocking network interrupts for the entire time here,
 402:  * we splx() while doing the actual copy to user space.
 403:  * Although the sockbuf is locked, new data may still be appended,
 404:  * and thus we must maintain consistency of the sockbuf during that time.
 405:  */
 406: soreceive(so, aname, uio, flags, rightsp)
 407:     register struct socket *so;
 408:     struct mbuf **aname;
 409:     register struct uio *uio;
 410:     int flags;
 411:     struct mbuf **rightsp;
 412: {
 413:     register struct mbuf *m;
 414:     register int len, error = 0, s, tomark;
 415:     struct protosw *pr = so->so_proto;
 416:     struct mbuf *nextrecord;
 417:     int moff;
 418: 
 419:     if (rightsp)
 420:         *rightsp = 0;
 421:     if (aname)
 422:         *aname = 0;
 423:     if (flags & MSG_OOB) {
 424:         m = m_get(M_WAIT, MT_DATA);
 425:         error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
 426:             m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
 427:         if (error)
 428:             goto bad;
 429:         do {
 430:             len = uio->uio_resid;
 431:             if (len > m->m_len)
 432:                 len = m->m_len;
 433:             error =
 434:                 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
 435:             m = m_free(m);
 436:         } while (uio->uio_resid && error == 0 && m);
 437: bad:
 438:         if (m)
 439:             m_freem(m);
 440:         return (error);
 441:     }
 442: 
 443: restart:
 444:     sblock(&so->so_rcv);
 445:     s = splnet();
 446: 
 447: #define rcverr(errno)   { error = errno; splx(s); goto release; }
 448:     if (so->so_rcv.sb_cc == 0) {
 449:         if (so->so_error) {
 450:             error = so->so_error;
 451:             so->so_error = 0;
 452:             splx(s);
 453:             goto release;
 454:         }
 455:         if (so->so_state & SS_CANTRCVMORE) {
 456:             splx(s);
 457:             goto release;
 458:         }
 459:         if ((so->so_state & SS_ISCONNECTED) == 0 &&
 460:             (so->so_proto->pr_flags & PR_CONNREQUIRED))
 461:             rcverr(ENOTCONN);
 462:         if (uio->uio_resid == 0)
 463:             goto release;
 464:         if (so->so_state & SS_NBIO)
 465:             rcverr(EWOULDBLOCK);
 466:         sbunlock(&so->so_rcv);
 467:         sbwait(&so->so_rcv);
 468:         splx(s);
 469:         goto restart;
 470:     }
 471:     u.u_ru.ru_msgrcv++;
 472:     m = so->so_rcv.sb_mb;
 473:     if (m == 0)
 474:         panic("receive 1");
 475:     nextrecord = m->m_act;
 476:     if (pr->pr_flags & PR_ADDR) {
 477:         if (m->m_type != MT_SONAME)
 478:             panic("receive 1a");
 479:         if (flags & MSG_PEEK) {
 480:             if (aname)
 481:                 *aname = m_copy(m, 0, m->m_len);
 482:             m = m->m_next;
 483:         } else {
 484:             sbfree(&so->so_rcv, m);
 485:             if (aname) {
 486:                 *aname = m;
 487:                 m = m->m_next;
 488:                 (*aname)->m_next = 0;
 489:                 so->so_rcv.sb_mb = m;
 490:             } else {
 491:                 MFREE(m, so->so_rcv.sb_mb);
 492:                 m = so->so_rcv.sb_mb;
 493:             }
 494:             if (m)
 495:                 m->m_act = nextrecord;
 496:         }
 497:     }
 498:     if (m && m->m_type == MT_RIGHTS) {
 499:         if ((pr->pr_flags & PR_RIGHTS) == 0)
 500:             panic("receive 2");
 501:         if (flags & MSG_PEEK) {
 502:             if (rightsp)
 503:                 *rightsp = m_copy(m, 0, m->m_len);
 504:             m = m->m_next;
 505:         } else {
 506:             sbfree(&so->so_rcv, m);
 507:             if (rightsp) {
 508:                 *rightsp = m;
 509:                 so->so_rcv.sb_mb = m->m_next;
 510:                 m->m_next = 0;
 511:                 m = so->so_rcv.sb_mb;
 512:             } else {
 513:                 MFREE(m, so->so_rcv.sb_mb);
 514:                 m = so->so_rcv.sb_mb;
 515:             }
 516:             if (m)
 517:                 m->m_act = nextrecord;
 518:         }
 519:     }
 520:     moff = 0;
 521:     tomark = so->so_oobmark;
 522:     while (m && uio->uio_resid > 0 && error == 0) {
 523:         if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
 524:             panic("receive 3");
 525:         len = uio->uio_resid;
 526:         so->so_state &= ~SS_RCVATMARK;
 527:         if (tomark && len > tomark)
 528:             len = tomark;
 529:         if (len > m->m_len - moff)
 530:             len = m->m_len - moff;
 531:         splx(s);
 532:         error =
 533:             uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
 534:         s = splnet();
 535:         if (len == m->m_len - moff) {
 536:             if (flags & MSG_PEEK) {
 537:                 m = m->m_next;
 538:                 moff = 0;
 539:             } else {
 540:                 nextrecord = m->m_act;
 541:                 sbfree(&so->so_rcv, m);
 542:                 MFREE(m, so->so_rcv.sb_mb);
 543:                 m = so->so_rcv.sb_mb;
 544:                 if (m)
 545:                     m->m_act = nextrecord;
 546:             }
 547:         } else {
 548:             if (flags & MSG_PEEK)
 549:                 moff += len;
 550:             else {
 551:                 m->m_off += len;
 552:                 m->m_len -= len;
 553:                 so->so_rcv.sb_cc -= len;
 554:             }
 555:         }
 556:         if ((flags & MSG_PEEK) == 0 && so->so_oobmark) {
 557:             so->so_oobmark -= len;
 558:             if (so->so_oobmark == 0) {
 559:                 so->so_state |= SS_RCVATMARK;
 560:                 break;
 561:             }
 562:         }
 563:         if (tomark) {
 564:             tomark -= len;
 565:             if (tomark == 0)
 566:                 break;
 567:         }
 568:     }
 569:     if ((flags & MSG_PEEK) == 0) {
 570:         if (m == 0)
 571:             so->so_rcv.sb_mb = nextrecord;
 572:         else if (pr->pr_flags & PR_ATOMIC)
 573:             (void) sbdroprecord(&so->so_rcv);
 574:         if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
 575:             (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
 576:                 (struct mbuf *)0, (struct mbuf *)0);
 577:         if (error == 0 && rightsp && *rightsp &&
 578:             pr->pr_domain->dom_externalize)
 579:             error = (*pr->pr_domain->dom_externalize)(*rightsp);
 580:     }
 581: release:
 582:     sbunlock(&so->so_rcv);
 583:     splx(s);
 584:     return (error);
 585: }
 586: 
 587: soshutdown(so, how)
 588:     register struct socket *so;
 589:     register int how;
 590: {
 591:     register struct protosw *pr = so->so_proto;
 592: 
 593:     how++;
 594:     if (how & FREAD)
 595:         sorflush(so);
 596:     if (how & FWRITE)
 597:         return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
 598:             (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
 599:     return (0);
 600: }
 601: 
 602: sorflush(so)
 603:     register struct socket *so;
 604: {
 605:     register struct sockbuf *sb = &so->so_rcv;
 606:     register struct protosw *pr = so->so_proto;
 607:     register int s;
 608:     struct sockbuf asb;
 609: 
 610:     sblock(sb);
 611:     s = splimp();
 612:     socantrcvmore(so);
 613:     sbunlock(sb);
 614:     asb = *sb;
 615:     bzero((caddr_t)sb, sizeof (*sb));
 616:     splx(s);
 617:     if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
 618:         (*pr->pr_domain->dom_dispose)(asb.sb_mb);
 619:     sbrelease(&asb);
 620: }
 621: 
 622: sosetopt(so, level, optname, m0)
 623:     register struct socket *so;
 624:     int level, optname;
 625:     struct mbuf *m0;
 626: {
 627:     int error = 0;
 628:     register struct mbuf *m = m0;
 629: 
 630:     if (level != SOL_SOCKET) {
 631:         if (so->so_proto && so->so_proto->pr_ctloutput)
 632:             return ((*so->so_proto->pr_ctloutput)
 633:                   (PRCO_SETOPT, so, level, optname, &m0));
 634:         error = ENOPROTOOPT;
 635:     } else {
 636:         switch (optname) {
 637: 
 638:         case SO_LINGER:
 639:             if (m == NULL || m->m_len != sizeof (struct linger)) {
 640:                 error = EINVAL;
 641:                 goto bad;
 642:             }
 643:             so->so_linger = mtod(m, struct linger *)->l_linger;
 644:             /* fall thru... */
 645: 
 646:         case SO_DEBUG:
 647:         case SO_KEEPALIVE:
 648:         case SO_DONTROUTE:
 649:         case SO_USELOOPBACK:
 650:         case SO_BROADCAST:
 651:         case SO_REUSEADDR:
 652:         case SO_OOBINLINE:
 653:             if (m == NULL || m->m_len < sizeof (int)) {
 654:                 error = EINVAL;
 655:                 goto bad;
 656:             }
 657:             if (*mtod(m, int *))
 658:                 so->so_options |= optname;
 659:             else
 660:                 so->so_options &= ~optname;
 661:             break;
 662: 
 663:         case SO_SNDBUF:
 664:         case SO_RCVBUF:
 665:         case SO_SNDLOWAT:
 666:         case SO_RCVLOWAT:
 667:         case SO_SNDTIMEO:
 668:         case SO_RCVTIMEO:
 669:             if (m == NULL || m->m_len < sizeof (int)) {
 670:                 error = EINVAL;
 671:                 goto bad;
 672:             }
 673:             switch (optname) {
 674: 
 675:             case SO_SNDBUF:
 676:             case SO_RCVBUF:
 677:                 if (sbreserve(optname == SO_SNDBUF ? &so->so_snd :
 678:                     &so->so_rcv, *mtod(m, int *)) == 0) {
 679:                     error = ENOBUFS;
 680:                     goto bad;
 681:                 }
 682:                 break;
 683: 
 684:             case SO_SNDLOWAT:
 685:                 so->so_snd.sb_lowat = *mtod(m, int *);
 686:                 break;
 687:             case SO_RCVLOWAT:
 688:                 so->so_rcv.sb_lowat = *mtod(m, int *);
 689:                 break;
 690:             case SO_SNDTIMEO:
 691:                 so->so_snd.sb_timeo = *mtod(m, int *);
 692:                 break;
 693:             case SO_RCVTIMEO:
 694:                 so->so_rcv.sb_timeo = *mtod(m, int *);
 695:                 break;
 696:             }
 697:             break;
 698: 
 699:         default:
 700:             error = ENOPROTOOPT;
 701:             break;
 702:         }
 703:     }
 704: bad:
 705:     if (m)
 706:         (void) m_free(m);
 707:     return (error);
 708: }
 709: 
 710: sogetopt(so, level, optname, mp)
 711:     register struct socket *so;
 712:     int level, optname;
 713:     struct mbuf **mp;
 714: {
 715:     register struct mbuf *m;
 716: 
 717:     if (level != SOL_SOCKET) {
 718:         if (so->so_proto && so->so_proto->pr_ctloutput) {
 719:             return ((*so->so_proto->pr_ctloutput)
 720:                   (PRCO_GETOPT, so, level, optname, mp));
 721:         } else
 722:             return (ENOPROTOOPT);
 723:     } else {
 724:         m = m_get(M_WAIT, MT_SOOPTS);
 725:         m->m_len = sizeof (int);
 726: 
 727:         switch (optname) {
 728: 
 729:         case SO_LINGER:
 730:             m->m_len = sizeof (struct linger);
 731:             mtod(m, struct linger *)->l_onoff =
 732:                 so->so_options & SO_LINGER;
 733:             mtod(m, struct linger *)->l_linger = so->so_linger;
 734:             break;
 735: 
 736:         case SO_USELOOPBACK:
 737:         case SO_DONTROUTE:
 738:         case SO_DEBUG:
 739:         case SO_KEEPALIVE:
 740:         case SO_REUSEADDR:
 741:         case SO_BROADCAST:
 742:         case SO_OOBINLINE:
 743:             *mtod(m, int *) = so->so_options & optname;
 744:             break;
 745: 
 746:         case SO_TYPE:
 747:             *mtod(m, int *) = so->so_type;
 748:             break;
 749: 
 750:         case SO_ERROR:
 751:             *mtod(m, int *) = so->so_error;
 752:             so->so_error = 0;
 753:             break;
 754: 
 755:         case SO_SNDBUF:
 756:             *mtod(m, int *) = so->so_snd.sb_hiwat;
 757:             break;
 758: 
 759:         case SO_RCVBUF:
 760:             *mtod(m, int *) = so->so_rcv.sb_hiwat;
 761:             break;
 762: 
 763:         case SO_SNDLOWAT:
 764:             *mtod(m, int *) = so->so_snd.sb_lowat;
 765:             break;
 766: 
 767:         case SO_RCVLOWAT:
 768:             *mtod(m, int *) = so->so_rcv.sb_lowat;
 769:             break;
 770: 
 771:         case SO_SNDTIMEO:
 772:             *mtod(m, int *) = so->so_snd.sb_timeo;
 773:             break;
 774: 
 775:         case SO_RCVTIMEO:
 776:             *mtod(m, int *) = so->so_rcv.sb_timeo;
 777:             break;
 778: 
 779:         default:
 780:             (void)m_free(m);
 781:             return (ENOPROTOOPT);
 782:         }
 783:         *mp = m;
 784:         return (0);
 785:     }
 786: }
 787: 
 788: sohasoutofband(so)
 789:     register struct socket *so;
 790: {
 791:     struct proc *p;
 792: 
 793:     if (so->so_pgrp < 0)
 794:         gsignal(-so->so_pgrp, SIGURG);
 795:     else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0)
 796:         psignal(p, SIGURG);
 797:     if (so->so_rcv.sb_sel) {
 798:         selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
 799:         so->so_rcv.sb_sel = 0;
 800:         so->so_rcv.sb_flags &= ~SB_COLL;
 801:     }
 802: }

Defined functions

soabort defined in line 189; used 5 times
soaccept defined in line 198; used 1 times
sobind defined in line 81; used 1 times
soclose defined in line 141; used 5 times
soconnect defined in line 214; used 1 times
soconnect2 defined in line 238; used 2 times
socreate defined in line 43; used 5 times
sodisconnect defined in line 251; used 2 times
sogetopt defined in line 710; used 1 times
solisten defined in line 95; used 1 times
soreceive defined in line 406; used 3 times
sorflush defined in line 602; used 2 times
sosend defined in line 281; used 3 times
sosetopt defined in line 622; used 1 times
soshutdown defined in line 587; used 1 times

Defined macros

rcverr defined in line 447; used 2 times
snderr defined in line 301; used 3 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2223
Valid CSS Valid XHTML 1.0 Strict