bsdSockLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:66k
开发平台:

MultiPlatform

  1. /* bsdSockLib.c - UNIX BSD 4.4 compatible socket library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01u,05nov01,vvv  fixed compilation warnings
  8. 01t,15oct01,rae  merge from truestack ver 01u, base 01r (SPRs 34005, 30608)
  9. 01s,10nov00,spm  merged from version 01s of tor3_x branch (SPR #30608 fix)
  10. 01r,29apr99,pul  Upgraded NPT phase3 code to tor2.0.0
  11. 01q,16mar99,spm  recovered orphaned code from tor2_0_x branch (SPR #25770)
  12. 01p,02feb99,sgv  Added zbufsockrtn routine
  13. 01o,02dec98,n_s  fixed sendmsg and recvmsg. spr 23552
  14. 01n,10nov98,spm  unmapped closed socket file descriptors (SPR #21583)
  15. 01m,26aug98,n_s  added return val check to mBufClGet in accept (). spr #22238.
  16. 01l,17mar98,vin  fixed a nonblocking I/O bug SPR 20542.
  17. 01k,17mar98,jmb  Merge patch by jmb from 03nov97: set small receive buffer 
  18.                  which  HPSIM is TCP client. (SPR 8709) 
  19. 01j,17mar98,jmb  Merge patch by jmb from 31oct97: Set receive buffer when 
  20.                  HPSIM is a TCP server.  Work-aroun for MTU mismatch and
  21.                  pty problem in the SLIP connection.  (SPR 8709)
  22. 01i,10dec97,sgv  fixed a bug in recvmsg, intialized control and from variables
  23.  to NULL. 
  24. 01h,06oct97,sgv  fixed sendmsg/recvmsg call, mbufs are not freed when EINVAL 
  25.  is returned
  26. 01g,06oct97,spm  added optional binary compatibility for BSD 4.3 applications
  27. 01f,25jul97,vin  fixed so_accept function call, saved new fd in the socket
  28.  structure.
  29. 01e,03dec96,vin  changed m_getclr to fit the new declaration.
  30. 01d,22nov96,vin  modified for BSD44.
  31. 01c,07aug95,dzb  NOMANUAL on headers.
  32. 01b,25jul95,dzb  changed to just use DEV_HDR device header.
  33. 01a,21jul95,dzb  created from sockLib.c, ver 04g.
  34. */
  35. /*
  36. This library provides UNIX BSD 4.4 compatible socket calls.  These calls
  37. may be used to open, close, read, and write sockets, either on the same
  38. CPU or over a network.  The calling sequences of these routines are
  39. identical to UNIX BSD 4.4.
  40. ADDRESS FAMILY
  41. VxWorks sockets support only the Internet Domain address family; use
  42. AF_INET for the <domain> argument in subroutines that require it.
  43. There is no support for the UNIX Domain address family.
  44. IOCTL FUNCTIONS
  45. Sockets respond to the following ioctl() functions.  These functions are
  46. defined in the header files ioLib.h and ioctl.h.
  47. .iP "FIONBIO" 18 3
  48. Turns on/off non-blocking I/O.
  49. .CS
  50.     on = TRUE;
  51.     status = ioctl (sFd, FIONBIO, &on);
  52. .CE
  53. .iP "FIONREAD"
  54. Reports the number of bytes available to read on the socket.  On the return
  55. of ioctl(), <bytesAvailable> has the number of bytes available to read
  56. on the socket.
  57. .CS
  58.     status = ioctl (sFd, FIONREAD, &bytesAvailable);
  59. .CE
  60. .iP "SIOCATMARK"
  61. Reports whether there is out-of-band data to be read on the socket.  On
  62. the return of ioctl(), <atMark> will be TRUE (1) if there is out-of-band
  63. data, otherwise it will be FALSE (0).
  64. .CS
  65.     status = ioctl (sFd, SIOCATMARK, &atMark);
  66. .CE
  67. INCLUDE FILES: types.h, bsdSockLib.h, socketvar.h
  68. SEE ALSO: netLib,
  69. .pG "Network"
  70. NOMANUAL
  71. */
  72. #include "vxWorks.h"
  73. #include "sockFunc.h"
  74. #include "bsdSockMap.h" /* map socket routines to bsdxxx() */
  75. #include "strLib.h"
  76. #include "errnoLib.h"
  77. #include "netLib.h"
  78. #include "ioLib.h"
  79. #include "iosLib.h"
  80. #include "tickLib.h"
  81. #include "vwModNum.h"
  82. #include "net/systm.h"
  83. #include "net/mbuf.h"
  84. #include "net/protosw.h"
  85. #include "net/socketvar.h"
  86. #include "net/uio.h"
  87. #include "bsdSockLib.h"
  88. #include "netinet/in.h"
  89. #ifdef VIRTUAL_STACK
  90. #include "netinet/vsLib.h"
  91. #endif    /* VIRTUAL_STACK */
  92. IMPORT STATUS soo_ioctl (); /* for call into sys_socket.c */
  93. /* locals */
  94. LOCAL DEV_HDR bsdSockDev; /* BSD-specific device header */
  95. LOCAL int bsdSockDrvNum; /* BSD socket driver number */
  96. LOCAL char * bsdSockName = "(socket)"; /* file name of BSD sockets */
  97. /* globals */
  98. BOOL  bsdSock43ApiFlag = FALSE;  /* Provide backward binary */
  99.                                         /* compatibility for BSD 4.3? */
  100.                                         /* (Set TRUE by default with */
  101.                                         /* BSD43_COMPATIBLE in configAll.h). */
  102. IMPORT SOCK_FUNC ** pSockFdMap;
  103. /* declare BSD socket interface function table */
  104. SOCK_FUNC bsdSockFunc =
  105.     {
  106.     (FUNCPTR) sockLibInit,
  107.     (FUNCPTR) accept,
  108.     (FUNCPTR) bind,
  109.     (FUNCPTR) connect,
  110.     (FUNCPTR) connectWithTimeout,
  111.     (FUNCPTR) getpeername,
  112.     (FUNCPTR) getsockname,
  113.     (FUNCPTR) listen,
  114.     (FUNCPTR) recv,
  115.     (FUNCPTR) recvfrom,
  116.     (FUNCPTR) recvmsg,
  117.     (FUNCPTR) send,
  118.     (FUNCPTR) sendto,
  119.     (FUNCPTR) sendmsg,
  120.     (FUNCPTR) shutdown,
  121.     (FUNCPTR) socket,
  122.     (FUNCPTR) getsockopt,
  123.     (FUNCPTR) setsockopt,
  124.     (FUNCPTR) zbufsockrtn
  125.     };
  126. /* forward declarations  */
  127. LOCAL STATUS bsdSockClose (struct socket *so);
  128. LOCAL int bsdSockWrite (struct socket *so, char *buf, int bufLen);
  129. LOCAL int bsdSockRead (struct socket *so, caddr_t buf, int bufLen);
  130. LOCAL int bsdSockargs (struct mbuf ** aname, caddr_t name,
  131.     int namelen, int type);
  132. LOCAL void  bsdSockAddrRevert (struct sockaddr *);
  133. #ifdef VIRTUAL_STACK
  134. LOCAL STATUS    stackInstFromSockVsidSet (int s);
  135. #endif /* VIRTUAL_STACK */
  136. /*******************************************************************************
  137. *
  138. * bsdSockLibInit - install the BSD "socket driver" into the I/O system
  139. *
  140. * bsdSockLibInit must be called once at configuration time before any socket
  141. * operations are performed.
  142. *
  143. * RETURNS: a pointer to the BSD socket table, or NULL.
  144. *
  145. * NOMANUAL
  146. */
  147. SOCK_FUNC * sockLibInit (void)
  148.     {
  149.     if (bsdSockDrvNum > 0)
  150.         return (&bsdSockFunc);
  151.     if ((bsdSockDrvNum = iosDrvInstall ((FUNCPTR) NULL, (FUNCPTR) NULL,
  152.         (FUNCPTR) NULL, (FUNCPTR) bsdSockClose, (FUNCPTR) bsdSockRead,
  153. (FUNCPTR) bsdSockWrite, (FUNCPTR) soo_ioctl)) == ERROR)
  154. return (NULL);
  155.     bsdSockDev.drvNum = bsdSockDrvNum; /* to please I/O system */
  156.     bsdSockDev.name   = bsdSockName; /* for iosFdSet name optimiz. */
  157.     return (&bsdSockFunc);
  158.     }
  159. /*******************************************************************************
  160. *
  161. * bsdSocket - open a socket
  162. *
  163. * This routine opens a socket and returns a socket descriptor.
  164. * The socket descriptor is passed to the other socket routines to identify the
  165. * socket.  The socket descriptor is a standard I/O system file descriptor
  166. * (fd) and can be used with the close(), read(), write(), and ioctl() routines.
  167. *
  168. * Available socket types include:
  169. * .iP SOCK_STREAM 18
  170. * connection-based (stream) socket.
  171. * .iP SOCK_DGRAM
  172. * datagram (UDP) socket.
  173. * .iP SOCK_RAW
  174. * raw socket.
  175. * .LP
  176. *
  177. * RETURNS: A socket descriptor, or ERROR.
  178. *
  179. * NOMANUAL
  180. */
  181. int socket
  182.     (
  183.     int domain,         /* address family (e.g. AF_INET) */
  184.     int type,           /* SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW */
  185.     int protocol        /* socket protocol (usually 0) */
  186.     )
  187.     {
  188.     struct socket *so;
  189.     int fd;
  190. #ifndef  _WRS_VXWORKS_5_X
  191.     OBJ_ID fdObject;
  192. #endif
  193.     FAST int spl = splnet ();
  194.     int status = socreate (domain, &so, type, protocol);
  195.     splx (spl);
  196.     if (status)
  197. {
  198. netErrnoSet (status);
  199.         return (ERROR);
  200. }
  201.     /* stick the socket into a file descriptor */
  202.     if ((fd = iosFdNew ((DEV_HDR *) &bsdSockDev, bsdSockName, (int) so)) ==
  203. ERROR)
  204. {
  205. (void)bsdSockClose (so);
  206. return (ERROR);
  207. }
  208. #ifndef  _WRS_VXWORKS_5_X
  209.     /* set ownership of socket semaphores */
  210.     fdObject = iosFdObjIdGet (fd);
  211.     if (fdObject == NULL)
  212.         {
  213. (void)bsdSockClose (so);
  214. return (ERROR);
  215.         }
  216.     status = objOwnerSet (so->so_timeoSem, fdObject);
  217.     if (status == ERROR)
  218.         {
  219. (void)bsdSockClose (so);
  220. return (ERROR);
  221.         }
  222.     status = objOwnerSet (so->so_rcv.sb_Sem, fdObject);
  223.     if (status == ERROR)
  224.         {
  225. (void)bsdSockClose (so);
  226. return (ERROR);
  227.         }
  228.     status = objOwnerSet (so->so_snd.sb_Sem, fdObject);
  229.     if (status == ERROR)
  230.         {
  231. (void)bsdSockClose (so);
  232. return (ERROR);
  233.         }
  234. #endif /*  _WRS_VXWORKS_5_X */
  235.     
  236.     /* save fd in the socket structure */
  237.     so->so_fd = fd;
  238. #ifdef VIRTUAL_STACK
  239.     
  240.     /* set the vsid in the socket to the current stack */
  241.     status = setsockopt (fd, SOL_SOCKET, SO_VSID,
  242.                                 (char *)&myStackNum, sizeof (myStackNum));
  243.     if (status)
  244.         {
  245.         netErrnoSet (status);
  246.         (void)bsdSockClose (so);
  247.         return (ERROR);
  248.         }
  249. #endif    /* VIRTUAL_STACK */
  250.     
  251.     return (fd);
  252.     }
  253. /*******************************************************************************
  254. *
  255. * bsdSockClose - close a socket
  256. *
  257. * bsdSockClose is called by the I/O system to close a socket.
  258. *
  259. */
  260. LOCAL STATUS bsdSockClose
  261.     (
  262.     struct socket *so
  263.     )
  264.     {
  265.     FAST int ret;
  266.     FAST int sx;
  267.     int fd;
  268. #ifdef VIRTUAL_STACK
  269.     /* Check if we are in the correct stack */
  270.     
  271.     if (stackInstFromSockVsidSet (so->so_fd) != OK)
  272.         return (ERROR);
  273. #endif    /* VIRTUAL_STACK */
  274.     sx = splnet ();
  275.     fd = so->so_fd;
  276.     if (so->so_state & SS_NOFDREF)
  277.         ret = 0;
  278.     else
  279.         ret = soclose (so);
  280.     splx (sx);
  281.     /* 
  282.      * Remove the mapping installed by the switchboard. Performing this
  283.      * step here is ugly, but the alternative is worse.
  284.      */
  285.     pSockFdMap [fd] = NULL;
  286.     return (ret);
  287.     }
  288. /*******************************************************************************
  289. *
  290. * bsdBind - bind a name to a socket
  291. *
  292. * This routine associates a network address (also referred to as its "name")
  293. * with a specified socket so that other processes can connect or send to it.
  294. * When a socket is created with socket(), it belongs to an address family
  295. * but has no assigned name.
  296. *
  297. * RETURNS:
  298. * OK, or ERROR if there is an invalid socket, the address is either
  299. * unavailable or in use, or the socket is already bound.
  300. *
  301. * NOMANUAL
  302. */
  303. STATUS bind
  304.     (
  305.     int s,                      /* socket descriptor */
  306.     struct sockaddr *name,      /* name to be bound */
  307.     int namelen                 /* length of name */
  308.     )
  309.     {
  310.     struct mbuf *nam;
  311.     int status;
  312.     struct socket *so;
  313.     /* extract the socket from the fd */
  314.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  315.         return (ERROR);
  316. #ifdef VIRTUAL_STACK
  317.     if (stackInstFromSockVsidSet (s) != OK)
  318.         return (ERROR);
  319. #endif    /* VIRTUAL_STACK */
  320.     
  321.     status = bsdSockargs (&nam, (caddr_t) name, namelen, MT_SONAME);
  322.     if (status)
  323. {
  324. netErrnoSet (status);
  325.         return (ERROR);
  326. }
  327.     status = sobind (so, nam);
  328.     if (status)
  329. {
  330. netErrnoSet (status);
  331. m_freem (nam);
  332.         return (ERROR);
  333. }
  334.     m_freem (nam);
  335.     return (OK);
  336.     }
  337. /*******************************************************************************
  338. *
  339. * bsdListen - enable connections to a socket
  340. *
  341. * This routine enables connections to a socket.  It also specifies the
  342. * maximum number of unaccepted connections that can be pending at one time
  343. * (<backlog>).  After enabling connections with listen(), connections are
  344. * actually accepted by accept().
  345. *
  346. * RETURNS: OK, or ERROR if the socket is invalid or unable to listen.
  347. *
  348. * NOMANUAL
  349. */
  350. STATUS listen
  351.     (
  352.     int s,              /* socket descriptor */
  353.     int backlog         /* number of connections to queue */
  354.     )
  355.     {
  356.     FAST int status;
  357.     FAST struct socket *so;
  358.     /* extract the socket from the fd */
  359.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  360.         return (ERROR);
  361. #ifdef VIRTUAL_STACK
  362.     if (stackInstFromSockVsidSet (s) != OK)
  363.         return (ERROR);
  364. #endif    /* VIRTUAL_STACK */
  365.     
  366.     status = solisten (so, backlog);
  367.     if (status)
  368. {
  369. netErrnoSet (status);
  370.         return (ERROR);
  371. }
  372. #if (CPU == SIMHPPA)
  373. /*
  374.  *  Set the size of the receive buffer.
  375.  *  This is the way (without rewriting the user app) to get
  376.  *  data from the master to auto-segment and fit in the pty.
  377.  */
  378. {
  379.     int bLen = 660;
  380.     return (setsockopt (s, SOL_SOCKET, SO_RCVBUF, &bLen, sizeof (bLen)));
  381. }
  382. #endif
  383.     return (OK);
  384.     }
  385. /*******************************************************************************
  386. *
  387. * bsdAccept - accept a connection from a socket
  388. *
  389. * This routine accepts a connection on a socket, and returns a new socket
  390. * created for the connection.  The socket must be bound to an address with
  391. * bind(), and enabled for connections by a call to listen().  The accept()
  392. * routine dequeues the first connection and creates a new socket with the
  393. * same properties as <s>.  It blocks the caller until a connection is
  394. * present, unless the socket is marked as non-blocking.
  395. *
  396. * The parameter <addrlen> should be initialized to the size of the available
  397. * buffer pointed to by <addr>.  Upon return, <addrlen> contains the size in
  398. * bytes of the peer's address stored in <addr>.
  399. *
  400. * RETURNS
  401. * A socket descriptor, or ERROR if the call fails.
  402. *
  403. * NOMANUAL
  404. */
  405. int accept
  406.     (
  407.     int s,                      /* socket descriptor */
  408.     struct sockaddr *addr,      /* peer address */
  409.     int *addrlen                /* peer address length */
  410.     )
  411.     {
  412.     struct mbuf *nam;
  413.     int namelen = *addrlen;
  414.     int slev;
  415.     FAST struct socket *so;
  416.     FAST int fd;
  417. #ifndef  _WRS_VXWORKS_5_X
  418.     OBJ_ID fdObject;
  419.     STATUS status;
  420. #endif
  421.     /* extract the socket from the fd */
  422.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  423.         return (ERROR);
  424. #ifdef VIRTUAL_STACK
  425.     if (stackInstFromSockVsidSet (s) != OK)
  426.         return (ERROR);
  427. #endif    /* VIRTUAL_STACK */
  428.     slev = splnet ();
  429.     if ((so->so_options & SO_ACCEPTCONN) == 0)
  430.         {
  431.         netErrnoSet (EINVAL);
  432.         splx (slev);
  433.         return (ERROR);
  434.         }
  435.     if ((so->so_state & SS_NBIO) && so->so_qlen == 0)
  436.         {
  437.         netErrnoSet (EWOULDBLOCK);
  438.         splx(slev);
  439.         return (ERROR);
  440.         }
  441.     while (so->so_qlen == 0 && so->so_error == 0)
  442.         {
  443.         if (so->so_state & SS_CANTRCVMORE)
  444.             {
  445.             so->so_error = ECONNABORTED;
  446.             break;
  447.             }
  448.         ksleep (so->so_timeoSem);
  449.         }
  450.     if (so->so_error)
  451.         {
  452.         netErrnoSet ((int) so->so_error);
  453.         so->so_error = 0;
  454.         splx (slev);
  455.         return (ERROR);
  456.         }
  457.     if ( (nam = mBufClGet (M_WAIT, MT_SONAME, CL_SIZE_128, TRUE)) == NULL)
  458. {
  459. netErrnoSet (ENOBUFS);
  460. splx (slev);
  461. return (ERROR);
  462. }
  463.     {
  464.     struct socket *aso = so->so_q;
  465.     if (soqremque(aso, 1) == 0)
  466. panic ("accept");
  467.     so = aso;
  468.     }
  469.     (void) soaccept (so, nam);
  470.     if (addr)
  471.         {
  472.         if (namelen > nam->m_len)
  473.             namelen = nam->m_len;
  474.         /* XXX SHOULD COPY OUT A CHAIN HERE */
  475.         (void) copyout (mtod(nam, caddr_t), (caddr_t)addr,
  476. namelen);
  477.         (void) copyout ((caddr_t)&namelen, (caddr_t)addrlen,
  478. sizeof (*addrlen));
  479.         if (bsdSock43ApiFlag)
  480.             {
  481.             /* Convert the address structure contents to the BSD 4.3 format. */
  482.             bsdSockAddrRevert (addr);
  483.             }
  484.         }
  485.     m_freem (nam);
  486.     splx (slev);
  487.     /* put the new socket into an fd */
  488.     if ((fd = iosFdNew ((DEV_HDR *) &bsdSockDev, bsdSockName, (int) so)) ==
  489. ERROR)
  490. {
  491. (void)bsdSockClose (so);
  492. return (ERROR);
  493. }
  494. #ifndef _WRS_VXWORKS_5_X
  495.     
  496.     /* set ownership of socket semaphores */
  497.     
  498.     fdObject = iosFdObjIdGet (fd);
  499.     if (fdObject == NULL)
  500.         {
  501.         (void)bsdSockClose (so);
  502.         return (ERROR);
  503.         }
  504.     status = objOwnerSet (so->so_timeoSem, fdObject);
  505.     if (status == ERROR)
  506.         {
  507.         (void)bsdSockClose (so);
  508.         return (ERROR);
  509.         }
  510.     status = objOwnerSet (so->so_rcv.sb_Sem, fdObject);
  511.     if (status == ERROR)
  512.         {
  513.         (void)bsdSockClose (so);
  514.         return (ERROR);
  515.         }
  516.     status = objOwnerSet (so->so_snd.sb_Sem, fdObject);
  517.     if (status == ERROR)
  518.         {
  519.         (void)bsdSockClose (so);
  520.         return (ERROR);
  521.         }
  522. #endif /*  _WRS_VXWORKS_5_X */
  523.     
  524.     /* save fd in the socket structure */
  525.     so->so_fd = fd;
  526. #ifdef VIRTUAL_STACK
  527.     
  528.     /* set the vsid in the socket to the current stack */
  529.     if (setsockopt (fd, SOL_SOCKET, SO_VSID,
  530.                             (char *)&myStackNum, sizeof (myStackNum)) != OK)
  531.         {
  532.         (void)bsdSockClose (so);
  533.         return (ERROR);
  534.         }
  535. #endif    /* VIRTUAL_STACK */
  536.     
  537.     return (fd);
  538.     }
  539. /*******************************************************************************
  540. *
  541. * bsdConnect - initiate a connection to a socket
  542. *
  543. * If <s> is a socket of type SOCK_STREAM, this routine establishes a virtual
  544. * circuit between <s> and another socket specified by <name>.  If <s> is of
  545. * type SOCK_DGRAM, it permanently specifies the peer to which messages
  546. * are sent.  If <s> is of type SOCK_RAW, it specifies the raw socket upon
  547. * which data is to be sent and received.  The <name> parameter specifies the
  548. * address of the other socket.
  549. *
  550. * RETURNS
  551. * OK, or ERROR if the call fails.
  552. *
  553. * NOMANUAL
  554. */
  555. STATUS connect
  556.     (
  557.     int s,                      /* socket descriptor */
  558.     struct sockaddr *name,      /* addr of socket to connect */
  559.     int namelen                 /* length of name, in bytes */
  560.     )
  561.     {
  562.     struct mbuf *nam;
  563.     int slev;
  564.     int status;
  565.     FAST struct socket *so;
  566.     /* extract the socket from the fd */
  567.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  568.         return (ERROR);
  569. #ifdef VIRTUAL_STACK
  570.     if (stackInstFromSockVsidSet (s) != OK)
  571.         return (ERROR);
  572. #endif    /* VIRTUAL_STACK */
  573.     /*
  574.      * For non-blocking sockets, exit immediately if a previous connection
  575.      * attempt is still pending.
  576.      */
  577.     slev = splnet ();
  578.     if ((so->so_state & SS_NBIO) &&
  579. (so->so_state & SS_ISCONNECTING)) {
  580.         splx (slev);
  581. netErrnoSet (EALREADY);
  582. return (ERROR);
  583. }
  584.     splx (slev);
  585.     status = bsdSockargs (&nam, (caddr_t)name, namelen, MT_SONAME);
  586.     if (status)
  587. {
  588. netErrnoSet (status);
  589.         return (ERROR);
  590. }
  591. #if (CPU == SIMHPPA)
  592. /*
  593.  *  Set the size of the receive buffer.
  594.  *  This is the way (without rewriting the user app) to get
  595.  *  data from the master to auto-segment and fit in the pty.
  596.  */
  597. {
  598.     int bLen = 660;
  599.     status = setsockopt (s, SOL_SOCKET, SO_RCVBUF, &bLen, sizeof (bLen));
  600.     if (status == ERROR)
  601. return (ERROR);
  602. }
  603. #endif
  604.     /*
  605.      * Attempt to establish the connection. For TCP sockets, this routine
  606.      * just begins the three-way handshake process. For all other sockets,
  607.      * it succeeds or fails immediately.
  608.      */
  609.     status = soconnect (so, nam);
  610.     if (status)
  611. {
  612.         /*
  613.          * Fatal error: unable to record remote address or (TCP only)
  614.          * couldn't send initial SYN segment.
  615.          */
  616. netErrnoSet (status);
  617. so->so_state &= ~SS_ISCONNECTING;
  618. m_freem(nam);
  619. return (ERROR);
  620. }
  621.     /*
  622.      * For non-blocking sockets, exit if the connection attempt is
  623.      * still pending. This condition only occurs for TCP sockets if
  624.      * no SYN reply arrives before the soconnect() routine completes.
  625.      */
  626.     slev = splnet();
  627.     if ((so->so_state & SS_NBIO) &&
  628.         (so->so_state & SS_ISCONNECTING))
  629.         {
  630.         netErrnoSet (EINPROGRESS);
  631. splx (slev);
  632. m_freem (nam);
  633.         return (ERROR);
  634.         }
  635.     /*
  636.      * Wait until a pending connection completes or a timeout occurs.
  637.      * This delay might occur for TCP sockets. Other socket types
  638.      * "connect" or fail instantly.
  639.      */
  640.     while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
  641.         ksleep (so->so_timeoSem);
  642.     if (so->so_error)
  643. {
  644.         /* Connection attempt failed immediately or (TCP only) timed out. */
  645.         status = ERROR;
  646. netErrnoSet ((int) so->so_error);
  647. so->so_error = 0;
  648. }
  649.     else
  650.         {
  651.         /* Connection attempt succeeded. */
  652.         status = OK;
  653.         }
  654.     splx (slev);
  655.     m_freem (nam);
  656.     return (status);
  657.     }
  658. /******************************************************************************
  659. *
  660. * bsdConnectWithTimeout - attempt socket connection within a specified duration
  661. *
  662. * This routine performs the same function as connect(); however, in addition,
  663. * users can specify how long to continue attempting the new connection.  
  664. *
  665. * If the <timeVal> is a NULL pointer, this routine performs exactly like
  666. * connect().  If <timeVal> is not NULL, it will attempt to establish a new
  667. * connection for the duration of the time specified in <timeVal>, after
  668. * which it will report a time-out error if the connection is not
  669. * established.
  670. *
  671. * RETURNS: OK, or ERROR if a connection cannot be established before timeout
  672. *
  673. * SEE ALSO: connect()
  674. *
  675. * NOMANUAL
  676. */
  677. STATUS connectWithTimeout
  678.     (
  679.     int                 sock,           /* socket descriptor */
  680.     struct sockaddr     *adrs,          /* addr of the socket to connect */
  681.     int                 adrsLen,        /* length of the socket, in bytes */
  682.     struct timeval      *timeVal        /* time-out value */
  683.     )
  684.     {
  685.     int on = 0;
  686.     fd_set writeFds;
  687.     int retVal = ERROR;
  688.     int  error;
  689.     int peerAdrsLen;
  690.     struct sockaddr peerAdrs;
  691.     struct socket *so;
  692.     if (timeVal == NULL)
  693. return (connect (sock, adrs, adrsLen));
  694.     if ((so = (struct socket *) iosFdValue (sock)) == (struct socket *) ERROR)
  695.         return (ERROR);
  696. #ifdef VIRTUAL_STACK
  697.     if (stackInstFromSockVsidSet (sock) != OK)
  698.         return (ERROR);
  699. #endif    /* VIRTUAL_STACK */
  700.     
  701.     if (!(so->so_state & SS_NBIO))
  702. {
  703. on = 1; /* set NBIO to have the connect() return without pending */
  704.         if ((ioctl (sock, FIONBIO, (int) &on)) == ERROR)
  705.     return (ERROR);
  706. }
  707.     if (connect (sock, adrs, adrsLen) < 0)
  708. {
  709. /*
  710.          * When a TCP socket is set to non-blocking mode, the connect() 
  711.          * routine might return EINPROGRESS (if the three-way handshake
  712.          * is not completed immediately) or EALREADY (if a previous connect
  713.          * attempt is still pending). All other errors (for any socket type)
  714.          * indicate a fatal problem, such as insufficient memory to record
  715.          * the remote address or (for TCP) an inability to transmit the
  716.          * initial SYN segment.
  717.  */
  718.         error = errnoGet () & 0xffff;
  719. if (error == EINPROGRESS || error == EALREADY)
  720.             {
  721.     /*
  722.              * Use the select() routine to monitor the socket status. The
  723.              * socket will be writable when the three-way handshake completes
  724.              * or when the handshake timeout occurs.
  725.      */
  726.     FD_ZERO (&writeFds);
  727.     FD_SET (sock, &writeFds);
  728.     if (select (FD_SETSIZE, (fd_set *) NULL, &writeFds,
  729. (fd_set *) NULL, timeVal) > 0)
  730. {
  731. /* The FD_ISSET test is theoretically redundant, but safer. */
  732. if (FD_ISSET (sock, &writeFds))
  733.     {
  734.     /*
  735.                      * The connection attempt has completed. The getpeername()
  736.                      * routine retrieves the remote address if the three-way
  737.                      * handshake succeeded and fails if the attempt timed out.
  738.      */
  739.     peerAdrsLen = sizeof (peerAdrs);
  740.     if (getpeername (sock, &peerAdrs, &peerAdrsLen) != ERROR)
  741. retVal = OK;
  742.     }
  743. }
  744.     else
  745. netErrnoSet (ETIMEDOUT);
  746.     }
  747. }
  748.     else
  749. retVal = OK;
  750.     if (on)
  751. {
  752. on = 0; /* turn OFF the non-blocking I/O */
  753.         if ((ioctl (sock, FIONBIO, (int) &on)) == ERROR)
  754.     return (ERROR);
  755. }
  756.     return (retVal);
  757.     }
  758. /*******************************************************************************
  759. *
  760. * bsdSendto - send a message to a socket
  761. *
  762. * This routine sends a message to the datagram socket named by <to>.  The
  763. * socket <s> will be received by the receiver as the sending socket.
  764. * The maximum length of <buf> is subject to the limits on UDP buffer
  765. * size; see the discussion of SO_SNDBUF in the setsockopt() manual
  766. * entry.
  767. *
  768. * RETURNS
  769. * The number of bytes sent, or ERROR if the call fails.
  770. * SEE ALSO
  771. * setsockopt()
  772. *
  773. * NOMANUAL
  774. */
  775. int sendto
  776.     (
  777.     FAST int             s,             /* socket to send data to */
  778.     FAST caddr_t         buf,           /* pointer to data buffer */
  779.     FAST int             bufLen,        /* length of buffer */
  780.     FAST int             flags,         /* flags to underlying protocols */
  781.     FAST struct sockaddr *to,           /* recipient's address */
  782.     FAST int             tolen          /* length of <to> sockaddr */
  783.     )
  784.     {
  785.     FAST struct socket  *so;
  786.     FAST int spl;
  787.     int status;
  788.     struct mbuf *mto;
  789.     int len; /* value/result */
  790.     struct uio usrIo; /* user IO structure */
  791.     struct iovec ioVec; /* IO vector structure */
  792.     struct mbuf * pMbuf = NULL; /* pointer to mbuf */
  793.     struct uio * pUsrIo = NULL; /* pointer to User IO structure */
  794.     /* extract the socket from the fd */
  795.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  796. {
  797. if ((flags & MSG_MBUF) && (buf))
  798.     m_freem ((struct mbuf *)buf);
  799.         return (ERROR);
  800. }
  801. #ifdef VIRTUAL_STACK
  802.     if (stackInstFromSockVsidSet (s) != OK)
  803.         return (ERROR);
  804. #endif    /* VIRTUAL_STACK */
  805.     spl = splnet ();
  806.     status = bsdSockargs (&mto, (char *) to, tolen, MT_SONAME);
  807.     if (status)
  808. {
  809. netErrnoSet (status);
  810. if ((flags & MSG_MBUF) && (buf))
  811.     m_freem ((struct mbuf *)buf);
  812.         splx (spl);
  813. return (ERROR);
  814. }
  815.     if (flags & MSG_MBUF)
  816. {
  817. pMbuf = (struct mbuf *) buf; 
  818. len = bufLen;
  819. }
  820.     else
  821. {
  822. usrIo.uio_iov = &ioVec;
  823. usrIo.uio_iovcnt = 1;
  824. usrIo.uio_offset = 0;
  825. usrIo.uio_resid = bufLen;
  826. usrIo.uio_segflg = UIO_USERSPACE;
  827. usrIo.uio_rw = UIO_WRITE;
  828. ioVec.iov_base = (caddr_t) buf;
  829. ioVec.iov_len = bufLen;
  830. pUsrIo = &usrIo; 
  831. len = usrIo.uio_resid;
  832. }
  833.     status = sosend (so, mto,  pUsrIo, pMbuf, 0, flags);
  834.     
  835.     m_free (mto);
  836.     splx (spl);
  837.     if (status)
  838.         {
  839.         if (pUsrIo != NULL && pUsrIo->uio_resid != len &&
  840.             (status == EINTR || status == EWOULDBLOCK))
  841.             status = OK;
  842.         }
  843.     return (status == OK ? ((pUsrIo == NULL) ? len : (len - pUsrIo->uio_resid))
  844.     : ERROR);
  845.     }
  846. /*******************************************************************************
  847. *
  848. * bsdSend - send data to a socket
  849. *
  850. * This routine transmits data to a previously established connection-based
  851. * (stream) socket.
  852. *
  853. * The maximum length of <buf> is subject to the limits
  854. * on TCP buffer size; see the discussion of SO_SNDBUF in the
  855. * setsockopt() manual entry.
  856. *
  857. * RETURNS
  858. * The number of bytes sent, or ERROR if the call fails.
  859. * SEE ALSO
  860. * setsockopt()
  861. *
  862. * NOMANUAL
  863. */
  864. int send
  865.     (
  866.     FAST int            s,              /* socket to send to */
  867.     FAST char           *buf,           /* pointer to buffer to transmit */
  868.     FAST int            bufLen,         /* length of buffer */
  869.     FAST int            flags           /* flags to underlying protocols */
  870.     )
  871.     {
  872.     FAST struct socket  *so;
  873.     FAST int status;
  874.     FAST int spl;
  875.     int len; /* value/result */
  876.     struct uio usrIo; /* user IO structure */
  877.     struct iovec ioVec; /* IO vector structure */
  878.     struct mbuf * pMbuf = NULL; /* pointer to mbuf */
  879.     struct uio * pUsrIo = NULL; /* pointer to User IO structure */
  880.     /* extract the socket from the fd */
  881.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  882. {
  883. if ((flags & MSG_MBUF) && (buf))
  884.     m_freem ((struct mbuf *)buf);
  885.         return (ERROR);
  886. }
  887. #ifdef VIRTUAL_STACK
  888.     if (stackInstFromSockVsidSet (s) != OK)
  889.         return (ERROR);
  890. #endif    /* VIRTUAL_STACK */
  891.     
  892.     spl = splnet ();
  893.     if (flags & MSG_MBUF)
  894. {
  895. pMbuf = (struct mbuf *) buf; 
  896. len = bufLen;
  897. }
  898.     else
  899. {
  900. usrIo.uio_iov = &ioVec;
  901. usrIo.uio_iovcnt = 1;
  902. usrIo.uio_offset = 0;
  903. usrIo.uio_resid = bufLen;
  904. usrIo.uio_segflg = UIO_USERSPACE;
  905. usrIo.uio_rw = UIO_WRITE;
  906. ioVec.iov_base = (caddr_t) buf;
  907. ioVec.iov_len = bufLen;
  908. pUsrIo = &usrIo;
  909. len = usrIo.uio_resid;
  910. }
  911.     status = sosend (so, (struct mbuf *) NULL,  pUsrIo, pMbuf,
  912.      (struct mbuf *)NULL, flags);
  913.     splx (spl);
  914.     if (status)
  915.         {
  916.         if (pUsrIo != NULL && pUsrIo->uio_resid != len &&
  917.             (status == EINTR || status == EWOULDBLOCK))
  918.             status = OK;
  919.         }
  920.     return (status == OK ? ((pUsrIo == NULL) ? len : (len - pUsrIo->uio_resid))
  921.     : ERROR);
  922.     }
  923. /*******************************************************************************
  924. *
  925. * bsdSockWrite - write to a socket
  926. *
  927. * This routine is called by the I/O system when a write is done on a socket.
  928. */
  929. LOCAL int bsdSockWrite
  930.     (
  931.     FAST struct socket  *so,
  932.     FAST char           *buf,
  933.     FAST int            bufLen
  934.     )
  935.     {
  936.     FAST int status;
  937.     FAST int spl;
  938.     int len; /* value/result */
  939.     struct uio usrIo; /* user IO structure */
  940.     struct iovec ioVec; /* IO vector structure */
  941. #ifdef VIRTUAL_STACK
  942.     if (stackInstFromSockVsidSet (so->so_fd) != OK)
  943.         return (ERROR);
  944. #endif    /* VIRTUAL_STACK */
  945.     
  946.     spl = splnet ();
  947.     usrIo.uio_iov = &ioVec;
  948.     usrIo.uio_iovcnt = 1;
  949.     usrIo.uio_offset = 0;
  950.     usrIo.uio_resid = bufLen;
  951.     usrIo.uio_segflg = UIO_USERSPACE;
  952.     usrIo.uio_rw = UIO_WRITE;
  953.     ioVec.iov_base = (caddr_t) buf;
  954.     ioVec.iov_len = bufLen;
  955.     len = usrIo.uio_resid;
  956.     status = sosend (so, (struct mbuf *) NULL,  &usrIo, (struct mbuf *)0,
  957.      (struct mbuf *)NULL, 0);
  958.     splx (spl);
  959.     if (status)
  960.         {
  961.         if (usrIo.uio_resid != len &&
  962.             (status == EINTR || status == EWOULDBLOCK))
  963.             status = OK;
  964.         }
  965.     return (status == OK ? (len - usrIo.uio_resid)  : ERROR);
  966.     }
  967. /*******************************************************************************
  968. *
  969. * bsdSendmsg - send a message to a socket
  970. *
  971. * This routine sends a message to a datagram socket.  It may be used in 
  972. * place of sendto() to decrease the overhead of reconstructing the 
  973. * message-header structure (`msghdr') for each message.
  974. * RETURNS
  975. * The number of bytes sent, or ERROR if the call fails.
  976. *
  977. * NOMANUAL
  978. */
  979. int sendmsg
  980.     (
  981.     int                 sd,     /* socket to send to */
  982.     struct msghdr       *mp,    /* scatter-gather message header */
  983.     int                 flags   /* flags to underlying protocols */
  984.     )
  985.     {
  986.     FAST struct iovec  *iov;
  987.     FAST struct iovec   * pIovCopy; /* kernel copy of user iov */
  988.     FAST int  ix;
  989.     struct socket  *so;
  990.     struct uio  auio;
  991.     struct iovec        aiov [UIO_SMALLIOV];  /* use stack for small user iov */
  992.     struct mbuf *to;
  993.     struct mbuf *control;
  994.     int  len;
  995.     int  status;
  996.     int  slev;
  997.     BOOL                mallocedIov;    /* TRUE if kernel iov copy malloced */
  998.                                         /* from system pool */
  999.     int                 sendLen;        /* length of sent message */
  1000.     if (flags & MSG_MBUF)
  1001. {
  1002.         netErrnoSet (EINVAL);
  1003.         return (ERROR); /* mbuf uio not supported */
  1004. }
  1005.     /* extract the socket from the fd */
  1006.     if ((so = (struct socket *) iosFdValue (sd)) == (struct socket *) ERROR)
  1007.         return (ERROR);
  1008. #ifdef VIRTUAL_STACK
  1009.     if (stackInstFromSockVsidSet (sd) != OK)
  1010.         return (ERROR);
  1011. #endif    /* VIRTUAL_STACK */
  1012.     
  1013.     /* allocate space to copy user struct iovec */
  1014.     if (mp->msg_iovlen >= UIO_SMALLIOV)
  1015. {
  1016. if (mp->msg_iovlen >= UIO_MAXIOV)
  1017.     {
  1018.     netErrnoSet (EMSGSIZE);
  1019.     return (ERROR);
  1020.     }
  1021. MALLOC (pIovCopy, struct iovec *, 
  1022. sizeof (struct iovec) * mp->msg_iovlen, MT_DATA, M_WAIT);
  1023. if (pIovCopy == NULL)
  1024.     {
  1025.     netErrnoSet (ENOBUFS);
  1026.     return (ERROR);
  1027.     }
  1028. mallocedIov = TRUE;
  1029. }
  1030.     else
  1031. {
  1032. pIovCopy = aiov;
  1033. mallocedIov = FALSE;
  1034. }
  1035.     slev = splnet ();
  1036.     auio.uio_iov  = pIovCopy;
  1037.     auio.uio_iovcnt  = mp->msg_iovlen;
  1038.     auio.uio_segflg  = UIO_USERSPACE;
  1039.     auio.uio_offset  = 0;
  1040.     auio.uio_rw  = UIO_WRITE;
  1041.     auio.uio_resid  = 0;
  1042.     iov  = mp->msg_iov;
  1043.     for (ix = 0; ix < mp->msg_iovlen; ix++, iov++)
  1044.         {
  1045.         if (iov->iov_len < 0)
  1046.             {
  1047.             netErrnoSet (EINVAL);
  1048.     splx (slev);
  1049.     if (mallocedIov)
  1050. {
  1051. FREE (auio.uio_iov, MT_IOV);
  1052. }
  1053.             return (ERROR);
  1054.             }
  1055.         if (iov->iov_len == 0)
  1056.             continue;
  1057. pIovCopy->iov_len = iov->iov_len;
  1058. pIovCopy->iov_base = iov->iov_base;
  1059. pIovCopy++;
  1060.         auio.uio_resid += iov->iov_len;
  1061.         }
  1062.     /* Save a pointer to struct iovec copy */
  1063.     pIovCopy = auio.uio_iov;
  1064.     if (mp->msg_name)
  1065.         {
  1066.         status = bsdSockargs (&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
  1067.         if (status)
  1068.     {
  1069.     netErrnoSet (status);
  1070.     splx (slev);
  1071.     if (mallocedIov)
  1072. {
  1073. FREE (pIovCopy, MT_DATA);
  1074. }
  1075.             return (ERROR);
  1076.     }
  1077.         }
  1078.     else
  1079.         to = 0;
  1080.     if (mp->msg_control)
  1081.         {
  1082.         status = bsdSockargs (&control, mp->msg_control, mp->msg_controllen,
  1083.                           MT_CONTROL);
  1084.         if (status)
  1085.     {
  1086.     if (to)
  1087. m_freem(to);
  1088.     netErrnoSet (status);
  1089.     splx (slev);
  1090.     if (mallocedIov)
  1091. {
  1092. FREE (pIovCopy, MT_DATA);
  1093. }
  1094.     return (ERROR);
  1095.     }
  1096.         }
  1097.     else
  1098.         control = 0;
  1099.     len = auio.uio_resid;
  1100.     status = sosend (so, to, &auio, (struct mbuf *)0, control, flags);
  1101.     sendLen = len - auio.uio_resid;
  1102.     /* If status has been set to EINVAL in TCP, then TCP has freed the
  1103.      * mbufs. We do not free the mbufs, we return the errno
  1104.      * to the application.
  1105.      */
  1106.     if (status == EINVAL)
  1107. {
  1108. netErrnoSet (status);
  1109. splx (slev);
  1110. if (mallocedIov)
  1111.     {
  1112.     FREE (pIovCopy, MT_DATA);
  1113.     }
  1114. return (ERROR);
  1115. }
  1116.     /* if status is not EINVAL, we free the mbufs as TCP has not freed it */
  1117.     if (control)
  1118.         m_freem(control);
  1119.     if (to)
  1120.         m_freem(to);
  1121.     splx (slev);
  1122.     if (mallocedIov)
  1123. {
  1124. FREE (pIovCopy, MT_DATA);
  1125. }
  1126.     
  1127.     if (status)
  1128. {
  1129.         if (auio.uio_resid != len &&
  1130.             (status == EINTR || status == EWOULDBLOCK))
  1131.             status = OK;
  1132. }
  1133.     return (status == OK ? sendLen : ERROR);
  1134.     }
  1135. /*******************************************************************************
  1136. *
  1137. * bsdRecvfrom - receive a message from a socket
  1138. *
  1139. * This routine receives a message from a datagram socket regardless of 
  1140. * whether it is connected.  If <from> is non-zero, the address of the
  1141. * sender's socket is copied to it.  The value-result parameter <pFromLen>
  1142. * should be initialized to the size of the <from> buffer.  On return,
  1143. * <pFromLen> contains the actual size of the address stored in <from>.
  1144. * The maximum length of <buf> is subject to the limits on UDP buffer
  1145. * size; see the discussion of SO_RCVBUF in the setsockopt() manual
  1146. * entry.
  1147. * RETURNS
  1148. * The number of number of bytes received, or ERROR if the call fails.
  1149. * SEE ALSO
  1150. * setsockopt()
  1151. *
  1152. * NOMANUAL
  1153. */
  1154. int recvfrom
  1155.     (
  1156.     FAST int             s,         /* socket to receive from */
  1157.     FAST char            *buf,      /* pointer to data buffer */
  1158.     FAST int             bufLen,    /* length of buffer */
  1159.     FAST int             flags,     /* flags to underlying protocols */
  1160.     FAST struct sockaddr *from,     /* where to copy sender's addr */
  1161.     FAST int             *pFromLen  /* value/result length of <from> */
  1162.     )
  1163.     {
  1164.     FAST struct socket *so;
  1165.     FAST int spl;
  1166.     FAST int fromLen;
  1167.     int status;
  1168.     struct mbuf * mfrom;
  1169.     int len; /* value/result */
  1170.     struct uio usrIo; /* user IO structure */
  1171.     struct iovec ioVec; /* IO vector structure */
  1172.     int soFlags;
  1173.     struct mbuf ** ppRcvMbuf = NULL; /* for zero copy interface */
  1174. #ifdef VIRTUAL_STACK
  1175.     if (stackInstFromSockVsidSet (s) != OK)
  1176.         return (ERROR);
  1177. #endif    /* VIRTUAL_STACK */
  1178.     /* extract the socket from the fd */
  1179.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  1180.         return (ERROR);
  1181.     spl = splnet ();
  1182.     usrIo.uio_iov = &ioVec;
  1183.     usrIo.uio_iovcnt = 1;
  1184.     usrIo.uio_offset = 0;
  1185.     usrIo.uio_resid = bufLen;
  1186.     usrIo.uio_segflg = UIO_USERSPACE;
  1187.     usrIo.uio_rw = UIO_READ;
  1188.     ioVec.iov_base = (caddr_t) buf;
  1189.     ioVec.iov_len = bufLen;
  1190.     soFlags = flags;
  1191.     if (flags & MSG_MBUF) /* if zero copy interface enabled */
  1192. ppRcvMbuf = (struct mbuf **)buf;
  1193.     len = usrIo.uio_resid;
  1194.     status = soreceive (so, &mfrom, &usrIo, ppRcvMbuf, (struct mbuf **)0, 
  1195. &soFlags);
  1196.     if (from && pFromLen)
  1197. {
  1198.         fromLen = *pFromLen;
  1199.      if (fromLen <= 0 || mfrom == NULL)
  1200.     fromLen = 0;
  1201.      else
  1202.     {
  1203.     if (fromLen > mfrom->m_len)
  1204.      fromLen = mfrom->m_len;
  1205.     bcopy ((char *) mtod (mfrom, char *), (char *) from, fromLen);
  1206.     }
  1207.      *pFromLen = fromLen;
  1208.         if (bsdSock43ApiFlag)
  1209.             {
  1210.             /* Convert the address structure contents to the BSD 4.3 format. */
  1211.             bsdSockAddrRevert (from);
  1212.             }
  1213. }
  1214.     if (mfrom != NULL)
  1215.         m_freem (mfrom);
  1216.     splx (spl);
  1217.     if (status)
  1218.         {
  1219.         if (usrIo.uio_resid != len &&
  1220.             (status == EINTR || status == EWOULDBLOCK))
  1221.             status = OK;
  1222.         }
  1223.     return (status == OK ? (len - usrIo.uio_resid)  : ERROR);
  1224.     }
  1225. /*******************************************************************************
  1226. *
  1227. * bsdRecv - receive data from a socket
  1228. *
  1229. * This routine receives data from a connection-based (stream) socket.
  1230. *
  1231. * The maximum length of <buf> is subject to the limits on TCP buffer
  1232. * size; see the discussion of SO_RCVBUF in the setsockopt() manual
  1233. * entry.
  1234. * RETURNS
  1235. * The number of bytes received, or ERROR if the call fails.
  1236. * SEE ALSO
  1237. * setsockopt()
  1238. *
  1239. * NOMANUAL
  1240. */
  1241. int recv
  1242.     (
  1243.     FAST int    s,      /* socket to receive data from */
  1244.     FAST char   *buf,   /* buffer to write data to */
  1245.     FAST int    bufLen, /* length of buffer */
  1246.     FAST int    flags   /* flags to underlying protocols */
  1247.     )
  1248.     {
  1249.     FAST struct socket *so;
  1250.     FAST int spl;
  1251.     FAST int status;
  1252.     int len;
  1253.     struct uio usrIo; /* user IO structure */
  1254.     struct iovec ioVec; /* IO vector structure */
  1255.     int soFlags;
  1256.     struct mbuf ** ppRcvMbuf = NULL; /* for zero copy interface */
  1257.     /* extract the socket from the fd */
  1258.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  1259.         return (ERROR);
  1260. #ifdef VIRTUAL_STACK
  1261.     if (stackInstFromSockVsidSet (s) != OK)
  1262.         return (ERROR);
  1263. #endif    /* VIRTUAL_STACK */
  1264.     
  1265.     spl = splnet ();
  1266.     usrIo.uio_iov = &ioVec;
  1267.     usrIo.uio_iovcnt = 1;
  1268.     usrIo.uio_offset = 0;
  1269.     usrIo.uio_resid = bufLen;
  1270.     usrIo.uio_segflg = UIO_USERSPACE;
  1271.     usrIo.uio_rw = UIO_READ;
  1272.     ioVec.iov_base = (caddr_t) buf;
  1273.     ioVec.iov_len = bufLen;
  1274.     soFlags = flags;
  1275.     if (flags & MSG_MBUF) /* if zero copy interface enabled */
  1276. ppRcvMbuf = (struct mbuf **)buf;
  1277.     len = usrIo.uio_resid;
  1278.     status = soreceive (so, (struct mbuf **)NULL, &usrIo, ppRcvMbuf, 
  1279. (struct mbuf **)0, &soFlags);
  1280.     splx (spl);
  1281.     if (status)
  1282.         {
  1283.         if (usrIo.uio_resid != len &&
  1284.             (status == EINTR || status == EWOULDBLOCK))
  1285.             status = OK;
  1286.         }
  1287.     return (status == OK ? (len - usrIo.uio_resid)  : ERROR);
  1288.     }
  1289. /*******************************************************************************
  1290. *
  1291. * bsdSockRead - read from a socket
  1292. *
  1293. * bsdSockRead is called by the I/O system to do a read on a socket.
  1294. */
  1295. LOCAL int bsdSockRead
  1296.     (
  1297.     FAST struct socket  *so,
  1298.     FAST caddr_t        buf,
  1299.     FAST int            bufLen
  1300.     )
  1301.     {
  1302.     FAST int spl;
  1303.     FAST int status;
  1304.     int len;
  1305.     struct uio usrIo; /* user IO structure */
  1306.     struct iovec ioVec; /* IO vector structure */
  1307.     int soFlags = 0;
  1308. #ifdef VIRTUAL_STACK
  1309.     if (stackInstFromSockVsidSet (so->so_fd) != OK)
  1310.         return (ERROR);
  1311. #endif    /* VIRTUAL_STACK */
  1312.     
  1313.     spl = splnet ();
  1314.     usrIo.uio_iov = &ioVec;
  1315.     usrIo.uio_iovcnt = 1;
  1316.     usrIo.uio_offset = 0;
  1317.     usrIo.uio_resid = bufLen;
  1318.     usrIo.uio_segflg = UIO_USERSPACE;
  1319.     usrIo.uio_rw = UIO_READ;
  1320.     ioVec.iov_base = (caddr_t) buf;
  1321.     ioVec.iov_len = bufLen;
  1322.     len = usrIo.uio_resid;
  1323.     status = soreceive (so, (struct mbuf **)NULL, &usrIo, (struct mbuf **)0, 
  1324. (struct mbuf **)0, &soFlags);
  1325.     splx (spl);
  1326.     if (status)
  1327.         {
  1328.         if (usrIo.uio_resid != len &&
  1329.             (status == EINTR || status == EWOULDBLOCK))
  1330.             status = OK;
  1331.         }
  1332.     return (status == OK ? (len - usrIo.uio_resid)  : ERROR);
  1333.     }
  1334. /*******************************************************************************
  1335. *
  1336. * bsdRecvmsg - receive a message from a socket
  1337. *
  1338. * This routine receives a message from a datagram socket.  It may be used in
  1339. * place of recvfrom() to decrease the overhead of breaking down the
  1340. * message-header structure `msghdr' for each message.
  1341. *
  1342. * RETURNS
  1343. * The number of bytes received, or ERROR if the call fails.
  1344. *
  1345. * NOMANUAL
  1346. */
  1347. int recvmsg
  1348.     (
  1349.     int                 sd,     /* socket to receive from */
  1350.     struct msghdr       *mp,    /* scatter-gather message header */
  1351.     int                 flags   /* flags to underlying protocols */
  1352.     )
  1353.     {
  1354.     FAST struct iovec  *iov;
  1355.     FAST struct iovec   * pIovCopy; /* kernel copy of user iov */
  1356.     FAST int  ix;
  1357.     caddr_t namelenp;
  1358.     caddr_t controllenp;
  1359.     struct socket *so;
  1360.     struct uio  auio;
  1361.     struct iovec        aiov [UIO_SMALLIOV];  /* use stack for small user iov */
  1362.     struct mbuf  *from = NULL;
  1363.     struct mbuf *control = NULL;
  1364.     int  len;
  1365.     int  status;
  1366.     int  slev;
  1367.     BOOL                mallocedIov;    /* TRUE if kernel iov copy malloced */
  1368.                                         /* from system pool */
  1369.     int                 recvLen;        /* length of received message */
  1370.     if (flags & MSG_MBUF)
  1371. {
  1372.         netErrnoSet (EINVAL);
  1373.         return (ERROR); /* mbuf uio not supported */
  1374. }
  1375.     /* extract the socket from the fd */
  1376.     if ((so = (struct socket *) iosFdValue (sd)) == (struct socket *) ERROR)
  1377.         return (ERROR);
  1378. #ifdef VIRTUAL_STACK
  1379.     if (stackInstFromSockVsidSet (sd) != OK)
  1380.         return (ERROR);
  1381. #endif    /* VIRTUAL_STACK */
  1382.     
  1383.     /* allocate space to copy user struct iovec */
  1384.     if (mp->msg_iovlen >= UIO_SMALLIOV)
  1385. {
  1386. if (mp->msg_iovlen >= UIO_MAXIOV)
  1387.     {
  1388.     netErrnoSet (EMSGSIZE);
  1389.     return (ERROR);
  1390.     }
  1391. MALLOC (pIovCopy, struct iovec *, 
  1392. sizeof (struct iovec) * mp->msg_iovlen, MT_DATA, M_WAIT);
  1393. if (pIovCopy == NULL)
  1394.     {
  1395.     netErrnoSet (ENOBUFS);
  1396.     return (ERROR);
  1397.     }
  1398. mallocedIov = TRUE;
  1399. }
  1400.     else
  1401. {
  1402. pIovCopy = aiov;
  1403. mallocedIov = FALSE;
  1404. }
  1405.     slev = splnet ();
  1406.     namelenp = (caddr_t) &mp->msg_namelen;
  1407.     controllenp = (caddr_t) &mp->msg_controllen;
  1408.     mp->msg_flags = flags;
  1409.     
  1410.     auio.uio_iov        = pIovCopy;
  1411.     auio.uio_iovcnt  = mp->msg_iovlen;
  1412.     auio.uio_segflg  = UIO_USERSPACE;
  1413.     auio.uio_offset = 0;
  1414.     auio.uio_resid  = 0;
  1415.     auio.uio_rw  = UIO_READ;
  1416.     iov  = mp->msg_iov;
  1417.     for (ix = 0; ix < mp->msg_iovlen; ix++, iov++)
  1418.         {
  1419.         if (iov->iov_len < 0)
  1420.             {
  1421.             netErrnoSet (EINVAL);
  1422.     splx (slev);
  1423.     if (mallocedIov)
  1424. {
  1425. FREE (pIovCopy, MT_DATA);
  1426. }
  1427.             return (ERROR);
  1428.             }
  1429.         if (iov->iov_len == 0)
  1430.             continue;
  1431. pIovCopy->iov_len = iov->iov_len;
  1432. pIovCopy->iov_base = iov->iov_base;
  1433. pIovCopy++;
  1434.         auio.uio_resid += iov->iov_len;
  1435.         }
  1436.     /* Save a pointer to struct iovec copy */
  1437.     pIovCopy = auio.uio_iov;
  1438.     len = auio.uio_resid;
  1439.     status = soreceive (so, &from, &auio, (struct mbuf **)0, 
  1440. mp->msg_control ? &control : (struct mbuf **)0,
  1441. &mp->msg_flags);
  1442.     
  1443.     recvLen = len - auio.uio_resid;
  1444.     if (mp->msg_name)
  1445.         {
  1446.         len = mp->msg_namelen;
  1447.         if (len <= 0 || from == 0)
  1448.             len = 0;
  1449.         else
  1450.             {
  1451.             if (len > from->m_len)
  1452.                 len = from->m_len;
  1453.             (void) copyout((caddr_t) mtod(from, caddr_t),
  1454.    (caddr_t) mp->msg_name, len);
  1455.             }
  1456.         (void) copyout ((caddr_t) &len, namelenp, sizeof (int));
  1457.         if (bsdSock43ApiFlag)
  1458.             {
  1459.             /* Convert the address structure contents to the BSD 4.3 format. */
  1460.             bsdSockAddrRevert ((struct sockaddr *)mp->msg_name);
  1461.             }
  1462.         }
  1463.     if (mp->msg_control)
  1464.         {
  1465.         len = mp->msg_controllen;
  1466.         if (len <= 0 || control == 0)
  1467.             len = 0;
  1468.         else
  1469.             {
  1470.             if (len > control->m_len)
  1471.                 len = control->m_len;
  1472.             (void) copyout ((caddr_t) mtod(control, caddr_t),
  1473.     (caddr_t) mp->msg_control, len);
  1474.             }
  1475.         (void) copyout ((caddr_t) &len, controllenp, sizeof (int));
  1476.         }
  1477.     /* If status has been set to EINVAL in TCP, then TCP has freed the
  1478.      * mbufs. We do not free the mbufs, we return the errno
  1479.      * to the application.
  1480.      */
  1481.     if (status == EINVAL)
  1482. {
  1483. netErrnoSet (status);
  1484. splx (slev);
  1485. if (mallocedIov)
  1486.     {
  1487.     FREE (pIovCopy, MT_DATA);
  1488.     }
  1489. return (ERROR);
  1490. }
  1491.     /* if status is not EINVAL, we free the mbufs as TCP has not freed it */
  1492.     if (control)
  1493.         m_freem(control);
  1494.     if (from)
  1495.         m_freem(from);
  1496.     splx (slev);
  1497.     if (mallocedIov)
  1498. {
  1499. FREE (pIovCopy, MT_DATA);
  1500. }
  1501.     if (status)
  1502. {
  1503.         if (auio.uio_resid != len &&
  1504.             (status == EINTR || status == EWOULDBLOCK))
  1505.             status = OK;
  1506. }
  1507.     return (status == OK ? recvLen : ERROR);
  1508.     }
  1509. /*******************************************************************************
  1510. *
  1511. * bsdSetsockopt - set socket options
  1512. *
  1513. * This routine sets the options associated with a socket.
  1514. * To manipulate options at the "socket" level, <level> should be SOL_SOCKET.
  1515. * Any other levels should use the appropriate protocol number.
  1516. *
  1517. * OPTIONS FOR STREAM SOCKETS
  1518. * The following sections discuss the socket options available for
  1519. * stream (TCP) sockets.
  1520. *
  1521. * .SS "SO_KEEPALIVE -- Detecting a Dead Connection"
  1522. * Specify the SO_KEEPALIVE option to make the transport protocol (TCP)
  1523. * initiate a timer to detect a dead connection:
  1524. * .CS
  1525. *     setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof (optval));
  1526. * .CE
  1527. * This prevents an application from  hanging on an invalid connection. 
  1528. * The value at <optval> for this option is an integer (type `int'),
  1529. * either 1 (on) or 0 (off).
  1530. * The integrity of a connection is verified by transmitting
  1531. * zero-length TCP segments triggered by a timer, to force a response
  1532. * from a peer node.  If the peer does not respond after repeated
  1533. * transmissions of the KEEPALIVE segments, the connection is dropped,
  1534. * all protocol data structures are reclaimed, and processes sleeping
  1535. * on the connection are awakened with an ETIMEDOUT error.
  1536. * The ETIMEDOUT timeout can happen in two ways.  If the connection is
  1537. * not yet established, the KEEPALIVE timer expires after idling
  1538. * for TCPTV_KEEP_INIT.  If the connection is established, the
  1539. * KEEPALIVE timer starts up when there is no traffic for
  1540. * TCPTV_KEEP_IDLE.  If no response is received from the peer after
  1541. * sending the KEEPALIVE segment TCPTV_KEEPCNT times with interval
  1542. * TCPTV_KEEPINTVL, TCP assumes that the connection is invalid.
  1543. * The parameters TCPTV_KEEP_INIT, TCPTV_KEEP_IDLE, TCPTV_KEEPCNT, and
  1544. * TCPTV_KEEPINTVL are defined in the file vw/h/net/tcp_timer.h.
  1545. *
  1546. * .SS "SO_LINGER -- Closing a Connection"
  1547. * Specify the SO_LINGER option to determine whether TCP should perform a  
  1548. * "graceful" close:
  1549. * .CS
  1550. *     setsockopt (sock, SOL_SOCKET, SO_LINGER, &optval, sizeof (optval));
  1551. * .CE
  1552. * For a "graceful" close, when a connection is shut down TCP tries
  1553. * to make sure that all the unacknowledged data in transmission channel
  1554. * are acknowledged, and the peer is shut down properly, by going through an
  1555. * elaborate set of state transitions.
  1556. * The value at <optval> indicates the amount of time to linger if
  1557. * there is unacknowledged data, using `struct linger' in
  1558. * vw/h/sys/socket.h.  The `linger' structure has two members:
  1559. * `l_onoff' and `l_linger'.  `l_onoff' can be set to 1 to turn on the
  1560. * SO_LINGER option, or set to 0 to turn off the SO_LINGER option.
  1561. * `l_linger' indicates the amount of time to linger.  If `l_onoff' is
  1562. * turned on and `l_linger' is set to 0, a default value TCP_LINGERTIME
  1563. * (specified in netinet/tcp_timer.h) is used for incoming
  1564. * connections accepted on the socket.
  1565. * When SO_LINGER is turned on and the `l_linger' field is set to 0,
  1566. * TCP simply drops the connection by sending out an RST if a
  1567. * connection is already established; frees up the space for the TCP
  1568. * protocol control block; and wakes up all tasks sleeping on the
  1569. * socket.
  1570. * For the client side socket, the value of `l_linger' is not changed
  1571. * if it is set to 0.  To make sure that the value of `l_linger' is 0
  1572. * on a newly accepted socket connection, issue another setsockopt()
  1573. * after the accept() call.
  1574. * Currently the exact value of `l_linger' time is actually ignored
  1575. * (other than checking for 0); that is, TCP performs the state
  1576. * transitions if `l_linger' is not 0, but does not explicitly use its
  1577. * value.
  1578. * .SS "TCP_NODELAY -- Delivering Messages Immediately"
  1579. * Specify the TCP_NODELAY option for real-time protocols, such as the X
  1580. * Window System Protocol, that require immediate delivery of many small
  1581. * messages:
  1582. * .CS
  1583. *     setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof (optval));
  1584. * .CE
  1585. * The value at <optval> is an integer (type `int') set to either 1
  1586. * (on) or 0 (off).
  1587. * By default, the VxWorks TCP implementation employs an algorithm that
  1588. * attempts to avoid the congestion that can be produced by a large number
  1589. * of small TCP segments. This typically arises with virtual terminal
  1590. * applications (such as telnet or rlogin) across networks that have
  1591. * low bandwidth and long delays.  The algorithm attempts to have no
  1592. * more than one outstanding unacknowledged segment in the transmission
  1593. * channel while queueing up the rest of the smaller segments for later
  1594. * transmission.  Another segment is sent only if enough new data is
  1595. * available to make up a maximum sized segment, or if the outstanding
  1596. * data is acknowledged.
  1597. * This congestion-avoidance algorithm works well for virtual terminal
  1598. * protocols and bulk data transfer protocols such as FTP without any
  1599. * noticeable side effects.  However, real-time protocols that require
  1600. * immediate delivery of many small messages, such as the X Window
  1601. * System Protocol, need to defeat this facility to guarantee proper
  1602. * responsiveness in their operation.
  1603. * TCP_NODELAY is a mechanism to turn off the use of this algorithm.
  1604. * If this option is turned on and there is data to be sent out, TCP
  1605. * bypasses the congestion-avoidance algorithm: any available data
  1606. * segments are sent out if there is enough space in the send window.
  1607. * OPTION FOR DATAGRAM SOCKETS
  1608. * The following section discusses an option for datagram (UDP) sockets.
  1609. * .SS "SO_BROADCAST -- Sending to Multiple Destinations"
  1610. * Specify the SO_BROADCAST option when an application needs to send
  1611. * data to more than one destination:
  1612. * .CS
  1613. *     setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof (optval));
  1614. * .CE
  1615. * The value at <optval> is an integer (type <int>), either 1 (on) or 0
  1616. * (off).
  1617. * OPTIONS FOR BOTH STREAM AND DATAGRAM SOCKETS
  1618. * The following sections describe options that can be used with either
  1619. * stream or datagram sockets.
  1620. * .SS "SO_REUSEADDR -- Reusing a Socket Address"
  1621. * Specify the SO_REUSEADDR option to bind a stream socket to a local
  1622. * port that may be still bound to another stream socket:
  1623. * .CS
  1624. *     setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval));
  1625. * .CE
  1626. * The value at <optval> is an integer (type <int>), either 1 (on) or 0
  1627. * (off).
  1628. * When the SO_REUSEADDR option is turned on, applications may bind a
  1629. * stream socket to a local port even if it is still bound to another
  1630. * stream socket, if that other socket is associated with a "zombie" protocol
  1631. * control block context not yet freed from previous sessions.  The
  1632. * uniqueness of port number combinations for each connection is still
  1633. * preserved through sanity checks performed at actual connection
  1634. * setup time.  If this option is not turned on and an application
  1635. * attempts to bind to a port which is being used by a zombie protocol
  1636. * control block, the bind() call fails.
  1637. * .SS "SO_SNDBUF -- Specifying the Size of the Send Buffer"
  1638. * Specify the SO_SNDBUF option to adjust the maximum size of the
  1639. * socket-level send buffer:
  1640. * .CS
  1641. *     setsockopt (sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof (optval));
  1642. * .CE
  1643. * The value at <optval> is an integer (type `int') that specifies the
  1644. * size of the socket-level send buffer to be allocated.
  1645. * When stream or datagram sockets are created, each transport protocol
  1646. * reserves a set amount of space at the socket level for use when the
  1647. * sockets are attached to a protocol.  For TCP, the default size of
  1648. * the send buffer is 8192 bytes.  For UDP, the default size of the
  1649. * send buffer is 9216 bytes.  Socket-level buffers are allocated
  1650. * dynamically from the mbuf pool.
  1651. * The effect of setting the maximum size of buffers (for both
  1652. * SO_SNDBUF and SO_RCVBUF, described below) is not actually to
  1653. * allocate the mbufs from the mbuf pool, but to set the high-water
  1654. * mark in the protocol data structure which is used later to limit the
  1655. * amount of mbuf allocation.  Thus, the maximum size specified for the
  1656. * socket level send and receive buffers can affect the performance of
  1657. * bulk data transfers.  For example, the size of the TCP receive
  1658. * windows is limited by the remaining socket-level buffer space.
  1659. * These parameters must be adjusted to produce the optimal result for
  1660. * a given application.
  1661. * .SS "SO_RCVBUF -- Specifying the Size of the Receive Buffer"
  1662. * Specify the SO_RCVBUF option to adjust the maximum size of the
  1663. * socket-level receive buffer:
  1664. * .CS
  1665. *     setsockopt (sock, SOL_SOCKET, SO_RCVBUF, &optval, sizeof (optval));
  1666. * .CE
  1667. * The value at <optval> is an integer (type `int') that specifies the
  1668. * size of the socket-level receive buffer to be allocated.
  1669. * When stream or datagram sockets are created, each transport protocol
  1670. * reserves a set amount of space at the socket level for use when the
  1671. * sockets are attached to a protocol.  For TCP, the default size is
  1672. * 8192 bytes.  UDP reserves 41600 bytes, enough space for up to forty
  1673. * incoming datagrams (1 Kbyte each).
  1674. *
  1675. * See the SO_SNDBUF discussion above for a discussion of the impact of
  1676. * buffer size on application performance.
  1677. * .SS "SO_OOBINLINE -- Placing Urgent Data in the Normal Data Stream"
  1678. * Specify the SO_OOBINLINE option to place urgent data within the
  1679. * normal receive data stream:
  1680. * .CS
  1681. *     setsockopt (sock, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof (optval));
  1682. * .CE
  1683. * TCP provides an expedited data service which does not conform to the
  1684. * normal constraints of sequencing and flow control of data
  1685. * streams. The expedited service delivers "out-of-band" (urgent) data
  1686. * ahead of other "normal" data to provide interrupt-like services (for
  1687. * example, when you hit a ^C during telnet or rlogin session while
  1688. * data is being displayed on the screen.)
  1689. * TCP does not actually maintain a separate stream to support the
  1690. * urgent data.  Instead, urgent data delivery is implemented as a
  1691. * pointer (in the TCP header) which points to the sequence number of
  1692. * the octet following the urgent data. If more than one transmission
  1693. * of urgent data is received from the peer, they are all put into the
  1694. * normal stream. This is intended for applications that cannot afford
  1695. * to miss out on any urgent data but are usually too slow to respond
  1696. * to them promptly.
  1697. * RETURNS:
  1698. * OK, or ERROR if there is an invalid socket, an unknown option, an option
  1699. * length greater than CL_SIZE_128, insufficient mbufs, or the call is unable 
  1700. * to set the specified option.
  1701. *
  1702. * NOMANUAL
  1703. */
  1704. STATUS setsockopt
  1705.     (
  1706.     int s,              /* target socket */
  1707.     int level,          /* protocol level of option */
  1708.     int optname,        /* option name */
  1709.     char *optval,       /* pointer to option value */
  1710.     int optlen          /* option length */
  1711.     )
  1712.     {
  1713.     FAST struct mbuf *m = NULL;
  1714.     FAST struct socket *so;
  1715.     FAST int status;
  1716.     /* extract the socket from the fd */
  1717.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  1718.         return (ERROR);
  1719.     if (optlen > CL_SIZE_128)
  1720.         {
  1721.         netErrnoSet (EINVAL);
  1722.         return (ERROR);
  1723.         }
  1724.     if (optval)
  1725.         {
  1726.         m = mBufClGet(M_WAIT, MT_SOOPTS, CL_SIZE_128, TRUE);
  1727.         if (m == NULL)
  1728.             {
  1729.     netErrnoSet (ENOBUFS);
  1730.     return (ERROR);
  1731.             }
  1732. copyin(optval, mtod(m, caddr_t), optlen);
  1733.         m->m_len = optlen;
  1734.         }
  1735.     if ((status = sosetopt (so, level, optname, m)) != 0)
  1736. {
  1737. netErrnoSet (status);
  1738. return (ERROR);
  1739. }
  1740.     return (OK);
  1741.     }
  1742. /*******************************************************************************
  1743. *
  1744. * bsdGetsockopt - get socket options
  1745. *
  1746. * This routine returns relevant option values associated with a socket.
  1747. * To manipulate options at the "socket" level, <level> should be SOL_SOCKET.
  1748. * Any other levels should use the appropriate protocol number.
  1749. *
  1750. * RETURNS:
  1751. * OK, or ERROR if there is an invalid socket, an unknown option, or the call
  1752. * is unable to get the specified option.
  1753. *
  1754. * SEE ALSO: setsockopt()
  1755. *
  1756. * NOMANUAL
  1757. */
  1758. STATUS getsockopt
  1759.     (
  1760.     int         s,              /* socket */
  1761.     int         level,          /* protocol level for options */
  1762.     int         optname,        /* name of option */
  1763.     char        *optval,        /* where to put option */
  1764.     int         *optlen         /* where to put option length */
  1765.     )
  1766.     {
  1767.     FAST struct socket *so;
  1768.     FAST int status;
  1769.     int valsize;
  1770.     struct mbuf  *m = NULL;
  1771.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  1772.         return (ERROR);
  1773.     if (optval) /* optval can be NULL */
  1774. copyin ((char *) optlen, (char *) &valsize, sizeof (valsize));
  1775.     else
  1776. valsize = 0;
  1777.     if ((status = sogetopt (so, level, optname, &m)) != 0)
  1778. {
  1779. netErrnoSet (status);
  1780. return (ERROR);
  1781. }
  1782.     if (optval && valsize && m != NULL)
  1783. {
  1784. if (valsize > m->m_len)
  1785.     valsize = m->m_len;
  1786. copyout ((char *) mtod (m, char *), optval, valsize);
  1787. copyout ((char *) &valsize, (char *) optlen, sizeof (valsize));
  1788. }
  1789.     if (m != NULL)
  1790. m_free (m);
  1791.     return (OK);
  1792.     }
  1793. /*******************************************************************************
  1794. *
  1795. * bsdSockargs - encapsulate socket arguments into an mbuf
  1796. */
  1797. LOCAL int bsdSockargs
  1798.     (
  1799.     struct mbuf         **aname,
  1800.     caddr_t             name,
  1801.     int                 namelen,
  1802.     int type
  1803.     )
  1804.     {
  1805.     FAST struct mbuf *m;
  1806.     FAST struct sockaddr *sa;
  1807.     if (namelen > CL_SIZE_128)
  1808.         return (EINVAL);
  1809.     m = mBufClGet (M_WAIT, type, CL_SIZE_128, TRUE);
  1810.     if (m == NULL)
  1811.         return (ENOBUFS);
  1812.     m->m_len = namelen;
  1813.     copyin (name, mtod(m, caddr_t), namelen);
  1814.     *aname = m;
  1815.     if (type == MT_SONAME)
  1816. {
  1817. sa = mtod(m, struct sockaddr *);
  1818.         if (bsdSock43ApiFlag)  /* Accept calls from BSD 4.3 applications? */
  1819.             {
  1820.             /* 
  1821.              * Convert the address structure contents from the BSD 4.3 format.
  1822.              * For BSD 4.4, the 16-bit BSD 4.3 sa_family field has been split 
  1823.              * into an 8-bit sa_len field followed by an 8-bit sa_family field.
  1824.              * The resized 8-bit family field will be set correctly by BSD 4.3 
  1825.              * applications compiled for a big endian architecture, but the
  1826.              * new length field will be set to zero. However, that field is
  1827.              * set correctly by the default processing. The following code
  1828.              * handles BSD 4.3 applications compiled for a little endian
  1829.              * architecture.
  1830.              */
  1831.             if (sa->sa_family == 0 && sa->sa_len == AF_INET)
  1832.                 {
  1833.                 /* 
  1834.                  * Due to the reversed byte ordering, BSD 4.3 applications 
  1835.                  * which were compiled for a little endian architecture will 
  1836.                  * provide an address structure whose sa_len field contains 
  1837.                  * the family specification. This processing would also
  1838.                  * change the address structure of a BSD 4.4 application with 
  1839.                  * a family of AF_UNSPEC and a length of 2 into an AF_INET
  1840.                  * socket, but that address structure is not valid anyway.
  1841.                  */
  1842.                 sa->sa_family = sa->sa_len;
  1843.                 }
  1844.             }
  1845. sa->sa_len = namelen;
  1846. }
  1847.     return (OK);
  1848.     }
  1849. /*******************************************************************************
  1850. *
  1851. * bsdSockAddrRevert - convert a BSD 4.4 address structure to BSD 4.3 format
  1852. *
  1853. * This routine is provided for backward compatibility with BSD 4.3 
  1854. * applications. It changes the contents of the 8-bit sa_family and sa_len 
  1855. * fields used in BSD 4.4 to match the expected contents of the corresponding
  1856. * 16-bit sa_family field for BSD 4.3 addresses.
  1857. *
  1858. * RETURNS: N/A
  1859. *
  1860. * ERRNO: N/A
  1861. *
  1862. * NOMANUAL
  1863. */
  1864. LOCAL void bsdSockAddrRevert
  1865.     (
  1866.     struct sockaddr *  pSrcAddr  /* BSD 4.4 address for conversion */
  1867.     )
  1868.     {
  1869. #if (_BYTE_ORDER == _BIG_ENDIAN)
  1870.     /*
  1871.      * For BSD 4.3 applications compiled with a big endian architecture,
  1872.      * the sa_len field corresponds to the upper 8 bits of the family field,
  1873.      * and must be set to zero. The sa_family field is unchanged.
  1874.      */
  1875.     pSrcAddr->sa_len = 0;
  1876. #else
  1877.     /*
  1878.      * Due to the reversed byte ordering, BSD 4.3 applications compiled for
  1879.      * a little endian architecture expect the low-order bits of the family 
  1880.      * specification in the high-order bits of the associated address, which 
  1881.      * corresponds to the sa_len field of the BSD 4.4 address structure. The 
  1882.      * BSD 4.4 sa_family field will be interpreted as the high-order bits of
  1883.      * the family specification, and must be set to zero.
  1884.      */
  1885.     pSrcAddr->sa_len = pSrcAddr->sa_family;
  1886.     pSrcAddr->sa_family = 0;
  1887. #endif /* _BYTE_ORDER == _BIG_ENDIAN */
  1888.     return;
  1889.     }
  1890. /*******************************************************************************
  1891. *
  1892. * bsdGetsockname - get a socket name
  1893. *
  1894. * This routine gets the current name for the specified socket <s>.
  1895. * The parameter <namelen> should be initialized to indicate the amount of
  1896. * space referenced by <name>.  On return, the name of the socket is copied to
  1897. * <name> and the actual size of the socket name is copied to <namelen>.
  1898. *
  1899. * RETURNS: OK, or ERROR if the socket is invalid
  1900. * or not connected.
  1901. *
  1902. * NOMANUAL
  1903. */
  1904. STATUS getsockname
  1905.     (
  1906.     int s,                      /* socket descriptor */
  1907.     struct sockaddr *name,      /* where to return name */
  1908.     int *namelen                /* space available in name, later */
  1909.                                 /* filled in with actual name size */
  1910.     )
  1911.     {
  1912.     FAST struct mbuf *m;
  1913.     FAST int status;
  1914.     FAST struct socket *so;
  1915.     /* extract the socket from the fd */
  1916.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  1917.         return (ERROR);
  1918. #ifdef VIRTUAL_STACK
  1919.     if (stackInstFromSockVsidSet (s) != OK)
  1920.         return (ERROR);
  1921. #endif    /* VIRTUAL_STACK */
  1922.     
  1923.     m = m_getclr (M_WAIT, MT_SONAME, CL_SIZE_128, TRUE);
  1924.     if (m == NULL)
  1925. {
  1926. netErrnoSet (ENOBUFS);
  1927. return (ERROR);
  1928. }
  1929.     status = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
  1930.     if (status)
  1931. {
  1932. m_freem(m);
  1933. netErrnoSet (status);
  1934. return (ERROR);
  1935. }
  1936.     if (*namelen > m->m_len)
  1937. *namelen = m->m_len;
  1938.     copyout (mtod(m, caddr_t), (caddr_t) name, *namelen);
  1939.     if (bsdSock43ApiFlag)
  1940.         {
  1941.         /* Convert the address structure contents to the BSD 4.3 format. */
  1942.         bsdSockAddrRevert (name);
  1943.         }
  1944.     m_freem(m);
  1945.     return (OK);
  1946.     }
  1947. /*******************************************************************************
  1948. *
  1949. * bsdGetpeername - get the name of a connected peer
  1950. *
  1951. * This routine gets the name of the peer connected to socket <s>.
  1952. * The parameter <namelen> should be initialized to indicate the amount of
  1953. * space referenced by <name>.  On return, the name of the socket is copied to
  1954. * <name> and the actual size of the socket name is copied to <namelen>.
  1955. *
  1956. * RETURNS: OK, or ERROR if the socket is invalid
  1957. * or not connected.
  1958. *
  1959. * NOMANUAL
  1960. */
  1961. STATUS getpeername
  1962.     (
  1963.     int s,                      /* socket descriptor */
  1964.     struct sockaddr *name,      /* where to put name */
  1965.     int *namelen                /* space available in name, later */
  1966.                                 /* filled in with actual name size */
  1967.     )
  1968.     {
  1969.     FAST struct socket *so;
  1970.     FAST struct mbuf *m;
  1971.     FAST int status;
  1972.     /* extract the socket from the fd */
  1973.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  1974.         return (ERROR);
  1975. #ifdef VIRTUAL_STACK
  1976.     if (stackInstFromSockVsidSet (s) != OK)
  1977.         return (ERROR);
  1978. #endif    /* VIRTUAL_STACK */    
  1979.     if ((so->so_state & SS_ISCONNECTED) == 0)
  1980. {
  1981. netErrnoSet (ENOTCONN);
  1982. return (ERROR);
  1983. }
  1984.     m = m_getclr(M_WAIT, MT_SONAME, CL_SIZE_128, TRUE);
  1985.     if (m == NULL)
  1986. {
  1987. netErrnoSet (ENOBUFS);
  1988. return (ERROR);
  1989. }
  1990.     status = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
  1991.     if (status)
  1992. {
  1993. netErrnoSet (status);
  1994. m_freem (m);
  1995. return (ERROR);
  1996. }
  1997.     if (*namelen > m->m_len)
  1998. *namelen = m->m_len;
  1999.     copyout (mtod(m, caddr_t), (caddr_t) name, *namelen);
  2000.     if (bsdSock43ApiFlag)
  2001.         {
  2002.         /* Convert the address structure contents to the BSD 4.3 format. */
  2003.         bsdSockAddrRevert (name);
  2004.         }
  2005.     m_freem (m);
  2006.     return (OK);
  2007.     }
  2008. /******************************************************************************
  2009. *
  2010. * bsdShutdown - shut down a network connection
  2011. *
  2012. * This routine shuts down all, or part, of a connection-based socket <s>.
  2013. * If the value of <how> is 0, receives will be disallowed.  If <how> is 1,
  2014. * sends will be disallowed.  If <how> is 2, both sends and receives are
  2015. * disallowed.
  2016. *
  2017. * RETURNS: OK, or ERROR if the socket is invalid or not connected.
  2018. *
  2019. * NOMANUAL
  2020. */
  2021. STATUS shutdown
  2022.     (
  2023.     int s,      /* the socket to shutdown */
  2024.     int how     /* 0 = receives disallowed */
  2025.                 /* 1 = sends disallowed */
  2026.                 /* 2 = sends and receives disallowed */
  2027.     )
  2028.     {
  2029.     struct socket *so;
  2030.     /* extract the socket from the fd */
  2031.     if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR)
  2032.         return (ERROR);
  2033. #ifdef VIRTUAL_STACK
  2034.     if (stackInstFromSockVsidSet (s) != OK)
  2035.         return (ERROR);
  2036. #endif    /* VIRTUAL_STACK */    
  2037.     return (soshutdown (so, how));
  2038.     }
  2039. STATUS bsdZbufSockRtn ( void )
  2040.    {
  2041.    /* This routine returns TRUE is the backend supports Zbufs, or
  2042.     * else it returns FALSE
  2043.     */
  2044.    return TRUE;
  2045.    }
  2046. #ifdef VIRTUAL_STACK
  2047. /******************************************************************************
  2048. *
  2049. *
  2050. * stackInstFromSockVsidSet - set stack instance from socket vsid
  2051. *
  2052. * This routine will lookup the value of the VSID in the socket and
  2053. * associate the current task's context with that of this VSID.
  2054. *
  2055. * RETURNS
  2056. * OK if we set it successfully, or ERROR if the call fails.
  2057. *
  2058. * SEE ALSO
  2059. * getsockopt(), virtualStackNumTaskIdSet()
  2060. *
  2061. * NOMANUAL
  2062. */
  2063. STATUS stackInstFromSockVsidSet
  2064.     (
  2065.     int    s                    /* socket descriptor */
  2066.     )
  2067.     {
  2068.     int    stackInstance;       /* stack inst obtained using getsockopt */
  2069.     int    status;
  2070.     int    stackInstLen = sizeof (stackInstance); /* length of the stack instance */
  2071.     /*
  2072.      * get the stack instance associated with this socket
  2073.      * and check the context of the current task.
  2074.      * If they don't match, we can't proceed.
  2075.      */
  2076.     status = getsockopt (s, SOL_SOCKET, SO_VSID,
  2077.                               (char *)&stackInstance, &stackInstLen);
  2078.     if ((status != OK) || (myStackNum != stackInstance))
  2079.         {
  2080.         return (ERROR);
  2081.         }
  2082.     return (OK);
  2083.     }
  2084. #endif /* VIRTUAL_STACK */