123421Smckusick /* 263180Sbostic * Copyright (c) 1982, 1986, 1988, 1990, 1993 363180Sbostic * The Regents of the University of California. All rights reserved. 423421Smckusick * 544450Sbostic * %sccs.include.redist.c% 633185Sbostic * 7*66800Smckusick * @(#)uipc_socket.c 8.3 (Berkeley) 04/15/94 823421Smckusick */ 94786Swnj 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/systm.h> 1256517Sbostic #include <sys/proc.h> 1356517Sbostic #include <sys/file.h> 1456517Sbostic #include <sys/malloc.h> 1556517Sbostic #include <sys/mbuf.h> 1656517Sbostic #include <sys/domain.h> 1756517Sbostic #include <sys/kernel.h> 1856517Sbostic #include <sys/protosw.h> 1956517Sbostic #include <sys/socket.h> 2056517Sbostic #include <sys/socketvar.h> 2156517Sbostic #include <sys/resourcevar.h> 224786Swnj 234786Swnj /* 248300Sroot * Socket operation routines. 258300Sroot * These routines are called by the routines in 268300Sroot * sys_socket.c or from a system process, and 278300Sroot * implement the semantics of socket operations by 288300Sroot * switching out to the protocol specific routines. 294786Swnj */ 308594Sroot /*ARGSUSED*/ 3110267Ssam socreate(dom, aso, type, proto) 3252482Storek int dom; 334786Swnj struct socket **aso; 3412757Ssam register int type; 3512757Ssam int proto; 364786Swnj { 3750942Ssklower struct proc *p = curproc; /* XXX */ 384786Swnj register struct protosw *prp; 394786Swnj register struct socket *so; 4012757Ssam register int error; 414786Swnj 424890Swnj if (proto) 4321767Skarels prp = pffindproto(dom, proto, type); 444890Swnj else 459168Ssam prp = pffindtype(dom, type); 4659973Ssklower if (prp == 0 || prp->pr_usrreq == 0) 474890Swnj return (EPROTONOSUPPORT); 488300Sroot if (prp->pr_type != type) 498300Sroot return (EPROTOTYPE); 5037478Ssklower MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT); 5137478Ssklower bzero((caddr_t)so, sizeof(*so)); 529168Ssam so->so_type = type; 5350942Ssklower if (p->p_ucred->cr_uid == 0) 546214Swnj so->so_state = SS_PRIV; 554786Swnj so->so_proto = prp; 5612757Ssam error = 5712757Ssam (*prp->pr_usrreq)(so, PRU_ATTACH, 5821767Skarels (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0); 594979Swnj if (error) { 607507Sroot so->so_state |= SS_NOFDREF; 617180Swnj sofree(so); 624890Swnj return (error); 634786Swnj } 644786Swnj *aso = so; 654786Swnj return (0); 664786Swnj } 674786Swnj 6810267Ssam sobind(so, nam) 698300Sroot struct socket *so; 708300Sroot struct mbuf *nam; 718300Sroot { 728300Sroot int s = splnet(); 738300Sroot int error; 748300Sroot 7541908Skarels error = 7641908Skarels (*so->so_proto->pr_usrreq)(so, PRU_BIND, 7712757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 788300Sroot splx(s); 798300Sroot return (error); 808300Sroot } 818300Sroot 828300Sroot solisten(so, backlog) 8312757Ssam register struct socket *so; 848300Sroot int backlog; 858300Sroot { 8612757Ssam int s = splnet(), error; 878300Sroot 8812757Ssam error = 8912757Ssam (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 9012757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 918300Sroot if (error) { 928300Sroot splx(s); 938300Sroot return (error); 948300Sroot } 9538584Skarels if (so->so_q == 0) 968300Sroot so->so_options |= SO_ACCEPTCONN; 978300Sroot if (backlog < 0) 988300Sroot backlog = 0; 9935384Skarels so->so_qlimit = min(backlog, SOMAXCONN); 10012493Ssam splx(s); 1018300Sroot return (0); 1028300Sroot } 1038300Sroot 1044916Swnj sofree(so) 10512757Ssam register struct socket *so; 1064916Swnj { 1074916Swnj 10831810Skarels if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 10931810Skarels return; 1107507Sroot if (so->so_head) { 1117507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1127507Sroot panic("sofree dq"); 1137507Sroot so->so_head = 0; 1147507Sroot } 1154950Swnj sbrelease(&so->so_snd); 11612757Ssam sorflush(so); 11737478Ssklower FREE(so, M_SOCKET); 1184916Swnj } 1194916Swnj 1204786Swnj /* 1214890Swnj * Close a socket on last file table reference removal. 1224890Swnj * Initiate disconnect if connected. 1234890Swnj * Free socket when disconnect complete. 1244829Swnj */ 12512757Ssam soclose(so) 1264829Swnj register struct socket *so; 1274829Swnj { 1284890Swnj int s = splnet(); /* conservative */ 12933372Sbostic int error = 0; 1304829Swnj 1317507Sroot if (so->so_options & SO_ACCEPTCONN) { 13238584Skarels while (so->so_q0) 13310399Ssam (void) soabort(so->so_q0); 13438584Skarels while (so->so_q) 13510399Ssam (void) soabort(so->so_q); 1367507Sroot } 1374890Swnj if (so->so_pcb == 0) 1384890Swnj goto discard; 1394890Swnj if (so->so_state & SS_ISCONNECTED) { 1404890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 14126245Skarels error = sodisconnect(so); 14212757Ssam if (error) 14312757Ssam goto drop; 1444890Swnj } 14510267Ssam if (so->so_options & SO_LINGER) { 1465281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 14712757Ssam (so->so_state & SS_NBIO)) 14812757Ssam goto drop; 1495281Sroot while (so->so_state & SS_ISCONNECTED) 15040706Skarels if (error = tsleep((caddr_t)&so->so_timeo, 15140706Skarels PSOCK | PCATCH, netcls, so->so_linger)) 15240706Skarels break; 1534890Swnj } 1544890Swnj } 1555580Sroot drop: 1566880Ssam if (so->so_pcb) { 15712757Ssam int error2 = 15812757Ssam (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 15912757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 16012757Ssam if (error == 0) 16112757Ssam error = error2; 1626880Ssam } 1634890Swnj discard: 16410399Ssam if (so->so_state & SS_NOFDREF) 16510399Ssam panic("soclose: NOFDREF"); 1667507Sroot so->so_state |= SS_NOFDREF; 1674950Swnj sofree(so); 1684890Swnj splx(s); 16912757Ssam return (error); 1704829Swnj } 1714829Swnj 17210399Ssam /* 17310399Ssam * Must be called at splnet... 17410399Ssam */ 17510399Ssam soabort(so) 17610399Ssam struct socket *so; 17710399Ssam { 17810399Ssam 17912757Ssam return ( 18012757Ssam (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 18112757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 18210399Ssam } 18310399Ssam 18410267Ssam soaccept(so, nam) 18512757Ssam register struct socket *so; 1868300Sroot struct mbuf *nam; 1874927Swnj { 1884927Swnj int s = splnet(); 1894927Swnj int error; 1904927Swnj 19110399Ssam if ((so->so_state & SS_NOFDREF) == 0) 19210399Ssam panic("soaccept: !NOFDREF"); 19310267Ssam so->so_state &= ~SS_NOFDREF; 1948300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 19512757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 1964927Swnj splx(s); 1974927Swnj return (error); 1984927Swnj } 1994927Swnj 20010267Ssam soconnect(so, nam) 20112757Ssam register struct socket *so; 2028300Sroot struct mbuf *nam; 2034786Swnj { 20430414Skarels int s; 2054890Swnj int error; 2064786Swnj 20730414Skarels if (so->so_options & SO_ACCEPTCONN) 20830414Skarels return (EOPNOTSUPP); 20930414Skarels s = splnet(); 21024768Skarels /* 21124768Skarels * If protocol is connection-based, can only connect once. 21224768Skarels * Otherwise, if connected, try to disconnect first. 21324768Skarels * This allows user to disconnect by connecting to, e.g., 21424768Skarels * a null address. 21524768Skarels */ 21624768Skarels if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && 21724768Skarels ((so->so_proto->pr_flags & PR_CONNREQUIRED) || 21824768Skarels (error = sodisconnect(so)))) 2194890Swnj error = EISCONN; 22024768Skarels else 22124768Skarels error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 22224768Skarels (struct mbuf *)0, nam, (struct mbuf *)0); 2234890Swnj splx(s); 2244890Swnj return (error); 2254786Swnj } 2264786Swnj 22712757Ssam soconnect2(so1, so2) 22812757Ssam register struct socket *so1; 22912757Ssam struct socket *so2; 23012757Ssam { 23112757Ssam int s = splnet(); 23212757Ssam int error; 23312757Ssam 23413113Ssam error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 23513113Ssam (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 23612757Ssam splx(s); 23712757Ssam return (error); 23812757Ssam } 23912757Ssam 24026245Skarels sodisconnect(so) 24112757Ssam register struct socket *so; 2424786Swnj { 2434890Swnj int s = splnet(); 2444890Swnj int error; 2454786Swnj 2464890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2474890Swnj error = ENOTCONN; 2484890Swnj goto bad; 2494890Swnj } 2504890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2514890Swnj error = EALREADY; 2524890Swnj goto bad; 2534890Swnj } 2548300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 25526245Skarels (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 2564890Swnj bad: 2574890Swnj splx(s); 2584890Swnj return (error); 2594786Swnj } 2604786Swnj 26151755Smckusick #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK) 2624786Swnj /* 2634890Swnj * Send on a socket. 2644890Swnj * If send must go all at once and message is larger than 2654890Swnj * send buffering, then hard error. 2664890Swnj * Lock against other senders. 2674890Swnj * If must go all at once and not enough room now, then 2684890Swnj * inform user that this would block and do nothing. 26916412Skarels * Otherwise, if nonblocking, send as much as possible. 27041908Skarels * The data to be sent is described by "uio" if nonzero, 27141908Skarels * otherwise by the mbuf chain "top" (which must be null 27241908Skarels * if uio is not). Data provided in mbuf chain must be small 27341908Skarels * enough to send all at once. 27441908Skarels * 27541908Skarels * Returns nonzero on error, timeout or signal; callers 27641908Skarels * must check for short counts if EINTR/ERESTART are returned. 27741908Skarels * Data and control buffers are freed on return. 2784786Swnj */ 27943417Skarels sosend(so, addr, uio, top, control, flags) 2804786Swnj register struct socket *so; 28141908Skarels struct mbuf *addr; 28241908Skarels struct uio *uio; 28341908Skarels struct mbuf *top; 28441908Skarels struct mbuf *control; 2858319Sroot int flags; 2864786Swnj { 28750942Ssklower struct proc *p = curproc; /* XXX */ 28841908Skarels struct mbuf **mp; 28935384Skarels register struct mbuf *m; 29041908Skarels register long space, len, resid; 29141908Skarels int clen = 0, error, s, dontroute, mlen; 29241908Skarels int atomic = sosendallatonce(so) || top; 2934786Swnj 29441908Skarels if (uio) 29541908Skarels resid = uio->uio_resid; 29641908Skarels else 29741908Skarels resid = top->m_pkthdr.len; 298*66800Smckusick /* 299*66800Smckusick * In theory resid should be unsigned. 300*66800Smckusick * However, space must be signed, as it might be less than 0 301*66800Smckusick * if we over-committed, and we must use a signed comparison 302*66800Smckusick * of space and resid. On the other hand, a negative resid 303*66800Smckusick * causes us to loop sending 0-length segments to the protocol. 304*66800Smckusick */ 305*66800Smckusick if (resid < 0) 306*66800Smckusick return (EINVAL); 30712757Ssam dontroute = 30812757Ssam (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 30912757Ssam (so->so_proto->pr_flags & PR_ATOMIC); 31050942Ssklower p->p_stats->p_ru.ru_msgsnd++; 31140632Skarels if (control) 31241908Skarels clen = control->m_len; 31316412Skarels #define snderr(errno) { error = errno; splx(s); goto release; } 31416412Skarels 3156419Sroot restart: 31651755Smckusick if (error = sblock(&so->so_snd, SBLOCKWAIT(flags))) 31741908Skarels goto out; 31816412Skarels do { 31916412Skarels s = splnet(); 32021108Skarels if (so->so_state & SS_CANTSENDMORE) 32116412Skarels snderr(EPIPE); 32237478Ssklower if (so->so_error) 32337478Ssklower snderr(so->so_error); 32416412Skarels if ((so->so_state & SS_ISCONNECTED) == 0) { 32537478Ssklower if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 32649059Ssklower if ((so->so_state & SS_ISCONFIRMING) == 0 && 32749059Ssklower !(resid == 0 && clen != 0)) 32837478Ssklower snderr(ENOTCONN); 32941908Skarels } else if (addr == 0) 33016412Skarels snderr(EDESTADDRREQ); 33116412Skarels } 33241908Skarels space = sbspace(&so->so_snd); 33316412Skarels if (flags & MSG_OOB) 33441908Skarels space += 1024; 33551755Smckusick if (atomic && resid > so->so_snd.sb_hiwat || 33651755Smckusick clen > so->so_snd.sb_hiwat) 33751755Smckusick snderr(EMSGSIZE); 33851755Smckusick if (space < resid + clen && uio && 33941908Skarels (atomic || space < so->so_snd.sb_lowat || space < clen)) { 34041908Skarels if (so->so_state & SS_NBIO) 34141908Skarels snderr(EWOULDBLOCK); 34241908Skarels sbunlock(&so->so_snd); 34343417Skarels error = sbwait(&so->so_snd); 34441908Skarels splx(s); 34541908Skarels if (error) 34641908Skarels goto out; 34741908Skarels goto restart; 34816412Skarels } 34916412Skarels splx(s); 35016412Skarels mp = ⊤ 35141908Skarels space -= clen; 35243417Skarels do { 35343417Skarels if (uio == NULL) { 35441908Skarels /* 35541908Skarels * Data is prepackaged in "top". 35641908Skarels */ 35741908Skarels resid = 0; 35841908Skarels if (flags & MSG_EOR) 35941908Skarels top->m_flags |= M_EOR; 36043417Skarels } else do { 36135384Skarels if (top == 0) { 36235384Skarels MGETHDR(m, M_WAIT, MT_DATA); 36335384Skarels mlen = MHLEN; 36435384Skarels m->m_pkthdr.len = 0; 36535384Skarels m->m_pkthdr.rcvif = (struct ifnet *)0; 36635384Skarels } else { 36735384Skarels MGET(m, M_WAIT, MT_DATA); 36835384Skarels mlen = MLEN; 36935384Skarels } 37041908Skarels if (resid >= MINCLSIZE && space >= MCLBYTES) { 37135384Skarels MCLGET(m, M_WAIT); 37235384Skarels if ((m->m_flags & M_EXT) == 0) 37316412Skarels goto nopages; 37435384Skarels mlen = MCLBYTES; 37535384Skarels #ifdef MAPPED_MBUFS 37641908Skarels len = min(MCLBYTES, resid); 37741908Skarels #else 37860996Skarels if (atomic && top == 0) { 37941908Skarels len = min(MCLBYTES - max_hdr, resid); 38035384Skarels m->m_data += max_hdr; 38146452Ssklower } else 38246452Ssklower len = min(MCLBYTES, resid); 38335384Skarels #endif 38435384Skarels space -= MCLBYTES; 38516412Skarels } else { 38616412Skarels nopages: 38741908Skarels len = min(min(mlen, resid), space); 38821767Skarels space -= len; 38935384Skarels /* 39035384Skarels * For datagram protocols, leave room 39135384Skarels * for protocol headers in first mbuf. 39235384Skarels */ 39335391Skarels if (atomic && top == 0 && len < mlen) 39435384Skarels MH_ALIGN(m, len); 39516412Skarels } 39645515Skarels error = uiomove(mtod(m, caddr_t), (int)len, uio); 39741908Skarels resid = uio->uio_resid; 39816412Skarels m->m_len = len; 39916412Skarels *mp = m; 40035384Skarels top->m_pkthdr.len += len; 40116412Skarels if (error) 40216412Skarels goto release; 40316412Skarels mp = &m->m_next; 40441908Skarels if (resid <= 0) { 40541908Skarels if (flags & MSG_EOR) 40635384Skarels top->m_flags |= M_EOR; 40721108Skarels break; 40835384Skarels } 40935384Skarels } while (space > 0 && atomic); 41035384Skarels if (dontroute) 41135384Skarels so->so_options |= SO_DONTROUTE; 41235384Skarels s = splnet(); /* XXX */ 41335384Skarels error = (*so->so_proto->pr_usrreq)(so, 41435384Skarels (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 41541908Skarels top, addr, control); 41635384Skarels splx(s); 41735384Skarels if (dontroute) 41835384Skarels so->so_options &= ~SO_DONTROUTE; 41941908Skarels clen = 0; 42041908Skarels control = 0; 42135384Skarels top = 0; 42235384Skarels mp = ⊤ 42335384Skarels if (error) 42435384Skarels goto release; 42541908Skarels } while (resid && space > 0); 42641908Skarels } while (resid); 4274890Swnj 4284786Swnj release: 4294890Swnj sbunlock(&so->so_snd); 43041908Skarels out: 4316419Sroot if (top) 4326419Sroot m_freem(top); 43341908Skarels if (control) 43441908Skarels m_freem(control); 4354786Swnj return (error); 4364786Swnj } 4374786Swnj 43825629Skarels /* 43925629Skarels * Implement receive operations on a socket. 44025629Skarels * We depend on the way that records are added to the sockbuf 44125629Skarels * by sbappend*. In particular, each record (mbufs linked through m_next) 44225629Skarels * must begin with an address if the protocol so specifies, 44341908Skarels * followed by an optional mbuf or mbufs containing ancillary data, 44441908Skarels * and then zero or more mbufs of data. 44525629Skarels * In order to avoid blocking network interrupts for the entire time here, 44625629Skarels * we splx() while doing the actual copy to user space. 44725629Skarels * Although the sockbuf is locked, new data may still be appended, 44825629Skarels * and thus we must maintain consistency of the sockbuf during that time. 44945515Skarels * 45041908Skarels * The caller may receive the data as a single mbuf chain by supplying 45143417Skarels * an mbuf **mp0 for use in returning the chain. The uio is then used 45241908Skarels * only for the count in uio_resid. 45325629Skarels */ 45443417Skarels soreceive(so, paddr, uio, mp0, controlp, flagsp) 4554786Swnj register struct socket *so; 45641908Skarels struct mbuf **paddr; 45741908Skarels struct uio *uio; 45843417Skarels struct mbuf **mp0; 45941908Skarels struct mbuf **controlp; 46035384Skarels int *flagsp; 4614786Swnj { 46243417Skarels register struct mbuf *m, **mp; 46343417Skarels register int flags, len, error, s, offset; 46412757Ssam struct protosw *pr = so->so_proto; 46541908Skarels struct mbuf *nextrecord; 46641908Skarels int moff, type; 46758301Smckusick int orig_resid = uio->uio_resid; 4684786Swnj 46943417Skarels mp = mp0; 47041908Skarels if (paddr) 47141908Skarels *paddr = 0; 47235384Skarels if (controlp) 47335384Skarels *controlp = 0; 47435384Skarels if (flagsp) 47535384Skarels flags = *flagsp &~ MSG_EOR; 47645515Skarels else 47735384Skarels flags = 0; 47812757Ssam if (flags & MSG_OOB) { 4799635Ssam m = m_get(M_WAIT, MT_DATA); 48012757Ssam error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 48124768Skarels m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); 4828594Sroot if (error) 48310137Ssam goto bad; 4848319Sroot do { 48541908Skarels error = uiomove(mtod(m, caddr_t), 48641908Skarels (int) min(uio->uio_resid, m->m_len), uio); 4878319Sroot m = m_free(m); 4888594Sroot } while (uio->uio_resid && error == 0 && m); 48910137Ssam bad: 4908319Sroot if (m) 4918771Sroot m_freem(m); 4928594Sroot return (error); 4938319Sroot } 49441908Skarels if (mp) 49541908Skarels *mp = (struct mbuf *)0; 49643417Skarels if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) 49735384Skarels (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 49835384Skarels (struct mbuf *)0, (struct mbuf *)0); 4998319Sroot 5004890Swnj restart: 50151755Smckusick if (error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) 50240706Skarels return (error); 5038835Sroot s = splnet(); 5044890Swnj 50537478Ssklower m = so->so_rcv.sb_mb; 50644383Skarels /* 50744383Skarels * If we have less data than requested, block awaiting more 50844383Skarels * (subject to any timeout) if: 50944383Skarels * 1. the current count is less than the low water mark, or 51044383Skarels * 2. MSG_WAITALL is set, and it is possible to do the entire 51144383Skarels * receive operation at once if we block (resid <= hiwat). 51251755Smckusick * 3. MSG_DONTWAIT is not set 51344383Skarels * If MSG_WAITALL is set but resid is larger than the receive buffer, 51444383Skarels * we have to do the receive in sections, and thus risk returning 51544383Skarels * a short count if a timeout or signal occurs after we start. 51644383Skarels */ 51751755Smckusick if (m == 0 || ((flags & MSG_DONTWAIT) == 0 && 51851755Smckusick so->so_rcv.sb_cc < uio->uio_resid) && 51944383Skarels (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || 52050942Ssklower ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && 52158301Smckusick m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0) { 52241908Skarels #ifdef DIAGNOSTIC 52341908Skarels if (m == 0 && so->so_rcv.sb_cc) 52437478Ssklower panic("receive 1"); 52541908Skarels #endif 5265168Swnj if (so->so_error) { 52746479Skarels if (m) 52851022Ssklower goto dontblock; 5295168Swnj error = so->so_error; 53046479Skarels if ((flags & MSG_PEEK) == 0) 53146479Skarels so->so_error = 0; 5325168Swnj goto release; 5335168Swnj } 53446479Skarels if (so->so_state & SS_CANTRCVMORE) { 53546479Skarels if (m) 53651022Ssklower goto dontblock; 53746479Skarels else 53846479Skarels goto release; 53946479Skarels } 54050942Ssklower for (; m; m = m->m_next) 54150942Ssklower if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { 54250942Ssklower m = so->so_rcv.sb_mb; 54350942Ssklower goto dontblock; 54450942Ssklower } 54538584Skarels if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && 54632567Sbostic (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 54732567Sbostic error = ENOTCONN; 54832567Sbostic goto release; 5494890Swnj } 55043417Skarels if (uio->uio_resid == 0) 55125629Skarels goto release; 55251755Smckusick if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { 55332567Sbostic error = EWOULDBLOCK; 55432567Sbostic goto release; 55532567Sbostic } 5564890Swnj sbunlock(&so->so_rcv); 55743417Skarels error = sbwait(&so->so_rcv); 5585012Swnj splx(s); 55941908Skarels if (error) 56041908Skarels return (error); 5614890Swnj goto restart; 5624786Swnj } 56350942Ssklower dontblock: 56452926Smckusick if (uio->uio_procp) 56552926Smckusick uio->uio_procp->p_stats->p_ru.ru_msgrcv++; 56635384Skarels nextrecord = m->m_nextpkt; 56712757Ssam if (pr->pr_flags & PR_ADDR) { 56841908Skarels #ifdef DIAGNOSTIC 56925629Skarels if (m->m_type != MT_SONAME) 57016993Skarels panic("receive 1a"); 57141908Skarels #endif 57258301Smckusick orig_resid = 0; 57316993Skarels if (flags & MSG_PEEK) { 57441908Skarels if (paddr) 57541908Skarels *paddr = m_copy(m, 0, m->m_len); 57625629Skarels m = m->m_next; 57716993Skarels } else { 57825629Skarels sbfree(&so->so_rcv, m); 57941908Skarels if (paddr) { 58041908Skarels *paddr = m; 58135384Skarels so->so_rcv.sb_mb = m->m_next; 58235384Skarels m->m_next = 0; 58335384Skarels m = so->so_rcv.sb_mb; 58425629Skarels } else { 58526958Skarels MFREE(m, so->so_rcv.sb_mb); 58626958Skarels m = so->so_rcv.sb_mb; 58725629Skarels } 58816993Skarels } 58916993Skarels } 59041908Skarels while (m && m->m_type == MT_CONTROL && error == 0) { 59116993Skarels if (flags & MSG_PEEK) { 59235384Skarels if (controlp) 59335384Skarels *controlp = m_copy(m, 0, m->m_len); 59435384Skarels m = m->m_next; 59535384Skarels } else { 59635384Skarels sbfree(&so->so_rcv, m); 59735384Skarels if (controlp) { 59843097Ssklower if (pr->pr_domain->dom_externalize && 59943097Ssklower mtod(m, struct cmsghdr *)->cmsg_type == 60043097Ssklower SCM_RIGHTS) 60141908Skarels error = (*pr->pr_domain->dom_externalize)(m); 60235384Skarels *controlp = m; 60335384Skarels so->so_rcv.sb_mb = m->m_next; 60435384Skarels m->m_next = 0; 60535384Skarels m = so->so_rcv.sb_mb; 60635384Skarels } else { 60735384Skarels MFREE(m, so->so_rcv.sb_mb); 60835384Skarels m = so->so_rcv.sb_mb; 60935384Skarels } 61035384Skarels } 61158301Smckusick if (controlp) { 61258301Smckusick orig_resid = 0; 61341908Skarels controlp = &(*controlp)->m_next; 61458301Smckusick } 61535384Skarels } 61641908Skarels if (m) { 61744383Skarels if ((flags & MSG_PEEK) == 0) 61844383Skarels m->m_nextpkt = nextrecord; 61941908Skarels type = m->m_type; 62046452Ssklower if (type == MT_OOBDATA) 62146452Ssklower flags |= MSG_OOB; 62241908Skarels } 6238319Sroot moff = 0; 62432092Skarels offset = 0; 62546452Ssklower while (m && uio->uio_resid > 0 && error == 0) { 62646452Ssklower if (m->m_type == MT_OOBDATA) { 62746452Ssklower if (type != MT_OOBDATA) 62846452Ssklower break; 62946452Ssklower } else if (type == MT_OOBDATA) 63046452Ssklower break; 63141908Skarels #ifdef DIAGNOSTIC 63235384Skarels else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 63325629Skarels panic("receive 3"); 63441908Skarels #endif 6357747Sroot so->so_state &= ~SS_RCVATMARK; 63643417Skarels len = uio->uio_resid; 63732092Skarels if (so->so_oobmark && len > so->so_oobmark - offset) 63832092Skarels len = so->so_oobmark - offset; 63921767Skarels if (len > m->m_len - moff) 6408319Sroot len = m->m_len - moff; 64141908Skarels /* 64241908Skarels * If mp is set, just pass back the mbufs. 64341908Skarels * Otherwise copy them out via the uio, then free. 64441908Skarels * Sockbuf must be consistent here (points to current mbuf, 64541908Skarels * it points to next record) when we drop priority; 64641908Skarels * we must note any additions to the sockbuf when we 64741908Skarels * block interrupts again. 64841908Skarels */ 64941908Skarels if (mp == 0) { 65041908Skarels splx(s); 65141908Skarels error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); 65241908Skarels s = splnet(); 65343417Skarels } else 65443417Skarels uio->uio_resid -= len; 65521767Skarels if (len == m->m_len - moff) { 65650942Ssklower if (m->m_flags & M_EOR) 65750942Ssklower flags |= MSG_EOR; 65825629Skarels if (flags & MSG_PEEK) { 65925629Skarels m = m->m_next; 66025629Skarels moff = 0; 66125629Skarels } else { 66235384Skarels nextrecord = m->m_nextpkt; 66325629Skarels sbfree(&so->so_rcv, m); 66441908Skarels if (mp) { 66541908Skarels *mp = m; 66641908Skarels mp = &m->m_next; 66743417Skarels so->so_rcv.sb_mb = m = m->m_next; 66843417Skarels *mp = (struct mbuf *)0; 66941908Skarels } else { 67041908Skarels MFREE(m, so->so_rcv.sb_mb); 67141908Skarels m = so->so_rcv.sb_mb; 67241908Skarels } 67326958Skarels if (m) 67435384Skarels m->m_nextpkt = nextrecord; 67525629Skarels } 6764786Swnj } else { 67712757Ssam if (flags & MSG_PEEK) 6788319Sroot moff += len; 6798319Sroot else { 68043417Skarels if (mp) 68143417Skarels *mp = m_copym(m, 0, len, M_WAIT); 68235384Skarels m->m_data += len; 6838319Sroot m->m_len -= len; 6848319Sroot so->so_rcv.sb_cc -= len; 6858319Sroot } 6864786Swnj } 68732092Skarels if (so->so_oobmark) { 68832092Skarels if ((flags & MSG_PEEK) == 0) { 68932092Skarels so->so_oobmark -= len; 69032092Skarels if (so->so_oobmark == 0) { 69132092Skarels so->so_state |= SS_RCVATMARK; 69232092Skarels break; 69332092Skarels } 69458530Storek } else { 69532092Skarels offset += len; 69658530Storek if (offset == so->so_oobmark) 69758530Storek break; 69858530Storek } 6997747Sroot } 70050942Ssklower if (flags & MSG_EOR) 70140632Skarels break; 70241908Skarels /* 70341908Skarels * If the MSG_WAITALL flag is set (for non-atomic socket), 70443417Skarels * we must not quit until "uio->uio_resid == 0" or an error 70541908Skarels * termination. If a signal/timeout occurs, return 70643417Skarels * with a short count but without error. 70741908Skarels * Keep sockbuf locked against other readers. 70841908Skarels */ 70943417Skarels while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 && 71058301Smckusick !sosendallatonce(so) && !nextrecord) { 71146479Skarels if (so->so_error || so->so_state & SS_CANTRCVMORE) 71246479Skarels break; 71341908Skarels error = sbwait(&so->so_rcv); 71441908Skarels if (error) { 71541908Skarels sbunlock(&so->so_rcv); 71641908Skarels splx(s); 71741908Skarels return (0); 71841908Skarels } 71950942Ssklower if (m = so->so_rcv.sb_mb) 72041908Skarels nextrecord = m->m_nextpkt; 72141908Skarels } 72216993Skarels } 72358301Smckusick 72458301Smckusick if (m && pr->pr_flags & PR_ATOMIC) { 72558301Smckusick flags |= MSG_TRUNC; 72658301Smckusick if ((flags & MSG_PEEK) == 0) 72758301Smckusick (void) sbdroprecord(&so->so_rcv); 72858301Smckusick } 72916993Skarels if ((flags & MSG_PEEK) == 0) { 73026500Skarels if (m == 0) 73116993Skarels so->so_rcv.sb_mb = nextrecord; 73216993Skarels if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 73316993Skarels (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 73437478Ssklower (struct mbuf *)flags, (struct mbuf *)0, 73537478Ssklower (struct mbuf *)0); 73616993Skarels } 73758301Smckusick if (orig_resid == uio->uio_resid && orig_resid && 73858301Smckusick (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { 73958301Smckusick sbunlock(&so->so_rcv); 74058301Smckusick splx(s); 74158301Smckusick goto restart; 74258301Smckusick } 74358301Smckusick 74435384Skarels if (flagsp) 74535384Skarels *flagsp |= flags; 7464890Swnj release: 7474916Swnj sbunlock(&so->so_rcv); 7484890Swnj splx(s); 7494916Swnj return (error); 7504786Swnj } 7514786Swnj 75210267Ssam soshutdown(so, how) 75312757Ssam register struct socket *so; 75412757Ssam register int how; 75510267Ssam { 75612757Ssam register struct protosw *pr = so->so_proto; 75710267Ssam 75810267Ssam how++; 75912757Ssam if (how & FREAD) 76012757Ssam sorflush(so); 76110267Ssam if (how & FWRITE) 76212757Ssam return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 76312757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 76410267Ssam return (0); 76510267Ssam } 76610267Ssam 76712757Ssam sorflush(so) 76812757Ssam register struct socket *so; 76912757Ssam { 77012757Ssam register struct sockbuf *sb = &so->so_rcv; 77112757Ssam register struct protosw *pr = so->so_proto; 77212757Ssam register int s; 77312757Ssam struct sockbuf asb; 77412757Ssam 77540706Skarels sb->sb_flags |= SB_NOINTR; 77651755Smckusick (void) sblock(sb, M_WAITOK); 77712757Ssam s = splimp(); 77812757Ssam socantrcvmore(so); 77912757Ssam sbunlock(sb); 78012757Ssam asb = *sb; 78112757Ssam bzero((caddr_t)sb, sizeof (*sb)); 78212757Ssam splx(s); 78316993Skarels if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 78416993Skarels (*pr->pr_domain->dom_dispose)(asb.sb_mb); 78512757Ssam sbrelease(&asb); 78612757Ssam } 78712757Ssam 78818553Skarels sosetopt(so, level, optname, m0) 78912757Ssam register struct socket *so; 79010267Ssam int level, optname; 79118553Skarels struct mbuf *m0; 79210267Ssam { 79317158Ssam int error = 0; 79418553Skarels register struct mbuf *m = m0; 79510267Ssam 79617158Ssam if (level != SOL_SOCKET) { 79718369Skarels if (so->so_proto && so->so_proto->pr_ctloutput) 79818369Skarels return ((*so->so_proto->pr_ctloutput) 79918553Skarels (PRCO_SETOPT, so, level, optname, &m0)); 80018369Skarels error = ENOPROTOOPT; 80118369Skarels } else { 80218369Skarels switch (optname) { 80310267Ssam 80418369Skarels case SO_LINGER: 80518369Skarels if (m == NULL || m->m_len != sizeof (struct linger)) { 80618369Skarels error = EINVAL; 80718369Skarels goto bad; 80818369Skarels } 80918369Skarels so->so_linger = mtod(m, struct linger *)->l_linger; 81018369Skarels /* fall thru... */ 81117158Ssam 81218369Skarels case SO_DEBUG: 81318369Skarels case SO_KEEPALIVE: 81418369Skarels case SO_DONTROUTE: 81518369Skarels case SO_USELOOPBACK: 81618369Skarels case SO_BROADCAST: 81718369Skarels case SO_REUSEADDR: 81855349Ssklower case SO_REUSEPORT: 81927191Skarels case SO_OOBINLINE: 82018369Skarels if (m == NULL || m->m_len < sizeof (int)) { 82118369Skarels error = EINVAL; 82218369Skarels goto bad; 82318369Skarels } 82418369Skarels if (*mtod(m, int *)) 82518369Skarels so->so_options |= optname; 82618369Skarels else 82718369Skarels so->so_options &= ~optname; 82818369Skarels break; 82918369Skarels 83018369Skarels case SO_SNDBUF: 83141908Skarels case SO_RCVBUF: 83240706Skarels case SO_SNDLOWAT: 83341908Skarels case SO_RCVLOWAT: 83418369Skarels if (m == NULL || m->m_len < sizeof (int)) { 83518369Skarels error = EINVAL; 83618369Skarels goto bad; 83718369Skarels } 83818369Skarels switch (optname) { 83918369Skarels 84018369Skarels case SO_SNDBUF: 84118369Skarels case SO_RCVBUF: 84241908Skarels if (sbreserve(optname == SO_SNDBUF ? 84341908Skarels &so->so_snd : &so->so_rcv, 84441908Skarels (u_long) *mtod(m, int *)) == 0) { 84518369Skarels error = ENOBUFS; 84618369Skarels goto bad; 84718369Skarels } 84818369Skarels break; 84918369Skarels 85018369Skarels case SO_SNDLOWAT: 85141908Skarels so->so_snd.sb_lowat = *mtod(m, int *); 85241908Skarels break; 85318369Skarels case SO_RCVLOWAT: 85441908Skarels so->so_rcv.sb_lowat = *mtod(m, int *); 85518369Skarels break; 85644721Skarels } 85744721Skarels break; 85844721Skarels 85944721Skarels case SO_SNDTIMEO: 86044721Skarels case SO_RCVTIMEO: 86144721Skarels { 86244721Skarels struct timeval *tv; 86344721Skarels short val; 86444721Skarels 86544721Skarels if (m == NULL || m->m_len < sizeof (*tv)) { 86644721Skarels error = EINVAL; 86744721Skarels goto bad; 86844721Skarels } 86944721Skarels tv = mtod(m, struct timeval *); 87044721Skarels if (tv->tv_sec > SHRT_MAX / hz - hz) { 87144721Skarels error = EDOM; 87244721Skarels goto bad; 87344721Skarels } 87444721Skarels val = tv->tv_sec * hz + tv->tv_usec / tick; 87544721Skarels 87644721Skarels switch (optname) { 87744721Skarels 87818369Skarels case SO_SNDTIMEO: 87944721Skarels so->so_snd.sb_timeo = val; 88041908Skarels break; 88118369Skarels case SO_RCVTIMEO: 88244721Skarels so->so_rcv.sb_timeo = val; 88318369Skarels break; 88418369Skarels } 88518369Skarels break; 88644721Skarels } 88718369Skarels 88818369Skarels default: 88918369Skarels error = ENOPROTOOPT; 89018369Skarels break; 89117158Ssam } 89265370Sbostic if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) { 89350942Ssklower (void) ((*so->so_proto->pr_ctloutput) 89450942Ssklower (PRCO_SETOPT, so, level, optname, &m0)); 89565370Sbostic m = NULL; /* freed by protocol */ 89665370Sbostic } 89710267Ssam } 89817158Ssam bad: 89917158Ssam if (m) 90017158Ssam (void) m_free(m); 90117158Ssam return (error); 90210267Ssam } 90310267Ssam 90417158Ssam sogetopt(so, level, optname, mp) 90512757Ssam register struct socket *so; 90610267Ssam int level, optname; 90717158Ssam struct mbuf **mp; 90817158Ssam { 90912757Ssam register struct mbuf *m; 91010267Ssam 91118369Skarels if (level != SOL_SOCKET) { 91218369Skarels if (so->so_proto && so->so_proto->pr_ctloutput) { 91318369Skarels return ((*so->so_proto->pr_ctloutput) 91418369Skarels (PRCO_GETOPT, so, level, optname, mp)); 91545515Skarels } else 91618369Skarels return (ENOPROTOOPT); 91718369Skarels } else { 91817158Ssam m = m_get(M_WAIT, MT_SOOPTS); 91925502Skarels m->m_len = sizeof (int); 92025502Skarels 92118369Skarels switch (optname) { 92217158Ssam 92318369Skarels case SO_LINGER: 92418369Skarels m->m_len = sizeof (struct linger); 92518369Skarels mtod(m, struct linger *)->l_onoff = 92618369Skarels so->so_options & SO_LINGER; 92718369Skarels mtod(m, struct linger *)->l_linger = so->so_linger; 92818369Skarels break; 92910267Ssam 93018369Skarels case SO_USELOOPBACK: 93118369Skarels case SO_DONTROUTE: 93218369Skarels case SO_DEBUG: 93318369Skarels case SO_KEEPALIVE: 93418369Skarels case SO_REUSEADDR: 93555349Ssklower case SO_REUSEPORT: 93618369Skarels case SO_BROADCAST: 93727191Skarels case SO_OOBINLINE: 93818369Skarels *mtod(m, int *) = so->so_options & optname; 93918369Skarels break; 94018369Skarels 94125502Skarels case SO_TYPE: 94225502Skarels *mtod(m, int *) = so->so_type; 94325502Skarels break; 94425502Skarels 94524768Skarels case SO_ERROR: 94624768Skarels *mtod(m, int *) = so->so_error; 94724768Skarels so->so_error = 0; 94824768Skarels break; 94924768Skarels 95018369Skarels case SO_SNDBUF: 95118369Skarels *mtod(m, int *) = so->so_snd.sb_hiwat; 95218369Skarels break; 95318369Skarels 95418369Skarels case SO_RCVBUF: 95518369Skarels *mtod(m, int *) = so->so_rcv.sb_hiwat; 95618369Skarels break; 95718369Skarels 95818369Skarels case SO_SNDLOWAT: 95918369Skarels *mtod(m, int *) = so->so_snd.sb_lowat; 96018369Skarels break; 96118369Skarels 96218369Skarels case SO_RCVLOWAT: 96318369Skarels *mtod(m, int *) = so->so_rcv.sb_lowat; 96418369Skarels break; 96518369Skarels 96618369Skarels case SO_SNDTIMEO: 96744721Skarels case SO_RCVTIMEO: 96844721Skarels { 96944721Skarels int val = (optname == SO_SNDTIMEO ? 97044721Skarels so->so_snd.sb_timeo : so->so_rcv.sb_timeo); 97118369Skarels 97244721Skarels m->m_len = sizeof(struct timeval); 97344721Skarels mtod(m, struct timeval *)->tv_sec = val / hz; 97444721Skarels mtod(m, struct timeval *)->tv_usec = 97544721Skarels (val % hz) / tick; 97618369Skarels break; 97744721Skarels } 97818369Skarels 97918369Skarels default: 98026362Skarels (void)m_free(m); 98118369Skarels return (ENOPROTOOPT); 98218369Skarels } 98318369Skarels *mp = m; 98418369Skarels return (0); 98510267Ssam } 98610267Ssam } 98710267Ssam 9885423Swnj sohasoutofband(so) 98912757Ssam register struct socket *so; 9905423Swnj { 99123233Skarels struct proc *p; 9925423Swnj 99337478Ssklower if (so->so_pgid < 0) 99437478Ssklower gsignal(-so->so_pgid, SIGURG); 99537478Ssklower else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) 99623233Skarels psignal(p, SIGURG); 99752526Smckusick selwakeup(&so->so_rcv.sb_sel); 9985423Swnj } 999