0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * CDDL HEADER START
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The contents of this file are subject to the terms of the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Common Development and Distribution License (the "License").
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * You may not use this file except in compliance with the License.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * See the License for the specific language governing permissions
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * and limitations under the License.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * When distributing Covered Code, include this CDDL HEADER in each
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If applicable, add the following below this CDDL HEADER, with the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * fields enclosed by brackets "[]" replaced with your own identifying
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * information: Portions Copyright [yyyy] [name of copyright owner]
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * CDDL HEADER END
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * Copyright (c) 2014, Joyent, Inc. All rights reserved.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void so_queue_oob(struct sonode *, mblk_t *, size_t);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_accept_notsupp(struct sonode *lso, int fflag,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_listen_notsupp(struct sonode *so, int backlog, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getsockname_notsupp(struct sonode *so, struct sockaddr *sa,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getpeername_notsupp(struct sonode *so, struct sockaddr *addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t *addrlen, boolean_t accept, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_shutdown_notsupp(struct sonode *so, int how, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_sendmblk_notsupp(struct sonode *so, struct msghdr *msg, int fflag,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Generic Socket Ops
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (socket_init_common(so, pso, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_BIND(so, name, namelen, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(flags == _SOBIND_XPG4_2 || flags == _SOBIND_SOCKBSD);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* X/Open requires this check */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "caused EINVAL\n");
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * a bind to a NULL address is interpreted as unbind. So just
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * do the downcall.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * This check has to be made for X/Open
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * sockets however application failures have
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * been observed when it is applied to
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * all sockets.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Force a zero sa_family to match so_family.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Some programs like inetd(1M) don't set the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * family field. Other programs leave
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * sin_family set to garbage - SunOS 4.X does
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * not check the family field on a bind.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * We use the family field that
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * was passed in to the socket() call.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * With IPv6 we require the family to match
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * unlike in IPv4.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Verify that apps don't forget to clear
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * sin6_scope_id etc
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "bind with uninitialized sin6_scope_id "
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "(%d) on socket. Pid = %d\n",
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "bind with uninitialized __sin6_src_id "
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "(%d) on socket. Pid = %d\n",
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#endif /* DEBUG */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Just pass the request to the protocol */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * First we check if either NCA or KSSL has been enabled for
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * the requested address, and if so, we fall back to TPI.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If neither of those two services are enabled, then we just
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * pass the request to the protocol.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Note that KSSL can only be enabled on a socket if NCA is NOT
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * enabled for that socket, hence the else-statement below.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (nl7c_enabled && ((so->so_family == AF_INET ||
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * NL7C is not supported in non-global zones,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * we enforce this restriction here.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* NCA should be used, so fall back to TPI */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (SOP_BIND(so, name, namelen, flags, cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_bind(so, name, &namelen, cr)) < 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_listen(struct sonode *so, int backlog, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_LISTEN(so, backlog, cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_listen(so, &backlog, cr)) < 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_listen)(so->so_proto_handle,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_connect(struct sonode *so, struct sockaddr *name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t namelen, int fflag, int flags, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_CONNECT(so, name, namelen, fflag, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If there is a pending error, return error
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * This can happen if a non blocking operation caused an error.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_connect(so, (struct sockaddr *)name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_connect)(so->so_proto_handle,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_accept(struct sonode *so, int fflag, struct cred *cr, struct sonode **nsop)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_ACCEPT(so, fflag, cr, nsop));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return ((so->so_type == SOCK_DGRAM || so->so_type == SOCK_RAW) ?
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = so_acceptq_dequeue(so, (fflag & (FNONBLOCK|FNDELAY)),
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* finish the accept */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = (*so->so_downcalls->sd_accept)(so->so_proto_handle,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson nso->so_proto_handle, (sock_upper_handle_t)nso, cr)) != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_SENDMSG(so, msg, uiop, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(flags & MSG_XPG4_2) && msg->msg_controllen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Old way of passing fd's is not supported
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid > so->so_proto_props.sopp_maxpsz &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * For atomic sends we will only do one iteration.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Send down OOB messages even if the send path is being
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * flow controlled (assuming the protocol supports OOB data).
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Need to wait until the protocol is ready to receive
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * more data for transmission.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = so_snd_wait_qnotfull(so, dontblock)) != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Time to send data to the protocol. We either copy the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * data into mblks or pass the uio directly to the protocol.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * We decide what to do based on the available down calls.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* save the resid in case of failure */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark so->so_proto_props.sopp_tail, &error)) == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The send failed. We do not have to free the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * mblks, because that is the protocol's
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * responsibility. However, uio_resid must
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * remain accurate, so adjust that here.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_sendmblk_impl(struct sonode *so, struct nmsghdr *msg, int fflag,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct cred *cr, mblk_t **mpp, sof_instance_t *fil,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Socket filters are not flow controlled */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Need to wait until the protocol is ready to receive
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * more data for transmission.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = so_snd_wait_qnotfull(so, dontblock)) != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * We only allow so_maxpsz of data to be sent down to
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * the protocol at time.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (mp = SOF_FILTER_DATA_OUT_FROM(so, fil, mp, msg,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The send failed. The protocol will free the mblks
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * that were sent down. Let the caller deal with the
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Let the filter know whether the protocol is flow controlled */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (fil_inject && error == 0 && SO_SND_FLOWCTRLD(so))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_sendmblk(struct sonode *so, struct nmsghdr *msg, int fflag,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SO_BLOCK_FALLBACK(so, SOP_SENDMBLK(so, msg, fflag, cr, mpp));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = so_sendmblk_impl(so, msg, fflag, cr, mpp, so->so_filter_top,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_shutdown(struct sonode *so, int how, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_SHUTDOWN(so, how, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * SunOS 4.X has no check for datagram sockets.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * 5.X checks that it is connected (ENOTCONN)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * X/Open requires that we check the connected state.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "caused ENOTCONN\n");
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_shutdown(so, &how, cr)) < 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = ((*so->so_downcalls->sd_shutdown)(so->so_proto_handle,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Protocol agreed to shutdown. We need to flush the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * receive buffer if the receive side is being shutdown.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* wait for active reader to finish */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getsockname(struct sonode *so, struct sockaddr *addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_GETSOCKNAME(so, addr, addrlen, cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_getsockname(so, addr, addrlen, cr)) < 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getpeername(struct sonode *so, struct sockaddr *addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t *addrlen, boolean_t accept, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_GETPEERNAME(so, addr, addrlen, accept, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Added this check for X/Open */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning printf("sockfs: X/Open getpeername check => EINVAL\n");
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_getpeername(so, addr, addrlen, cr)) < 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getsockopt(struct sonode *so, int level, int option_name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *optval, socklen_t *optlenp, int flags, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (sof_getsockopt(so, option_name, optval, optlenp, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOP_GETSOCKOPT(so, level, option_name, optval, optlenp, flags, cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_getsockopt(so, level, option_name, optval,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = socket_getopt_common(so, level, option_name, optval,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, level, option_name, optval, optlenp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If a protocol does not support a particular
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * socket option, set can fail (not allowed)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * but get can not fail. This is the previous
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * sockfs bahvior.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct linger)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct timeval)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct so_snd_bufinfo)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct so_snd_bufinfo));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct so_snd_bufinfo);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_setsockopt(struct sonode *so, int level, int option_name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning const void *optval, socklen_t optlen, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (sof_setsockopt(so, option_name, optval, optlen, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOP_SETSOCKOPT(so, level, option_name, optval, optlen, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* X/Open requires this check */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_CANTSENDMORE && !xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning printf("sockfs: X/Open setsockopt check => EINVAL\n");
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_setsockopt(so, level, option_name,
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian * We pass down these two options to protocol in order
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian * to support some third part protocols which need to
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian * know them. For those protocols which don't care
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian * these two options, simply return 0.
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian sizeof (struct timeval));
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning * XXX XPG 4.2 applications retrieve SO_RCVBUF from
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning * sockfs since the transport might adjust the value
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning * and not return exactly what was set by the
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning * application.
3986c91e1475e8a41e75969310e5abe7fb516983anders (so->so_proto_handle, level, option_name, opt, optlen, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_IOCTL(so, cmd, arg, mode, cr, rvalp));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If there is a pending error, return error
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * This can happen if a non blocking operation caused an error.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * calling strioc can result in the socket falling back to TPI,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * if that is supported.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_ioctl(so, cmd, arg, mode,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = socket_ioctl_common(so, cmd, arg, mode, cr, rvalp)) < 0 &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (error = socket_strioc_common(so, cmd, arg, mode, cr, rvalp)) < 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_ioctl)(so->so_proto_handle,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_poll(struct sonode *so, short events, int anyyet, short *reventsp,
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * In sockets the errors are represented as input/output events
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & events;
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * If the socket is in a state where it can send data
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * turn on POLLWRBAND and POLLOUT events.
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib if ((so->so_mode & SM_CONNREQUIRED) == 0 || (state & SS_ISCONNECTED)) {
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * out of band data is allowed even if the connection
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * is flow controlled
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * As long as there is buffer to send data
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * turn on POLLOUT events
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Turn on POLLIN whenever there is data on the receive queue,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * or the socket is in a state where no more data will be received.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Also, if the socket is accepting connections, flip the bit if
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * there is something on the queue.
f0267584ae28753b6da2c2ca09285102868a3f4aanders * We do an initial check for events without holding locks. However,
f0267584ae28753b6da2c2ca09285102868a3f4aanders * if there are no event available, then we redo the check for POLLIN
f0267584ae28753b6da2c2ca09285102868a3f4aanders * events under the lock.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Pending connections */
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill * If we're looking for POLLRDHUP, indicate it if we have sent the
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill * last rx signal for the socket.
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill if ((events & POLLRDHUP) && (state & SS_SENTLASTREADSIG))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* so_downcalls is null for sctp */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_downcalls != NULL && so->so_downcalls->sd_poll != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, events & SO_PROTO_POLLEV, anyyet,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* do not recheck events */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Urgent data */
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * If the socket has become disconnected, we set POLLHUP.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * Note that if we are in this state, we will have set POLLIN
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * (SO_HAVE_DATA() is true on a disconnected socket), but not
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * POLLOUT (SS_ISCONNECTED is false). This is in keeping with
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * the semantics of POLLHUP, which is defined to be mutually
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * exclusive with respect to POLLOUT but not POLLIN. We are
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * therefore setting POLLHUP primarily for the benefit of
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * those not polling on POLLIN, as they have no other way of
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * knowing that the socket has been disconnected.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill mask = SS_SENTLASTREADSIG | SS_SENTLASTWRITESIG;
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill if ((state & (mask | SS_ISCONNECTED)) == mask)
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill if ((!*reventsp && !anyyet) || (events & POLLET)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Check for read events again, but this time under lock */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Generic Upcalls
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_connected(sock_upper_handle_t sock_handle, sock_connid_t id,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Wake ones who're waiting for conn to become established.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_disconnected(sock_upper_handle_t sock_handle, sock_connid_t id, int error)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * If we aren't currently connected, then this isn't a disconnect but
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * rather a failure to connect.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill connect_failed = !(so->so_state & SS_ISCONNECTED);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_notify_disconnected(so, connect_failed, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_opctl(sock_upper_handle_t sock_handle, sock_opctl_action_t action,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * The protocol can stop generating newconn upcalls when
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * the backlog is full, so to make sure the listener does
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * not end up with a queue full of deferred connections
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * we reduce the backlog by one. Thus the listener will
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * start closing deferred connections before the backlog
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_txq_full(sock_upper_handle_t sock_handle, boolean_t qfull)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* so_notify_writable drops so_lock */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sock_lower_handle_t proto_handle, sock_downcalls_t *sock_downcalls,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct cred *peer_cred, pid_t peer_cpid, sock_upcalls_t **sock_upcallsp)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)parenthandle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_filter_active == 0 || !sof_sonode_drop_deferred(so)))) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nso = socket_newconn(so, proto_handle, sock_downcalls, SOCKET_NOSLEEP,
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson * The new socket (nso), proto_handle and sock_upcallsp are all
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson * valid at this point. But as soon as nso is placed in the accept
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson * queue that can no longer be assumed (since an accept() thread may
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson * pull it off the queue and close the socket).
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & (SS_CLOSING|SS_FALLBACK_PENDING|SS_FALLBACK_COMP)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* drop proto ref */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&so->so_acceptq_defer, nso);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_set_prop(sock_upper_handle_t sock_handle, struct sock_proto_props *soppp)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxblk = soppp->sopp_maxblk;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_wroff = soppp->sopp_wroff;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_tail = soppp->sopp_tail;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rxhiwat = soppp->sopp_rxhiwat;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rxlowat = soppp->sopp_rxlowat;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxpsz = soppp->sopp_maxpsz;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_minpsz = soppp->sopp_minpsz;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_zcopyflag |= STZCVMSAFE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_zcopyflag &= ~STZCVMUNSAFE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if (soppp->sopp_zcopyflag & ZCVMUNSAFE) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_zcopyflag |= STZCVMUNSAFE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_zcopyflag &= ~STZCVMSAFE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_zcopyflag |= STRCOPYCACHED;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_oobinline = soppp->sopp_oobinline;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rcvtimer = soppp->sopp_rcvtimer;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rcvthresh = soppp->sopp_rcvthresh;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxaddrlen = soppp->sopp_maxaddrlen;
081c0aa8fd8d801a6b12e7245814d260095dc103Anders Persson so->so_proto_props.sopp_loopback = soppp->sopp_loopback;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_bottom; inst != NULL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning soppp->sopp_flags &= ~(SOCKOPT_MAXBLK | SOCKOPT_WROFF | SOCKOPT_TAIL |
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT | SOCKOPT_MAXPSZ |
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOCKOPT_ZCOPY | SOCKOPT_OOBINLINE | SOCKOPT_RCVTIMER |
081c0aa8fd8d801a6b12e7245814d260095dc103Anders Persson SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ |
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_queue_msg_impl(struct sonode *so, mblk_t *mp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson size_t msg_size, int flags, int *errorp, boolean_t *force_pushp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* the notify functions will drop the lock */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(DB_TYPE(mp) == M_DATA || DB_TYPE(mp) == M_PROTO);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (DB_TYPE(mp) == M_PROTO && !__TPI_PRIM_ISALIGNED(mp->b_rptr)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* The read pointer is not aligned correctly for TPI */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "sockfs: Unaligned TPI message received. rptr = %p\n",
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (; filter != NULL; filter = filter->sofi_prev) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)filter, filter->sofi_cookie, mp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson DTRACE_PROBE2(filter__data, (sof_instance_t), filter,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Data was consumed/dropped, just do space check */
4117443759eb8485e3cfd93459f86a41ea241d20Anders Persson if (so->so_state & (SS_FALLBACK_DRAIN | SS_FALLBACK_COMP)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (-1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & (SS_CANTRCVMORE | SS_CLOSING)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* process the mblk via I/OAT if capable */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning space_left = so->so_rcvbuf - so->so_rcv_queued;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (force_push || so->so_rcv_queued >= so->so_rcv_thresh ||
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * so_notify_data will release the lock
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Make sure the recv push timer is running */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson space_left = so->so_rcvbuf - so->so_rcv_queued;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_queue_msg(sock_upper_handle_t sock_handle, mblk_t *mp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson size_t msg_size, int flags, int *errorp, boolean_t *force_pushp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = (struct sonode *)sock_handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (so_queue_msg_impl(so, mp, msg_size, flags, errorp, force_pushp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set the offset of where the oob data is relative to the bytes in
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * queued. Also generate SIGURG
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_signal_oob(sock_upper_handle_t sock_handle, ssize_t offset)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * New urgent data on the way so forget about any old
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * urgent data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state &= ~(SS_HAVEOOBDATA|SS_HADOOBDATA);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Record that urgent data is pending.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dprintso(so, 1, ("sock: discarding old oob\n"));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * set the offset where the urgent byte is
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Queue the OOB byte
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_queue_oob(struct sonode *so, mblk_t *mp, size_t len)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_close(struct sonode *so, int flag, struct cred *cr)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * No new data will be enqueued once the CLOSING flag is set.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * We grab and release the accept lock to ensure that any
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * thread about to insert a socket in so_newconn completes
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * before we flush the queue. Any thread calling so_newconn
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * after we drop the lock will observe the SS_CLOSING flag,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * which will stop it from inserting the socket in the queue.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_close)(so->so_proto_handle, flag, cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Protocol made a synchronous close; remove proto ref */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Protocol is in the process of closing, it will make a
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * 'closed' upcall to remove the reference.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Upcall made by the protocol when it's doing an asynchronous close. It
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * will drop the protocol's reference on the socket.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_zcopy_notify(sock_upper_handle_t sock_handle)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_set_error(sock_upper_handle_t sock_handle, int error)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * so_recvmsg - read data from the socket
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * There are two ways of obtaining data; either we ask the protocol to
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * copy directly into the supplied buffer, or we copy data from the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * sonode's receive queue. The decision which one to use depends on
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * whether the protocol has a sd_recv_uio down call.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_RECVMSG(so, msg, uiop, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_state & (SS_ISCONNECTED|SS_CANTRCVMORE)) == 0 &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if (so->so_downcalls->sd_recv_uio != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = sorecvoob(so, msg, uiop, msg->msg_flags,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If the protocol has the recv down call, then pass the request
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Reading data from the socket buffer
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set msg_controllen and msg_namelen to zero here to make it
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * simpler in the cases that no control or name is returned.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Set SOREADLOCKED */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = so_dequeue_msg(so, &mctlp, uiop, &rval, flags);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * For datagrams the MOREDATA flag is used to set MSG_TRUNC.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * For non-datagrams MOREDATA is used to set MSG_EOR.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((rval.r_val1 & MOREDATA) && (so->so_mode & SM_ATOMIC))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Set MSG_EOR based on MOREDATA */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If some data was received (i.e. not EOF) and the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * read/recv* has not been satisfied wait for some more.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson /* so_queue_msg has already verified length and alignment */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dprintso(so, 1, ("so_recvmsg: type %d\n", tpr->type));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set msg_flags to MSG_EOR based on
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * MORE_flag and MOREDATA.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If some data was received (i.e. not EOF) and the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * read/recv* has not been satisfied wait for some more.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Caller wants source address */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning addr = sogetoff(mctlp, tpr->unitdata_ind.SRC_offset,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Extract any source address option.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Determine how large cmsg buffer is needed.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning opt = sogetoff(mctlp, tpr->unitdata_ind.OPT_offset,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_getopt_srcaddr(opt, optlen, &addr, &addrlen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else if (ncontrollen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Return address to caller.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Caller handles truncation if length
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * exceeds msg_namelen.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * NOTE: AF_UNIX NUL termination is ensured by
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * the sender's copyin_name().
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Return control msg to caller.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Caller handles truncation if length
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * exceeds msg_controllen.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Determine how large cmsg buffer is needed.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else if (ncontrollen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Return control msg to caller.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Caller handles truncation if length
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * exceeds msg_controllen.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set msg_flags to MSG_EOR based on
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * DATA_flag and MOREDATA.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If some data was received (i.e. not EOF) and the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * read/recv* has not been satisfied wait for some more.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Not possible to wait if control info was received.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&