0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * CDDL HEADER START
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
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 *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * or http://www.opensolaris.org/os/licensing.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * See the License for the specific language governing permissions
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * and limitations under the License.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
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 *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * CDDL HEADER END
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill/*
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * Copyright (c) 2014, Joyent, Inc. All rights reserved.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill */
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/types.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/param.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/systm.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/sysmacros.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/debug.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/cmn_err.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/stropts.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/socket.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/socketvar.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#define _SUN_TPI_VERSION 2
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/tihdr.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/sockio.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/kmem_impl.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/strsubr.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/strsun.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/ddi.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <netinet/in.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <inet/ip.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <fs/sockfs/sockcommon.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <fs/sockfs/sockfilter_impl.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/socket_proto.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <fs/sockfs/socktpi_impl.h>
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson#include <fs/sockfs/sodirect.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/tihdr.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <fs/sockfs/nl7c.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningextern int xnet_skip_checks;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningextern int xnet_check_print;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonstatic void so_queue_oob(struct sonode *, mblk_t *, size_t);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_accept_notsupp(struct sonode *lso, int fflag,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct cred *cr, struct sonode **nsop)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_listen_notsupp(struct sonode *so, int backlog, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getsockname_notsupp(struct sonode *so, struct sockaddr *sa,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t *len, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getpeername_notsupp(struct sonode *so, struct sockaddr *addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t *addrlen, boolean_t accept, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_shutdown_notsupp(struct sonode *so, int how, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_sendmblk_notsupp(struct sonode *so, struct msghdr *msg, int fflag,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct cred *cr, mblk_t **mpp)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Generic Socket Ops
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (socket_init_common(so, pso, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int flags, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_BIND(so, name, namelen, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(flags == _SOBIND_XPG4_2 || flags == _SOBIND_SOCKBSD);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* X/Open requires this check */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (xnet_check_print) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning printf("sockfs: X/Open bind state check "
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "caused EINVAL\n");
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * a bind to a NULL address is interpreted as unbind. So just
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * do the downcall.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (name == NULL)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto dobind;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning switch (so->so_family) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case AF_INET:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((size_t)namelen != sizeof (sin_t)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = name->sa_family != so->so_family ?
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning EAFNOSUPPORT : EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & _SOBIND_XPG4_2) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (name->sa_family != so->so_family)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EAFNOSUPPORT;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Force a zero sa_family to match so_family.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning name->sa_family = so->so_family;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case AF_INET6: {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#ifdef DEBUG
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sin6_t *sin6 = (sin6_t *)name;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#endif
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((size_t)namelen != sizeof (sin6_t)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = name->sa_family != so->so_family ?
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning EAFNOSUPPORT : EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (name->sa_family != so->so_family) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * With IPv6 we require the family to match
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * unlike in IPv4.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EAFNOSUPPORT;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#ifdef DEBUG
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Verify that apps don't forget to clear
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * sin6_scope_id etc
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sin6->sin6_scope_id != 0 &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning !IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning zcmn_err(getzoneid(), CE_WARN,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "bind with uninitialized sin6_scope_id "
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "(%d) on socket. Pid = %d\n",
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (int)sin6->sin6_scope_id,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (int)curproc->p_pid);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sin6->__sin6_src_id != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning zcmn_err(getzoneid(), CE_WARN,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "bind with uninitialized __sin6_src_id "
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "(%d) on socket. Pid = %d\n",
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (int)sin6->__sin6_src_id,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (int)curproc->p_pid);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#endif /* DEBUG */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning default:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Just pass the request to the protocol */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto dobind;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 *
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (nl7c_enabled && ((so->so_family == AF_INET ||
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_family == AF_INET6) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nl7c_lookup_addr(name, namelen) != NULL)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * NL7C is not supported in non-global zones,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * we enforce this restriction here.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_zoneid == GLOBAL_ZONEID) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* NCA should be used, so fall back to TPI */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = so_tpi_fallback(so, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (SOP_BIND(so, name, namelen, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdobind:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_bind(so, name, &namelen, cr)) < 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_bind)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_proto_handle, name, namelen, cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdone:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_listen(struct sonode *so, int backlog, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_LISTEN(so, backlog, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((so)->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_listen(so, &backlog, cr)) < 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_listen)(so->so_proto_handle,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson backlog, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_connect(struct sonode *so, struct sockaddr *name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t namelen, int fflag, int flags, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sock_connid_t id;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_CONNECT(so, name, namelen, fflag, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = sogeterr(so, B_TRUE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_connect(so, (struct sockaddr *)name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson &namelen, cr)) < 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_connect)(so->so_proto_handle,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson name, namelen, &id, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (error == EINPROGRESS)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = so_wait_connected(so,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson fflag & (FNONBLOCK|FNDELAY), id);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdone:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*ARGSUSED*/
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_accept(struct sonode *so, int fflag, struct cred *cr, struct sonode **nsop)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *nso;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *nsop = NULL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_ACCEPT(so, fflag, cr, nsop));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_state & SS_ACCEPTCONN) == 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return ((so->so_type == SOCK_DGRAM || so->so_type == SOCK_RAW) ?
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning EOPNOTSUPP : EINVAL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = so_acceptq_dequeue(so, (fflag & (FNONBLOCK|FNDELAY)),
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &nso)) == 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(nso != NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* finish the accept */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((so->so_filter_active > 0 &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_accept(nso, cr)) > 0) ||
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 Xiangning (void) socket_close(nso, 0, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_destroy(nso);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *nsop = nso;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error, flags;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning boolean_t dontblock;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ssize_t orig_resid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mblk_t *mp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_SENDMSG(so, msg, uiop, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning flags = msg->msg_flags;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dontblock = (flags & MSG_DONTWAIT) ||
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (uiop->uio_fmode & (FNONBLOCK|FNDELAY));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(flags & MSG_XPG4_2) && msg->msg_controllen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Old way of passing fd's is not supported
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_mode & SM_ATOMIC) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid > so->so_proto_props.sopp_maxpsz &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxpsz != -1) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EMSGSIZE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * For atomic sends we will only do one iteration.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning do {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_CANTSENDMORE) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EPIPE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = sogeterr(so, B_TRUE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (flags & MSG_OOB) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_mode & SM_EXDATA) == 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EOPNOTSUPP;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else if (SO_SND_FLOWCTRLD(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Need to wait until the protocol is ready to receive
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * more data for transmission.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = so_snd_wait_qnotfull(so, dontblock)) != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_downcalls->sd_send_uio != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_send_uio)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, uiop, msg, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* save the resid in case of failure */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning orig_resid = uiop->uio_resid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((mp = socopyinuio(uiop,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxpsz,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_wroff,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxblk,
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark so->so_proto_props.sopp_tail, &error)) == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(uiop->uio_resid >= 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0 &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ((mp = SOF_FILTER_DATA_OUT(so, mp, msg, cr,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson &error)) == NULL)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (error != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_send)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, mp, msg, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid = orig_resid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } while (uiop->uio_resid > 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
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 boolean_t fil_inject)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning boolean_t dontblock;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t size;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mblk_t *mp = *mpp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_downcalls->sd_send == NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EOPNOTSUPP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dontblock = (msg->msg_flags & MSG_DONTWAIT) ||
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (fflag & (FNONBLOCK|FNDELAY));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size = msgdsize(mp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_mode & SM_ATOMIC) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size > so->so_proto_props.sopp_maxpsz &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxpsz != -1) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EMSGSIZE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning while (mp != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mblk_t *nmp, *last_mblk;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t mlen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_CANTSENDMORE) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EPIPE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = sogeterr(so, B_TRUE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Socket filters are not flow controlled */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (SO_SND_FLOWCTRLD(so) && !fil_inject) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Need to wait until the protocol is ready to receive
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * more data for transmission.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = so_snd_wait_qnotfull(so, dontblock)) != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * We only allow so_maxpsz of data to be sent down to
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * the protocol at time.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mlen = MBLKL(mp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nmp = mp->b_cont;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning last_mblk = mp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning while (nmp != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mlen += MBLKL(nmp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (mlen > so->so_proto_props.sopp_maxpsz) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning last_mblk->b_cont = NULL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning last_mblk = nmp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nmp = nmp->b_cont;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0 &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (mp = SOF_FILTER_DATA_OUT_FROM(so, fil, mp, msg,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cr, &error)) == NULL) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *mpp = mp = nmp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (error != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_send)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, mp, msg, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The send failed. The protocol will free the mblks
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * that were sent down. Let the caller deal with the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * rest.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *mpp = nmp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *mpp = mp = nmp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Let the filter know whether the protocol is flow controlled */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (fil_inject && error == 0 && SO_SND_FLOWCTRLD(so))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = ENOSPC;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#pragma inline(so_sendmblk_impl)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonint
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_sendmblk(struct sonode *so, struct nmsghdr *msg, int fflag,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct cred *cr, mblk_t **mpp)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson int error;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SO_BLOCK_FALLBACK(so, SOP_SENDMBLK(so, msg, fflag, cr, mpp));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((so->so_mode & SM_SENDFILESUPP) == 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SO_UNBLOCK_FALLBACK(so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (EOPNOTSUPP);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = so_sendmblk_impl(so, msg, fflag, cr, mpp, so->so_filter_top,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson B_FALSE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_shutdown(struct sonode *so, int how, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_SHUTDOWN(so, how, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(so->so_state & SS_ISCONNECTED)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = ENOTCONN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (xnet_check_print) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning printf("sockfs: X/Open shutdown check "
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "caused ENOTCONN\n");
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_shutdown(so, &how, cr)) < 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = ((*so->so_downcalls->sd_shutdown)(so->so_proto_handle,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson how, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Protocol agreed to shutdown. We need to flush the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * receive buffer if the receive side is being shutdown.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error == 0 && how != SHUT_WR) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* wait for active reader to finish */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) so_lock_read(so, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_rcv_flush(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_unlock_read(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdone:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getsockname(struct sonode *so, struct sockaddr *addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t *addrlen, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_GETSOCKNAME(so, addr, addrlen, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_getsockname(so, addr, addrlen, cr)) < 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_getsockname)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_proto_handle, addr, addrlen, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getpeername(struct sonode *so, struct sockaddr *addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t *addrlen, boolean_t accept, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_GETPEERNAME(so, addr, addrlen, accept, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (accept) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_getpeername)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, addr, addrlen, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if (!(so->so_state & SS_ISCONNECTED)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = ENOTCONN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Added this check for X/Open */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (xnet_check_print) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning printf("sockfs: X/Open getpeername check => EINVAL\n");
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else if (so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_getpeername(so, addr, addrlen, cr)) < 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_getpeername)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, addr, addrlen, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_getsockopt(struct sonode *so, int level, int option_name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *optval, socklen_t *optlenp, int flags, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (level == SOL_FILTER)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (sof_getsockopt(so, option_name, optval, optlenp, cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOP_GETSOCKOPT(so, level, option_name, optval, optlenp, flags, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_getsockopt(so, level, option_name, optval,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson optlenp, cr)) < 0) &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = socket_getopt_common(so, level, option_name, optval,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson optlenp, flags)) < 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_getsockopt)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, level, option_name, optval, optlenp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error == ENOPROTOOPT) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (level == SOL_SOCKET) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning switch (option_name) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_LINGER:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (*optlenp < (t_uscalar_t)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct linger)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bzero(optval, sizeof (struct linger));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *optlenp = sizeof (struct linger);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_RCVTIMEO:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_SNDTIMEO:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (*optlenp < (t_uscalar_t)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct timeval)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bzero(optval, sizeof (struct timeval));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *optlenp = sizeof (struct timeval);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_SND_BUFINFO:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (*optlenp < (t_uscalar_t)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct so_snd_bufinfo)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EINVAL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bzero(optval,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct so_snd_bufinfo));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *optlenp =
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (struct so_snd_bufinfo);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_DEBUG:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_REUSEADDR:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_KEEPALIVE:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_DONTROUTE:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_BROADCAST:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_USELOOPBACK:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_OOBINLINE:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_DGRAM_ERRIND:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_SNDBUF:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SO_RCVBUF:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *((int32_t *)optval) = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *optlenp = sizeof (int32_t);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning default:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_setsockopt(struct sonode *so, int level, int option_name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning const void *optval, socklen_t optlen, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
3986c91e1475e8a41e75969310e5abe7fb516983anders struct timeval tl;
3986c91e1475e8a41e75969310e5abe7fb516983anders const void *opt = optval;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (level == SOL_FILTER)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (sof_setsockopt(so, option_name, optval, optlen, cr));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOP_SETSOCKOPT(so, level, option_name, optval, optlen, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* X/Open requires this check */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_CANTSENDMORE && !xnet_skip_checks) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (xnet_check_print)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning printf("sockfs: X/Open setsockopt check => EINVAL\n");
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (EINVAL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0 &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_setsockopt(so, level, option_name,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void *)optval, &optlen, cr)) >= 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto done;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning if (level == SOL_SOCKET) {
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning switch (option_name) {
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning case SO_RCVTIMEO:
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning case SO_SNDTIMEO: {
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian /*
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.
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian */
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning clock_t t_usec;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian if (get_udatamodel() == DATAMODEL_NONE ||
e5083e819e9d0322245ac20a9e8d367b88b4064fshenjian get_udatamodel() == DATAMODEL_NATIVE) {
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian if (optlen != sizeof (struct timeval)) {
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian error = EINVAL;
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian goto done;
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian }
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian bcopy((struct timeval *)optval, &tl,
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian sizeof (struct timeval));
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian } else {
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian if (optlen != sizeof (struct timeval32)) {
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian error = EINVAL;
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian goto done;
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian }
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian TIMEVAL32_TO_TIMEVAL(&tl,
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian (struct timeval32 *)optval);
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning }
3986c91e1475e8a41e75969310e5abe7fb516983anders opt = &tl;
3986c91e1475e8a41e75969310e5abe7fb516983anders optlen = sizeof (tl);
22238f73378cc4cb6fd470f00810959bdd55aff6shenjian t_usec = tl.tv_sec * 1000 * 1000 + tl.tv_usec;
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning mutex_enter(&so->so_lock);
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning if (option_name == SO_RCVTIMEO)
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning so->so_rcvtimeo = drv_usectohz(t_usec);
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning else
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning so->so_sndtimeo = drv_usectohz(t_usec);
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning mutex_exit(&so->so_lock);
34dfe6834cf56b6816de4f0528362e98e322c5a1shenjian break;
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning }
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning case SO_RCVBUF:
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning /*
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.
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning */
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning so->so_xpg_rcvbuf = *(int32_t *)optval;
a5adac4d8d51bc60d7d7f5763966ce1290dc1277Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_setsockopt)
3986c91e1475e8a41e75969310e5abe7fb516983anders (so->so_proto_handle, level, option_name, opt, optlen, cr);
22238f73378cc4cb6fd470f00810959bdd55aff6shenjiandone:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct cred *cr, int32_t *rvalp)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_IOCTL(so, cmd, arg, mode, cr, rvalp));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = sogeterr(so, B_TRUE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * calling strioc can result in the socket falling back to TPI,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * if that is supported.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if ((so->so_filter_active == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (error = sof_filter_ioctl(so, cmd, arg, mode,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson rvalp, cr)) < 0) &&
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 Xiangning cmd, arg, mode, rvalp, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdone:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_poll(struct sonode *so, short events, int anyyet, short *reventsp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct pollhead **phpp)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill int state = so->so_state, mask;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib /*
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * In sockets the errors are represented as input/output events
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_error != 0 &&
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib ((POLLIN|POLLRDNORM|POLLOUT) & events) != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & events;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * If the socket is in a state where it can send data
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * turn on POLLWRBAND and POLLOUT events.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib if ((so->so_mode & SM_CONNREQUIRED) == 0 || (state & SS_ISCONNECTED)) {
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib /*
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * out of band data is allowed even if the connection
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * is flow controlled
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib */
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib *reventsp |= POLLWRBAND & events;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!SO_SND_FLOWCTRLD(so)) {
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib /*
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * As long as there is buffer to send data
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib * turn on POLLOUT events
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib */
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib *reventsp |= POLLOUT & events;
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 *
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Pending connections */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!list_is_empty(&so->so_acceptq_list))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp |= (POLLIN|POLLRDNORM) & events;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill /*
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 */
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill if ((events & POLLRDHUP) && (state & SS_SENTLASTREADSIG))
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill *reventsp |= POLLRDHUP;
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Data */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* so_downcalls is null for sctp */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_downcalls != NULL && so->so_downcalls->sd_poll != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp |= (*so->so_downcalls->sd_poll)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, events & SO_PROTO_POLLEV, anyyet,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning CRED()) & events;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT((*reventsp & ~events) == 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* do not recheck events */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning events &= ~SO_PROTO_POLLEV;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (SO_HAVE_DATA(so))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp |= (POLLIN|POLLRDNORM) & events;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Urgent data */
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib if ((state & SS_OOBPEND) != 0) {
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib *reventsp |= (POLLRDBAND | POLLPRI) & events;
af89d820d181e8b4eada2d1e9b042d910b0951e5Rao Shoaib }
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill /*
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 */
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill mask = SS_SENTLASTREADSIG | SS_SENTLASTWRITESIG;
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill if ((state & (mask | SS_ISCONNECTED)) == mask)
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill *reventsp |= POLLHUP;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill if ((!*reventsp && !anyyet) || (events & POLLET)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Check for read events again, but this time under lock */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (events & (POLLIN|POLLRDNORM)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (SO_HAVE_DATA(so) ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson !list_is_empty(&so->so_acceptq_list)) {
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill if (events & POLLET) {
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill so->so_pollev |= SO_POLLEV_IN;
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill *phpp = &so->so_poll_list;
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill }
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *reventsp |= (POLLIN|POLLRDNORM) & events;
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_pollev |= SO_POLLEV_IN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *phpp = &so->so_poll_list;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Generic Upcalls
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_connected(sock_upper_handle_t sock_handle, sock_connid_t id,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning cred_t *peer_cred, pid_t peer_cpid)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(so->so_proto_handle != NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (peer_cred != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_peercred != NULL)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning crfree(so->so_peercred);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning crhold(peer_cred);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_peercred = peer_cred;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_cpid = peer_cpid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_connid = id;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning soisconnected(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Wake ones who're waiting for conn to become established.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_connected(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_disconnected(sock_upper_handle_t sock_handle, sock_connid_t id, int error)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson boolean_t connect_failed;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill /*
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * If we aren't currently connected, then this isn't a disconnect but
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * rather a failure to connect.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill */
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill connect_failed = !(so->so_state & SS_ISCONNECTED);
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_connid = id;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning soisdisconnected(so, error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_notify_disconnected(so, connect_failed, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_opctl(sock_upper_handle_t sock_handle, sock_opctl_action_t action,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uintptr_t arg)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning switch (action) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SOCK_OPCTL_SHUT_SEND:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socantsendmore(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_disconnecting(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SOCK_OPCTL_SHUT_RECV: {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socantrcvmore(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_eof(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case SOCK_OPCTL_ENAB_ACCEPT:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_ACCEPTCONN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_backlog = (unsigned int)arg;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
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
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * is full.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_backlog = MAX(1, so->so_backlog - 1);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning default:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning break;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_txq_full(sock_upper_handle_t sock_handle, boolean_t qfull)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (qfull) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_snd_qfull(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_snd_qnotfull(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* so_notify_writable drops so_lock */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_writable(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningsock_upper_handle_t
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_newconn(sock_upper_handle_t parenthandle,
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{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)parenthandle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *nso;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(proto_handle != NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_state & SS_ACCEPTCONN) == 0 ||
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_acceptq_len >= so->so_backlog &&
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (so->so_filter_active == 0 || !sof_sonode_drop_deferred(so)))) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nso = socket_newconn(so, proto_handle, sock_downcalls, SOCKET_NOSLEEP,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (nso == NULL)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (peer_cred != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning crhold(peer_cred);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nso->so_peercred = peer_cred;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning nso->so_cpid = peer_cpid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson nso->so_listener = so;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson /*
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).
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson */
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson *sock_upcallsp = &so_upcalls;
d68ef20e3fe871e73146fc684d29d335521dcd99Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & (SS_CLOSING|SS_FALLBACK_PENDING|SS_FALLBACK_COMP)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(nso->so_count == 1);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson nso->so_count--;
b1cd7879d8fc9fb80c59139db15960e8e6d6bf93Anders Persson nso->so_listener = NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* drop proto ref */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson VN_RELE(SOTOV(nso));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socket_destroy(nso);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (NULL);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_acceptq_len++;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (nso->so_state & SS_FIL_DEFER) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&so->so_acceptq_defer, nso);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson list_insert_tail(&so->so_acceptq_list, nso);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson cv_signal(&so->so_acceptq_cv);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_notify_newconn(so);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return ((sock_upper_handle_t)nso);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_set_prop(sock_upper_handle_t sock_handle, struct sock_proto_props *soppp)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_MAXBLK)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxblk = soppp->sopp_maxblk;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_WROFF)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_wroff = soppp->sopp_wroff;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_TAIL)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_tail = soppp->sopp_tail;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_RCVHIWAT)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rxhiwat = soppp->sopp_rxhiwat;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_RCVLOWAT)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rxlowat = soppp->sopp_rxlowat;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_MAXPSZ)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxpsz = soppp->sopp_maxpsz;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_MINPSZ)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_minpsz = soppp->sopp_minpsz;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_ZCOPY) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_zcopyflag & ZCVMSAFE) {
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 }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_zcopyflag & COPYCACHED) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_zcopyflag |= STRCOPYCACHED;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_OOBINLINE)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_oobinline = soppp->sopp_oobinline;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_RCVTIMER)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rcvtimer = soppp->sopp_rcvtimer;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_RCVTHRESH)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_rcvthresh = soppp->sopp_rcvthresh;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (soppp->sopp_flags & SOCKOPT_MAXADDRLEN)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_proto_props.sopp_maxaddrlen = soppp->sopp_maxaddrlen;
081c0aa8fd8d801a6b12e7245814d260095dc103Anders Persson if (soppp->sopp_flags & SOCKOPT_LOOPBACK)
081c0aa8fd8d801a6b12e7245814d260095dc103Anders Persson so->so_proto_props.sopp_loopback = soppp->sopp_loopback;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *inst;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ssize_t maxblk;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ushort_t wroff, tail;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson maxblk = so->so_proto_props.sopp_maxblk;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson wroff = so->so_proto_props.sopp_wroff;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson tail = so->so_proto_props.sopp_tail;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (inst = so->so_filter_bottom; inst != NULL;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson inst = inst->sofi_prev) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (SOF_INTERESTED(inst, mblk_prop)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (*inst->sofi_ops->sofop_mblk_prop)(
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)inst, inst->sofi_cookie,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson &maxblk, &wroff, &tail);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_proto_props.sopp_maxblk = maxblk;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_proto_props.sopp_wroff = wroff;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_proto_props.sopp_tail = tail;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#ifdef DEBUG
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 |
081c0aa8fd8d801a6b12e7245814d260095dc103Anders Persson SOCKOPT_LOOPBACK);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(soppp->sopp_flags == 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#endif
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/* ARGSUSED */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningssize_t
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,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_instance_t *filter)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning boolean_t force_push = B_TRUE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int space_left;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sodirect_t *sodp = so->so_direct;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(errorp != NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *errorp = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (mp == NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (so->so_downcalls->sd_recv_uio != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* the notify functions will drop the lock */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (flags & MSG_OOB)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_oobdata(so, IS_SO_OOB_INLINE(so));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_data(so, msg_size);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ASSERT(msg_size == 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto space_check;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(mp->b_next == NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(DB_TYPE(mp) == M_DATA || DB_TYPE(mp) == M_PROTO);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(msg_size == msgdsize(mp));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
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 zcmn_err(getzoneid(), CE_WARN,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning "sockfs: Unaligned TPI message received. rptr = %p\n",
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void *)mp->b_rptr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mp);
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson mutex_enter(&so->so_lock);
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (sodp != NULL)
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson SOD_UIOAFINI(sodp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto space_check;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson for (; filter != NULL; filter = filter->sofi_prev) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (!SOF_INTERESTED(filter, data_in))
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson continue;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mp = (*filter->sofi_ops->sofop_data_in)(
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (sof_handle_t)filter, filter->sofi_cookie, mp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson flags, &msg_size);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson ASSERT(msgdsize(mp) == msg_size);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson DTRACE_PROBE2(filter__data, (sof_instance_t), filter,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (mblk_t *), mp);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Data was consumed/dropped, just do space check */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (msg_size == 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto space_check;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (flags & MSG_OOB) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_queue_oob(so, mp, msg_size);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto space_check;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (force_pushp != NULL)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson force_push = *force_pushp;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
4117443759eb8485e3cfd93459f86a41ea241d20Anders Persson if (so->so_state & (SS_FALLBACK_DRAIN | SS_FALLBACK_COMP)) {
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (sodp != NULL)
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson SOD_DISABLE(sodp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *errorp = EOPNOTSUPP;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (-1);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & (SS_CANTRCVMORE | SS_CLOSING)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mp);
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (sodp != NULL)
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson SOD_DISABLE(sodp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* process the mblk via I/OAT if capable */
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (sodp != NULL && sodp->sod_enabled) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (DB_TYPE(mp) == M_DATA) {
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson sod_uioa_mblk_init(sodp, mp, msg_size);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOD_UIOAFINI(sodp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (mp->b_next == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_enqueue_msg(so, mp, msg_size);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning do {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mblk_t *nmp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((nmp = mp->b_next) != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mp->b_next = NULL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_enqueue_msg(so, mp, msgdsize(mp));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mp = nmp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } while (mp != NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning space_left = so->so_rcvbuf - so->so_rcv_queued;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (space_left <= 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_flowctrld = B_TRUE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *errorp = ENOSPC;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning space_left = -1;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (force_push || so->so_rcv_queued >= so->so_rcv_thresh ||
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson so->so_rcv_queued >= so->so_rcv_wanted) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOCKET_TIMER_CANCEL(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * so_notify_data will release the lock
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_data(so, so->so_rcv_queued);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (force_pushp != NULL)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *force_pushp = B_TRUE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto done;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if (so->so_rcv_timer_tid == 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Make sure the recv push timer is running */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOCKET_TIMER_START(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdone_unlock:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningdone:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (space_left);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonspace_check:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson space_left = so->so_rcvbuf - so->so_rcv_queued;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (space_left <= 0) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_flowctrld = B_TRUE;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson *errorp = ENOSPC;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson space_left = -1;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson goto done_unlock;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#pragma inline(so_queue_msg_impl)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonssize_t
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{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = (struct sonode *)sock_handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson return (so_queue_msg_impl(so, mp, msg_size, flags, errorp, force_pushp,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_filter_bottom));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set the offset of where the oob data is relative to the bytes in
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * queued. Also generate SIGURG
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_signal_oob(sock_upper_handle_t sock_handle, ssize_t offset)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(offset >= 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (so->so_direct != NULL)
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson SOD_UIOAFINI(so->so_direct);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * New urgent data on the way so forget about any old
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * urgent data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state &= ~(SS_HAVEOOBDATA|SS_HADOOBDATA);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Record that urgent data is pending.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_OOBPEND;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_oobmsg != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dprintso(so, 1, ("sock: discarding old oob\n"));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(so->so_oobmsg);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_oobmsg = NULL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * set the offset where the urgent byte is
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_oobmark = so->so_rcv_queued + offset;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_oobmark == 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_RCVATMARK;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state &= ~SS_RCVATMARK;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_oobsig(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Queue the OOB byte
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic void
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_queue_oob(struct sonode *so, mblk_t *mp, size_t len)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (so->so_direct != NULL)
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson SOD_UIOAFINI(so->so_direct);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(mp != NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!IS_SO_OOB_INLINE(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_oobmsg = mp;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_HAVEOOBDATA;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_enqueue_msg(so, mp, len);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_oobdata(so, IS_SO_OOB_INLINE(so));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_close(struct sonode *so, int flag, struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * No new data will be enqueued once the CLOSING flag is set.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so->so_state |= SS_CLOSING;
d36be52ed67a633ea5724b688769f5c0e7e4c203Rao Shoaib ASSERT(so_verify_oobstate(so));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_rcv_flush(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson if (so->so_filter_active > 0)
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson sof_sonode_closing(so);
e82bc0ba9649a7146fdab88089eaa4b8502b2da4Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_state & SS_ACCEPTCONN) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
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 */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_enter(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson mutex_exit(&so->so_acceptq_lock);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_acceptq_flush(so, B_TRUE);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = (*so->so_downcalls->sd_close)(so->so_proto_handle, flag, cr);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson switch (error) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson default:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* Protocol made a synchronous close; remove proto ref */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson VN_RELE(SOTOV(so));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson case EINPROGRESS:
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Protocol is in the process of closing, it will make a
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * 'closed' upcall to remove the reference.
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson error = 0;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson break;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson/*
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 */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_closed(sock_upper_handle_t sock_handle)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson{
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson struct sonode *so = (struct sonode *)sock_handle;
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson VN_RELE(SOTOV(so));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson}
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_zcopy_notify(sock_upper_handle_t sock_handle)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_copyflag |= STZCNOTIFY;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning cv_broadcast(&so->so_copy_cv);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_set_error(sock_upper_handle_t sock_handle, int error)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sonode *so = (struct sonode *)sock_handle;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning soseterror(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_notify_error(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * so_recvmsg - read data from the socket
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
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 Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct cred *cr)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning rval_t rval;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int flags = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_uscalar_t controllen, namelen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int error = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int ret;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mblk_t *mctlp = NULL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning union T_primitives *tpr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *control;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ssize_t saved_resid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct uio *suiop;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_BLOCK_FALLBACK(so, SOP_RECVMSG(so, msg, uiop, cr));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_state & (SS_ISCONNECTED|SS_CANTRCVMORE)) == 0 &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_mode & SM_CONNREQUIRED)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ENOTCONN);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (msg->msg_flags & MSG_PEEK)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags &= ~MSG_WAITALL;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_mode & SM_ATOMIC)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_TRUNC;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (msg->msg_flags & MSG_OOB) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so->so_mode & SM_EXDATA) == 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EOPNOTSUPP;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else if (so->so_downcalls->sd_recv_uio != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_recv_uio)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, uiop, msg, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = sorecvoob(so, msg, uiop, msg->msg_flags,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning IS_SO_OOB_INLINE(so));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If the protocol has the recv down call, then pass the request
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * down.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_downcalls->sd_recv_uio != NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = (*so->so_downcalls->sd_recv_uio)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so->so_proto_handle, uiop, msg, cr);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Reading data from the socket buffer
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning flags = msg->msg_flags;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning controllen = msg->msg_controllen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning namelen = msg->msg_namelen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_controllen = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_namelen = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Set SOREADLOCKED */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = so_lock_read_intr(so,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning suiop = sod_rcv_init(so, flags, &uiop);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningretry:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning saved_resid = uiop->uio_resid;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = so_dequeue_msg(so, &mctlp, uiop, &rval, flags);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(!(rval.r_val1 & MORECTL));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((rval.r_val1 & MOREDATA) && (so->so_mode & SM_ATOMIC))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_TRUNC;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (mctlp == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dprintso(so, 1, ("so_recvmsg: got M_DATA\n"));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Set MSG_EOR based on MOREDATA */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(rval.r_val1 & MOREDATA)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_SAVEDEOR) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_EOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state &= ~SS_SAVEDEOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson flags |= MSG_NOMARK;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto retry;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out_locked;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson /* so_queue_msg has already verified length and alignment */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning tpr = (union T_primitives *)mctlp->b_rptr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning dprintso(so, 1, ("so_recvmsg: type %d\n", tpr->type));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning switch (tpr->type) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case T_DATA_IND: {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set msg_flags to MSG_EOR based on
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * MORE_flag and MOREDATA.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state &= ~SS_SAVEDEOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(tpr->data_ind.MORE_flag & 1)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(rval.r_val1 & MOREDATA))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_EOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_SAVEDEOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson flags |= MSG_NOMARK;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto retry;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out_locked;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case T_UNITDATA_IND: {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *addr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_uscalar_t addrlen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *abuf;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_uscalar_t optlen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *opt;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (namelen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* Caller wants source address */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning addrlen = tpr->unitdata_ind.SRC_length;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning addr = sogetoff(mctlp, tpr->unitdata_ind.SRC_offset,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning addrlen, 1);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (addr == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EPROTO;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(so->so_family != AF_UNIX);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning optlen = tpr->unitdata_ind.OPT_length;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (optlen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_uscalar_t ncontrollen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Extract any source address option.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Determine how large cmsg buffer is needed.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning opt = sogetoff(mctlp, tpr->unitdata_ind.OPT_offset,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning optlen, __TPI_ALIGN_SIZE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (opt == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EPROTO;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_family == AF_UNIX)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_getopt_srcaddr(opt, optlen, &addr, &addrlen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ncontrollen = so_cmsglen(mctlp, opt, optlen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning !(flags & MSG_XPG4_2));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (controllen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning controllen = ncontrollen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else if (ncontrollen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_CTRUNC;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning controllen = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (namelen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning abuf = kmem_alloc(addrlen, KM_SLEEP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bcopy(addr, abuf, addrlen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_name = abuf;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_namelen = addrlen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (controllen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Return control msg to caller.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Caller handles truncation if length
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * exceeds msg_controllen.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning control = kmem_zalloc(controllen, KM_SLEEP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = so_opt2cmsg(mctlp, opt, optlen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning !(flags & MSG_XPG4_2), control, controllen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (msg->msg_namelen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning kmem_free(msg->msg_name,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_namelen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning kmem_free(control, controllen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_control = control;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_controllen = controllen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning case T_OPTDATA_IND: {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct T_optdata_req *tdr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning void *opt;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_uscalar_t optlen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning tdr = (struct T_optdata_req *)mctlp->b_rptr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning optlen = tdr->OPT_length;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (optlen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_uscalar_t ncontrollen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Determine how large cmsg buffer is needed.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning opt = sogetoff(mctlp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning tpr->optdata_ind.OPT_offset, optlen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning __TPI_ALIGN_SIZE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (opt == NULL) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EPROTO;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ncontrollen = so_cmsglen(mctlp, opt, optlen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning !(flags & MSG_XPG4_2));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (controllen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning controllen = ncontrollen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else if (ncontrollen != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_CTRUNC;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning controllen = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (controllen != 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Return control msg to caller.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Caller handles truncation if length
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * exceeds msg_controllen.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning control = kmem_zalloc(controllen, KM_SLEEP);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = so_opt2cmsg(mctlp, opt, optlen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning !(flags & MSG_XPG4_2), control, controllen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (error) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning kmem_free(control, controllen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning eprintsoline(so, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_control = control;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_controllen = controllen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Set msg_flags to MSG_EOR based on
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * DATA_flag and MOREDATA.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state &= ~SS_SAVEDEOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(tpr->data_ind.MORE_flag & 1)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(rval.r_val1 & MOREDATA))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning msg->msg_flags |= MSG_EOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_SAVEDEOR;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /*
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 */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((flags & MSG_WAITALL) && !(msg->msg_flags & MSG_EOR) &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning controllen == 0 &&
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning uiop->uio_resid != saved_resid && uiop->uio_resid > 0) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson flags |= MSG_NOMARK;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto retry;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning goto out_locked;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning default:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning cmn_err(CE_CONT, "so_recvmsg bad type %x \n",
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning tpr->type);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning freemsg(mctlp);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = EPROTO;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningout:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_enter(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningout_locked:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ret = sod_rcv_done(so, suiop, uiop);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (ret != 0 && error == 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning error = ret;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_unlock_read(so); /* Clear SOREADLOCKED */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_UNBLOCK_FALLBACK(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningsonodeops_t so_sonodeops = {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_init, /* sop_init */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_accept, /* sop_accept */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_bind, /* sop_bind */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_listen, /* sop_listen */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_connect, /* sop_connect */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_recvmsg, /* sop_recvmsg */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_sendmsg, /* sop_sendmsg */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_sendmblk, /* sop_sendmblk */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_getpeername, /* sop_getpeername */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_getsockname, /* sop_getsockname */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_shutdown, /* sop_shutdown */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_getsockopt, /* sop_getsockopt */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_setsockopt, /* sop_setsockopt */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_ioctl, /* sop_ioctl */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_poll, /* sop_poll */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_close, /* sop_close */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning};
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningsock_upcalls_t so_upcalls = {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_newconn,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_connected,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_disconnected,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_opctl,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_queue_msg,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_set_prop,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_txq_full,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_signal_oob,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so_zcopy_notify,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_set_error,
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson so_closed
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning};