1*8391Swnj /* uipc_socket.c 4.52 82/10/09 */ 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" 17*8391Swnj #include "../h/uio.h" 186355Ssam #include "../net/route.h" 194786Swnj 204786Swnj /* 218300Sroot * Socket operation routines. 228300Sroot * These routines are called by the routines in 238300Sroot * sys_socket.c or from a system process, and 248300Sroot * implement the semantics of socket operations by 258300Sroot * switching out to the protocol specific routines. 264786Swnj */ 274786Swnj 288300Sroot socreate(dom, aso, type, proto, opt) 294786Swnj struct socket **aso; 308300Sroot int type, proto; 318300Sroot struct socketopt *opt; 324786Swnj { 334786Swnj register struct protosw *prp; 344786Swnj register struct socket *so; 354786Swnj struct mbuf *m; 368300Sroot int pf, error; 374786Swnj 388300Sroot pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ 394890Swnj if (proto) 404890Swnj prp = pffindproto(pf, proto); 414890Swnj else 424890Swnj prp = pffindtype(pf, type); 434890Swnj if (prp == 0) 444890Swnj return (EPROTONOSUPPORT); 458300Sroot if (prp->pr_type != type) 468300Sroot return (EPROTOTYPE); 474890Swnj m = m_getclr(M_WAIT); 484786Swnj if (m == 0) 494786Swnj return (ENOBUFS); 504786Swnj so = mtod(m, struct socket *); 518300Sroot so->so_options = 0; 526214Swnj so->so_state = 0; 536214Swnj if (u.u_uid == 0) 546214Swnj so->so_state = SS_PRIV; 554786Swnj so->so_proto = prp; 568300Sroot error = (*prp->pr_usrreq)(so, PRU_ATTACH, 578300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 584979Swnj if (error) { 597507Sroot so->so_state |= SS_NOFDREF; 607180Swnj sofree(so); 614890Swnj return (error); 624786Swnj } 634786Swnj *aso = so; 644786Swnj return (0); 654786Swnj } 664786Swnj 678300Sroot sobind(so, nam, opt) 688300Sroot struct socket *so; 698300Sroot struct mbuf *nam; 708300Sroot struct socketopt *opt; 718300Sroot { 728300Sroot int s = splnet(); 738300Sroot int error; 748300Sroot 758300Sroot error = 768300Sroot (*so->so_proto->pr_usrreq)(so, PRU_BIND, 778300Sroot (struct mbuf *)0, nam, opt); 788300Sroot splx(s); 798300Sroot return (error); 808300Sroot } 818300Sroot 828300Sroot solisten(so, backlog) 838300Sroot struct socket *so; 848300Sroot int backlog; 858300Sroot { 868300Sroot int s = splnet(); 878300Sroot int error; 888300Sroot 898300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, 908300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 918300Sroot if (error) { 928300Sroot splx(s); 938300Sroot return (error); 948300Sroot } 958300Sroot if (so->so_q == 0) { 968300Sroot so->so_q = so; 978300Sroot so->so_q0 = so; 988300Sroot so->so_options |= SO_ACCEPTCONN; 998300Sroot } 1008300Sroot if (backlog < 0) 1018300Sroot backlog = 0; 1028300Sroot so->so_qlimit = backlog < 5 ? backlog : 5; 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 */ 1334829Swnj 1347507Sroot if (so->so_options & SO_ACCEPTCONN) { 1357507Sroot while (so->so_q0 != so) 1367507Sroot soclose(so->so_q0, 1); 1377507Sroot while (so->so_q != so) 1387507Sroot soclose(so->so_q, 1); 1397507Sroot } 1404890Swnj if (so->so_pcb == 0) 1414890Swnj goto discard; 1426259Sroot if (exiting) 1436259Sroot so->so_options |= SO_KEEPALIVE; 1444890Swnj if (so->so_state & SS_ISCONNECTED) { 1454890Swnj if ((so->so_state & SS_ISDISCONNECTING) == 0) { 1464927Swnj u.u_error = sodisconnect(so, (struct sockaddr *)0); 1474890Swnj if (u.u_error) { 1485580Sroot if (exiting) 1495580Sroot goto drop; 1504890Swnj splx(s); 1514890Swnj return; 1524890Swnj } 1534890Swnj } 1545388Sroot if ((so->so_options & SO_DONTLINGER) == 0) { 1555281Sroot if ((so->so_state & SS_ISDISCONNECTING) && 1566214Swnj (so->so_state & SS_NBIO) && 1575580Sroot exiting == 0) { 1585281Sroot u.u_error = EINPROGRESS; 1595281Sroot splx(s); 1605281Sroot return; 1615281Sroot } 1625580Sroot /* should use tsleep here, for at most linger */ 1635281Sroot while (so->so_state & SS_ISCONNECTED) 1645281Sroot sleep((caddr_t)&so->so_timeo, PZERO+1); 1654890Swnj } 1664890Swnj } 1675580Sroot drop: 1686880Ssam if (so->so_pcb) { 1698300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 1708300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 1716880Ssam if (exiting == 0 && u.u_error) { 1726880Ssam splx(s); 1736880Ssam return; 1746880Ssam } 1756880Ssam } 1764890Swnj discard: 1777507Sroot so->so_state |= SS_NOFDREF; 1784950Swnj sofree(so); 1794890Swnj splx(s); 1804829Swnj } 1814829Swnj 1824916Swnj /*ARGSUSED*/ 1834890Swnj sostat(so, sb) 1844829Swnj struct socket *so; 1854890Swnj struct stat *sb; 1864829Swnj { 1874829Swnj 1885303Sroot bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ 1895303Sroot return (0); /* XXX */ 1904829Swnj } 1914829Swnj 1928300Sroot soaccept(so, nam, opt) 1934927Swnj struct socket *so; 1948300Sroot struct mbuf *nam; 1958300Sroot struct socketopt *opt; 1964927Swnj { 1974927Swnj int s = splnet(); 1984927Swnj int error; 1994927Swnj 2008300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 2018300Sroot (struct mbuf *)0, nam, opt); 2024927Swnj splx(s); 2034927Swnj return (error); 2044927Swnj } 2054927Swnj 2068300Sroot soconnect(so, nam, opt) 2074786Swnj struct socket *so; 2088300Sroot struct mbuf *nam; 2098300Sroot struct socketopt *opt; 2104786Swnj { 2114890Swnj int s = splnet(); 2124890Swnj int error; 2134786Swnj 2144890Swnj if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { 2154890Swnj error = EISCONN; 2164890Swnj goto bad; 2174890Swnj } 2188300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 2198300Sroot (struct mbuf *)0, nam, opt); 2204890Swnj bad: 2214890Swnj splx(s); 2224890Swnj return (error); 2234786Swnj } 2244786Swnj 2258300Sroot sodisconnect(so, nam) 2264786Swnj struct socket *so; 2278300Sroot struct mbuf *nam; 2284786Swnj { 2294890Swnj int s = splnet(); 2304890Swnj int error; 2314786Swnj 2324890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2334890Swnj error = ENOTCONN; 2344890Swnj goto bad; 2354890Swnj } 2364890Swnj if (so->so_state & SS_ISDISCONNECTING) { 2374890Swnj error = EALREADY; 2384890Swnj goto bad; 2394890Swnj } 2408300Sroot error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 2418300Sroot (struct mbuf *)0, nam, (struct socketopt *)0); 2424890Swnj bad: 2434890Swnj splx(s); 2444890Swnj return (error); 2454786Swnj } 2464786Swnj 2474786Swnj /* 2484890Swnj * Send on a socket. 2494890Swnj * If send must go all at once and message is larger than 2504890Swnj * send buffering, then hard error. 2514890Swnj * Lock against other senders. 2524890Swnj * If must go all at once and not enough room now, then 2534890Swnj * inform user that this would block and do nothing. 2544786Swnj */ 2558319Sroot sosend(so, nam, uio, flags) 2564786Swnj register struct socket *so; 2578300Sroot struct mbuf *nam; 2587827Sroot struct uio *uio; 2598319Sroot int flags; 2604786Swnj { 2614890Swnj struct mbuf *top = 0; 2624890Swnj register struct mbuf *m, **mp = ⊤ 2634916Swnj register u_int len; 2644916Swnj int error = 0, space, s; 2654786Swnj 2667827Sroot if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) 2674890Swnj return (EMSGSIZE); 2686419Sroot restart: 2694890Swnj sblock(&so->so_snd); 2704890Swnj #define snderr(errno) { error = errno; splx(s); goto release; } 2714890Swnj 2728041Sroot u.u_ru.ru_msgsnd++; 2736419Sroot again: 2744890Swnj s = splnet(); 2756419Sroot if (so->so_state & SS_CANTSENDMORE) { 2766419Sroot psignal(u.u_procp, SIGPIPE); 2776419Sroot snderr(EPIPE); 2786419Sroot } 2795168Swnj if (so->so_error) { 2805168Swnj error = so->so_error; 2816419Sroot so->so_error = 0; /* ??? */ 2825168Swnj splx(s); 2835168Swnj goto release; 2845168Swnj } 2854890Swnj if ((so->so_state & SS_ISCONNECTED) == 0) { 2864890Swnj if (so->so_proto->pr_flags & PR_CONNREQUIRED) 2874890Swnj snderr(ENOTCONN); 2888300Sroot if (nam == 0) 2894890Swnj snderr(EDESTADDRREQ); 2904890Swnj } 2914890Swnj if (top) { 2928319Sroot error = (*so->so_proto->pr_usrreq)(so, 2938319Sroot (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, 2948300Sroot top, (caddr_t)nam, (struct socketopt *)0); 2956419Sroot top = 0; 2964890Swnj if (error) { 2974890Swnj splx(s); 2984786Swnj goto release; 2994786Swnj } 3004890Swnj mp = ⊤ 3014786Swnj } 3027827Sroot if (uio->uio_resid == 0) { 3034979Swnj splx(s); 3044979Swnj goto release; 3054979Swnj } 3068319Sroot if (flags & SOF_OOB) 3078319Sroot space = 1024; 3088319Sroot else { 3098319Sroot space = sbspace(&so->so_snd); 3108319Sroot if (space <= 0 || 3118319Sroot sosendallatonce(so) && space < uio->uio_resid) { 3128319Sroot if (so->so_state & SS_NBIO) 3138319Sroot snderr(EWOULDBLOCK); 3148319Sroot sbunlock(&so->so_snd); 3158319Sroot sbwait(&so->so_snd); 3168319Sroot splx(s); 3178319Sroot goto restart; 3188319Sroot } 3194786Swnj } 3204890Swnj splx(s); 3217827Sroot while (uio->uio_resid > 0 && space > 0) { 3227827Sroot register struct iovec *iov = uio->uio_iov; 3237827Sroot 3247827Sroot if (iov->iov_len == 0) { 3257827Sroot uio->uio_iov++; 3267827Sroot uio->uio_iovcnt--; 3277827Sroot if (uio->uio_iovcnt < 0) 3287827Sroot panic("sosend"); 3297827Sroot continue; 3307827Sroot } 3314890Swnj MGET(m, 1); 3324890Swnj if (m == NULL) { 3336419Sroot error = ENOBUFS; /* SIGPIPE? */ 3344890Swnj goto release; 3354786Swnj } 3367827Sroot if (iov->iov_len >= CLBYTES && space >= CLBYTES) { 3374890Swnj register struct mbuf *p; 3385095Swnj MCLGET(p, 1); 3394890Swnj if (p == 0) 3404890Swnj goto nopages; 3414890Swnj m->m_off = (int)p - (int)m; 3425095Swnj len = CLBYTES; 3434890Swnj } else { 3444786Swnj nopages: 3457827Sroot len = MIN(MLEN, iov->iov_len); 3464786Swnj } 3477827Sroot uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 3484890Swnj m->m_len = len; 3494890Swnj *mp = m; 3504890Swnj mp = &m->m_next; 3518319Sroot if (flags & SOF_OOB) 3528319Sroot space -= len; 3538319Sroot else 3548319Sroot space = sbspace(&so->so_snd); 3554786Swnj } 3564890Swnj goto again; 3574890Swnj 3584786Swnj release: 3594890Swnj sbunlock(&so->so_snd); 3606419Sroot if (top) 3616419Sroot m_freem(top); 3624786Swnj return (error); 3634786Swnj } 3644786Swnj 3658319Sroot soreceive(so, aname, uio, flags) 3664786Swnj register struct socket *so; 3678300Sroot struct mbuf **aname; 3687747Sroot struct uio *uio; 3698319Sroot int flags; 3704786Swnj { 3717747Sroot register struct iovec *iov; 3724786Swnj register struct mbuf *m, *n; 3734916Swnj u_int len; 3748319Sroot int eor, s, error = 0, moff, tomark; 3754786Swnj 3768319Sroot if (flags & SOF_OOB) { 3778319Sroot struct mbuf *m = m_get(M_WAIT); 3788319Sroot 3798319Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 3808319Sroot m, (struct mbuf *)0, (struct socketopt *)0); 3818319Sroot len = uio->uio_resid; 3828319Sroot do { 3838319Sroot if (len > m->m_len) 3848319Sroot len = m->m_len; 3858319Sroot uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); 3868319Sroot m = m_free(m); 3878319Sroot } while (uio->uio_resid && u.u_error == 0 && m); 3888319Sroot if (m) 3898319Sroot (void) m_freem(m); 3908319Sroot return; 3918319Sroot } 3928319Sroot 3934890Swnj restart: 3944890Swnj sblock(&so->so_rcv); 3954890Swnj s = splnet(); 3964890Swnj 3974890Swnj #define rcverr(errno) { error = errno; splx(s); goto release; } 3984786Swnj if (so->so_rcv.sb_cc == 0) { 3995168Swnj if (so->so_error) { 4005168Swnj error = so->so_error; 4015168Swnj so->so_error = 0; 4025168Swnj splx(s); 4035168Swnj goto release; 4045168Swnj } 4054890Swnj if (so->so_state & SS_CANTRCVMORE) { 4064890Swnj splx(s); 4074890Swnj goto release; 4084890Swnj } 4095015Sroot if ((so->so_state & SS_ISCONNECTED) == 0 && 4105015Sroot (so->so_proto->pr_flags & PR_CONNREQUIRED)) 4115015Sroot rcverr(ENOTCONN); 4126214Swnj if (so->so_state & SS_NBIO) 4135168Swnj rcverr(EWOULDBLOCK); 4144890Swnj sbunlock(&so->so_rcv); 4154971Swnj sbwait(&so->so_rcv); 4165012Swnj splx(s); 4174890Swnj goto restart; 4184786Swnj } 4198041Sroot u.u_ru.ru_msgrcv++; 4204829Swnj m = so->so_rcv.sb_mb; 4214786Swnj if (m == 0) 4224786Swnj panic("receive"); 4235039Swnj if (so->so_proto->pr_flags & PR_ADDR) { 4248319Sroot if ((flags & SOF_PREVIEW) == 0) { 4258319Sroot so->so_rcv.sb_cc -= m->m_len; 4268319Sroot so->so_rcv.sb_mbcnt -= MSIZE; 4278319Sroot } 4288300Sroot if (aname) { 4298319Sroot if (flags & SOF_PREVIEW) 4308319Sroot *aname = m_copy(m, 0, m->m_len); 4318319Sroot else 4328319Sroot *aname = m; 4338300Sroot m = m->m_next; 4348300Sroot (*aname)->m_next = 0; 4358300Sroot } else 4368319Sroot if (flags & SOF_PREVIEW) 4378319Sroot m = m->m_next; 4388319Sroot else 4398319Sroot m = m_free(m); 4404890Swnj if (m == 0) 4414890Swnj panic("receive 2"); 4424890Swnj } 4434786Swnj eor = 0; 4448319Sroot moff = 0; 4458319Sroot tomark = so->so_oobmark; 4464786Swnj do { 4477827Sroot if (uio->uio_resid <= 0) 4487747Sroot break; 4497827Sroot len = uio->uio_resid; 4507747Sroot so->so_state &= ~SS_RCVATMARK; 4518319Sroot if (tomark && len > tomark) 4528319Sroot len = tomark; 4538319Sroot if (len > m->m_len - moff) 4548319Sroot len = m->m_len - moff; 4554786Swnj splx(s); 4568319Sroot uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); 4574786Swnj s = splnet(); 4584786Swnj if (len == m->m_len) { 4596091Sroot eor = (int)m->m_act; 4608319Sroot if (flags & SOF_PREVIEW) 4618319Sroot m = m->m_next; 4628319Sroot else { 4638319Sroot sbfree(&so->so_rcv, m); 4648319Sroot MFREE(m, n); 4658319Sroot m = n; 4668319Sroot } 4678319Sroot moff = 0; 4684786Swnj } else { 4698319Sroot if (flags & SOF_PREVIEW) 4708319Sroot moff += len; 4718319Sroot else { 4728319Sroot m->m_off += len; 4738319Sroot m->m_len -= len; 4748319Sroot so->so_rcv.sb_cc -= len; 4758319Sroot } 4764786Swnj } 4778319Sroot if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { 4787747Sroot so->so_oobmark -= len; 4797747Sroot if (so->so_oobmark == 0) { 4807747Sroot so->so_state |= SS_RCVATMARK; 4817747Sroot break; 4827747Sroot } 4837747Sroot } 4848319Sroot if (tomark) { 4858319Sroot tomark -= len; 4868319Sroot if (tomark == 0) 4878319Sroot break; 4888319Sroot } 4898319Sroot } while (m && !eor); 4908319Sroot if (flags & SOF_PREVIEW) 4918319Sroot goto release; 4928319Sroot so->so_rcv.sb_mb = m; 4934786Swnj if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) 4944786Swnj do { 4954786Swnj if (m == 0) 4964890Swnj panic("receive 3"); 4974890Swnj sbfree(&so->so_rcv, m); 4984786Swnj eor = (int)m->m_act; 4994786Swnj so->so_rcv.sb_mb = m->m_next; 5004786Swnj MFREE(m, n); 5014890Swnj m = n; 5024786Swnj } while (eor == 0); 5034890Swnj if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) 5048300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 5058300Sroot (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); 5064890Swnj release: 5074916Swnj sbunlock(&so->so_rcv); 5084890Swnj splx(s); 5094916Swnj return (error); 5104786Swnj } 5114786Swnj 5125423Swnj sohasoutofband(so) 5135423Swnj struct socket *so; 5145423Swnj { 5155423Swnj 5165423Swnj if (so->so_pgrp == 0) 5175423Swnj return; 5185423Swnj if (so->so_pgrp > 0) 5195423Swnj gsignal(so->so_pgrp, SIGURG); 5205429Swnj else { 5215429Swnj struct proc *p = pfind(-so->so_pgrp); 5225429Swnj 5235429Swnj if (p) 5245429Swnj psignal(p, SIGURG); 5255429Swnj } 5265423Swnj } 5275423Swnj 5284916Swnj /*ARGSUSED*/ 5297627Ssam soioctl(so, cmd, data) 5304829Swnj register struct socket *so; 5314829Swnj int cmd; 5327627Ssam register char *data; 5334786Swnj { 5344786Swnj 5355358Sroot switch (cmd) { 5364829Swnj 5377627Ssam case FIONBIO: 5387627Ssam if (*(int *)data) 5396214Swnj so->so_state |= SS_NBIO; 5405388Sroot else 5416214Swnj so->so_state &= ~SS_NBIO; 5425388Sroot return; 5435388Sroot 5447627Ssam case FIOASYNC: 5457627Ssam if (*(int *)data) 5466214Swnj so->so_state |= SS_ASYNC; 5475388Sroot else 5486214Swnj so->so_state &= ~SS_ASYNC; 5495388Sroot return; 5505388Sroot 5517627Ssam case SIOCSKEEP: 5527627Ssam if (*(int *)data) 5537507Sroot so->so_options &= ~SO_KEEPALIVE; 5547507Sroot else 5557491Ssam so->so_options |= SO_KEEPALIVE; 5565388Sroot return; 5575388Sroot 5587627Ssam case SIOCGKEEP: 5597627Ssam *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; 5605388Sroot return; 5615388Sroot 5627627Ssam case SIOCSLINGER: 5637627Ssam so->so_linger = *(int *)data; 5645388Sroot if (so->so_linger) 5655388Sroot so->so_options &= ~SO_DONTLINGER; 5665388Sroot else 5675388Sroot so->so_options |= SO_DONTLINGER; 5685388Sroot return; 5695388Sroot 5707627Ssam case SIOCGLINGER: 5717627Ssam *(int *)data = so->so_linger; 5725423Swnj return; 5735388Sroot 5747627Ssam case SIOCSPGRP: 5757627Ssam so->so_pgrp = *(int *)data; 5767627Ssam return; 5775423Swnj 5787627Ssam case SIOCGPGRP: 5797627Ssam *(int *)data = so->so_pgrp; 5807627Ssam return; 5817627Ssam 5825281Sroot case SIOCDONE: { 5837627Ssam int flags = *(int *)data; 5847627Ssam 5855388Sroot flags++; 5865281Sroot if (flags & FREAD) { 5875281Sroot int s = splimp(); 5885281Sroot socantrcvmore(so); 5895281Sroot sbflush(&so->so_rcv); 5906140Ssam splx(s); 5915281Sroot } 5925281Sroot if (flags & FWRITE) 5938300Sroot u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, 5948300Sroot (struct mbuf *)0, (struct mbuf *)0, 5958300Sroot (struct socketopt *)0); 5965281Sroot return; 5974829Swnj } 5985281Sroot 5995423Swnj case SIOCSENDOOB: { 6007627Ssam char oob = *(char *)data; 6018319Sroot struct mbuf *m = m_get(M_DONTWAIT); 6027627Ssam 6035423Swnj if (m == 0) { 6045423Swnj u.u_error = ENOBUFS; 6055423Swnj return; 6065423Swnj } 6078319Sroot m->m_len = 1; 6087627Ssam *mtod(m, char *) = oob; 6098300Sroot (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, 6108300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6115423Swnj return; 6125281Sroot } 6135423Swnj 6145423Swnj case SIOCRCVOOB: { 6158319Sroot struct mbuf *m = m_get(M_WAIT); 6167627Ssam 6175423Swnj if (m == 0) { 6185423Swnj u.u_error = ENOBUFS; 6195423Swnj return; 6205423Swnj } 6218319Sroot *mtod(m, caddr_t) = 0; 6228300Sroot (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, 6238300Sroot m, (struct mbuf *)0, (struct socketopt *)0); 6247627Ssam *(char *)data = *mtod(m, char *); 6257627Ssam (void) m_free(m); 6265423Swnj return; 6275423Swnj } 6285423Swnj 6297627Ssam case SIOCATMARK: 6307627Ssam *(int *)data = (so->so_state&SS_RCVATMARK) != 0; 6315423Swnj return; 6326355Ssam 6336355Ssam /* routing table update calls */ 6346355Ssam case SIOCADDRT: 6356355Ssam case SIOCDELRT: 6366355Ssam if (!suser()) 6376355Ssam return; 6387627Ssam u.u_error = rtrequest(cmd, (struct rtentry *)data); 6396355Ssam return; 6406355Ssam 6415445Swnj /* type/protocol specific ioctls */ 6425423Swnj } 6435445Swnj u.u_error = EOPNOTSUPP; 6444786Swnj } 645