uipc_sock.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:38k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* uipc_sock.c - uipc socket routines */
  2. /* Copyright 1984 - 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1988, 1990, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)uipc_socket.c 8.6 (Berkeley) 5/2/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01l,05jun02,vvv  fixed Nagle for large writes (SPR #72213)
  42. 01k,12oct01,rae  merge from truestack ver 01r, base 01h (SPR #64845 etc)
  43. 01j,07feb01,spm  updated socket handling to detect memory allocation failures
  44. 01i,24sep98,ham  considered if(m->m_extSize<max_hdr) in sosend() SPR#22209.
  45. 01h,26aug98,n_s  optimized processing of uio buffer in sosend. spr #22246.
  46. 01g,26aug98,n_s  added return val check for MALLOC in socreate and for 
  47.                  mBufClGet in soreceive. spr #22238.
  48. 01f,11aug97,vin  fixed problems in sosend, adjusted space in sosend
  49. 01e,23jan97,vin  added fix for SPR7502.
  50. 01d,03dec96,vin  replaced calloc(..) with MALLOC(..), free(..) with FREE(..)
  51. 01c,22nov96,vin  added cluster support, replaced m_get with mBufClGet and
  52.  m_gethdr with mHdrClGet.
  53. 01b,29aug96,vin  added zerocopy interface. 
  54. 01a,03mar96,vin  created from BSD4.4lite2. Integrated with 02u of uipc_sock.c
  55. */
  56. #include "vxWorks.h"
  57. #include "semLib.h"
  58. #include "memLib.h"
  59. #include "errno.h"
  60. #include "net/mbuf.h"
  61. #include "net/domain.h"
  62. #include "net/protosw.h"
  63. #include "sys/socket.h"
  64. #include "sys/times.h"
  65. #include "net/socketvar.h"
  66. #include "sys/ioctl.h"
  67. #include "net/uio.h"
  68. #include "net/route.h"
  69. #include "netinet/in.h"
  70. #include "net/if.h"
  71. #include "net/systm.h"
  72. #include "selectLib.h"
  73. #include "sockLib.h"
  74. #include "netLib.h"
  75. #ifdef WV_INSTRUMENTATION
  76. #ifdef INCLUDE_WVNET
  77. #include "wvNetLib.h"
  78. #endif
  79. #endif
  80. #ifdef WV_INSTRUMENTATION
  81. #ifdef INCLUDE_WVNET
  82.     /* Set common fields of event identifiers for this module. */
  83. LOCAL UCHAR wvNetModuleId = WV_NET_UISOCK_MODULE;  /* Value for uipc_sock.c */
  84. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  85. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  86. #endif    /* INCLUDE_WVNET */
  87. #endif
  88. extern int uiomove();
  89. /*
  90.  * Socket operation routines.
  91.  * These routines are called by the routines in
  92.  * sys_socket.c or from a system process, and
  93.  * implement the semantics of socket operations by
  94.  * switching out to the protocol specific routines.
  95.  */
  96. /*ARGSUSED*/
  97. int
  98. socreate(dom, aso, type, proto)
  99. int dom;
  100. struct socket **aso;
  101. register int type;
  102. int proto;
  103. {
  104. register struct protosw *prp;
  105. register struct socket *so;
  106. register int error;
  107. #ifdef WV_INSTRUMENTATION
  108. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  109.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 45, 11,
  110.                      WV_NETEVENT_SOCREATE_START)
  111. #endif  /* INCLUDE_WVNET */
  112. #endif
  113. if (proto)
  114. prp = pffindproto(dom, proto, type);
  115. else
  116. prp = pffindtype(dom, type);
  117. if (prp == 0 || prp->pr_usrreq == 0)
  118.             {
  119. #ifdef WV_INSTRUMENTATION
  120. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  121.             WV_NET_MARKER_3 (NET_AUX_EVENT, WV_NET_ERROR, 43, 6,
  122.                              WV_NETEVENT_SOCREATE_SEARCHFAIL,
  123.                              dom, proto, type)
  124. #endif  /* INCLUDE_WVNET */
  125. #endif
  126.             return (EPROTONOSUPPORT);
  127.             }
  128. if (prp->pr_type != type)
  129.             {
  130. /* XXX - This event does not occur because the search routines will always
  131.  *       return a protocol switch entry which matches the given type value.
  132. #ifdef WV_INSTRUMENTATION
  133. #ifdef INCLUDE_WVNET    /@ WV_NET_ERROR event @/
  134.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 44, 7,
  135.                              WV_NETEVENT_SOCREATE_BADTYPE, prp->pr_type, type)
  136. #endif  /@ INCLUDE_WVNET @/
  137. #endif
  138.  * XXX - end of unused event
  139.  */
  140.             return (EPROTOTYPE);
  141.             }
  142.         MALLOC(so, struct socket *, sizeof(*so), MT_SOCKET, M_WAIT);
  143. if (so == (struct socket *) NULL)
  144.     {
  145.     return (ENOBUFS);
  146.     }
  147.         bzero((caddr_t)so, sizeof(*so));
  148. so->so_options = 0; 
  149. so->so_type = type;
  150. /* all sockets will be priveledged */
  151. so->so_state = SS_PRIV;
  152. so->so_proto = prp;
  153. /* initialize socket semaphores */
  154. so->so_timeoSem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
  155.         if (so->so_timeoSem == NULL)
  156.             {
  157.             so->so_state |= SS_NOFDREF;
  158.             sofree(so);
  159.             return (ENOMEM);
  160.             }
  161. so->so_rcv.sb_Sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
  162.         if (so->so_rcv.sb_Sem == NULL)
  163.             {
  164.             so->so_state |= SS_NOFDREF;
  165.             sofree(so);
  166.             return (ENOMEM);
  167.             }
  168. so->so_snd.sb_Sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
  169.         if (so->so_snd.sb_Sem == NULL)
  170.             {
  171.             so->so_state |= SS_NOFDREF;
  172.             sofree(so);
  173.             return (ENOMEM);
  174.             }
  175. so->so_rcv.sb_want = 0;
  176. so->so_snd.sb_want = 0;
  177. /* initialize the select stuff */
  178. selWakeupListInit (&so->so_selWakeupList);
  179.         so->selectFlag = TRUE;
  180. error =
  181.     (*prp->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0,
  182. (struct mbuf *)(long)proto, (struct mbuf *)0);
  183. if (error) {
  184. so->so_state |= SS_NOFDREF;
  185. sofree(so);
  186. return (error);
  187. }
  188. *aso = so;
  189. return (0);
  190. }
  191. int
  192. sobind(so, nam)
  193. struct socket *so;
  194. struct mbuf *nam;
  195. {
  196. int s = splnet();
  197. int error;
  198. #ifdef WV_INSTRUMENTATION
  199. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  200.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 46, 12,
  201.                      WV_NETEVENT_SOBIND_START, so->so_fd)
  202. #endif  /* INCLUDE_WVNET */
  203. #endif
  204. error =
  205.     (*so->so_proto->pr_usrreq)(so, PRU_BIND,
  206. (struct mbuf *)0, nam, (struct mbuf *)0);
  207. splx(s);
  208. return (error);
  209. }
  210. int
  211. solisten(so, backlog)
  212. register struct socket *so;
  213. int backlog;
  214. {
  215. int s = splnet(), error;
  216. #ifdef WV_INSTRUMENTATION
  217. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  218.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 47, 13,
  219.                      WV_NETEVENT_SOLISTEN_START, so->so_fd)
  220. #endif  /* INCLUDE_WVNET */
  221. #endif
  222. error =
  223.     (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
  224. (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  225. if (error) {
  226. splx(s);
  227. return (error);
  228. }
  229. if (so->so_q == 0)
  230. so->so_options |= SO_ACCEPTCONN;
  231. if (backlog < 0)
  232. backlog = 0;
  233. so->so_qlimit = min(backlog, SOMAXCONN);
  234. splx(s);
  235. return (0);
  236. }
  237. void sofree
  238.     (
  239.     register struct socket *so
  240.     )
  241.     {
  242. #ifdef WV_INSTRUMENTATION
  243. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  244.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 48, 14,
  245.                      WV_NETEVENT_SOFREE_START, so->so_fd)
  246. #endif  /* INCLUDE_WVNET */
  247. #endif
  248.     if (so->so_state & SS_NOFDREF)
  249.         {
  250.         /*
  251.          * Always remove semaphores when closing socket. Existing TCP
  252.          * connections exit after the next test, preventing correct
  253.          * reclamation of these objects.
  254.          */
  255.         if (so->so_timeoSem)
  256.             {
  257.             semDelete (so->so_timeoSem);
  258.             so->so_timeoSem = NULL;
  259.             }
  260.         if (so->so_snd.sb_Sem)
  261.             {
  262.             semDelete (so->so_snd.sb_Sem);
  263.             so->so_snd.sb_Sem = NULL;
  264.             }
  265.         if (so->so_rcv.sb_Sem)
  266.             {
  267.             semDelete (so->so_rcv.sb_Sem);
  268.             so->so_rcv.sb_Sem = NULL;
  269.             }
  270.         if (so->selectFlag)
  271.             {
  272.             selWakeupListTerm (&so->so_selWakeupList);
  273.             so->selectFlag = FALSE;
  274.             }
  275.         }
  276.  
  277.     if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
  278.         return;
  279.     if (so->so_head)
  280.         {
  281.         if (!soqremque (so, 0) && !soqremque (so, 1))
  282.             {
  283. #ifdef WV_INSTRUMENTATION
  284. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  285.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 38, 1,
  286.                              WV_NETEVENT_SOFREE_PANIC, so->so_fd)
  287. #endif  /* INCLUDE_WVNET */
  288. #endif
  289.             panic ("sofree dq");
  290.             }
  291.         so->so_head = 0;
  292.         }
  293.     sbrelease (&so->so_snd);
  294.     sorflush (so);
  295.     FREE (so, MT_SOCKET); 
  296.     }
  297. /*
  298.  * Close a socket on last file table reference removal.
  299.  * Initiate disconnect if connected.
  300.  * Free socket when disconnect complete.
  301.  */
  302. int soclose
  303.     (
  304.     register struct socket *so
  305.     )
  306.     {
  307.     int s = splnet(); /* conservative */
  308.     int error = 0;
  309.     SEL_WAKEUP_NODE *pWakeupNode;
  310.     SEL_WAKEUP_LIST *pWakeupList;
  311. #ifdef WV_INSTRUMENTATION
  312. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  313.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 49, 15,
  314.                      WV_NETEVENT_SOCLOSE_START, so->so_fd)
  315. #endif  /* INCLUDE_WVNET */
  316. #endif
  317.     if (so->so_options & SO_ACCEPTCONN)
  318.         {
  319.         while (so->so_q0)
  320.                (void) soabort(so->so_q0);
  321.         while (so->so_q)
  322.                (void) soabort(so->so_q);
  323.         }
  324.     if (so->so_pcb == 0)
  325.         goto discard;
  326.     if (so->so_state & SS_ISCONNECTED)
  327.         {
  328.         if ((so->so_state & SS_ISDISCONNECTING) == 0)
  329.             {
  330.             error = sodisconnect(so);
  331.             if (error)
  332.                 goto drop;
  333.             }
  334.         if (so->so_options & SO_LINGER)
  335.             {
  336.             if ( (so->so_state & SS_ISDISCONNECTING) &&
  337.                 (so->so_state & SS_NBIO))
  338.                 goto drop;
  339.             while (so->so_state & SS_ISCONNECTED)
  340.                 {
  341. #ifdef WV_INSTRUMENTATION
  342. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  343.                 WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 52, 10,
  344.                                  WV_NETEVENT_SOCLOSE_WAIT, so->so_fd)
  345. #endif  /* INCLUDE_WVNET */
  346. #endif
  347.                 ksleep(so->so_timeoSem);
  348.                 }
  349.             }
  350.         }
  351. drop:
  352.     if (so->so_pcb)
  353.         {
  354.         int error2 = (*so->so_proto->pr_usrreq) (so, PRU_DETACH,
  355.                                                  (struct mbuf *)0, 
  356.                                                  (struct mbuf *)0, 
  357.                                                  (struct mbuf *)0);
  358.         if (error == 0)
  359.             error = error2;
  360.         }
  361. discard:
  362.     /* clean up the select wakeup list for this socket */
  363.     pWakeupList = &so->so_selWakeupList;
  364.     if (lstCount (&pWakeupList->wakeupList) != 0)
  365.         {
  366.         semTake (&pWakeupList->listMutex, WAIT_FOREVER);
  367.         while ((pWakeupNode =
  368.           (SEL_WAKEUP_NODE *) lstFirst (&pWakeupList->wakeupList)))
  369.     soo_unselect (so, pWakeupNode);
  370. semGive (&pWakeupList->listMutex);
  371. }
  372.     if (so->so_state & SS_NOFDREF)
  373.         {
  374. #ifdef WV_INSTRUMENTATION
  375. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  376.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 39, 2,
  377.                          WV_NETEVENT_SOCLOSE_PANIC, so->so_fd)
  378. #endif  /* INCLUDE_WVNET */
  379. #endif
  380.     
  381.         panic ("soclose: NOFDREF");
  382.         }
  383.     so->so_state |= SS_NOFDREF;
  384.     sofree (so);
  385.     splx (s);
  386.     return (error);
  387.     }
  388. /*
  389.  * Must be called at splnet...
  390.  */
  391. int soabort
  392.     (
  393.     struct socket *so
  394.     )
  395.     {
  396. #ifdef WV_INSTRUMENTATION
  397. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  398.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 50, 16,
  399.                      WV_NETEVENT_SOABORT_START, so->so_fd)
  400. #endif  /* INCLUDE_WVNET */
  401. #endif
  402.     return ( (*so->so_proto->pr_usrreq) (so, PRU_ABORT, (struct mbuf *)0,
  403.                                          (struct mbuf *)0, (struct mbuf *)0));
  404.     }
  405. int
  406. soaccept(so, nam)
  407. register struct socket *so;
  408. struct mbuf *nam;
  409. {
  410. int s = splnet();
  411. int error;
  412. #ifdef WV_INSTRUMENTATION
  413. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  414.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 51, 17,
  415.                      WV_NETEVENT_SOACCEPT_START, so->so_fd)
  416. #endif  /* INCLUDE_WVNET */
  417. #endif
  418.     if ( (so->so_state & SS_NOFDREF) == 0)
  419.         {
  420. #ifdef WV_INSTRUMENTATION
  421. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  422.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 40, 3,
  423.                          WV_NETEVENT_SOACCEPT_PANIC, so->so_fd)
  424. #endif  /* INCLUDE_WVNET */
  425. #endif
  426.         panic("soaccept: !NOFDREF");
  427.         }
  428.     so->so_state &= ~SS_NOFDREF;
  429.     error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, (struct mbuf *)0, 
  430.                                        nam, (struct mbuf *)0);
  431.     splx (s);
  432.     return (error);
  433.     }
  434. int
  435. soconnect(so, nam)
  436. register struct socket *so;
  437. struct mbuf *nam;
  438. {
  439. int s;
  440. int error;
  441. #ifdef WV_INSTRUMENTATION
  442. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  443.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 52, 18,
  444.                      WV_NETEVENT_SOCONNECT_START, so->so_fd)
  445. #endif  /* INCLUDE_WVNET */
  446. #endif
  447. if (so->so_options & SO_ACCEPTCONN)
  448.             {
  449. #ifdef WV_INSTRUMENTATION
  450. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  451.             WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 45, 8,
  452.                              WV_NETEVENT_SOCONNECT_BADSOCK, so->so_fd)
  453. #endif  /* INCLUDE_WVNET */
  454. #endif
  455.             return (EOPNOTSUPP);
  456.             }
  457. s = splnet();
  458. /*
  459.  * If protocol is connection-based, can only connect once.
  460.  * Otherwise, if connected, try to disconnect first.
  461.  * This allows user to disconnect by connecting to, e.g.,
  462.  * a null address.
  463.  */
  464. if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
  465.     ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
  466.     (error = sodisconnect(so))))
  467. error = EISCONN;
  468. else
  469. error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
  470.     (struct mbuf *)0, nam, (struct mbuf *)0);
  471. splx(s);
  472. return (error);
  473. }
  474. int
  475. soconnect2(so1, so2)
  476. register struct socket *so1;
  477. struct socket *so2;
  478. {
  479. int s = splnet();
  480. int error;
  481. /*
  482.  * XXX - This event cannot currently occur: the socket operation which uses
  483.  *       the soconnect2() routine is not supported by VxWorks
  484. #ifdef WV_INSTRUMENTATION
  485. #ifdef INCLUDE_WVNET    /@ WV_NET_VERBOSE event @/
  486.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 53, 19,
  487.                      WV_NETEVENT_SOCONNECT2_START, so1->so_fd, so2->so_fd)
  488. #endif  /@ INCLUDE_WVNET @/
  489. #endif
  490.  * XXX - end of unused event
  491.  */
  492. error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
  493.     (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
  494. splx(s);
  495. return (error);
  496. }
  497. int
  498. sodisconnect(so)
  499. register struct socket *so;
  500. {
  501. int s = splnet();
  502. int error;
  503. if ((so->so_state & SS_ISCONNECTED) == 0) {
  504. error = ENOTCONN;
  505. goto bad;
  506. }
  507. if (so->so_state & SS_ISDISCONNECTING) {
  508. error = EALREADY;
  509. goto bad;
  510. }
  511. error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
  512.     (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
  513. bad:
  514. splx(s);
  515. #ifdef WV_INSTRUMENTATION
  516. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  517.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 46, 9,
  518.                      WV_NETEVENT_SODISCONN_STATUS, so->so_fd, error)
  519. #endif  /* INCLUDE_WVNET */
  520. #endif
  521. return (error);
  522. }
  523. #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_DONTWAIT : M_WAIT)
  524. /*
  525.  * Send on a socket.
  526.  * If send must go all at once and message is larger than
  527.  * send buffering, then hard error.
  528.  * Lock against other senders.
  529.  * If must go all at once and not enough room now, then
  530.  * inform user that this would block and do nothing.
  531.  * Otherwise, if nonblocking, send as much as possible.
  532.  * The data to be sent is described by "uio" if nonzero,
  533.  * otherwise by the mbuf chain "top" (which must be null
  534.  * if uio is not).  Data provided in mbuf chain must be small
  535.  * enough to send all at once.
  536.  *
  537.  * Returns nonzero on error, timeout or signal; callers
  538.  * must check for short counts if EINTR/ERESTART are returned.
  539.  * Data and control buffers are freed on return.
  540.  *
  541.  * WRS mods removed sblock and sbunlock and replaced with splnet and splx
  542.  * which should serve the purpose.
  543.  * Removed null check of uio so that blocking can be implemented for zbufs
  544.  * also. 
  545.  * CAVEAT: the zbuf length cannot be more than the socket high water mark.
  546.  * The user should implement his flow control. 
  547.  * So this call would block only if zbuf length is bigger the space available
  548.  * in the socket buffer and less than the socket higt water mark. 
  549.  * Added a flag canWait which is set to M_DONTWAIT if the socket option SS_NBIO
  550.  * is set. This prevents blocking if the user chose SS_NBIO and for some reason
  551.  * if the system runs out of mbufs. canWait defaults to M_WAIT -(vinai).
  552.  */
  553. int
  554. sosend(so, addr, uio, top, control, flags)
  555. register struct socket *so;
  556. struct mbuf *addr;
  557. struct uio *uio;
  558. struct mbuf *top;
  559. struct mbuf *control;
  560. int flags;
  561. {
  562. struct mbuf **mp;
  563. register struct mbuf *m;
  564. register long space, len, resid;
  565. int clen = 0, error, s, dontroute;
  566. int atomic = sosendallatonce(so) || top;
  567. register int canWait;
  568. int outcount = 0;
  569. if (uio)
  570. resid = uio->uio_resid;
  571. else
  572. resid = top->m_pkthdr.len;
  573. /*
  574.  * In theory resid should be unsigned.
  575.  * However, space must be signed, as it might be less than 0
  576.  * if we over-committed, and we must use a signed comparison
  577.  * of space and resid.  On the other hand, a negative resid
  578.  * causes us to loop sending 0-length segments to the protocol.
  579.  */
  580. if (resid < 0)
  581. return (EINVAL);
  582. dontroute =
  583.     (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
  584.     (so->so_proto->pr_flags & PR_ATOMIC);
  585. if (control)
  586. clen = control->m_len;
  587. canWait = (so->so_state & SS_NBIO) ? M_DONTWAIT : M_WAIT;
  588. #define snderr(errno) { error = errno; splx(s); goto out; }
  589. s = splnet();
  590. restart:
  591. do {
  592. if (so->so_state & SS_CANTSENDMORE)
  593. snderr(EPIPE);
  594. if (so->so_error)
  595. snderr(so->so_error);
  596. if ((so->so_state & SS_ISCONNECTED) == 0) {
  597. if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
  598. if ((so->so_state & SS_ISCONFIRMING) == 0 &&
  599.     !(resid == 0 && clen != 0))
  600. snderr(ENOTCONN);
  601. } else if (addr == 0)
  602. snderr(EDESTADDRREQ);
  603. }
  604. space = sbspace(&so->so_snd);
  605. if (flags & MSG_OOB)
  606. space += 1024;
  607. if (atomic && ((resid > so->so_snd.sb_hiwat) ||
  608.     (clen > so->so_snd.sb_hiwat)))
  609. snderr(EMSGSIZE);
  610. if (space < resid + clen && 
  611.     (atomic || space < so->so_snd.sb_lowat || space < clen)) {
  612. if (so->so_state & SS_NBIO)
  613.     {
  614.     if (flags & MSG_MBUF)
  615. top = NULL; /* don't free the zero copy mbuf */
  616.     snderr(EWOULDBLOCK);
  617.     }
  618. sbwait(&so->so_snd);
  619. goto restart;
  620. }
  621. mp = &top;
  622. space -= clen;
  623. do {
  624.     if (uio == NULL) {
  625. /*
  626.  * Data is prepackaged in "top".
  627.  */
  628. resid = 0;
  629. if (flags & MSG_EOR)
  630. top->m_flags |= M_EOR;
  631.     } else do {
  632.         len = min(resid, space);
  633. if (top == 0) {
  634.         m = mBufClGet(canWait, MT_DATA, len + max_hdr,
  635.       FALSE);
  636. if (m == NULL)
  637.     snderr(ENOBUFS);
  638. len = min(len, m->m_extSize);
  639. m->m_flags |= M_PKTHDR;
  640. m->m_pkthdr.len = 0;
  641. m->m_pkthdr.rcvif = (struct ifnet *)0;
  642.                                 /*
  643.                                  * the assumption here is that max_hdr is
  644.                                  * always less than the minimum cluster size
  645.                                  * available.  Or don't set len, namely use
  646.                                  * len which set by min() above.
  647.                                  */
  648.                                 if (atomic && m->m_extSize > max_hdr) {
  649.                                  len = min((m->m_extSize - max_hdr),
  650.                                                   len);
  651.                                         m->m_data += max_hdr;
  652.                                 }
  653. }
  654. else
  655.     {
  656.     m = mBufClGet(canWait, MT_DATA, len, FALSE);
  657.     if (m == NULL)
  658. snderr(ENOBUFS);
  659.     len = min(len, m->m_extSize);
  660.     }
  661.                    
  662. space -= (m->m_extSize + MSIZE);
  663. error = uiomove(mtod(m, caddr_t), (int)len, uio);
  664. resid = uio->uio_resid;
  665. m->m_len = len;
  666. *mp = m;
  667. top->m_pkthdr.len += len;
  668. if (error)
  669. goto release;
  670. mp = &m->m_next;
  671. if (resid <= 0) {
  672. if (flags & MSG_EOR)
  673. top->m_flags |= M_EOR;
  674. break;
  675. }
  676.     } while (space > 0 && atomic);
  677.     if (dontroute)
  678.     so->so_options |= SO_DONTROUTE;
  679.                     if (!sosendallatonce (so))
  680. {
  681.         top->m_flags &= ~M_EOB;
  682.         if (((resid == 0) || (space <= 0)) && (outcount > 0))
  683.     top->m_flags |= M_EOB;
  684.                         outcount++;
  685.                         if (resid)
  686.     top->m_flags &= ~M_EOB;
  687.                         }
  688.     error = (*so->so_proto->pr_usrreq)(so,
  689. (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
  690. top, addr, control);
  691.     if (dontroute)
  692.     so->so_options &= ~SO_DONTROUTE;
  693.     clen = 0;
  694.     control = 0;
  695.     top = 0;
  696.     mp = &top;
  697.     if (error)
  698. goto release;
  699. } while (resid && space > 0);
  700. } while (resid);
  701. release:
  702. splx(s);
  703. out:
  704. if (top)
  705. m_freem(top);
  706. if (control)
  707. m_freem(control);
  708. if (error != 0)
  709.             {
  710. #ifdef WV_INSTRUMENTATION
  711. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  712.             WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 34, 4,
  713.                             WV_NETEVENT_SOSEND_FAIL, WV_NET_SEND,
  714.                             so->so_fd, error)
  715. #endif  /* INCLUDE_WVNET */
  716. #endif
  717.     netErrnoSet (error);
  718.             }
  719. #ifdef WV_INSTRUMENTATION
  720. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  721.         else
  722.             {
  723.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_VERBOSE, 54, 20,
  724.                             WV_NETEVENT_SOSEND_FINISH, WV_NET_SEND, so->so_fd)
  725.             }
  726. #endif  /* INCLUDE_WVNET */
  727. #endif
  728. return (error);
  729. }
  730. /*
  731.  * Implement receive operations on a socket.
  732.  * We depend on the way that records are added to the sockbuf
  733.  * by sbappend*.  In particular, each record (mbufs linked through m_next)
  734.  * must begin with an address if the protocol so specifies,
  735.  * followed by an optional mbuf or mbufs containing ancillary data,
  736.  * and then zero or more mbufs of data.
  737.  * In order to avoid blocking network interrupts for the entire time here,
  738.  * we splx() while doing the actual copy to user space.
  739.  * Although the sockbuf is locked, new data may still be appended,
  740.  * and thus we must maintain consistency of the sockbuf during that time.
  741.  *
  742.  * The caller may receive the data as a single mbuf chain by supplying
  743.  * an mbuf **mp0 for use in returning the chain.  The uio is then used
  744.  * only for the count in uio_resid.
  745.  *
  746.  * WRS mods: implement zero copy if out of band data is requested.
  747.  */
  748. int
  749. soreceive(so, paddr, uio, mp0, controlp, flagsp)
  750. register struct socket *so;
  751. struct mbuf **paddr;
  752. struct uio *uio;
  753. struct mbuf **mp0;
  754. struct mbuf **controlp;
  755. int *flagsp;
  756. {
  757. register struct mbuf *m, **mp;
  758. register int flags, len, error = 0, s, offset;
  759. struct protosw *pr = so->so_proto;
  760. struct mbuf *nextrecord;
  761. int moff, type = 0;
  762. int orig_resid = uio->uio_resid;
  763. mp = mp0;
  764. if (paddr)
  765. *paddr = 0;
  766. if (controlp)
  767. *controlp = 0;
  768. if (flagsp)
  769. flags = *flagsp &~ MSG_EOR;
  770. else
  771. flags = 0;
  772. /* this is the zero copy ptr To ptr to mbuf passed */
  773. if (mp)
  774. *mp = (struct mbuf *)0;
  775. if (flags & MSG_OOB) {
  776. m = mBufClGet(M_WAIT, MT_DATA, CL_SIZE_128, TRUE);
  777. if (m == (struct mbuf *) NULL)
  778.     {
  779.     return (ENOBUFS);
  780.     }
  781. error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
  782.     (struct mbuf *)(long)(flags & MSG_PEEK), (struct mbuf *)0);
  783. if (error)
  784. goto bad;
  785. if (mp) do {  /* if zero copy interface */
  786.     uio->uio_resid -= m->m_len; 
  787.     *mp = m; 
  788.     mp = &m->m_next; 
  789.     m = m->m_next; 
  790. } while (*mp);  
  791. else do { /* if not zero copy iface */
  792. error = uiomove(mtod(m, caddr_t),
  793.     (int) min(uio->uio_resid, m->m_len), uio);
  794. m = m_free(m);
  795. } while (uio->uio_resid && error == 0 && m);
  796. bad:
  797. if (m)
  798. m_freem(m);
  799. netErrnoSet (error);
  800. return (error);
  801. }
  802. if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
  803. (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
  804.     (struct mbuf *)0, (struct mbuf *)0);
  805. s = splnet();
  806. restart:
  807. m = so->so_rcv.sb_mb;
  808. /*
  809.  * If we have less data than requested, block awaiting more
  810.  * (subject to any timeout) if:
  811.  *   1. the current count is less than the low water mark, or
  812.  *   2. MSG_WAITALL is set, and it is possible to do the entire
  813.  * receive operation at once if we block (resid <= hiwat), or
  814.  *   3. MSG_DONTWAIT is not set.
  815.  * If MSG_WAITALL is set but resid is larger than the receive buffer,
  816.  * we have to do the receive in sections, and thus risk returning
  817.  * a short count if a timeout or signal occurs after we start.
  818.  */
  819. if ( m == 0 ||
  820.              ( ((flags & MSG_DONTWAIT) == 0) &&
  821.        (so->so_rcv.sb_cc < uio->uio_resid) &&
  822.        (so->so_rcv.sb_cc < so->so_rcv.sb_lowat)
  823.              ) ||
  824.      ( (flags & MSG_WAITALL) &&
  825.                (uio->uio_resid <= so->so_rcv.sb_hiwat) &&
  826.        (m->m_nextpkt == 0) &&
  827.                ((pr->pr_flags & PR_ATOMIC) == 0)
  828.              ) 
  829.            ) {
  830. #ifdef DIAGNOSTIC
  831. if (m == 0 && so->so_rcv.sb_cc)
  832. panic("receive 1");
  833. #endif
  834. if (so->so_error) {
  835. if (m)
  836. goto dontblock;
  837. error = so->so_error;
  838. if ((flags & MSG_PEEK) == 0)
  839. so->so_error = 0;
  840. goto release;
  841. }
  842. if (so->so_state & SS_CANTRCVMORE) {
  843. if (m)
  844. goto dontblock;
  845. else
  846. goto release;
  847. }
  848. for (; m; m = m->m_next)
  849. if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
  850. m = so->so_rcv.sb_mb;
  851. goto dontblock;
  852. }
  853. if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
  854.     (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
  855. error = ENOTCONN;
  856. goto release;
  857. }
  858. if (uio->uio_resid == 0)
  859. goto release;
  860. if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
  861. error = EWOULDBLOCK;
  862. goto release;
  863. }
  864. sbwait(&so->so_rcv);
  865. goto restart;
  866. }
  867. dontblock:
  868. nextrecord = m->m_nextpkt;
  869. if (pr->pr_flags & PR_ADDR) {
  870. #ifdef DIAGNOSTIC
  871. if (m->m_type != MT_SONAME)
  872. panic("receive 1a");
  873. #endif
  874. orig_resid = 0;
  875. if (flags & MSG_PEEK) {
  876. if (paddr)
  877. *paddr = m_copy(m, 0, m->m_len);
  878. m = m->m_next;
  879. } else {
  880. sbfree(&so->so_rcv, m);
  881. if (paddr) {
  882. *paddr = m;
  883. so->so_rcv.sb_mb = m->m_next;
  884. m->m_next = 0;
  885. m = so->so_rcv.sb_mb;
  886. } else {
  887. so->so_rcv.sb_mb = m_free(m);
  888. m = so->so_rcv.sb_mb;
  889. }
  890. }
  891. }
  892. while (m && m->m_type == MT_CONTROL && error == 0) {
  893. if (flags & MSG_PEEK) {
  894. if (controlp)
  895. *controlp = m_copy(m, 0, m->m_len);
  896. m = m->m_next;
  897. } else {
  898. sbfree(&so->so_rcv, m);
  899. if (controlp) {
  900. if (pr->pr_domain->dom_externalize &&
  901.     mtod(m, struct cmsghdr *)->cmsg_type ==
  902.     SCM_RIGHTS)
  903.    error = (*pr->pr_domain->dom_externalize)(m);
  904. *controlp = m;
  905. so->so_rcv.sb_mb = m->m_next;
  906. m->m_next = 0;
  907. m = so->so_rcv.sb_mb;
  908. } else {
  909. so->so_rcv.sb_mb = m_free(m);
  910. m = so->so_rcv.sb_mb;
  911. }
  912. }
  913. if (controlp) {
  914. orig_resid = 0;
  915. controlp = &(*controlp)->m_next;
  916. }
  917. }
  918. if (m) {
  919. if ((flags & MSG_PEEK) == 0)
  920. m->m_nextpkt = nextrecord;
  921. type = m->m_type;
  922. if (type == MT_OOBDATA)
  923. flags |= MSG_OOB;
  924. }
  925. moff = 0;
  926. offset = 0;
  927. while (m && uio->uio_resid > 0 && error == 0) {
  928. if (m->m_type == MT_OOBDATA) {
  929. if (type != MT_OOBDATA)
  930. break;
  931. } else if (type == MT_OOBDATA)
  932. break;
  933. #ifdef DIAGNOSTIC
  934. else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  935. panic("receive 3");
  936. #endif
  937. so->so_state &= ~SS_RCVATMARK;
  938. len = uio->uio_resid;
  939. if (so->so_oobmark && len > so->so_oobmark - offset)
  940. len = so->so_oobmark - offset;
  941. if (len > m->m_len - moff)
  942. len = m->m_len - moff;
  943. /*
  944.  * If mp is set, just pass back the mbufs.
  945.  * Otherwise copy them out via the uio, then free.
  946.  * Sockbuf must be consistent here (points to current mbuf,
  947.  * it points to next record) when we drop priority;
  948.  * we must note any additions to the sockbuf when we
  949.  * block interrupts again.
  950.  */
  951. if (mp == 0) {
  952. error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
  953. } else
  954. uio->uio_resid -= len;
  955. if (len == m->m_len - moff) {
  956. if (m->m_flags & M_EOR)
  957. flags |= MSG_EOR;
  958. if (flags & MSG_PEEK) {
  959. m = m->m_next;
  960. moff = 0;
  961. } else {
  962. nextrecord = m->m_nextpkt;
  963. sbfree(&so->so_rcv, m);
  964. if (mp) {
  965. *mp = m;
  966. mp = &m->m_next;
  967. so->so_rcv.sb_mb = m = m->m_next;
  968. *mp = (struct mbuf *)0;
  969. } else {
  970. so->so_rcv.sb_mb = m_free(m);
  971. m = so->so_rcv.sb_mb;
  972. }
  973. if (m)
  974. m->m_nextpkt = nextrecord;
  975. }
  976. } else {
  977. if (flags & MSG_PEEK)
  978. moff += len;
  979. else {
  980. if (mp)
  981.                                     {
  982.     *mp = m_copym(m, 0, len, M_WAIT);
  983.                                     if (*mp == NULL)
  984.                                         {
  985.                                         error = ENOBUFS;
  986.                                         goto release;
  987.                                         }
  988.                                     }
  989. m->m_data += len;
  990. m->m_len -= len;
  991. so->so_rcv.sb_cc -= len;
  992. }
  993. }
  994. if (so->so_oobmark) {
  995. if ((flags & MSG_PEEK) == 0) {
  996. so->so_oobmark -= len;
  997. if (so->so_oobmark == 0) {
  998. so->so_state |= SS_RCVATMARK;
  999. break;
  1000. }
  1001. } else {
  1002. offset += len;
  1003. if (offset == so->so_oobmark)
  1004. break;
  1005. }
  1006. }
  1007. if (flags & MSG_EOR)
  1008. break;
  1009. /*
  1010.  * If the MSG_WAITALL flag is set (for non-atomic socket),
  1011.  * we must not quit until "uio->uio_resid == 0" or an error
  1012.  * termination.  If a signal/timeout occurs, return
  1013.  * with a short count but without error.
  1014.  * Keep sockbuf locked against other readers.
  1015.  */
  1016. while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
  1017.     !sosendallatonce(so) && !nextrecord) {
  1018. if (so->so_error || so->so_state & SS_CANTRCVMORE)
  1019. break;
  1020. sbwait(&so->so_rcv);
  1021. if ((m = so->so_rcv.sb_mb))
  1022. nextrecord = m->m_nextpkt;
  1023. }
  1024. }
  1025. if (m && pr->pr_flags & PR_ATOMIC) {
  1026. flags |= MSG_TRUNC;
  1027. if ((flags & MSG_PEEK) == 0)
  1028. (void) sbdroprecord(&so->so_rcv);
  1029. }
  1030. if ((flags & MSG_PEEK) == 0) {
  1031. if (m == 0)
  1032. so->so_rcv.sb_mb = nextrecord;
  1033. if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
  1034. (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
  1035.     (struct mbuf *)(long)flags, (struct mbuf *)0,
  1036.     (struct mbuf *)0);
  1037. }
  1038. if (orig_resid == uio->uio_resid && orig_resid &&
  1039.     (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
  1040. goto restart;
  1041. }
  1042. if (flagsp)
  1043. *flagsp |= flags;
  1044. release:
  1045. splx(s);
  1046. if (error != 0)
  1047.             {
  1048. #ifdef WV_INSTRUMENTATION
  1049. #ifdef INCLUDE_WVNET    /* WV_NET_CRITICAL event */
  1050.             WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 35, 5,
  1051.                             WV_NETEVENT_SORECV_FAIL, WV_NET_RECV,
  1052.                             so->so_fd, error)
  1053. #endif  /* INCLUDE_WVNET */
  1054. #endif
  1055.     netErrnoSet (error);
  1056.             }
  1057. #ifdef WV_INSTRUMENTATION
  1058. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  1059.         else
  1060.             {
  1061.             WV_NET_EVENT_1 (NET_CORE_EVENT, WV_NET_VERBOSE, 55, 21,
  1062.                             WV_NETEVENT_SORECV_FINISH, WV_NET_RECV, so->so_fd)
  1063.             }
  1064. #endif  /* INCLUDE_WVNET */
  1065. #endif
  1066. return (error);
  1067. }
  1068. int
  1069. soshutdown(so, how)
  1070. register struct socket *so;
  1071. register int how;
  1072. {
  1073. register struct protosw *pr = so->so_proto;
  1074. #ifdef WV_INSTRUMENTATION
  1075. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  1076.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 56, 22,
  1077.                      WV_NETEVENT_SOSHUTDOWN_START, so->so_fd, how)
  1078. #endif  /* INCLUDE_WVNET */
  1079. #endif
  1080. how++;
  1081. if (how & 1) /* <=> FREAD of BSD44 */
  1082. sorflush(so);
  1083. if (how & 2) /* <=> FWRITE of BSD44 */
  1084. return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
  1085.     (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
  1086. return (0);
  1087. }
  1088. void
  1089. sorflush(so)
  1090. register struct socket *so;
  1091. {
  1092. register struct sockbuf *sb = &so->so_rcv;
  1093. register struct protosw *pr = so->so_proto;
  1094. register int s;
  1095. struct sockbuf asb;
  1096. sb->sb_flags |= SB_NOINTR;
  1097. s = splimp();
  1098. socantrcvmore(so);
  1099. asb = *sb;
  1100.         if (sb->sb_Sem)
  1101.             {
  1102.     semDelete (sb->sb_Sem);
  1103.             sb->sb_Sem = NULL;
  1104.             }
  1105. bzero((caddr_t)sb, sizeof (*sb));
  1106. splx(s);
  1107. if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
  1108. (*pr->pr_domain->dom_dispose)(asb.sb_mb);
  1109. sbrelease(&asb);
  1110. }
  1111. int
  1112. sosetopt(so, level, optname, m0)
  1113. register struct socket *so;
  1114. int level, optname;
  1115. struct mbuf *m0;
  1116. {
  1117. int error = 0;
  1118. register struct mbuf *m = m0;
  1119. if (level != SOL_SOCKET) {
  1120. if (so->so_proto && so->so_proto->pr_ctloutput)
  1121. return ((*so->so_proto->pr_ctloutput)
  1122.   (PRCO_SETOPT, so, level, optname, &m0));
  1123. error = ENOPROTOOPT;
  1124. } else {
  1125. switch (optname) {
  1126. case SO_LINGER:
  1127. if (m == NULL || m->m_len != sizeof (struct linger)) {
  1128. error = EINVAL;
  1129. goto bad;
  1130. }
  1131. so->so_linger = mtod(m, struct linger *)->l_linger;
  1132. /* fall thru... */
  1133. case SO_DEBUG:
  1134. case SO_KEEPALIVE:
  1135. case SO_DONTROUTE:
  1136. case SO_USELOOPBACK:
  1137. case SO_BROADCAST:
  1138. case SO_REUSEADDR:
  1139. case SO_REUSEPORT:
  1140. case SO_OOBINLINE:
  1141.                 case SO_USEPATHMTU:
  1142. if (m == NULL || m->m_len < sizeof (int)) {
  1143. error = EINVAL;
  1144. goto bad;
  1145. }
  1146. if (*mtod(m, int *))
  1147. so->so_options |= optname;
  1148. else
  1149. so->so_options &= ~optname;
  1150. break;
  1151. case SO_SNDBUF:
  1152. case SO_RCVBUF:
  1153. case SO_SNDLOWAT:
  1154. case SO_RCVLOWAT:
  1155. if (m == NULL || m->m_len < sizeof (int)) {
  1156. error = EINVAL;
  1157. goto bad;
  1158. }
  1159. switch (optname) {
  1160. case SO_SNDBUF:
  1161. case SO_RCVBUF:
  1162. if (sbreserve(optname == SO_SNDBUF ?
  1163.     &so->so_snd : &so->so_rcv,
  1164.     (u_long) *mtod(m, int *)) == 0) {
  1165. error = ENOBUFS;
  1166. goto bad;
  1167. }
  1168. break;
  1169. case SO_SNDLOWAT:
  1170. so->so_snd.sb_lowat = *mtod(m, int *);
  1171. break;
  1172. case SO_RCVLOWAT:
  1173. so->so_rcv.sb_lowat = *mtod(m, int *);
  1174. break;
  1175. }
  1176. break;
  1177. case SO_SNDTIMEO:
  1178. case SO_RCVTIMEO:
  1179.     {
  1180. switch (optname) {
  1181. case SO_SNDTIMEO:
  1182. so->so_snd.sb_timeo = *mtod(m, int *);
  1183. break;
  1184. case SO_RCVTIMEO:
  1185. so->so_rcv.sb_timeo = *mtod(m, int *);
  1186. break;
  1187. }
  1188. break;
  1189.     }
  1190. #ifdef VIRTUAL_STACK
  1191.                 case SO_VSID:
  1192.                     so->vsid = *mtod(m, int *);
  1193.                     break;
  1194. #endif /* VIRTUAL_STACK */
  1195. default:
  1196. error = ENOPROTOOPT;
  1197. break;
  1198. }
  1199. if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
  1200. (void) ((*so->so_proto->pr_ctloutput)
  1201.   (PRCO_SETOPT, so, level, optname, &m0));
  1202. m = NULL; /* freed by protocol */
  1203. }
  1204. }
  1205. bad:
  1206. if (m)
  1207. (void) m_free(m);
  1208. return (error);
  1209. }
  1210. int
  1211. sogetopt(so, level, optname, mp)
  1212. register struct socket *so;
  1213. int level, optname;
  1214. struct mbuf **mp;
  1215. {
  1216. register struct mbuf *m;
  1217. if (level != SOL_SOCKET) {
  1218. if (so->so_proto && so->so_proto->pr_ctloutput) {
  1219. return ((*so->so_proto->pr_ctloutput)
  1220.   (PRCO_GETOPT, so, level, optname, mp));
  1221. } else
  1222. return (ENOPROTOOPT);
  1223. } else {
  1224. m = mBufClGet(M_WAIT, MT_SOOPTS, CL_SIZE_128, TRUE);
  1225.                 if (m == (struct mbuf *) NULL)
  1226.                     return (ENOBUFS);
  1227. m->m_len = sizeof (int);
  1228. switch (optname) {
  1229. case SO_LINGER:
  1230. m->m_len = sizeof (struct linger);
  1231. mtod(m, struct linger *)->l_onoff =
  1232. so->so_options & SO_LINGER;
  1233. mtod(m, struct linger *)->l_linger = so->so_linger;
  1234. break;
  1235. case SO_USELOOPBACK:
  1236. case SO_DONTROUTE:
  1237. case SO_DEBUG:
  1238. case SO_KEEPALIVE:
  1239. case SO_REUSEADDR:
  1240. case SO_REUSEPORT:
  1241. case SO_BROADCAST:
  1242. case SO_OOBINLINE:
  1243. *mtod(m, int *) = so->so_options & optname;
  1244. break;
  1245. case SO_TYPE:
  1246. *mtod(m, int *) = so->so_type;
  1247. break;
  1248. case SO_ERROR:
  1249. *mtod(m, int *) = so->so_error;
  1250. so->so_error = 0;
  1251. break;
  1252. case SO_SNDBUF:
  1253. *mtod(m, int *) = so->so_snd.sb_hiwat;
  1254. break;
  1255. case SO_RCVBUF:
  1256. *mtod(m, int *) = so->so_rcv.sb_hiwat;
  1257. break;
  1258. case SO_SNDLOWAT:
  1259. *mtod(m, int *) = so->so_snd.sb_lowat;
  1260. break;
  1261. case SO_RCVLOWAT:
  1262. *mtod(m, int *) = so->so_rcv.sb_lowat;
  1263. break;
  1264. case SO_SNDTIMEO:
  1265. case SO_RCVTIMEO:
  1266.         *mtod(m, int *) = (optname == SO_SNDTIMEO ?
  1267.      so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
  1268. break;
  1269. #ifdef VIRTUAL_STACK
  1270.                 case SO_VSID:
  1271.                         *mtod(m, int *) = so->vsid;
  1272.                         break;
  1273. #endif /* VIRTUAL_STACK */
  1274. default:
  1275. (void)m_free(m);
  1276. return (ENOPROTOOPT);
  1277. }
  1278. *mp = m;
  1279. return (0);
  1280. }
  1281. }
  1282. void
  1283. sohasoutofband(so)
  1284. register struct socket *so;
  1285. {
  1286. #ifdef UNIXBSD44 /* support for out of band data later on */
  1287. /* 
  1288.    This can be done by maintaining a taskId in the
  1289.    in the socket structure and posting a SIGURG to
  1290.    the task which would invoke the signal handler
  1291.    for SIGURG if that signal is registered properly
  1292.    The taskId should be created in the socket structure
  1293.    at the time of the creation of the socket.
  1294.    */
  1295. struct proc *p;
  1296. if (so->so_pgid < 0)
  1297. gsignal(-so->so_pgid, SIGURG);
  1298. else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
  1299. psignal(p, SIGURG);
  1300. selwakeup(&so->so_rcv.sb_sel);
  1301. #endif /* UNIXBSD44 */
  1302. }
  1303. int uiomove(cp, n, uio)
  1304.     register caddr_t cp;
  1305.     register int n;
  1306.     register struct uio *uio;
  1307.     {
  1308.     register struct iovec *iov;
  1309.     u_int cnt;
  1310.     int error = 0;
  1311. #ifdef DIAGNOSTIC
  1312.     if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
  1313. panic("uiomove: mode");
  1314.     if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
  1315. panic("uiomove proc");
  1316. #endif
  1317.     while (n > 0 && uio->uio_resid) 
  1318. {
  1319. iov = uio->uio_iov;
  1320. cnt = iov->iov_len;
  1321. if (cnt == 0)
  1322.     {
  1323.     uio->uio_iov++;
  1324.     uio->uio_iovcnt--;
  1325.     continue;
  1326.     }
  1327. if (cnt > n)
  1328.     cnt = n;
  1329. if (uio->uio_rw == UIO_READ)
  1330.     bcopy((caddr_t)cp, iov->iov_base, cnt);
  1331. else
  1332.     bcopy(iov->iov_base, (caddr_t)cp, cnt);
  1333. iov->iov_base += cnt;
  1334. iov->iov_len -= cnt;
  1335. uio->uio_resid -= cnt;
  1336. uio->uio_offset += cnt;
  1337. cp += cnt;
  1338. n -= cnt;
  1339. }
  1340.     return (error);
  1341.     }