1*11571Ssam /* uipc_socket.c 4.72 83/03/15 */ 24786Swnj 34786Swnj #include "../h/param.h" 44829Swnj #include "../h/systm.h" 54786Swnj #include "../h/dir.h" 64786Swnj #include "../h/user.h" 74829Swnj #include "../h/proc.h" 84829Swnj #include "../h/file.h" 94786Swnj #include "../h/inode.h" 104829Swnj #include "../h/buf.h" 114786Swnj #include "../h/mbuf.h" 124829Swnj #include "../h/protosw.h" 134829Swnj #include "../h/socket.h" 144829Swnj #include "../h/socketvar.h" 154916Swnj #include "../h/stat.h" 165281Sroot #include "../h/ioctl.h" 178391Swnj #include "../h/uio.h" 186355Ssam #include "../net/route.h" 19*11571Ssam #include "../net/if.h" 204786Swnj 214786Swnj /* 228300Sroot * Socket operation routines. 238300Sroot * These routines are called by the routines in 248300Sroot * sys_socket.c or from a system process, and 258300Sroot * implement the semantics of socket operations by 268300Sroot * switching out to the protocol specific routines. 274786Swnj */ 284786Swnj 298594Sroot /*ARGSUSED*/ 3010267Ssam socreate(dom, aso, type, proto) 314786Swnj struct socket **aso; 328300Sroot int type, proto; 334786Swnj { 344786Swnj register struct protosw *prp; 354786Swnj register struct socket *so; 364786Swnj struct mbuf *m; 379168Ssam int error; 384786Swnj 394890Swnj if (proto) 409168Ssam prp = pffindproto(dom, proto); 414890Swnj else 429168Ssam prp = pffindtype(dom, type); 434890Swnj if (prp == 0) 444890Swnj return (EPROTONOSUPPORT); 458300Sroot if (prp->pr_type != type) 468300Sroot return (EPROTOTYPE); 479635Ssam m = m_getclr(M_WAIT, MT_SOCKET); 484786Swnj if (m == 0) 494786Swnj return (ENOBUFS); 504786Swnj so = mtod(m, struct socket *); 5110267Ssam so->so_options = SO_LINGER; 526214Swnj so->so_state = 0; 539168Ssam so->so_type = type; 546214Swnj if (u.u_uid == 0) 556214Swnj so->so_state = SS_PRIV; 564786Swnj so->so_proto = prp; 578300Sroot error = (*prp->pr_usrreq)(so, PRU_ATTACH, 5810267Ssam (struct mbuf *)0, (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 758300Sroot error = 7610267Ssam (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam); 778300Sroot splx(s); 788300Sroot return (error); 798300Sroot } 808300Sroot 818300Sroot solisten(so, backlog) 828300Sroot struct socket *so; 838300Sroot int backlog; 848300Sroot { 858300Sroot int s = splnet(); 868300Sroot int error; 878300Sroot 888300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 8910267Ssam (struct mbuf *)0, (struct mbuf *)0); 908300Sroot if (error) { 918300Sroot splx(s); 928300Sroot return (error); 938300Sroot } 948300Sroot if (so->so_q == 0) { 958300Sroot so->so_q = so; 968300Sroot so->so_q0 = so; 978300Sroot so->so_options |= SO_ACCEPTCONN; 988300Sroot } 998300Sroot if (backlog < 0) 1008300Sroot backlog = 0; 10110137Ssam #define SOMAXCONN 5 10210137Ssam so->so_qlimit = MIN(backlog, SOMAXCONN); 1038300Sroot so->so_options |= SO_NEWFDONCONN; 1048300Sroot return (0); 1058300Sroot } 1068300Sroot 1074916Swnj sofree(so) 1084916Swnj struct socket *so; 1094916Swnj { 1104916Swnj 1117507Sroot if (so->so_head) { 1127507Sroot if (!soqremque(so, 0) && !soqremque(so, 1)) 1137507Sroot panic("sofree dq"); 1147507Sroot so->so_head = 0; 1157507Sroot } 1167507Sroot if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) 1174950Swnj return; 1184950Swnj sbrelease(&so->so_snd); 1194950Swnj sbrelease(&so->so_rcv); 1204971Swnj (void) m_free(dtom(so)); 1214916Swnj } 1224916Swnj 1234786Swnj /* 1244890Swnj * Close a socket on last file table reference removal. 1254890Swnj * Initiate disconnect if connected. 1264890Swnj * Free socket when disconnect complete. 1274829Swnj */ 1285580Sroot soclose(so, exiting) 1294829Swnj register struct socket *so; 1305580Sroot int exiting; 1314829Swnj { 1324890Swnj int s = splnet(); /* conservative */ 1338713Sroot int error; 1344829Swnj 1357507Sroot if (so->so_options & SO_ACCEPTCONN) { 1367507Sroot while (so->so_q0 != so) 13710399Ssam (void) soabort(so->so_q0); 1387507Sroot while (so->so_q != so) 13910399Ssam (void) soabort(so->so_q); 1407507Sroot } 1414890Swnj if (so->so_pcb == 0) 1424890Swnj goto discard; 1436259Sroot if (exiting) 1446259Sroot so->so_options |= SO_KEEPALIVE; 1454890Swnj if (so->so_state & SS_ISCONNECTED) { 1464890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1478725Sroot error = sodisconnect(so, (struct mbuf *)0); 1488713Sroot if (error) { 1495580Sroot if (exiting) 1505580Sroot goto drop; 1514890Swnj splx(s); 1528713Sroot return (error); 1534890Swnj } 1544890Swnj } 15510267Ssam if (so->so_options & SO_LINGER) { 1565281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1576214Swnj (so->so_state & SS_NBIO) && 1588713Sroot exiting == 0) 1598713Sroot return (EINPROGRESS); 1605580Sroot /* should use tsleep here, for at most linger */ 1615281Sroot while (so->so_state & SS_ISCONNECTED) 1625281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1634890Swnj } 1644890Swnj } 1655580Sroot drop: 1666880Ssam if (so->so_pcb) { 1678713Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 16810267Ssam (struct mbuf *)0, (struct mbuf *)0); 1698713Sroot if (exiting == 0 && error) { 1706880Ssam splx(s); 1718713Sroot return (error); 1726880Ssam } 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); 1808713Sroot return (0); 1814829Swnj } 1824829Swnj 18310399Ssam /* 18410399Ssam * Must be called at splnet... 18510399Ssam */ 18610399Ssam soabort(so) 18710399Ssam struct socket *so; 18810399Ssam { 18910399Ssam int error; 19010399Ssam 19110399Ssam error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, 19210399Ssam (struct mbuf *)0, (struct mbuf *)0); 19310399Ssam return (error); 19410399Ssam } 19510399Ssam 1964916Swnj /*ARGSUSED*/ 1979026Sroot sostat(so, ub) 1984829Swnj struct socket *so; 1999026Sroot struct stat *ub; 2004829Swnj { 2019026Sroot struct stat sb; 2024829Swnj 2039026Sroot bzero((caddr_t)&sb, sizeof (sb)); /* XXX */ 2049168Ssam (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */ 2055303Sroot return (0); /* XXX */ 2064829Swnj } 2074829Swnj 20810267Ssam soaccept(so, nam) 2094927Swnj struct socket *so; 2108300Sroot struct mbuf *nam; 2114927Swnj { 2124927Swnj int s = splnet(); 2134927Swnj int error; 2144927Swnj 21510399Ssam if ((so->so_state & SS_NOFDREF) == 0) 21610399Ssam panic("soaccept: !NOFDREF"); 21710267Ssam so->so_state &= ~SS_NOFDREF; 2188300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 21910267Ssam (struct mbuf *)0, nam); 2204927Swnj splx(s); 2214927Swnj return (error); 2224927Swnj } 2234927Swnj 22410267Ssam soconnect(so, nam) 2254786Swnj struct socket *so; 2268300Sroot struct mbuf *nam; 2274786Swnj { 2284890Swnj int s = splnet(); 2294890Swnj int error; 2304786Swnj 2314890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2324890Swnj error = EISCONN; 2334890Swnj goto bad; 2344890Swnj } 2358300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 23610267Ssam (struct mbuf *)0, nam); 2374890Swnj bad: 2384890Swnj splx(s); 2394890Swnj return (error); 2404786Swnj } 2414786Swnj 2428300Sroot sodisconnect(so, nam) 2434786Swnj struct socket *so; 2448300Sroot struct mbuf *nam; 2454786Swnj { 2464890Swnj int s = splnet(); 2474890Swnj int error; 2484786Swnj 2494890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2504890Swnj error = ENOTCONN; 2514890Swnj goto bad; 2524890Swnj } 2534890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2544890Swnj error = EALREADY; 2554890Swnj goto bad; 2564890Swnj } 2578300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 25810267Ssam (struct mbuf *)0, nam); 2594890Swnj bad: 2604890Swnj splx(s); 2614890Swnj return (error); 2624786Swnj } 2634786Swnj 2644786Swnj /* 2654890Swnj * Send on a socket. 2664890Swnj * If send must go all at once and message is larger than 2674890Swnj * send buffering, then hard error. 2684890Swnj * Lock against other senders. 2694890Swnj * If must go all at once and not enough room now, then 2704890Swnj * inform user that this would block and do nothing. 2714786Swnj */ 2728319Sroot sosend(so, nam, uio, flags) 2734786Swnj register struct socket *so; 2748300Sroot struct mbuf *nam; 2757827Sroot struct uio *uio; 2768319Sroot int flags; 2774786Swnj { 2784890Swnj struct mbuf *top = 0; 2794890Swnj register struct mbuf *m, **mp = ⊤ 2808713Sroot register int len; 28110267Ssam int error = 0, space, s, dontroute; 2824786Swnj 2837827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2844890Swnj return (EMSGSIZE); 28510267Ssam dontroute = (flags & SOF_DONTROUTE) && 28610267Ssam (so->so_options & SO_DONTROUTE) == 0 && 28710267Ssam (so->so_proto->pr_flags & PR_ATOMIC); 2886419Sroot restart: 2894890Swnj sblock(&so->so_snd); 2904890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2914890Swnj 2928041Sroot u.u_ru.ru_msgsnd++; 2936419Sroot again: 2944890Swnj s = splnet(); 2956419Sroot if (so->so_state & SS_CANTSENDMORE) { 2966419Sroot psignal(u.u_procp, SIGPIPE); 2976419Sroot snderr(EPIPE); 2986419Sroot } 2995168Swnj if (so->so_error) { 3005168Swnj error = so->so_error; 3016419Sroot so->so_error = 0; /* ??? */ 3025168Swnj splx(s); 3035168Swnj goto release; 3045168Swnj } 3054890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 3064890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 3074890Swnj snderr(ENOTCONN); 3088300Sroot if (nam == 0) 3094890Swnj snderr(EDESTADDRREQ); 3104890Swnj } 3114890Swnj if (top) { 31210267Ssam if (dontroute) 31310267Ssam so->so_options |= SO_DONTROUTE; 3148319Sroot error = (*so->so_proto->pr_usrreq)(so, 3158319Sroot (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 31610267Ssam top, (caddr_t)nam); 31710267Ssam if (dontroute) 31810267Ssam so->so_options &= ~SO_DONTROUTE; 3196419Sroot top = 0; 3204890Swnj if (error) { 3214890Swnj splx(s); 3224786Swnj goto release; 3234786Swnj } 3244890Swnj mp = ⊤ 3254786Swnj } 3267827Sroot if (uio->uio_resid == 0) { 3274979Swnj splx(s); 3284979Swnj goto release; 3294979Swnj } 3308319Sroot if (flags & SOF_OOB) 3318319Sroot space = 1024; 3328319Sroot else { 3338319Sroot space = sbspace(&so->so_snd); 3348319Sroot if (space <= 0 || 3358319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3368319Sroot if (so->so_state & SS_NBIO) 3378319Sroot snderr(EWOULDBLOCK); 3388319Sroot sbunlock(&so->so_snd); 3398319Sroot sbwait(&so->so_snd); 3408319Sroot splx(s); 3418319Sroot goto restart; 3428319Sroot } 3434786Swnj } 3444890Swnj splx(s); 3457827Sroot while (uio->uio_resid > 0 && space > 0) { 3467827Sroot register struct iovec *iov = uio->uio_iov; 3477827Sroot 3487827Sroot if (iov->iov_len == 0) { 3497827Sroot uio->uio_iov++; 3507827Sroot uio->uio_iovcnt--; 3517827Sroot if (uio->uio_iovcnt < 0) 3527827Sroot panic("sosend"); 3537827Sroot continue; 3547827Sroot } 3559635Ssam MGET(m, M_WAIT, MT_DATA); 3564890Swnj if (m == NULL) { 3576419Sroot error = ENOBUFS; /* SIGPIPE? */ 3584890Swnj goto release; 3594786Swnj } 3607827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3614890Swnj register struct mbuf *p; 3625095Swnj MCLGET(p, 1); 3634890Swnj if (p == 0) 3644890Swnj goto nopages; 3654890Swnj m->m_off = (int)p - (int)m; 3665095Swnj len = CLBYTES; 3674890Swnj } else { 3684786Swnj nopages: 3697827Sroot len = MIN(MLEN, iov->iov_len); 3704786Swnj } 3718771Sroot (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3724890Swnj m->m_len = len; 3734890Swnj *mp = m; 3744890Swnj mp = &m->m_next; 3758319Sroot if (flags & SOF_OOB) 3768319Sroot space -= len; 3778319Sroot else 3788319Sroot space = sbspace(&so->so_snd); 3794786Swnj } 3804890Swnj goto again; 3814890Swnj 3824786Swnj release: 3834890Swnj sbunlock(&so->so_snd); 3846419Sroot if (top) 3856419Sroot m_freem(top); 3864786Swnj return (error); 3874786Swnj } 3884786Swnj 3898319Sroot soreceive(so, aname, uio, flags) 3904786Swnj register struct socket *so; 3918300Sroot struct mbuf **aname; 3927747Sroot struct uio *uio; 3938319Sroot int flags; 3944786Swnj { 3954786Swnj register struct mbuf *m, *n; 3968713Sroot int len; 3978319Sroot int eor, s, error = 0, moff, tomark; 3984786Swnj 3998319Sroot if (flags & SOF_OOB) { 4009635Ssam m = m_get(M_WAIT, MT_DATA); 40110137Ssam if (m == NULL) 40210137Ssam return (ENOBUFS); 4038594Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 40410267Ssam m, (struct mbuf *)0); 4058594Sroot if (error) 40610137Ssam goto bad; 4078319Sroot do { 40810137Ssam len = uio->uio_resid; 4098319Sroot if (len > m->m_len) 4108319Sroot len = m->m_len; 4118594Sroot error = 4128793Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 4138319Sroot m = m_free(m); 4148594Sroot } while (uio->uio_resid && error == 0 && m); 41510137Ssam bad: 4168319Sroot if (m) 4178771Sroot m_freem(m); 4188594Sroot return (error); 4198319Sroot } 4208319Sroot 4214890Swnj restart: 4224890Swnj sblock(&so->so_rcv); 4238835Sroot s = splnet(); 4244890Swnj 4254890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 4264786Swnj if (so->so_rcv.sb_cc == 0) { 4275168Swnj if (so->so_error) { 4285168Swnj error = so->so_error; 4295168Swnj so->so_error = 0; 4305168Swnj splx(s); 4315168Swnj goto release; 4325168Swnj } 4334890Swnj if (so->so_state & SS_CANTRCVMORE) { 4344890Swnj splx(s); 4354890Swnj goto release; 4364890Swnj } 4375015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4385015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4395015Sroot rcverr(ENOTCONN); 4406214Swnj if (so->so_state & SS_NBIO) 4415168Swnj rcverr(EWOULDBLOCK); 4424890Swnj sbunlock(&so->so_rcv); 4434971Swnj sbwait(&so->so_rcv); 4445012Swnj splx(s); 4454890Swnj goto restart; 4464786Swnj } 4478041Sroot u.u_ru.ru_msgrcv++; 4484829Swnj m = so->so_rcv.sb_mb; 4494786Swnj if (m == 0) 4504786Swnj panic("receive"); 4515039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4528319Sroot if ((flags & SOF_PREVIEW) == 0) { 4538319Sroot so->so_rcv.sb_cc -= m->m_len; 4548319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4558319Sroot } 4568300Sroot if (aname) { 45710137Ssam if (flags & SOF_PREVIEW) { 4588319Sroot *aname = m_copy(m, 0, m->m_len); 45910137Ssam if (*aname == NULL) 46010137Ssam panic("receive 2"); 46110137Ssam } else 4628319Sroot *aname = m; 4638300Sroot m = m->m_next; 4648300Sroot (*aname)->m_next = 0; 4658300Sroot } else 4668319Sroot if (flags & SOF_PREVIEW) 4678319Sroot m = m->m_next; 4688319Sroot else 4698319Sroot m = m_free(m); 4704890Swnj if (m == 0) 47110137Ssam panic("receive 3"); 4728548Sroot if ((flags & SOF_PREVIEW) == 0) 4738548Sroot so->so_rcv.sb_mb = m; 4744890Swnj } 4754786Swnj eor = 0; 4768319Sroot moff = 0; 4778319Sroot tomark = so->so_oobmark; 4784786Swnj do { 4797827Sroot if (uio->uio_resid <= 0) 4807747Sroot break; 4817827Sroot len = uio->uio_resid; 4827747Sroot so->so_state &= ~SS_RCVATMARK; 4838319Sroot if (tomark && len > tomark) 4848319Sroot len = tomark; 4858548Sroot if (moff+len > m->m_len - moff) 4868319Sroot len = m->m_len - moff; 4874786Swnj splx(s); 4888594Sroot error = 4898793Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4904786Swnj s = splnet(); 4914786Swnj if (len == m->m_len) { 4926091Sroot eor = (int)m->m_act; 4938319Sroot if (flags & SOF_PREVIEW) 4948319Sroot m = m->m_next; 4958319Sroot else { 4968319Sroot sbfree(&so->so_rcv, m); 4978319Sroot MFREE(m, n); 4988319Sroot m = n; 4998548Sroot so->so_rcv.sb_mb = m; 5008319Sroot } 5018319Sroot moff = 0; 5024786Swnj } else { 5038319Sroot if (flags & SOF_PREVIEW) 5048319Sroot moff += len; 5058319Sroot else { 5068319Sroot m->m_off += len; 5078319Sroot m->m_len -= len; 5088319Sroot so->so_rcv.sb_cc -= len; 5098319Sroot } 5104786Swnj } 5118319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 5127747Sroot so->so_oobmark -= len; 5137747Sroot if (so->so_oobmark == 0) { 5147747Sroot so->so_state |= SS_RCVATMARK; 5157747Sroot break; 5167747Sroot } 5177747Sroot } 5188319Sroot if (tomark) { 5198319Sroot tomark -= len; 5208319Sroot if (tomark == 0) 5218319Sroot break; 5228319Sroot } 5238594Sroot } while (m && error == 0 && !eor); 5248319Sroot if (flags & SOF_PREVIEW) 5258319Sroot goto release; 5264786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 5274786Swnj do { 5284786Swnj if (m == 0) 52910137Ssam panic("receive 4"); 5304890Swnj sbfree(&so->so_rcv, m); 5314786Swnj eor = (int)m->m_act; 5324786Swnj so->so_rcv.sb_mb = m->m_next; 5334786Swnj MFREE(m, n); 5344890Swnj m = n; 5354786Swnj } while (eor == 0); 5364890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5378300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 53810267Ssam (struct mbuf *)0, (struct mbuf *)0); 5394890Swnj release: 5404916Swnj sbunlock(&so->so_rcv); 5414890Swnj splx(s); 5424916Swnj return (error); 5434786Swnj } 5444786Swnj 54510267Ssam soshutdown(so, how) 54610267Ssam struct socket *so; 54710267Ssam int how; 54810267Ssam { 54910267Ssam 55010267Ssam how++; 55110267Ssam if (how & FREAD) { 55210267Ssam int s = splimp(); 55310267Ssam socantrcvmore(so); 55410267Ssam sbflush(&so->so_rcv); 55510267Ssam splx(s); 55610267Ssam } 55710267Ssam if (how & FWRITE) 55810267Ssam return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 55910267Ssam (struct mbuf *)0, (struct mbuf *)0)); 56010267Ssam return (0); 56110267Ssam } 56210267Ssam 56310267Ssam sosetopt(so, level, optname, m) 56410267Ssam struct socket *so; 56510267Ssam int level, optname; 56610267Ssam struct mbuf *m; 56710267Ssam { 56810267Ssam 56910267Ssam if (level != SOL_SOCKET) 57010267Ssam return (EINVAL); /* XXX */ 57110267Ssam switch (optname) { 57210267Ssam 57310267Ssam case SO_DEBUG: 57410269Ssam case SO_KEEPALIVE: 57510599Ssam case SO_DONTROUTE: 57610599Ssam case SO_USELOOPBACK: 57710599Ssam case SO_REUSEADDR: 57810599Ssam so->so_options |= optname; 57910269Ssam break; 58010269Ssam 58110267Ssam case SO_LINGER: 58210269Ssam if (m == NULL || m->m_len != sizeof (int)) 58310269Ssam return (EINVAL); 58410267Ssam so->so_options |= SO_LINGER; 58510269Ssam so->so_linger = *mtod(m, int *); 58610267Ssam break; 58710267Ssam 58810267Ssam case SO_DONTLINGER: 58910267Ssam so->so_options &= ~SO_LINGER; 59010267Ssam so->so_linger = 0; 59110267Ssam break; 59210267Ssam 59310267Ssam default: 59410267Ssam return (EINVAL); 59510267Ssam } 59610267Ssam return (0); 59710267Ssam } 59810267Ssam 59910267Ssam sogetopt(so, level, optname, m) 60010267Ssam struct socket *so; 60110267Ssam int level, optname; 60210267Ssam struct mbuf *m; 60310267Ssam { 60410267Ssam 60510267Ssam if (level != SOL_SOCKET) 60610267Ssam return (EINVAL); /* XXX */ 60710267Ssam switch (optname) { 60810267Ssam 60910267Ssam case SO_USELOOPBACK: 61010267Ssam case SO_DONTROUTE: 61110267Ssam case SO_DEBUG: 61210267Ssam case SO_KEEPALIVE: 61310267Ssam case SO_LINGER: 61410599Ssam case SO_REUSEADDR: 61510267Ssam if ((so->so_options & optname) == 0) 61610267Ssam return (ENOPROTOOPT); 61710269Ssam if (optname == SO_LINGER && m != NULL) { 61810267Ssam *mtod(m, int *) = so->so_linger; 61910267Ssam m->m_len = sizeof (so->so_linger); 62010267Ssam } 62110267Ssam break; 62210267Ssam 62310267Ssam default: 62410267Ssam return (EINVAL); 62510267Ssam } 62610267Ssam return (0); 62710267Ssam } 62810267Ssam 6295423Swnj sohasoutofband(so) 6305423Swnj struct socket *so; 6315423Swnj { 6325423Swnj 6335423Swnj if (so->so_pgrp == 0) 6345423Swnj return; 6355423Swnj if (so->so_pgrp > 0) 6365423Swnj gsignal(so->so_pgrp, SIGURG); 6375429Swnj else { 6385429Swnj struct proc *p = pfind(-so->so_pgrp); 6395429Swnj 6405429Swnj if (p) 6415429Swnj psignal(p, SIGURG); 6425429Swnj } 6435423Swnj } 6445423Swnj 6454916Swnj /*ARGSUSED*/ 6467627Ssam soioctl(so, cmd, data) 6474829Swnj register struct socket *so; 6484829Swnj int cmd; 6497627Ssam register char *data; 6504786Swnj { 6514786Swnj 6525358Sroot switch (cmd) { 6534829Swnj 6547627Ssam case FIONBIO: 6557627Ssam if (*(int *)data) 6566214Swnj so->so_state |= SS_NBIO; 6575388Sroot else 6586214Swnj so->so_state &= ~SS_NBIO; 6598594Sroot break; 6605388Sroot 6617627Ssam case FIOASYNC: 6627627Ssam if (*(int *)data) 6636214Swnj so->so_state |= SS_ASYNC; 6645388Sroot else 6656214Swnj so->so_state &= ~SS_ASYNC; 6668594Sroot break; 6675388Sroot 6687627Ssam case SIOCSPGRP: 6697627Ssam so->so_pgrp = *(int *)data; 6708594Sroot break; 6715423Swnj 6727627Ssam case SIOCGPGRP: 6737627Ssam *(int *)data = so->so_pgrp; 6748594Sroot break; 6757627Ssam 6767627Ssam case SIOCATMARK: 6777627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6788594Sroot break; 6796355Ssam 6806355Ssam /* routing table update calls */ 6816355Ssam case SIOCADDRT: 6826355Ssam case SIOCDELRT: 6836355Ssam if (!suser()) 68410137Ssam return (u.u_error); 6858560Sroot return (rtrequest(cmd, (struct rtentry *)data)); 6866355Ssam 687*11571Ssam /* interface parameter requests */ 688*11571Ssam case SIOCSIFADDR: 689*11571Ssam case SIOCSIFFLAGS: 690*11571Ssam if (!suser()) 691*11571Ssam return (u.u_error); 692*11571Ssam return (ifrequest(cmd, data)); 693*11571Ssam 694*11571Ssam case SIOCGIFADDR: 695*11571Ssam case SIOCGIFFLAGS: 696*11571Ssam return (ifrequest(cmd, data)); 697*11571Ssam 698*11571Ssam case SIOCGIFCONF: 699*11571Ssam return (ifconf(cmd, data)); 700*11571Ssam 7015445Swnj /* type/protocol specific ioctls */ 7028594Sroot default: 70310137Ssam return (ENOTTY); /* XXX */ 7045423Swnj } 7058594Sroot return (0); 7064786Swnj } 707