# 2.11BSD#431 - /usr/src/sys/sys/uipc_socket.c

##### Functions

    asoqremque        X
    connwhile         X
    soabort           X
    soacc1            X
    soaccept          X
    sobind            X
    soclose           X
    soconnect         X
    soconnect2        X
    socreate          X
    sodisconnect      X
    sofree            X
    sogetnam          X
    sogetopt          X
    sogetpeer         X
    sohasoutofband    X
    solisten          X
    soreceive         X
    sorflush          X
    sosend            X
    sosetopt          X
    soshutdown        X

##### Macros

    snderr            X

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

#### Defined functions

asoqremque defined in line 863; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 9-11(2)

connwhile defined in line 881; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 18-20(2)

soabort defined in line 186; used 5 times

- in line 146-148(2)
- in /usr/src/sys/netinet/tcp_input.c line 1148, 1162
- in /usr/src/sys/netns/spp_usrreq.c line 246

soacc1 defined in line 832; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 90-92(2)

soaccept defined in line 195; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 94-96(2)

sobind defined in line 78; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 99-101(2)

soclose defined in line 138; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 104-106(2)

soconnect defined in line 211; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 108-110(2)

soconnect2 defined in line 256; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 113-115(2)

socreate defined in line 40; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 118-120(2)

sodisconnect defined in line 269; used 2 times

- in line 154, 235

sofree defined in line 117; used 8 times

- in line 71, 178
- in /usr/src/sys/net/raw_cb.c line 83
- in /usr/src/sys/net/raw_usrreq.c line 273
- in /usr/src/sys/netinet/in_pcb.c line 230
- in /usr/src/sys/netns/idp_usrreq.c line 480
- in /usr/src/sys/netns/ns_pcb.c line 194
- in /usr/src/sys/sys/uipc_usrreq.c line 478

sogetnam defined in line 893; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 123-125(2)

sogetopt defined in line 730; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 128-130(2)

sogetpeer defined in line 900; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 133-135(2)

sohasoutofband defined in line 808; used 2 times

- in /usr/src/sys/netinet/tcp_input.c line 1002
- in /usr/src/sys/netns/spp_usrreq.c line 480

solisten defined in line 92; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 138-140(2)

soreceive defined in line 424; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 159-161(2)

sorflush defined in line 617; used 2 times

- in line 129, 610

sosend defined in line 299; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 165-167(2)

sosetopt defined in line 637; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 171-173(2)

soshutdown defined in line 602; used 2 times

- in /usr/src/sys/pdp/net_mac.h line 176-178(2)

#### Defined macros

snderr defined in line 319; used 3 times

- in line 326, 335-337(2)

Last modified: 1994-11-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2696 |