📄 bsdsocklib.c
字号:
* setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof (optval));* .CE* The value at <optval> is an integer (type <int>), either 1 (on) or 0* (off).* * OPTIONS FOR BOTH STREAM AND DATAGRAM SOCKETS* The following sections describe options that can be used with either* stream or datagram sockets.* * .SS "SO_REUSEADDR -- Reusing a Socket Address"* Specify the SO_REUSEADDR option to bind a stream socket to a local* port that may be still bound to another stream socket:* .CS* setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval));* .CE* The value at <optval> is an integer (type <int>), either 1 (on) or 0* (off).* * When the SO_REUSEADDR option is turned on, applications may bind a* stream socket to a local port even if it is still bound to another* stream socket, if that other socket is associated with a "zombie" protocol* control block context not yet freed from previous sessions. The* uniqueness of port number combinations for each connection is still* preserved through sanity checks performed at actual connection* setup time. If this option is not turned on and an application* attempts to bind to a port which is being used by a zombie protocol* control block, the bind() call fails.* * .SS "SO_SNDBUF -- Specifying the Size of the Send Buffer"* Specify the SO_SNDBUF option to adjust the maximum size of the* socket-level send buffer:* .CS* setsockopt (sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof (optval));* .CE* The value at <optval> is an integer (type `int') that specifies the* size of the socket-level send buffer to be allocated.* * When stream or datagram sockets are created, each transport protocol* reserves a set amount of space at the socket level for use when the* sockets are attached to a protocol. For TCP, the default size of* the send buffer is 8192 bytes. For UDP, the default size of the* send buffer is 9216 bytes. Socket-level buffers are allocated* dynamically from the mbuf pool.* * The effect of setting the maximum size of buffers (for both* SO_SNDBUF and SO_RCVBUF, described below) is not actually to* allocate the mbufs from the mbuf pool, but to set the high-water* mark in the protocol data structure which is used later to limit the* amount of mbuf allocation. Thus, the maximum size specified for the* socket level send and receive buffers can affect the performance of* bulk data transfers. For example, the size of the TCP receive* windows is limited by the remaining socket-level buffer space.* These parameters must be adjusted to produce the optimal result for* a given application.* * .SS "SO_RCVBUF -- Specifying the Size of the Receive Buffer"* Specify the SO_RCVBUF option to adjust the maximum size of the* socket-level receive buffer:* .CS* setsockopt (sock, SOL_SOCKET, SO_RCVBUF, &optval, sizeof (optval));* .CE* The value at <optval> is an integer (type `int') that specifies the* size of the socket-level receive buffer to be allocated.* * When stream or datagram sockets are created, each transport protocol* reserves a set amount of space at the socket level for use when the* sockets are attached to a protocol. For TCP, the default size is* 8192 bytes. UDP reserves 41600 bytes, enough space for up to forty* incoming datagrams (1 Kbyte each).** See the SO_SNDBUF discussion above for a discussion of the impact of* buffer size on application performance.* * .SS "SO_OOBINLINE -- Placing Urgent Data in the Normal Data Stream"* Specify the SO_OOBINLINE option to place urgent data within the* normal receive data stream:* .CS* setsockopt (sock, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof (optval));* .CE* TCP provides an expedited data service which does not conform to the* normal constraints of sequencing and flow control of data* streams. The expedited service delivers "out-of-band" (urgent) data* ahead of other "normal" data to provide interrupt-like services (for* example, when you hit a ^C during telnet or rlogin session while* data is being displayed on the screen.)* * TCP does not actually maintain a separate stream to support the* urgent data. Instead, urgent data delivery is implemented as a* pointer (in the TCP header) which points to the sequence number of* the octet following the urgent data. If more than one transmission* of urgent data is received from the peer, they are all put into the* normal stream. This is intended for applications that cannot afford* to miss out on any urgent data but are usually too slow to respond* to them promptly.* * RETURNS:* OK, or ERROR if there is an invalid socket, an unknown option, an option* length greater than CL_SIZE_128, insufficient mbufs, or the call is unable * to set the specified option.** NOMANUAL*/STATUS setsockopt ( int s, /* target socket */ int level, /* protocol level of option */ int optname, /* option name */ char *optval, /* pointer to option value */ int optlen /* option length */ ) { FAST struct mbuf *m = NULL; FAST struct socket *so; FAST int status; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); if (optlen > CL_SIZE_128) { netErrnoSet (EINVAL); return (ERROR); } if (optval) { m = mBufClGet(M_WAIT, MT_SOOPTS, CL_SIZE_128, TRUE); if (m == NULL) { netErrnoSet (ENOBUFS); return (ERROR); } copyin(optval, mtod(m, caddr_t), optlen); m->m_len = optlen; } if ((status = sosetopt (so, level, optname, m)) != 0) { netErrnoSet (status); return (ERROR); } return (OK); }/********************************************************************************* bsdGetsockopt - get socket options** This routine returns relevant option values associated with a socket.* To manipulate options at the "socket" level, <level> should be SOL_SOCKET.* Any other levels should use the appropriate protocol number.** RETURNS:* OK, or ERROR if there is an invalid socket, an unknown option, or the call* is unable to get the specified option.** SEE ALSO: setsockopt()** NOMANUAL*/STATUS getsockopt ( int s, /* socket */ int level, /* protocol level for options */ int optname, /* name of option */ char *optval, /* where to put option */ int *optlen /* where to put option length */ ) { FAST struct socket *so; FAST int status; int valsize; struct mbuf *m = NULL; if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR); if (optval) /* optval can be NULL */ copyin ((char *) optlen, (char *) &valsize, sizeof (valsize)); else valsize = 0; if ((status = sogetopt (so, level, optname, &m)) != 0) { netErrnoSet (status); return (ERROR); } if (optval && valsize && m != NULL) { if (valsize > m->m_len) valsize = m->m_len; copyout ((char *) mtod (m, char *), optval, valsize); copyout ((char *) &valsize, (char *) optlen, sizeof (valsize)); } if (m != NULL) m_free (m); return (OK); }/********************************************************************************* bsdSockargs - encapsulate socket arguments into an mbuf*/LOCAL int bsdSockargs ( struct mbuf **aname, caddr_t name, int namelen, int type ) { FAST struct mbuf *m; FAST struct sockaddr *sa; if (namelen > CL_SIZE_128) return (EINVAL); m = mBufClGet (M_WAIT, type, CL_SIZE_128, TRUE); if (m == NULL) return (ENOBUFS); m->m_len = namelen; copyin (name, mtod(m, caddr_t), namelen); *aname = m; if (type == MT_SONAME) { sa = mtod(m, struct sockaddr *); if (bsdSock43ApiFlag) /* Accept calls from BSD 4.3 applications? */ { /* * Convert the address structure contents from the BSD 4.3 format. * For BSD 4.4, the 16-bit BSD 4.3 sa_family field has been split * into an 8-bit sa_len field followed by an 8-bit sa_family field. * The resized 8-bit family field will be set correctly by BSD 4.3 * applications compiled for a big endian architecture, but the * new length field will be set to zero. However, that field is * set correctly by the default processing. The following code * handles BSD 4.3 applications compiled for a little endian * architecture. */ if (sa->sa_family == 0 && sa->sa_len == AF_INET) { /* * Due to the reversed byte ordering, BSD 4.3 applications * which were compiled for a little endian architecture will * provide an address structure whose sa_len field contains * the family specification. This processing would also * change the address structure of a BSD 4.4 application with * a family of AF_UNSPEC and a length of 2 into an AF_INET * socket, but that address structure is not valid anyway. */ sa->sa_family = sa->sa_len; } } sa->sa_len = namelen; } return (OK); }/********************************************************************************* bsdSockAddrRevert - convert a BSD 4.4 address structure to BSD 4.3 format** This routine is provided for backward compatibility with BSD 4.3 * applications. It changes the contents of the 8-bit sa_family and sa_len * fields used in BSD 4.4 to match the expected contents of the corresponding* 16-bit sa_family field for BSD 4.3 addresses.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void bsdSockAddrRevert ( struct sockaddr * pSrcAddr /* BSD 4.4 address for conversion */ ) {#if (_BYTE_ORDER == _BIG_ENDIAN) /* * For BSD 4.3 applications compiled with a big endian architecture, * the sa_len field corresponds to the upper 8 bits of the family field, * and must be set to zero. The sa_family field is unchanged. */ pSrcAddr->sa_len = 0;#else /* * Due to the reversed byte ordering, BSD 4.3 applications compiled for * a little endian architecture expect the low-order bits of the family * specification in the high-order bits of the associated address, which * corresponds to the sa_len field of the BSD 4.4 address structure. The * BSD 4.4 sa_family field will be interpreted as the high-order bits of * the family specification, and must be set to zero. */ pSrcAddr->sa_len = pSrcAddr->sa_family; pSrcAddr->sa_family = 0;#endif /* _BYTE_ORDER == _BIG_ENDIAN */ return; }/********************************************************************************* bsdGetsockname - get a socket name** This routine gets the current name for the specified socket <s>.* The parameter <namelen> should be initialized to indicate the amount of* space referenced by <name>. On return, the name of the socket is copied to* <name> and the actual size of the socket name is copied to <namelen>.** RETURNS: OK, or ERROR if the socket is invalid* or not connected.** NOMANUAL*/STATUS getsockname ( int s, /* socket descriptor */ struct sockaddr *name, /* where to return name */ int *namelen /* space available in name, later */ /* filled in with actual name size */ ) { FAST struct mbuf *m; FAST int status; FAST struct socket *so; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR);#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ m = m_getclr (M_WAIT, MT_SONAME, CL_SIZE_128, TRUE); if (m == NULL) { netErrnoSet (ENOBUFS); return (ERROR); } status = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); if (status) { m_freem(m); netErrnoSet (status); return (ERROR); } if (*namelen > m->m_len) *namelen = m->m_len; copyout (mtod(m, caddr_t), (caddr_t) name, *namelen); if (bsdSock43ApiFlag) { /* Convert the address structure contents to the BSD 4.3 format. */ bsdSockAddrRevert (name); } m_freem(m); return (OK); }/********************************************************************************* bsdGetpeername - get the name of a connected peer** This routine gets the name of the peer connected to socket <s>.* The parameter <namelen> should be initialized to indicate the amount of* space referenced by <name>. On return, the name of the socket is copied to* <name> and the actual size of the socket name is copied to <namelen>.** RETURNS: OK, or ERROR if the socket is invalid* or not connected.** NOMANUAL*/STATUS getpeername ( int s, /* socket descriptor */ struct sockaddr *name, /* where to put name */ int *namelen /* space available in name, later */ /* filled in with actual name size */ ) { FAST struct socket *so; FAST struct mbuf *m; FAST int status; /* extract the socket from the fd */ if ((so = (struct socket *) iosFdValue (s)) == (struct socket *) ERROR) return (ERROR);#ifdef VIRTUAL_STACK if (stackInstFromSockVsidSet (s) != OK) return (ERROR);#endif /* VIRTUAL_STACK */ if ((so->so_state & SS_ISCONNECTED) == 0) { netErrnoSet (ENOTCONN); return (ERROR); } m = m_getclr(M_WAIT, MT_SONAME, CL_SIZE_128, TRUE); if (m == NULL) { netErrnoSet (ENOBUFS); return (ERROR); } status = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); if (status) { netErrnoSet (status); m_freem (m); return (ERROR); } if (*namelen > m->m_len) *namelen = m->m_len; copyout (mtod(m, caddr_t), (caddr_t) name, *namelen); if (bsdSock43ApiFlag) { /* Convert the address structure contents to the BSD 4.3 format. */ bsdSockAddrRevert (name); } m_freem (m); return (OK); }/******************************************************************************** bsdShutdown - shut down a network connection** This routine shuts down all, or part, of a connection-based socket <s>.* If the value of <how> is 0, receives will be disallowed. If <how> is 1,* sends will be disallowed. If
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -