10f1702c5SYu Xiangning /*
20f1702c5SYu Xiangning * CDDL HEADER START
30f1702c5SYu Xiangning *
40f1702c5SYu Xiangning * The contents of this file are subject to the terms of the
50f1702c5SYu Xiangning * Common Development and Distribution License (the "License").
60f1702c5SYu Xiangning * You may not use this file except in compliance with the License.
70f1702c5SYu Xiangning *
80f1702c5SYu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90f1702c5SYu Xiangning * or http://www.opensolaris.org/os/licensing.
100f1702c5SYu Xiangning * See the License for the specific language governing permissions
110f1702c5SYu Xiangning * and limitations under the License.
120f1702c5SYu Xiangning *
130f1702c5SYu Xiangning * When distributing Covered Code, include this CDDL HEADER in each
140f1702c5SYu Xiangning * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150f1702c5SYu Xiangning * If applicable, add the following below this CDDL HEADER, with the
160f1702c5SYu Xiangning * fields enclosed by brackets "[]" replaced with your own identifying
170f1702c5SYu Xiangning * information: Portions Copyright [yyyy] [name of copyright owner]
180f1702c5SYu Xiangning *
190f1702c5SYu Xiangning * CDDL HEADER END
200f1702c5SYu Xiangning */
210f1702c5SYu Xiangning
220f1702c5SYu Xiangning /*
230f1702c5SYu Xiangning * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240f1702c5SYu Xiangning * Use is subject to license terms.
250f1702c5SYu Xiangning */
26ade42b55SSebastien Roy /*
27ade42b55SSebastien Roy * Copyright (c) 2017 by Delphix. All rights reserved.
28*e7434800SJason King * Copyright 2021 Racktop Systems, Inc.
29ade42b55SSebastien Roy */
300f1702c5SYu Xiangning
310f1702c5SYu Xiangning #include <sys/types.h>
320f1702c5SYu Xiangning #include <sys/t_lock.h>
330f1702c5SYu Xiangning #include <sys/param.h>
340f1702c5SYu Xiangning #include <sys/systm.h>
350f1702c5SYu Xiangning #include <sys/bitmap.h>
360f1702c5SYu Xiangning #include <sys/debug.h>
370f1702c5SYu Xiangning #include <sys/errno.h>
380f1702c5SYu Xiangning #include <sys/strsubr.h>
390f1702c5SYu Xiangning #include <sys/cmn_err.h>
400f1702c5SYu Xiangning #include <sys/sysmacros.h>
410f1702c5SYu Xiangning #include <sys/filio.h>
420f1702c5SYu Xiangning #include <sys/flock.h>
430f1702c5SYu Xiangning #include <sys/stat.h>
440f1702c5SYu Xiangning #include <sys/share.h>
450f1702c5SYu Xiangning
460f1702c5SYu Xiangning #include <sys/vfs.h>
470f1702c5SYu Xiangning #include <sys/vfs_opreg.h>
480f1702c5SYu Xiangning
490f1702c5SYu Xiangning #include <sys/sockio.h>
500f1702c5SYu Xiangning #include <sys/socket.h>
510f1702c5SYu Xiangning #include <sys/socketvar.h>
520f1702c5SYu Xiangning #include <sys/strsun.h>
530f1702c5SYu Xiangning
540f1702c5SYu Xiangning #include <fs/sockfs/sockcommon.h>
550f1702c5SYu Xiangning #include <fs/sockfs/socktpi.h>
560f1702c5SYu Xiangning
570f1702c5SYu Xiangning /*
580f1702c5SYu Xiangning * Generic vnode ops
590f1702c5SYu Xiangning */
600f1702c5SYu Xiangning static int socket_vop_open(struct vnode **, int, struct cred *,
610f1702c5SYu Xiangning caller_context_t *);
620f1702c5SYu Xiangning static int socket_vop_close(struct vnode *, int, int, offset_t,
630f1702c5SYu Xiangning struct cred *, caller_context_t *);
640f1702c5SYu Xiangning static int socket_vop_read(struct vnode *, struct uio *, int,
650f1702c5SYu Xiangning struct cred *, caller_context_t *);
660f1702c5SYu Xiangning static int socket_vop_write(struct vnode *, struct uio *, int,
670f1702c5SYu Xiangning struct cred *, caller_context_t *);
680f1702c5SYu Xiangning static int socket_vop_ioctl(struct vnode *, int, intptr_t, int,
690f1702c5SYu Xiangning struct cred *, int32_t *, caller_context_t *);
700f1702c5SYu Xiangning static int socket_vop_setfl(struct vnode *, int, int, cred_t *,
710f1702c5SYu Xiangning caller_context_t *);
72*e7434800SJason King static int socket_vop_getattr(struct vnode *, struct vattr *, int,
730f1702c5SYu Xiangning struct cred *, caller_context_t *);
74*e7434800SJason King static int socket_vop_setattr(struct vnode *, struct vattr *, int,
750f1702c5SYu Xiangning struct cred *, caller_context_t *);
76*e7434800SJason King static int socket_vop_access(struct vnode *, int, int, struct cred *,
770f1702c5SYu Xiangning caller_context_t *);
78*e7434800SJason King static int socket_vop_fsync(struct vnode *, int, struct cred *,
790f1702c5SYu Xiangning caller_context_t *);
800f1702c5SYu Xiangning static void socket_vop_inactive(struct vnode *, struct cred *,
810f1702c5SYu Xiangning caller_context_t *);
82*e7434800SJason King static int socket_vop_fid(struct vnode *, struct fid *,
830f1702c5SYu Xiangning caller_context_t *);
84*e7434800SJason King static int socket_vop_seek(struct vnode *, offset_t, offset_t *,
850f1702c5SYu Xiangning caller_context_t *);
860f1702c5SYu Xiangning static int socket_vop_poll(struct vnode *, short, int, short *,
870f1702c5SYu Xiangning struct pollhead **, caller_context_t *);
880f1702c5SYu Xiangning
890f1702c5SYu Xiangning extern int socket_close_internal(struct sonode *, int, cred_t *);
900f1702c5SYu Xiangning extern void socket_destroy_internal(struct sonode *, cred_t *);
910f1702c5SYu Xiangning
920f1702c5SYu Xiangning struct vnodeops *socket_vnodeops;
930f1702c5SYu Xiangning const fs_operation_def_t socket_vnodeops_template[] = {
940f1702c5SYu Xiangning VOPNAME_OPEN, { .vop_open = socket_vop_open },
950f1702c5SYu Xiangning VOPNAME_CLOSE, { .vop_close = socket_vop_close },
960f1702c5SYu Xiangning VOPNAME_READ, { .vop_read = socket_vop_read },
970f1702c5SYu Xiangning VOPNAME_WRITE, { .vop_write = socket_vop_write },
980f1702c5SYu Xiangning VOPNAME_IOCTL, { .vop_ioctl = socket_vop_ioctl },
990f1702c5SYu Xiangning VOPNAME_SETFL, { .vop_setfl = socket_vop_setfl },
1000f1702c5SYu Xiangning VOPNAME_GETATTR, { .vop_getattr = socket_vop_getattr },
1010f1702c5SYu Xiangning VOPNAME_SETATTR, { .vop_setattr = socket_vop_setattr },
1020f1702c5SYu Xiangning VOPNAME_ACCESS, { .vop_access = socket_vop_access },
1030f1702c5SYu Xiangning VOPNAME_FSYNC, { .vop_fsync = socket_vop_fsync },
1040f1702c5SYu Xiangning VOPNAME_INACTIVE, { .vop_inactive = socket_vop_inactive },
1050f1702c5SYu Xiangning VOPNAME_FID, { .vop_fid = socket_vop_fid },
1060f1702c5SYu Xiangning VOPNAME_SEEK, { .vop_seek = socket_vop_seek },
1070f1702c5SYu Xiangning VOPNAME_POLL, { .vop_poll = socket_vop_poll },
1080f1702c5SYu Xiangning VOPNAME_DISPOSE, { .error = fs_error },
1090f1702c5SYu Xiangning NULL, NULL
1100f1702c5SYu Xiangning };
1110f1702c5SYu Xiangning
1120f1702c5SYu Xiangning
1130f1702c5SYu Xiangning /*
1140f1702c5SYu Xiangning * generic vnode ops
1150f1702c5SYu Xiangning */
1160f1702c5SYu Xiangning
1170f1702c5SYu Xiangning /*ARGSUSED*/
1180f1702c5SYu Xiangning static int
socket_vop_open(struct vnode ** vpp,int flag,struct cred * cr,caller_context_t * ct)1190f1702c5SYu Xiangning socket_vop_open(struct vnode **vpp, int flag, struct cred *cr,
1200f1702c5SYu Xiangning caller_context_t *ct)
1210f1702c5SYu Xiangning {
1220f1702c5SYu Xiangning struct vnode *vp = *vpp;
1230f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
1240f1702c5SYu Xiangning
1250f1702c5SYu Xiangning flag &= ~FCREAT; /* paranoia */
1260f1702c5SYu Xiangning mutex_enter(&so->so_lock);
1270f1702c5SYu Xiangning so->so_count++;
1280f1702c5SYu Xiangning mutex_exit(&so->so_lock);
1290f1702c5SYu Xiangning
1300f1702c5SYu Xiangning ASSERT(so->so_count != 0); /* wraparound */
1310f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
1320f1702c5SYu Xiangning
1330f1702c5SYu Xiangning return (0);
1340f1702c5SYu Xiangning }
1350f1702c5SYu Xiangning
1360f1702c5SYu Xiangning /*ARGSUSED*/
1370f1702c5SYu Xiangning static int
socket_vop_close(struct vnode * vp,int flag,int count,offset_t offset,struct cred * cr,caller_context_t * ct)1380f1702c5SYu Xiangning socket_vop_close(struct vnode *vp, int flag, int count, offset_t offset,
1390f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
1400f1702c5SYu Xiangning {
1410f1702c5SYu Xiangning struct sonode *so;
1420f1702c5SYu Xiangning int error = 0;
1430f1702c5SYu Xiangning
1440f1702c5SYu Xiangning so = VTOSO(vp);
1450f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
1460f1702c5SYu Xiangning
1470f1702c5SYu Xiangning cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
1480f1702c5SYu Xiangning cleanshares(vp, ttoproc(curthread)->p_pid);
1490f1702c5SYu Xiangning
1500f1702c5SYu Xiangning if (vp->v_stream)
1510f1702c5SYu Xiangning strclean(vp);
1520f1702c5SYu Xiangning
1530f1702c5SYu Xiangning if (count > 1) {
1540f1702c5SYu Xiangning dprint(2, ("socket_vop_close: count %d\n", count));
1550f1702c5SYu Xiangning return (0);
1560f1702c5SYu Xiangning }
1570f1702c5SYu Xiangning
1580f1702c5SYu Xiangning mutex_enter(&so->so_lock);
1590f1702c5SYu Xiangning if (--so->so_count == 0) {
1600f1702c5SYu Xiangning /*
1610f1702c5SYu Xiangning * Initiate connection shutdown.
1620f1702c5SYu Xiangning */
1630f1702c5SYu Xiangning mutex_exit(&so->so_lock);
1640f1702c5SYu Xiangning error = socket_close_internal(so, flag, cr);
1650f1702c5SYu Xiangning } else {
1660f1702c5SYu Xiangning mutex_exit(&so->so_lock);
1670f1702c5SYu Xiangning }
1680f1702c5SYu Xiangning
1690f1702c5SYu Xiangning return (error);
1700f1702c5SYu Xiangning }
1710f1702c5SYu Xiangning
1720f1702c5SYu Xiangning /*ARGSUSED2*/
1730f1702c5SYu Xiangning static int
socket_vop_read(struct vnode * vp,struct uio * uiop,int ioflag,struct cred * cr,caller_context_t * ct)1740f1702c5SYu Xiangning socket_vop_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cr,
1750f1702c5SYu Xiangning caller_context_t *ct)
1760f1702c5SYu Xiangning {
1770f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
1780f1702c5SYu Xiangning struct nmsghdr lmsg;
1790f1702c5SYu Xiangning
1800f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
1810f1702c5SYu Xiangning bzero((void *)&lmsg, sizeof (lmsg));
1820f1702c5SYu Xiangning
1830f1702c5SYu Xiangning return (socket_recvmsg(so, &lmsg, uiop, cr));
1840f1702c5SYu Xiangning }
1850f1702c5SYu Xiangning
1860f1702c5SYu Xiangning /*ARGSUSED2*/
1870f1702c5SYu Xiangning static int
socket_vop_write(struct vnode * vp,struct uio * uiop,int ioflag,struct cred * cr,caller_context_t * ct)1880f1702c5SYu Xiangning socket_vop_write(struct vnode *vp, struct uio *uiop, int ioflag,
1890f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
1900f1702c5SYu Xiangning {
1910f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
1920f1702c5SYu Xiangning struct nmsghdr lmsg;
1930f1702c5SYu Xiangning
1940f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
1950f1702c5SYu Xiangning bzero((void *)&lmsg, sizeof (lmsg));
1960f1702c5SYu Xiangning
1970f1702c5SYu Xiangning if (!(so->so_mode & SM_BYTESTREAM)) {
1980f1702c5SYu Xiangning /*
1990f1702c5SYu Xiangning * If the socket is not byte stream set MSG_EOR
2000f1702c5SYu Xiangning */
2010f1702c5SYu Xiangning lmsg.msg_flags = MSG_EOR;
2020f1702c5SYu Xiangning }
2030f1702c5SYu Xiangning
2040f1702c5SYu Xiangning return (socket_sendmsg(so, &lmsg, uiop, cr));
2050f1702c5SYu Xiangning }
2060f1702c5SYu Xiangning
2070f1702c5SYu Xiangning /*ARGSUSED4*/
2080f1702c5SYu Xiangning static int
socket_vop_ioctl(struct vnode * vp,int cmd,intptr_t arg,int mode,struct cred * cr,int32_t * rvalp,caller_context_t * ct)2090f1702c5SYu Xiangning socket_vop_ioctl(struct vnode *vp, int cmd, intptr_t arg, int mode,
2100f1702c5SYu Xiangning struct cred *cr, int32_t *rvalp, caller_context_t *ct)
2110f1702c5SYu Xiangning {
2120f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
2130f1702c5SYu Xiangning
2140f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
2150f1702c5SYu Xiangning
2160f1702c5SYu Xiangning return (socket_ioctl(so, cmd, arg, mode, cr, rvalp));
2170f1702c5SYu Xiangning }
2180f1702c5SYu Xiangning
2190f1702c5SYu Xiangning /*
2200f1702c5SYu Xiangning * Allow any flags. Record FNDELAY and FNONBLOCK so that they can be inherited
2210f1702c5SYu Xiangning * from listener to acceptor.
2220f1702c5SYu Xiangning */
2230f1702c5SYu Xiangning /* ARGSUSED */
2240f1702c5SYu Xiangning static int
socket_vop_setfl(vnode_t * vp,int oflags,int nflags,cred_t * cr,caller_context_t * ct)2250f1702c5SYu Xiangning socket_vop_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr,
2260f1702c5SYu Xiangning caller_context_t *ct)
2270f1702c5SYu Xiangning {
2280f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
2290f1702c5SYu Xiangning int error = 0;
2300f1702c5SYu Xiangning
2310f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
2320f1702c5SYu Xiangning
2330f1702c5SYu Xiangning mutex_enter(&so->so_lock);
2340f1702c5SYu Xiangning if (nflags & FNDELAY)
2350f1702c5SYu Xiangning so->so_state |= SS_NDELAY;
2360f1702c5SYu Xiangning else
2370f1702c5SYu Xiangning so->so_state &= ~SS_NDELAY;
2380f1702c5SYu Xiangning if (nflags & FNONBLOCK)
2390f1702c5SYu Xiangning so->so_state |= SS_NONBLOCK;
2400f1702c5SYu Xiangning else
2410f1702c5SYu Xiangning so->so_state &= ~SS_NONBLOCK;
2420f1702c5SYu Xiangning mutex_exit(&so->so_lock);
2430f1702c5SYu Xiangning
2440f1702c5SYu Xiangning if (so->so_state & SS_ASYNC)
2450f1702c5SYu Xiangning oflags |= FASYNC;
2460f1702c5SYu Xiangning /*
2470f1702c5SYu Xiangning * Sets/clears the SS_ASYNC flag based on the presence/absence
2480f1702c5SYu Xiangning * of the FASYNC flag passed to fcntl(F_SETFL).
2490f1702c5SYu Xiangning * This exists solely for BSD fcntl() FASYNC compatibility.
2500f1702c5SYu Xiangning */
2510f1702c5SYu Xiangning if ((oflags ^ nflags) & FASYNC && so->so_version != SOV_STREAM) {
2520f1702c5SYu Xiangning int async = nflags & FASYNC;
2530f1702c5SYu Xiangning int32_t rv;
2540f1702c5SYu Xiangning
2550f1702c5SYu Xiangning /*
2560f1702c5SYu Xiangning * For non-TPI sockets all we have to do is set/remove the
2570f1702c5SYu Xiangning * SS_ASYNC bit, but for TPI it is more involved. For that
2580f1702c5SYu Xiangning * reason we delegate the job to the protocol's ioctl handler.
2590f1702c5SYu Xiangning */
2600f1702c5SYu Xiangning error = socket_ioctl(so, FIOASYNC, (intptr_t)&async, FKIOCTL,
2610f1702c5SYu Xiangning cr, &rv);
2620f1702c5SYu Xiangning }
2630f1702c5SYu Xiangning return (error);
2640f1702c5SYu Xiangning }
2650f1702c5SYu Xiangning
2660f1702c5SYu Xiangning
2670f1702c5SYu Xiangning /*
2680f1702c5SYu Xiangning * Get the made up attributes for the vnode.
2690f1702c5SYu Xiangning * 4.3BSD returns the current time for all the timestamps.
2700f1702c5SYu Xiangning * 4.4BSD returns 0 for all the timestamps.
2710f1702c5SYu Xiangning * Here we use the access and modified times recorded in the sonode.
2720f1702c5SYu Xiangning *
2730f1702c5SYu Xiangning * Just like in BSD there is not effect on the underlying file system node
2740f1702c5SYu Xiangning * bound to an AF_UNIX pathname.
2750f1702c5SYu Xiangning *
2760f1702c5SYu Xiangning * When sockmod has been popped this will act just like a stream. Since
2770f1702c5SYu Xiangning * a socket is always a clone there is no need to inspect the attributes
2780f1702c5SYu Xiangning * of the "realvp".
2790f1702c5SYu Xiangning */
2800f1702c5SYu Xiangning /* ARGSUSED */
2810f1702c5SYu Xiangning int
socket_vop_getattr(struct vnode * vp,struct vattr * vap,int flags,struct cred * cr,caller_context_t * ct)2820f1702c5SYu Xiangning socket_vop_getattr(struct vnode *vp, struct vattr *vap, int flags,
2830f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
2840f1702c5SYu Xiangning {
2850f1702c5SYu Xiangning dev_t fsid;
286*e7434800SJason King struct sonode *so;
2870f1702c5SYu Xiangning static int sonode_shift = 0;
2880f1702c5SYu Xiangning
2890f1702c5SYu Xiangning /*
2900f1702c5SYu Xiangning * Calculate the amount of bitshift to a sonode pointer which will
291*e7434800SJason King * still keep it unique. See below. Note that highbit() uses
292*e7434800SJason King * 1-based indexing for the highest bit set (and 0 for 'no bits set').
293*e7434800SJason King * To use the result of highbit() as a shift value, we must subtract 1
294*e7434800SJason King * from the result.
2950f1702c5SYu Xiangning */
296*e7434800SJason King if (sonode_shift == 0) {
297*e7434800SJason King int bit = highbit(sizeof (struct sonode));
298*e7434800SJason King
299*e7434800SJason King /* Sanity check */
300*e7434800SJason King VERIFY3S(bit, >, 0);
301*e7434800SJason King sonode_shift = bit - 1;
302*e7434800SJason King }
3030f1702c5SYu Xiangning
3040f1702c5SYu Xiangning so = VTOSO(vp);
3050f1702c5SYu Xiangning fsid = sockdev;
3060f1702c5SYu Xiangning
3070f1702c5SYu Xiangning if (so->so_version == SOV_STREAM) {
3080f1702c5SYu Xiangning /*
3090f1702c5SYu Xiangning * The imaginary "sockmod" has been popped - act
3100f1702c5SYu Xiangning * as a stream
3110f1702c5SYu Xiangning */
3120f1702c5SYu Xiangning vap->va_type = VCHR;
3130f1702c5SYu Xiangning vap->va_mode = 0;
3140f1702c5SYu Xiangning } else {
3150f1702c5SYu Xiangning vap->va_type = vp->v_type;
3160f1702c5SYu Xiangning vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
3170f1702c5SYu Xiangning S_IROTH|S_IWOTH;
3180f1702c5SYu Xiangning }
3190f1702c5SYu Xiangning vap->va_uid = vap->va_gid = 0;
3200f1702c5SYu Xiangning vap->va_fsid = fsid;
3210f1702c5SYu Xiangning /*
322*e7434800SJason King * If the va_nodeid is > UINT32_MAX, then stat(2) might fail in
323*e7434800SJason King * unexpected ways inside non-largefile aware 32-bit processes --
324*e7434800SJason King * historically, socket inode values (va_nodeid values) were capped at
325*e7434800SJason King * UINT16_MAX (for even more ancient reasons long since unnecessary).
326*e7434800SJason King * To avoid the potential of surprise failures, we shift down
327*e7434800SJason King * the sonode pointer address to try and get the most
328*e7434800SJason King * uniqueness into 32-bits. In practice, this represents the unique
329*e7434800SJason King * portion of the kernel address space, so the chance of duplicate
330*e7434800SJason King * socket inode values is minimized.
3310f1702c5SYu Xiangning */
332*e7434800SJason King vap->va_nodeid = ((ino_t)so >> sonode_shift) & 0xFFFFFFFF;
3330f1702c5SYu Xiangning vap->va_nlink = 0;
3340f1702c5SYu Xiangning vap->va_size = 0;
3350f1702c5SYu Xiangning
3360f1702c5SYu Xiangning /*
3370f1702c5SYu Xiangning * We need to zero out the va_rdev to avoid some fstats getting
3380f1702c5SYu Xiangning * EOVERFLOW. This also mimics SunOS 4.x and BSD behavior.
3390f1702c5SYu Xiangning */
3400f1702c5SYu Xiangning vap->va_rdev = (dev_t)0;
3410f1702c5SYu Xiangning vap->va_blksize = MAXBSIZE;
3420f1702c5SYu Xiangning vap->va_nblocks = btod(vap->va_size);
3430f1702c5SYu Xiangning
3440f1702c5SYu Xiangning if (!SOCK_IS_NONSTR(so)) {
3450f1702c5SYu Xiangning sotpi_info_t *sti = SOTOTPI(so);
3460f1702c5SYu Xiangning
3470f1702c5SYu Xiangning mutex_enter(&so->so_lock);
3480f1702c5SYu Xiangning vap->va_atime.tv_sec = sti->sti_atime;
3490f1702c5SYu Xiangning vap->va_mtime.tv_sec = sti->sti_mtime;
3500f1702c5SYu Xiangning vap->va_ctime.tv_sec = sti->sti_ctime;
3510f1702c5SYu Xiangning mutex_exit(&so->so_lock);
3520f1702c5SYu Xiangning } else {
3530f1702c5SYu Xiangning vap->va_atime.tv_sec = 0;
3540f1702c5SYu Xiangning vap->va_mtime.tv_sec = 0;
3550f1702c5SYu Xiangning vap->va_ctime.tv_sec = 0;
3560f1702c5SYu Xiangning }
3570f1702c5SYu Xiangning
3580f1702c5SYu Xiangning vap->va_atime.tv_nsec = 0;
3590f1702c5SYu Xiangning vap->va_mtime.tv_nsec = 0;
3600f1702c5SYu Xiangning vap->va_ctime.tv_nsec = 0;
3610f1702c5SYu Xiangning vap->va_seq = 0;
3620f1702c5SYu Xiangning
3630f1702c5SYu Xiangning return (0);
3640f1702c5SYu Xiangning }
3650f1702c5SYu Xiangning
3660f1702c5SYu Xiangning /*
3670f1702c5SYu Xiangning * Set attributes.
3680f1702c5SYu Xiangning * Just like in BSD there is not effect on the underlying file system node
3690f1702c5SYu Xiangning * bound to an AF_UNIX pathname.
3700f1702c5SYu Xiangning *
3710f1702c5SYu Xiangning * When sockmod has been popped this will act just like a stream. Since
3720f1702c5SYu Xiangning * a socket is always a clone there is no need to modify the attributes
3730f1702c5SYu Xiangning * of the "realvp".
3740f1702c5SYu Xiangning */
3750f1702c5SYu Xiangning /* ARGSUSED */
3760f1702c5SYu Xiangning int
socket_vop_setattr(struct vnode * vp,struct vattr * vap,int flags,struct cred * cr,caller_context_t * ct)3770f1702c5SYu Xiangning socket_vop_setattr(struct vnode *vp, struct vattr *vap, int flags,
3780f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
3790f1702c5SYu Xiangning {
3800f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
3810f1702c5SYu Xiangning
3820f1702c5SYu Xiangning /*
3830f1702c5SYu Xiangning * If times were changed, and we have a STREAMS socket, then update
3840f1702c5SYu Xiangning * the sonode.
3850f1702c5SYu Xiangning */
3860f1702c5SYu Xiangning if (!SOCK_IS_NONSTR(so)) {
3870f1702c5SYu Xiangning sotpi_info_t *sti = SOTOTPI(so);
3880f1702c5SYu Xiangning
3890f1702c5SYu Xiangning mutex_enter(&so->so_lock);
3900f1702c5SYu Xiangning if (vap->va_mask & AT_ATIME)
3910f1702c5SYu Xiangning sti->sti_atime = vap->va_atime.tv_sec;
3920f1702c5SYu Xiangning if (vap->va_mask & AT_MTIME) {
3930f1702c5SYu Xiangning sti->sti_mtime = vap->va_mtime.tv_sec;
3940f1702c5SYu Xiangning sti->sti_ctime = gethrestime_sec();
3950f1702c5SYu Xiangning }
3960f1702c5SYu Xiangning mutex_exit(&so->so_lock);
3970f1702c5SYu Xiangning }
3980f1702c5SYu Xiangning
3990f1702c5SYu Xiangning return (0);
4000f1702c5SYu Xiangning }
4010f1702c5SYu Xiangning
4020f1702c5SYu Xiangning /*
4030f1702c5SYu Xiangning * Check if user is allowed to access vp. For non-STREAMS based sockets,
4040f1702c5SYu Xiangning * there might not be a device attached to the file system. So for those
4050f1702c5SYu Xiangning * types of sockets there are no permissions to check.
4060f1702c5SYu Xiangning *
4070f1702c5SYu Xiangning * XXX Should there be some other mechanism to check access rights?
4080f1702c5SYu Xiangning */
4090f1702c5SYu Xiangning /*ARGSUSED*/
4100f1702c5SYu Xiangning int
socket_vop_access(struct vnode * vp,int mode,int flags,struct cred * cr,caller_context_t * ct)4110f1702c5SYu Xiangning socket_vop_access(struct vnode *vp, int mode, int flags, struct cred *cr,
4120f1702c5SYu Xiangning caller_context_t *ct)
4130f1702c5SYu Xiangning {
4140f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
4150f1702c5SYu Xiangning
4160f1702c5SYu Xiangning if (!SOCK_IS_NONSTR(so)) {
4170f1702c5SYu Xiangning ASSERT(so->so_sockparams->sp_sdev_info.sd_vnode != NULL);
4180f1702c5SYu Xiangning return (VOP_ACCESS(so->so_sockparams->sp_sdev_info.sd_vnode,
4190f1702c5SYu Xiangning mode, flags, cr, NULL));
4200f1702c5SYu Xiangning }
4210f1702c5SYu Xiangning return (0);
4220f1702c5SYu Xiangning }
4230f1702c5SYu Xiangning
4240f1702c5SYu Xiangning /*
4250f1702c5SYu Xiangning * 4.3BSD and 4.4BSD fail a fsync on a socket with EINVAL.
4260f1702c5SYu Xiangning * This code does the same to be compatible and also to not give an
4270f1702c5SYu Xiangning * application the impression that the data has actually been "synced"
4280f1702c5SYu Xiangning * to the other end of the connection.
4290f1702c5SYu Xiangning */
4300f1702c5SYu Xiangning /* ARGSUSED */
4310f1702c5SYu Xiangning int
socket_vop_fsync(struct vnode * vp,int syncflag,struct cred * cr,caller_context_t * ct)4320f1702c5SYu Xiangning socket_vop_fsync(struct vnode *vp, int syncflag, struct cred *cr,
4330f1702c5SYu Xiangning caller_context_t *ct)
4340f1702c5SYu Xiangning {
4350f1702c5SYu Xiangning return (EINVAL);
4360f1702c5SYu Xiangning }
4370f1702c5SYu Xiangning
4380f1702c5SYu Xiangning /*ARGSUSED*/
4390f1702c5SYu Xiangning static void
socket_vop_inactive(struct vnode * vp,struct cred * cr,caller_context_t * ct)4400f1702c5SYu Xiangning socket_vop_inactive(struct vnode *vp, struct cred *cr, caller_context_t *ct)
4410f1702c5SYu Xiangning {
4420f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
4430f1702c5SYu Xiangning
4440f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
4450f1702c5SYu Xiangning
4460f1702c5SYu Xiangning mutex_enter(&vp->v_lock);
4470f1702c5SYu Xiangning /*
4480f1702c5SYu Xiangning * If no one has reclaimed the vnode, remove from the
4490f1702c5SYu Xiangning * cache now.
4500f1702c5SYu Xiangning */
4510f1702c5SYu Xiangning if (vp->v_count < 1)
4520f1702c5SYu Xiangning cmn_err(CE_PANIC, "socket_inactive: Bad v_count");
4530f1702c5SYu Xiangning
454ade42b55SSebastien Roy VN_RELE_LOCKED(vp);
455ade42b55SSebastien Roy if (vp->v_count != 0) {
4560f1702c5SYu Xiangning mutex_exit(&vp->v_lock);
4570f1702c5SYu Xiangning return;
4580f1702c5SYu Xiangning }
4590f1702c5SYu Xiangning mutex_exit(&vp->v_lock);
4600f1702c5SYu Xiangning
4610f1702c5SYu Xiangning
4620f1702c5SYu Xiangning ASSERT(!vn_has_cached_data(vp));
4630f1702c5SYu Xiangning
4640f1702c5SYu Xiangning /* socket specfic clean-up */
4650f1702c5SYu Xiangning socket_destroy_internal(so, cr);
4660f1702c5SYu Xiangning }
4670f1702c5SYu Xiangning
4680f1702c5SYu Xiangning /* ARGSUSED */
4690f1702c5SYu Xiangning int
socket_vop_fid(struct vnode * vp,struct fid * fidp,caller_context_t * ct)4700f1702c5SYu Xiangning socket_vop_fid(struct vnode *vp, struct fid *fidp, caller_context_t *ct)
4710f1702c5SYu Xiangning {
4720f1702c5SYu Xiangning return (EINVAL);
4730f1702c5SYu Xiangning }
4740f1702c5SYu Xiangning
4750f1702c5SYu Xiangning /*
4760f1702c5SYu Xiangning * Sockets are not seekable.
4770f1702c5SYu Xiangning * (and there is a bug to fix STREAMS to make them fail this as well).
4780f1702c5SYu Xiangning */
4790f1702c5SYu Xiangning /*ARGSUSED*/
4800f1702c5SYu Xiangning int
socket_vop_seek(struct vnode * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)4810f1702c5SYu Xiangning socket_vop_seek(struct vnode *vp, offset_t ooff, offset_t *noffp,
4820f1702c5SYu Xiangning caller_context_t *ct)
4830f1702c5SYu Xiangning {
4840f1702c5SYu Xiangning return (ESPIPE);
4850f1702c5SYu Xiangning }
4860f1702c5SYu Xiangning
4870f1702c5SYu Xiangning /*ARGSUSED*/
4880f1702c5SYu Xiangning static int
socket_vop_poll(struct vnode * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)4890f1702c5SYu Xiangning socket_vop_poll(struct vnode *vp, short events, int anyyet, short *reventsp,
4900f1702c5SYu Xiangning struct pollhead **phpp, caller_context_t *ct)
4910f1702c5SYu Xiangning {
4920f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
4930f1702c5SYu Xiangning
4940f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
4950f1702c5SYu Xiangning
4960f1702c5SYu Xiangning return (socket_poll(so, events, anyyet, reventsp, phpp));
4970f1702c5SYu Xiangning }
498