123421Smckusick /* 2*41908Skarels * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California. 333185Sbostic * All rights reserved. 423421Smckusick * 533185Sbostic * Redistribution and use in source and binary forms are permitted 634861Sbostic * provided that the above copyright notice and this paragraph are 734861Sbostic * duplicated in all such forms and that any documentation, 834861Sbostic * advertising materials, and other materials related to such 934861Sbostic * distribution and use acknowledge that the software was developed 1034861Sbostic * by the University of California, Berkeley. The name of the 1134861Sbostic * University may not be used to endorse or promote products derived 1234861Sbostic * from this software without specific prior written permission. 1334861Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434861Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534861Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633185Sbostic * 17*41908Skarels * @(#)uipc_socket.c 7.18 (Berkeley) 05/14/90 1823421Smckusick */ 194786Swnj 2017102Sbloom #include "param.h" 2117102Sbloom #include "user.h" 2217102Sbloom #include "proc.h" 2317102Sbloom #include "file.h" 2435384Skarels #include "malloc.h" 2517102Sbloom #include "mbuf.h" 2617102Sbloom #include "domain.h" 2717102Sbloom #include "protosw.h" 2817102Sbloom #include "socket.h" 2917102Sbloom #include "socketvar.h" 304786Swnj 314786Swnj /* 328300Sroot * Socket operation routines. 338300Sroot * These routines are called by the routines in 348300Sroot * sys_socket.c or from a system process, and 358300Sroot * implement the semantics of socket operations by 368300Sroot * switching out to the protocol specific routines. 3712757Ssam * 3812757Ssam * TODO: 3912757Ssam * test socketpair 4021767Skarels * clean up async 4112757Ssam * out-of-band is a kludge 424786Swnj */ 438594Sroot /*ARGSUSED*/ 4410267Ssam socreate(dom, aso, type, proto) 454786Swnj struct socket **aso; 4612757Ssam register int type; 4712757Ssam int proto; 484786Swnj { 494786Swnj register struct protosw *prp; 504786Swnj register struct socket *so; 5112757Ssam register int error; 524786Swnj 534890Swnj if (proto) 5421767Skarels prp = pffindproto(dom, proto, type); 554890Swnj else 569168Ssam prp = pffindtype(dom, type); 574890Swnj if (prp == 0) 584890Swnj return (EPROTONOSUPPORT); 598300Sroot if (prp->pr_type != type) 608300Sroot return (EPROTOTYPE); 6137478Ssklower MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT); 6237478Ssklower bzero((caddr_t)so, sizeof(*so)); 639168Ssam so->so_type = type; 646214Swnj if (u.u_uid == 0) 656214Swnj so->so_state = SS_PRIV; 664786Swnj so->so_proto = prp; 6712757Ssam error = 6812757Ssam (*prp->pr_usrreq)(so, PRU_ATTACH, 6921767Skarels (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0); 704979Swnj if (error) { 717507Sroot so->so_state |= SS_NOFDREF; 727180Swnj sofree(so); 734890Swnj return (error); 744786Swnj } 754786Swnj *aso = so; 764786Swnj return (0); 774786Swnj } 784786Swnj 7910267Ssam sobind(so, nam) 808300Sroot struct socket *so; 818300Sroot struct mbuf *nam; 828300Sroot { 838300Sroot int s = splnet(); 848300Sroot int error; 858300Sroot 86*41908Skarels error = 87*41908Skarels (*so->so_proto->pr_usrreq)(so, PRU_BIND, 8812757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 898300Sroot splx(s); 908300Sroot return (error); 918300Sroot } 928300Sroot 938300Sroot solisten(so, backlog) 9412757Ssam register struct socket *so; 958300Sroot int backlog; 968300Sroot { 9712757Ssam int s = splnet(), error; 988300Sroot 9912757Ssam error = 10012757Ssam (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 10112757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 1028300Sroot if (error) { 1038300Sroot splx(s); 1048300Sroot return (error); 1058300Sroot } 10638584Skarels if (so->so_q == 0) 1078300Sroot so->so_options |= SO_ACCEPTCONN; 1088300Sroot if (backlog < 0) 1098300Sroot backlog = 0; 11035384Skarels so->so_qlimit = min(backlog, SOMAXCONN); 11112493Ssam splx(s); 1128300Sroot return (0); 1138300Sroot } 1148300Sroot 1154916Swnj sofree(so) 11612757Ssam register struct socket *so; 1174916Swnj { 1184916Swnj 11931810Skarels if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 12031810Skarels return; 1217507Sroot if (so->so_head) { 1227507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1237507Sroot panic("sofree dq"); 1247507Sroot so->so_head = 0; 1257507Sroot } 1264950Swnj sbrelease(&so->so_snd); 12712757Ssam sorflush(so); 12837478Ssklower FREE(so, M_SOCKET); 1294916Swnj } 1304916Swnj 1314786Swnj /* 1324890Swnj * Close a socket on last file table reference removal. 1334890Swnj * Initiate disconnect if connected. 1344890Swnj * Free socket when disconnect complete. 1354829Swnj */ 13612757Ssam soclose(so) 1374829Swnj register struct socket *so; 1384829Swnj { 1394890Swnj int s = splnet(); /* conservative */ 14033372Sbostic int error = 0; 1414829Swnj 1427507Sroot if (so->so_options & SO_ACCEPTCONN) { 14338584Skarels while (so->so_q0) 14410399Ssam (void) soabort(so->so_q0); 14538584Skarels while (so->so_q) 14610399Ssam (void) soabort(so->so_q); 1477507Sroot } 1484890Swnj if (so->so_pcb == 0) 1494890Swnj goto discard; 1504890Swnj if (so->so_state & SS_ISCONNECTED) { 1514890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 15226245Skarels error = sodisconnect(so); 15312757Ssam if (error) 15412757Ssam goto drop; 1554890Swnj } 15610267Ssam if (so->so_options & SO_LINGER) { 1575281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 15812757Ssam (so->so_state & SS_NBIO)) 15912757Ssam goto drop; 1605281Sroot while (so->so_state & SS_ISCONNECTED) 16140706Skarels if (error = tsleep((caddr_t)&so->so_timeo, 16240706Skarels PSOCK | PCATCH, netcls, so->so_linger)) 16340706Skarels break; 1644890Swnj } 1654890Swnj } 1665580Sroot drop: 1676880Ssam if (so->so_pcb) { 16812757Ssam int error2 = 16912757Ssam (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 17012757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 17112757Ssam if (error == 0) 17212757Ssam error = error2; 1736880Ssam } 1744890Swnj discard: 17510399Ssam if (so->so_state & SS_NOFDREF) 17610399Ssam panic("soclose: NOFDREF"); 1777507Sroot so->so_state |= SS_NOFDREF; 1784950Swnj sofree(so); 1794890Swnj splx(s); 18012757Ssam return (error); 1814829Swnj } 1824829Swnj 18310399Ssam /* 18410399Ssam * Must be called at splnet... 18510399Ssam */ 18610399Ssam soabort(so) 18710399Ssam struct socket *so; 18810399Ssam { 18910399Ssam 19012757Ssam return ( 19112757Ssam (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 19212757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 19310399Ssam } 19410399Ssam 19510267Ssam soaccept(so, nam) 19612757Ssam register struct socket *so; 1978300Sroot struct mbuf *nam; 1984927Swnj { 1994927Swnj int s = splnet(); 2004927Swnj int error; 2014927Swnj 20210399Ssam if ((so->so_state & SS_NOFDREF) == 0) 20310399Ssam panic("soaccept: !NOFDREF"); 20410267Ssam so->so_state &= ~SS_NOFDREF; 2058300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 20612757Ssam (struct mbuf *)0, nam, (struct mbuf *)0); 2074927Swnj splx(s); 2084927Swnj return (error); 2094927Swnj } 2104927Swnj 21110267Ssam soconnect(so, nam) 21212757Ssam register struct socket *so; 2138300Sroot struct mbuf *nam; 2144786Swnj { 21530414Skarels int s; 2164890Swnj int error; 2174786Swnj 21830414Skarels if (so->so_options & SO_ACCEPTCONN) 21930414Skarels return (EOPNOTSUPP); 22030414Skarels s = splnet(); 22124768Skarels /* 22224768Skarels * If protocol is connection-based, can only connect once. 22324768Skarels * Otherwise, if connected, try to disconnect first. 22424768Skarels * This allows user to disconnect by connecting to, e.g., 22524768Skarels * a null address. 22624768Skarels */ 22724768Skarels if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && 22824768Skarels ((so->so_proto->pr_flags & PR_CONNREQUIRED) || 22924768Skarels (error = sodisconnect(so)))) 2304890Swnj error = EISCONN; 23124768Skarels else 23224768Skarels error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 23324768Skarels (struct mbuf *)0, nam, (struct mbuf *)0); 2344890Swnj splx(s); 2354890Swnj return (error); 2364786Swnj } 2374786Swnj 23812757Ssam soconnect2(so1, so2) 23912757Ssam register struct socket *so1; 24012757Ssam struct socket *so2; 24112757Ssam { 24212757Ssam int s = splnet(); 24312757Ssam int error; 24412757Ssam 24513113Ssam error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2, 24613113Ssam (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); 24712757Ssam splx(s); 24812757Ssam return (error); 24912757Ssam } 25012757Ssam 25126245Skarels sodisconnect(so) 25212757Ssam register struct socket *so; 2534786Swnj { 2544890Swnj int s = splnet(); 2554890Swnj int error; 2564786Swnj 2574890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2584890Swnj error = ENOTCONN; 2594890Swnj goto bad; 2604890Swnj } 2614890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2624890Swnj error = EALREADY; 2634890Swnj goto bad; 2644890Swnj } 2658300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 26626245Skarels (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); 2674890Swnj bad: 2684890Swnj splx(s); 2694890Swnj return (error); 2704786Swnj } 2714786Swnj 2724786Swnj /* 2734890Swnj * Send on a socket. 2744890Swnj * If send must go all at once and message is larger than 2754890Swnj * send buffering, then hard error. 2764890Swnj * Lock against other senders. 2774890Swnj * If must go all at once and not enough room now, then 2784890Swnj * inform user that this would block and do nothing. 27916412Skarels * Otherwise, if nonblocking, send as much as possible. 280*41908Skarels * The data to be sent is described by "uio" if nonzero, 281*41908Skarels * otherwise by the mbuf chain "top" (which must be null 282*41908Skarels * if uio is not). Data provided in mbuf chain must be small 283*41908Skarels * enough to send all at once. 284*41908Skarels * 285*41908Skarels * Returns nonzero on error, timeout or signal; callers 286*41908Skarels * must check for short counts if EINTR/ERESTART are returned. 287*41908Skarels * Data and control buffers are freed on return. 2884786Swnj */ 289*41908Skarels sosend(so, addr, uio, top, control, flags/*, sbwait_func, sbwait_arg*/) 2904786Swnj register struct socket *so; 291*41908Skarels struct mbuf *addr; 292*41908Skarels struct uio *uio; 293*41908Skarels struct mbuf *top; 294*41908Skarels struct mbuf *control; 2958319Sroot int flags; 296*41908Skarels /* 297*41908Skarels int (*sbwait_func)(); 298*41908Skarels caddr_t sbwait_arg; 299*41908Skarels */ 3004786Swnj { 301*41908Skarels struct mbuf **mp; 30235384Skarels register struct mbuf *m; 303*41908Skarels register long space, len, resid; 304*41908Skarels int clen = 0, error, s, dontroute, mlen; 305*41908Skarels int atomic = sosendallatonce(so) || top; 3064786Swnj 307*41908Skarels if (uio) 308*41908Skarels resid = uio->uio_resid; 309*41908Skarels else 310*41908Skarels resid = top->m_pkthdr.len; 31112757Ssam dontroute = 31212757Ssam (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && 31312757Ssam (so->so_proto->pr_flags & PR_ATOMIC); 31416412Skarels u.u_ru.ru_msgsnd++; 31540632Skarels if (control) 316*41908Skarels clen = control->m_len; 31716412Skarels #define snderr(errno) { error = errno; splx(s); goto release; } 31816412Skarels 3196419Sroot restart: 32040706Skarels if (error = sblock(&so->so_snd)) 321*41908Skarels goto out; 32216412Skarels do { 32316412Skarels s = splnet(); 32421108Skarels if (so->so_state & SS_CANTSENDMORE) 32516412Skarels snderr(EPIPE); 32637478Ssklower if (so->so_error) 32737478Ssklower snderr(so->so_error); 32816412Skarels if ((so->so_state & SS_ISCONNECTED) == 0) { 32937478Ssklower if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 33038584Skarels if ((so->so_state & SS_ISCONFIRMING) == 0) 33137478Ssklower snderr(ENOTCONN); 332*41908Skarels } else if (addr == 0) 33316412Skarels snderr(EDESTADDRREQ); 33416412Skarels } 335*41908Skarels space = sbspace(&so->so_snd); 33616412Skarels if (flags & MSG_OOB) 337*41908Skarels space += 1024; 338*41908Skarels if (space < resid + clen && 339*41908Skarels (atomic || space < so->so_snd.sb_lowat || space < clen)) { 340*41908Skarels if (atomic && resid > so->so_snd.sb_hiwat || 341*41908Skarels clen > so->so_snd.sb_hiwat) 342*41908Skarels snderr(EMSGSIZE); 343*41908Skarels if (so->so_state & SS_NBIO) 344*41908Skarels snderr(EWOULDBLOCK); 345*41908Skarels sbunlock(&so->so_snd); 346*41908Skarels /* 347*41908Skarels if (sbwait_func) 348*41908Skarels error = (*sbwait_func)(&so->so_snd, sbwait_arg); 349*41908Skarels else 350*41908Skarels */ 351*41908Skarels error = sbwait(&so->so_snd); 352*41908Skarels splx(s); 353*41908Skarels if (error) 354*41908Skarels goto out; 355*41908Skarels goto restart; 35616412Skarels } 35716412Skarels splx(s); 35816412Skarels mp = ⊤ 359*41908Skarels space -= clen; 360*41908Skarels if (uio == NULL) { 361*41908Skarels /* 362*41908Skarels * Data is prepackaged in "top". 363*41908Skarels */ 364*41908Skarels resid = 0; 365*41908Skarels if (flags & MSG_EOR) 366*41908Skarels top->m_flags |= M_EOR; 367*41908Skarels } else do { 36835384Skarels do { 36935384Skarels if (top == 0) { 37035384Skarels MGETHDR(m, M_WAIT, MT_DATA); 37135384Skarels mlen = MHLEN; 37235384Skarels m->m_pkthdr.len = 0; 37335384Skarels m->m_pkthdr.rcvif = (struct ifnet *)0; 37435384Skarels } else { 37535384Skarels MGET(m, M_WAIT, MT_DATA); 37635384Skarels mlen = MLEN; 37735384Skarels } 378*41908Skarels if (resid >= MINCLSIZE && space >= MCLBYTES) { 37935384Skarels MCLGET(m, M_WAIT); 38035384Skarels if ((m->m_flags & M_EXT) == 0) 38116412Skarels goto nopages; 38235384Skarels mlen = MCLBYTES; 38335384Skarels #ifdef MAPPED_MBUFS 384*41908Skarels len = min(MCLBYTES, resid); 385*41908Skarels #else 386*41908Skarels if (top == 0) { 387*41908Skarels len = min(MCLBYTES - max_hdr, resid); 38835384Skarels m->m_data += max_hdr; 389*41908Skarels } 39035384Skarels #endif 39135384Skarels space -= MCLBYTES; 39216412Skarels } else { 39316412Skarels nopages: 394*41908Skarels len = min(min(mlen, resid), space); 39521767Skarels space -= len; 39635384Skarels /* 39735384Skarels * For datagram protocols, leave room 39835384Skarels * for protocol headers in first mbuf. 39935384Skarels */ 40035391Skarels if (atomic && top == 0 && len < mlen) 40135384Skarels MH_ALIGN(m, len); 40216412Skarels } 40337728Smckusick error = uiomove(mtod(m, caddr_t), len, uio); 404*41908Skarels resid = uio->uio_resid; 40516412Skarels m->m_len = len; 40616412Skarels *mp = m; 40735384Skarels top->m_pkthdr.len += len; 40816412Skarels if (error) 40916412Skarels goto release; 41016412Skarels mp = &m->m_next; 411*41908Skarels if (resid <= 0) { 412*41908Skarels if (flags & MSG_EOR) 41335384Skarels top->m_flags |= M_EOR; 41421108Skarels break; 41535384Skarels } 41635384Skarels } while (space > 0 && atomic); 41735384Skarels if (dontroute) 41835384Skarels so->so_options |= SO_DONTROUTE; 41935384Skarels s = splnet(); /* XXX */ 42035384Skarels error = (*so->so_proto->pr_usrreq)(so, 42135384Skarels (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, 422*41908Skarels top, addr, control); 42335384Skarels splx(s); 42435384Skarels if (dontroute) 42535384Skarels so->so_options &= ~SO_DONTROUTE; 426*41908Skarels clen = 0; 427*41908Skarels control = 0; 42835384Skarels top = 0; 42935384Skarels mp = ⊤ 43035384Skarels if (error) 43135384Skarels goto release; 432*41908Skarels } while (resid && space > 0); 433*41908Skarels } while (resid); 4344890Swnj 4354786Swnj release: 4364890Swnj sbunlock(&so->so_snd); 437*41908Skarels out: 4386419Sroot if (top) 4396419Sroot m_freem(top); 440*41908Skarels if (control) 441*41908Skarels m_freem(control); 4424786Swnj return (error); 4434786Swnj } 4444786Swnj 44525629Skarels /* 44625629Skarels * Implement receive operations on a socket. 44725629Skarels * We depend on the way that records are added to the sockbuf 44825629Skarels * by sbappend*. In particular, each record (mbufs linked through m_next) 44925629Skarels * must begin with an address if the protocol so specifies, 450*41908Skarels * followed by an optional mbuf or mbufs containing ancillary data, 451*41908Skarels * and then zero or more mbufs of data. 45225629Skarels * In order to avoid blocking network interrupts for the entire time here, 45325629Skarels * we splx() while doing the actual copy to user space. 45425629Skarels * Although the sockbuf is locked, new data may still be appended, 45525629Skarels * and thus we must maintain consistency of the sockbuf during that time. 456*41908Skarels * 457*41908Skarels * The caller may receive the data as a single mbuf chain by supplying 458*41908Skarels * an mbuf **mp for use in returning the chain. The uio is then used 459*41908Skarels * only for the count in uio_resid. 46025629Skarels */ 461*41908Skarels soreceive(so, paddr, uio, mp, controlp, flagsp/*, sbwait_func, sbwait_arg*/) 4624786Swnj register struct socket *so; 463*41908Skarels struct mbuf **paddr; 464*41908Skarels struct uio *uio; 465*41908Skarels struct mbuf **mp; 466*41908Skarels struct mbuf **controlp; 46735384Skarels int *flagsp; 468*41908Skarels /* 469*41908Skarels int (*sbwait_func)(); 470*41908Skarels caddr_t sbwait_arg; 471*41908Skarels */ 4724786Swnj { 47326958Skarels register struct mbuf *m; 474*41908Skarels register int resid, flags, len, error, s, offset; 47512757Ssam struct protosw *pr = so->so_proto; 476*41908Skarels struct mbuf *nextrecord; 477*41908Skarels int moff, type; 4784786Swnj 479*41908Skarels if (paddr) 480*41908Skarels *paddr = 0; 48135384Skarels if (controlp) 48235384Skarels *controlp = 0; 48335384Skarels if (flagsp) 48435384Skarels flags = *flagsp &~ MSG_EOR; 48535384Skarels else 48635384Skarels flags = 0; 48712757Ssam if (flags & MSG_OOB) { 4889635Ssam m = m_get(M_WAIT, MT_DATA); 48912757Ssam error = (*pr->pr_usrreq)(so, PRU_RCVOOB, 49024768Skarels m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); 4918594Sroot if (error) 49210137Ssam goto bad; 4938319Sroot do { 494*41908Skarels error = uiomove(mtod(m, caddr_t), 495*41908Skarels (int) min(uio->uio_resid, m->m_len), uio); 4968319Sroot m = m_free(m); 4978594Sroot } while (uio->uio_resid && error == 0 && m); 49810137Ssam bad: 4998319Sroot if (m) 5008771Sroot m_freem(m); 5018594Sroot return (error); 5028319Sroot } 503*41908Skarels if (mp) 504*41908Skarels *mp = (struct mbuf *)0; 505*41908Skarels resid = uio->uio_resid; 506*41908Skarels if (so->so_state & SS_ISCONFIRMING && resid) 50735384Skarels (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 50835384Skarels (struct mbuf *)0, (struct mbuf *)0); 5098319Sroot 5104890Swnj restart: 51140706Skarels if (error = sblock(&so->so_rcv)) 51240706Skarels return (error); 5138835Sroot s = splnet(); 5144890Swnj 51537478Ssklower m = so->so_rcv.sb_mb; 516*41908Skarels if (m == 0 || (so->so_rcv.sb_cc < resid && 517*41908Skarels so->so_rcv.sb_cc < so->so_rcv.sb_lowat)) { 518*41908Skarels #ifdef DIAGNOSTIC 519*41908Skarels if (m == 0 && so->so_rcv.sb_cc) 52037478Ssklower panic("receive 1"); 521*41908Skarels #endif 5225168Swnj if (so->so_error) { 5235168Swnj error = so->so_error; 5245168Swnj so->so_error = 0; 5255168Swnj goto release; 5265168Swnj } 52732567Sbostic if (so->so_state & SS_CANTRCVMORE) 5284890Swnj goto release; 52938584Skarels if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && 53032567Sbostic (so->so_proto->pr_flags & PR_CONNREQUIRED)) { 53132567Sbostic error = ENOTCONN; 53232567Sbostic goto release; 5334890Swnj } 534*41908Skarels if (resid == 0) 53525629Skarels goto release; 53632567Sbostic if (so->so_state & SS_NBIO) { 53732567Sbostic error = EWOULDBLOCK; 53832567Sbostic goto release; 53932567Sbostic } 5404890Swnj sbunlock(&so->so_rcv); 541*41908Skarels /* 542*41908Skarels if (sbwait_func) 543*41908Skarels error = (*sbwait_func)(&so->so_rcv, sbwait_arg); 544*41908Skarels else 545*41908Skarels */ 546*41908Skarels error = sbwait(&so->so_rcv); 5475012Swnj splx(s); 548*41908Skarels if (error) 549*41908Skarels return (error); 5504890Swnj goto restart; 5514786Swnj } 5528041Sroot u.u_ru.ru_msgrcv++; 553*41908Skarels #ifdef DIAGNOSTIC 55435384Skarels if (m->m_type == 0) 55535384Skarels panic("receive 3a"); 556*41908Skarels #endif 55735384Skarels nextrecord = m->m_nextpkt; 55812757Ssam if (pr->pr_flags & PR_ADDR) { 559*41908Skarels #ifdef DIAGNOSTIC 56025629Skarels if (m->m_type != MT_SONAME) 56116993Skarels panic("receive 1a"); 562*41908Skarels #endif 56316993Skarels if (flags & MSG_PEEK) { 564*41908Skarels if (paddr) 565*41908Skarels *paddr = m_copy(m, 0, m->m_len); 56625629Skarels m = m->m_next; 56716993Skarels } else { 56825629Skarels sbfree(&so->so_rcv, m); 569*41908Skarels if (paddr) { 570*41908Skarels *paddr = m; 57135384Skarels so->so_rcv.sb_mb = m->m_next; 57235384Skarels m->m_next = 0; 57335384Skarels m = so->so_rcv.sb_mb; 57425629Skarels } else { 57526958Skarels MFREE(m, so->so_rcv.sb_mb); 57626958Skarels m = so->so_rcv.sb_mb; 57725629Skarels } 57816993Skarels } 57916993Skarels } 580*41908Skarels while (m && m->m_type == MT_CONTROL && error == 0) { 58116993Skarels if (flags & MSG_PEEK) { 58235384Skarels if (controlp) 58335384Skarels *controlp = m_copy(m, 0, m->m_len); 58435384Skarels m = m->m_next; 58535384Skarels } else { 58635384Skarels sbfree(&so->so_rcv, m); 58735384Skarels if (controlp) { 588*41908Skarels if (mtod(m, struct cmsghdr *)->cmsg_type == 589*41908Skarels SCM_RIGHTS && 590*41908Skarels pr->pr_domain->dom_externalize) 591*41908Skarels error = (*pr->pr_domain->dom_externalize)(m); 59235384Skarels *controlp = m; 59335384Skarels so->so_rcv.sb_mb = m->m_next; 59435384Skarels m->m_next = 0; 59535384Skarels m = so->so_rcv.sb_mb; 59635384Skarels } else { 59735384Skarels MFREE(m, so->so_rcv.sb_mb); 59835384Skarels m = so->so_rcv.sb_mb; 59935384Skarels } 60035384Skarels } 601*41908Skarels if (controlp) 602*41908Skarels controlp = &(*controlp)->m_next; 60335384Skarels } 604*41908Skarels if (m) { 60535384Skarels m->m_nextpkt = nextrecord; 606*41908Skarels type = m->m_type; 607*41908Skarels } 6088319Sroot moff = 0; 60932092Skarels offset = 0; 610*41908Skarels while (m && m->m_type == type && resid > 0 && error == 0) { 61135384Skarels if (m->m_type == MT_OOBDATA) 61235384Skarels flags |= MSG_OOB; 613*41908Skarels #ifdef DIAGNOSTIC 61435384Skarels else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) 61525629Skarels panic("receive 3"); 616*41908Skarels #endif 617*41908Skarels type = m->m_type; 6187747Sroot so->so_state &= ~SS_RCVATMARK; 619*41908Skarels len = resid; 62032092Skarels if (so->so_oobmark && len > so->so_oobmark - offset) 62132092Skarels len = so->so_oobmark - offset; 62221767Skarels if (len > m->m_len - moff) 6238319Sroot len = m->m_len - moff; 624*41908Skarels /* 625*41908Skarels * If mp is set, just pass back the mbufs. 626*41908Skarels * Otherwise copy them out via the uio, then free. 627*41908Skarels * Sockbuf must be consistent here (points to current mbuf, 628*41908Skarels * it points to next record) when we drop priority; 629*41908Skarels * we must note any additions to the sockbuf when we 630*41908Skarels * block interrupts again. 631*41908Skarels */ 632*41908Skarels if (mp == 0) { 633*41908Skarels splx(s); 634*41908Skarels error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); 635*41908Skarels resid = uio->uio_resid; 636*41908Skarels s = splnet(); 637*41908Skarels } 63821767Skarels if (len == m->m_len - moff) { 639*41908Skarels if (m->m_flags & M_EOR) 640*41908Skarels flags |= MSG_EOR; 64125629Skarels if (flags & MSG_PEEK) { 64225629Skarels m = m->m_next; 64325629Skarels moff = 0; 64425629Skarels } else { 64535384Skarels nextrecord = m->m_nextpkt; 64625629Skarels sbfree(&so->so_rcv, m); 647*41908Skarels if (mp) { 648*41908Skarels *mp = m; 649*41908Skarels mp = &m->m_next; 650*41908Skarels m = m->m_next; 651*41908Skarels } else { 652*41908Skarels MFREE(m, so->so_rcv.sb_mb); 653*41908Skarels m = so->so_rcv.sb_mb; 654*41908Skarels } 65526958Skarels if (m) 65635384Skarels m->m_nextpkt = nextrecord; 65725629Skarels } 6584786Swnj } else { 65912757Ssam if (flags & MSG_PEEK) 6608319Sroot moff += len; 6618319Sroot else { 66235384Skarels m->m_data += len; 6638319Sroot m->m_len -= len; 6648319Sroot so->so_rcv.sb_cc -= len; 6658319Sroot } 6664786Swnj } 66732092Skarels if (so->so_oobmark) { 66832092Skarels if ((flags & MSG_PEEK) == 0) { 66932092Skarels so->so_oobmark -= len; 67032092Skarels if (so->so_oobmark == 0) { 67132092Skarels so->so_state |= SS_RCVATMARK; 67232092Skarels break; 67332092Skarels } 67432092Skarels } else 67532092Skarels offset += len; 6767747Sroot } 677*41908Skarels if (flags & MSG_EOR) 67840632Skarels break; 679*41908Skarels /* 680*41908Skarels * If the MSG_WAITALL flag is set (for non-atomic socket), 681*41908Skarels * we must not quit until "resid == 0" or an error 682*41908Skarels * termination. If a signal/timeout occurs, return 683*41908Skarels * prematurely but without error. 684*41908Skarels * Keep sockbuf locked against other readers. 685*41908Skarels */ 686*41908Skarels while (flags & MSG_WAITALL && m == 0 && resid > 0 && 687*41908Skarels !sosendallatonce(so)) { 688*41908Skarels error = sbwait(&so->so_rcv); 689*41908Skarels if (error) { 690*41908Skarels sbunlock(&so->so_rcv); 691*41908Skarels splx(s); 692*41908Skarels if (mp) 693*41908Skarels *mp = (struct mbuf *)0; 694*41908Skarels return (0); 695*41908Skarels } 696*41908Skarels if (m = so->so_rcv.sb_mb) 697*41908Skarels nextrecord = m->m_nextpkt; 698*41908Skarels if (so->so_error || so->so_state & SS_CANTRCVMORE) 699*41908Skarels break; 700*41908Skarels continue; 701*41908Skarels } 70216993Skarels } 703*41908Skarels if (mp) 704*41908Skarels *mp = (struct mbuf *)0; 70516993Skarels if ((flags & MSG_PEEK) == 0) { 70626500Skarels if (m == 0) 70716993Skarels so->so_rcv.sb_mb = nextrecord; 70835384Skarels else if (pr->pr_flags & PR_ATOMIC) { 70935384Skarels flags |= MSG_TRUNC; 71026958Skarels (void) sbdroprecord(&so->so_rcv); 71135384Skarels } 71216993Skarels if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) 71316993Skarels (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, 71437478Ssklower (struct mbuf *)flags, (struct mbuf *)0, 71537478Ssklower (struct mbuf *)0); 71616993Skarels } 71735384Skarels if (flagsp) 71835384Skarels *flagsp |= flags; 7194890Swnj release: 7204916Swnj sbunlock(&so->so_rcv); 7214890Swnj splx(s); 7224916Swnj return (error); 7234786Swnj } 7244786Swnj 72510267Ssam soshutdown(so, how) 72612757Ssam register struct socket *so; 72712757Ssam register int how; 72810267Ssam { 72912757Ssam register struct protosw *pr = so->so_proto; 73010267Ssam 73110267Ssam how++; 73212757Ssam if (how & FREAD) 73312757Ssam sorflush(so); 73410267Ssam if (how & FWRITE) 73512757Ssam return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, 73612757Ssam (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); 73710267Ssam return (0); 73810267Ssam } 73910267Ssam 74012757Ssam sorflush(so) 74112757Ssam register struct socket *so; 74212757Ssam { 74312757Ssam register struct sockbuf *sb = &so->so_rcv; 74412757Ssam register struct protosw *pr = so->so_proto; 74512757Ssam register int s; 74612757Ssam struct sockbuf asb; 74712757Ssam 74840706Skarels sb->sb_flags |= SB_NOINTR; 74940706Skarels (void) sblock(sb); 75012757Ssam s = splimp(); 75112757Ssam socantrcvmore(so); 75212757Ssam sbunlock(sb); 75312757Ssam asb = *sb; 75412757Ssam bzero((caddr_t)sb, sizeof (*sb)); 75512757Ssam splx(s); 75616993Skarels if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) 75716993Skarels (*pr->pr_domain->dom_dispose)(asb.sb_mb); 75812757Ssam sbrelease(&asb); 75912757Ssam } 76012757Ssam 76118553Skarels sosetopt(so, level, optname, m0) 76212757Ssam register struct socket *so; 76310267Ssam int level, optname; 76418553Skarels struct mbuf *m0; 76510267Ssam { 76617158Ssam int error = 0; 76718553Skarels register struct mbuf *m = m0; 76810267Ssam 76917158Ssam if (level != SOL_SOCKET) { 77018369Skarels if (so->so_proto && so->so_proto->pr_ctloutput) 77118369Skarels return ((*so->so_proto->pr_ctloutput) 77218553Skarels (PRCO_SETOPT, so, level, optname, &m0)); 77318369Skarels error = ENOPROTOOPT; 77418369Skarels } else { 77518369Skarels switch (optname) { 77610267Ssam 77718369Skarels case SO_LINGER: 77818369Skarels if (m == NULL || m->m_len != sizeof (struct linger)) { 77918369Skarels error = EINVAL; 78018369Skarels goto bad; 78118369Skarels } 78218369Skarels so->so_linger = mtod(m, struct linger *)->l_linger; 78318369Skarels /* fall thru... */ 78417158Ssam 78518369Skarels case SO_DEBUG: 78618369Skarels case SO_KEEPALIVE: 78718369Skarels case SO_DONTROUTE: 78818369Skarels case SO_USELOOPBACK: 78918369Skarels case SO_BROADCAST: 79018369Skarels case SO_REUSEADDR: 79127191Skarels case SO_OOBINLINE: 79218369Skarels if (m == NULL || m->m_len < sizeof (int)) { 79318369Skarels error = EINVAL; 79418369Skarels goto bad; 79518369Skarels } 79618369Skarels if (*mtod(m, int *)) 79718369Skarels so->so_options |= optname; 79818369Skarels else 79918369Skarels so->so_options &= ~optname; 80018369Skarels break; 80118369Skarels 80218369Skarels case SO_SNDBUF: 803*41908Skarels case SO_RCVBUF: 80440706Skarels case SO_SNDLOWAT: 805*41908Skarels case SO_RCVLOWAT: 80640706Skarels case SO_SNDTIMEO: 80718369Skarels case SO_RCVTIMEO: 80818369Skarels if (m == NULL || m->m_len < sizeof (int)) { 80918369Skarels error = EINVAL; 81018369Skarels goto bad; 81118369Skarels } 81218369Skarels switch (optname) { 81318369Skarels 81418369Skarels case SO_SNDBUF: 81518369Skarels case SO_RCVBUF: 816*41908Skarels if (sbreserve(optname == SO_SNDBUF ? 817*41908Skarels &so->so_snd : &so->so_rcv, 818*41908Skarels (u_long) *mtod(m, int *)) == 0) { 81918369Skarels error = ENOBUFS; 82018369Skarels goto bad; 82118369Skarels } 82218369Skarels break; 82318369Skarels 82418369Skarels case SO_SNDLOWAT: 825*41908Skarels so->so_snd.sb_lowat = *mtod(m, int *); 826*41908Skarels break; 82718369Skarels case SO_RCVLOWAT: 828*41908Skarels so->so_rcv.sb_lowat = *mtod(m, int *); 82918369Skarels break; 83018369Skarels case SO_SNDTIMEO: 831*41908Skarels so->so_snd.sb_timeo = *mtod(m, int *); 832*41908Skarels break; 83318369Skarels case SO_RCVTIMEO: 834*41908Skarels so->so_rcv.sb_timeo = *mtod(m, int *); 83518369Skarels break; 83618369Skarels } 83718369Skarels break; 83818369Skarels 83918369Skarels default: 84018369Skarels error = ENOPROTOOPT; 84118369Skarels break; 84217158Ssam } 84310267Ssam } 84417158Ssam bad: 84517158Ssam if (m) 84617158Ssam (void) m_free(m); 84717158Ssam return (error); 84810267Ssam } 84910267Ssam 85017158Ssam sogetopt(so, level, optname, mp) 85112757Ssam register struct socket *so; 85210267Ssam int level, optname; 85317158Ssam struct mbuf **mp; 85417158Ssam { 85512757Ssam register struct mbuf *m; 85610267Ssam 85718369Skarels if (level != SOL_SOCKET) { 85818369Skarels if (so->so_proto && so->so_proto->pr_ctloutput) { 85918369Skarels return ((*so->so_proto->pr_ctloutput) 86018369Skarels (PRCO_GETOPT, so, level, optname, mp)); 86118369Skarels } else 86218369Skarels return (ENOPROTOOPT); 86318369Skarels } else { 86417158Ssam m = m_get(M_WAIT, MT_SOOPTS); 86525502Skarels m->m_len = sizeof (int); 86625502Skarels 86718369Skarels switch (optname) { 86817158Ssam 86918369Skarels case SO_LINGER: 87018369Skarels m->m_len = sizeof (struct linger); 87118369Skarels mtod(m, struct linger *)->l_onoff = 87218369Skarels so->so_options & SO_LINGER; 87318369Skarels mtod(m, struct linger *)->l_linger = so->so_linger; 87418369Skarels break; 87510267Ssam 87618369Skarels case SO_USELOOPBACK: 87718369Skarels case SO_DONTROUTE: 87818369Skarels case SO_DEBUG: 87918369Skarels case SO_KEEPALIVE: 88018369Skarels case SO_REUSEADDR: 88118369Skarels case SO_BROADCAST: 88227191Skarels case SO_OOBINLINE: 88318369Skarels *mtod(m, int *) = so->so_options & optname; 88418369Skarels break; 88518369Skarels 88625502Skarels case SO_TYPE: 88725502Skarels *mtod(m, int *) = so->so_type; 88825502Skarels break; 88925502Skarels 89024768Skarels case SO_ERROR: 89124768Skarels *mtod(m, int *) = so->so_error; 89224768Skarels so->so_error = 0; 89324768Skarels break; 89424768Skarels 89518369Skarels case SO_SNDBUF: 89618369Skarels *mtod(m, int *) = so->so_snd.sb_hiwat; 89718369Skarels break; 89818369Skarels 89918369Skarels case SO_RCVBUF: 90018369Skarels *mtod(m, int *) = so->so_rcv.sb_hiwat; 90118369Skarels break; 90218369Skarels 90318369Skarels case SO_SNDLOWAT: 90418369Skarels *mtod(m, int *) = so->so_snd.sb_lowat; 90518369Skarels break; 90618369Skarels 90718369Skarels case SO_RCVLOWAT: 90818369Skarels *mtod(m, int *) = so->so_rcv.sb_lowat; 90918369Skarels break; 91018369Skarels 91118369Skarels case SO_SNDTIMEO: 91218369Skarels *mtod(m, int *) = so->so_snd.sb_timeo; 91318369Skarels break; 91418369Skarels 91518369Skarels case SO_RCVTIMEO: 91618369Skarels *mtod(m, int *) = so->so_rcv.sb_timeo; 91718369Skarels break; 91818369Skarels 91918369Skarels default: 92026362Skarels (void)m_free(m); 92118369Skarels return (ENOPROTOOPT); 92218369Skarels } 92318369Skarels *mp = m; 92418369Skarels return (0); 92510267Ssam } 92610267Ssam } 92710267Ssam 9285423Swnj sohasoutofband(so) 92912757Ssam register struct socket *so; 9305423Swnj { 93123233Skarels struct proc *p; 9325423Swnj 93337478Ssklower if (so->so_pgid < 0) 93437478Ssklower gsignal(-so->so_pgid, SIGURG); 93537478Ssklower else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) 93623233Skarels psignal(p, SIGURG); 93724768Skarels if (so->so_rcv.sb_sel) { 93824768Skarels selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL); 93924768Skarels so->so_rcv.sb_sel = 0; 94024768Skarels so->so_rcv.sb_flags &= ~SB_COLL; 94124768Skarels } 9425423Swnj } 943