1*0f1702c5SYu Xiangning /*
2*0f1702c5SYu Xiangning * CDDL HEADER START
3*0f1702c5SYu Xiangning *
4*0f1702c5SYu Xiangning * The contents of this file are subject to the terms of the
5*0f1702c5SYu Xiangning * Common Development and Distribution License (the "License").
6*0f1702c5SYu Xiangning * You may not use this file except in compliance with the License.
7*0f1702c5SYu Xiangning *
8*0f1702c5SYu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*0f1702c5SYu Xiangning * or http://www.opensolaris.org/os/licensing.
10*0f1702c5SYu Xiangning * See the License for the specific language governing permissions
11*0f1702c5SYu Xiangning * and limitations under the License.
12*0f1702c5SYu Xiangning *
13*0f1702c5SYu Xiangning * When distributing Covered Code, include this CDDL HEADER in each
14*0f1702c5SYu Xiangning * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*0f1702c5SYu Xiangning * If applicable, add the following below this CDDL HEADER, with the
16*0f1702c5SYu Xiangning * fields enclosed by brackets "[]" replaced with your own identifying
17*0f1702c5SYu Xiangning * information: Portions Copyright [yyyy] [name of copyright owner]
18*0f1702c5SYu Xiangning *
19*0f1702c5SYu Xiangning * CDDL HEADER END
20*0f1702c5SYu Xiangning */
21*0f1702c5SYu Xiangning
22*0f1702c5SYu Xiangning /*
23*0f1702c5SYu Xiangning * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24*0f1702c5SYu Xiangning * Use is subject to license terms.
25*0f1702c5SYu Xiangning */
26*0f1702c5SYu Xiangning
27*0f1702c5SYu Xiangning #include <sys/types.h>
28*0f1702c5SYu Xiangning #include <sys/t_lock.h>
29*0f1702c5SYu Xiangning #include <sys/param.h>
30*0f1702c5SYu Xiangning #include <sys/systm.h>
31*0f1702c5SYu Xiangning #include <sys/bitmap.h>
32*0f1702c5SYu Xiangning #include <sys/debug.h>
33*0f1702c5SYu Xiangning #include <sys/errno.h>
34*0f1702c5SYu Xiangning #include <sys/strsubr.h>
35*0f1702c5SYu Xiangning #include <sys/cmn_err.h>
36*0f1702c5SYu Xiangning #include <sys/sysmacros.h>
37*0f1702c5SYu Xiangning #include <sys/filio.h>
38*0f1702c5SYu Xiangning #include <sys/flock.h>
39*0f1702c5SYu Xiangning #include <sys/stat.h>
40*0f1702c5SYu Xiangning #include <sys/share.h>
41*0f1702c5SYu Xiangning
42*0f1702c5SYu Xiangning #include <sys/vfs.h>
43*0f1702c5SYu Xiangning #include <sys/vfs_opreg.h>
44*0f1702c5SYu Xiangning
45*0f1702c5SYu Xiangning #include <sys/sockio.h>
46*0f1702c5SYu Xiangning #include <sys/socket.h>
47*0f1702c5SYu Xiangning #include <sys/socketvar.h>
48*0f1702c5SYu Xiangning #include <sys/strsun.h>
49*0f1702c5SYu Xiangning
50*0f1702c5SYu Xiangning #include <fs/sockfs/sockcommon.h>
51*0f1702c5SYu Xiangning #include <fs/sockfs/socktpi.h>
52*0f1702c5SYu Xiangning
53*0f1702c5SYu Xiangning /*
54*0f1702c5SYu Xiangning * Generic vnode ops
55*0f1702c5SYu Xiangning */
56*0f1702c5SYu Xiangning static int socket_vop_open(struct vnode **, int, struct cred *,
57*0f1702c5SYu Xiangning caller_context_t *);
58*0f1702c5SYu Xiangning static int socket_vop_close(struct vnode *, int, int, offset_t,
59*0f1702c5SYu Xiangning struct cred *, caller_context_t *);
60*0f1702c5SYu Xiangning static int socket_vop_read(struct vnode *, struct uio *, int,
61*0f1702c5SYu Xiangning struct cred *, caller_context_t *);
62*0f1702c5SYu Xiangning static int socket_vop_write(struct vnode *, struct uio *, int,
63*0f1702c5SYu Xiangning struct cred *, caller_context_t *);
64*0f1702c5SYu Xiangning static int socket_vop_ioctl(struct vnode *, int, intptr_t, int,
65*0f1702c5SYu Xiangning struct cred *, int32_t *, caller_context_t *);
66*0f1702c5SYu Xiangning static int socket_vop_setfl(struct vnode *, int, int, cred_t *,
67*0f1702c5SYu Xiangning caller_context_t *);
68*0f1702c5SYu Xiangning static int socket_vop_getattr(struct vnode *, struct vattr *, int,
69*0f1702c5SYu Xiangning struct cred *, caller_context_t *);
70*0f1702c5SYu Xiangning static int socket_vop_setattr(struct vnode *, struct vattr *, int,
71*0f1702c5SYu Xiangning struct cred *, caller_context_t *);
72*0f1702c5SYu Xiangning static int socket_vop_access(struct vnode *, int, int, struct cred *,
73*0f1702c5SYu Xiangning caller_context_t *);
74*0f1702c5SYu Xiangning static int socket_vop_fsync(struct vnode *, int, struct cred *,
75*0f1702c5SYu Xiangning caller_context_t *);
76*0f1702c5SYu Xiangning static void socket_vop_inactive(struct vnode *, struct cred *,
77*0f1702c5SYu Xiangning caller_context_t *);
78*0f1702c5SYu Xiangning static int socket_vop_fid(struct vnode *, struct fid *,
79*0f1702c5SYu Xiangning caller_context_t *);
80*0f1702c5SYu Xiangning static int socket_vop_seek(struct vnode *, offset_t, offset_t *,
81*0f1702c5SYu Xiangning caller_context_t *);
82*0f1702c5SYu Xiangning static int socket_vop_poll(struct vnode *, short, int, short *,
83*0f1702c5SYu Xiangning struct pollhead **, caller_context_t *);
84*0f1702c5SYu Xiangning
85*0f1702c5SYu Xiangning extern int socket_close_internal(struct sonode *, int, cred_t *);
86*0f1702c5SYu Xiangning extern void socket_destroy_internal(struct sonode *, cred_t *);
87*0f1702c5SYu Xiangning
88*0f1702c5SYu Xiangning struct vnodeops *socket_vnodeops;
89*0f1702c5SYu Xiangning const fs_operation_def_t socket_vnodeops_template[] = {
90*0f1702c5SYu Xiangning VOPNAME_OPEN, { .vop_open = socket_vop_open },
91*0f1702c5SYu Xiangning VOPNAME_CLOSE, { .vop_close = socket_vop_close },
92*0f1702c5SYu Xiangning VOPNAME_READ, { .vop_read = socket_vop_read },
93*0f1702c5SYu Xiangning VOPNAME_WRITE, { .vop_write = socket_vop_write },
94*0f1702c5SYu Xiangning VOPNAME_IOCTL, { .vop_ioctl = socket_vop_ioctl },
95*0f1702c5SYu Xiangning VOPNAME_SETFL, { .vop_setfl = socket_vop_setfl },
96*0f1702c5SYu Xiangning VOPNAME_GETATTR, { .vop_getattr = socket_vop_getattr },
97*0f1702c5SYu Xiangning VOPNAME_SETATTR, { .vop_setattr = socket_vop_setattr },
98*0f1702c5SYu Xiangning VOPNAME_ACCESS, { .vop_access = socket_vop_access },
99*0f1702c5SYu Xiangning VOPNAME_FSYNC, { .vop_fsync = socket_vop_fsync },
100*0f1702c5SYu Xiangning VOPNAME_INACTIVE, { .vop_inactive = socket_vop_inactive },
101*0f1702c5SYu Xiangning VOPNAME_FID, { .vop_fid = socket_vop_fid },
102*0f1702c5SYu Xiangning VOPNAME_SEEK, { .vop_seek = socket_vop_seek },
103*0f1702c5SYu Xiangning VOPNAME_POLL, { .vop_poll = socket_vop_poll },
104*0f1702c5SYu Xiangning VOPNAME_DISPOSE, { .error = fs_error },
105*0f1702c5SYu Xiangning NULL, NULL
106*0f1702c5SYu Xiangning };
107*0f1702c5SYu Xiangning
108*0f1702c5SYu Xiangning
109*0f1702c5SYu Xiangning /*
110*0f1702c5SYu Xiangning * generic vnode ops
111*0f1702c5SYu Xiangning */
112*0f1702c5SYu Xiangning
113*0f1702c5SYu Xiangning /*ARGSUSED*/
114*0f1702c5SYu Xiangning static int
socket_vop_open(struct vnode ** vpp,int flag,struct cred * cr,caller_context_t * ct)115*0f1702c5SYu Xiangning socket_vop_open(struct vnode **vpp, int flag, struct cred *cr,
116*0f1702c5SYu Xiangning caller_context_t *ct)
117*0f1702c5SYu Xiangning {
118*0f1702c5SYu Xiangning struct vnode *vp = *vpp;
119*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
120*0f1702c5SYu Xiangning
121*0f1702c5SYu Xiangning flag &= ~FCREAT; /* paranoia */
122*0f1702c5SYu Xiangning mutex_enter(&so->so_lock);
123*0f1702c5SYu Xiangning so->so_count++;
124*0f1702c5SYu Xiangning mutex_exit(&so->so_lock);
125*0f1702c5SYu Xiangning
126*0f1702c5SYu Xiangning ASSERT(so->so_count != 0); /* wraparound */
127*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
128*0f1702c5SYu Xiangning
129*0f1702c5SYu Xiangning return (0);
130*0f1702c5SYu Xiangning }
131*0f1702c5SYu Xiangning
132*0f1702c5SYu Xiangning /*ARGSUSED*/
133*0f1702c5SYu Xiangning static int
socket_vop_close(struct vnode * vp,int flag,int count,offset_t offset,struct cred * cr,caller_context_t * ct)134*0f1702c5SYu Xiangning socket_vop_close(struct vnode *vp, int flag, int count, offset_t offset,
135*0f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
136*0f1702c5SYu Xiangning {
137*0f1702c5SYu Xiangning struct sonode *so;
138*0f1702c5SYu Xiangning int error = 0;
139*0f1702c5SYu Xiangning
140*0f1702c5SYu Xiangning so = VTOSO(vp);
141*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
142*0f1702c5SYu Xiangning
143*0f1702c5SYu Xiangning cleanlocks(vp, ttoproc(curthread)->p_pid, 0);
144*0f1702c5SYu Xiangning cleanshares(vp, ttoproc(curthread)->p_pid);
145*0f1702c5SYu Xiangning
146*0f1702c5SYu Xiangning if (vp->v_stream)
147*0f1702c5SYu Xiangning strclean(vp);
148*0f1702c5SYu Xiangning
149*0f1702c5SYu Xiangning if (count > 1) {
150*0f1702c5SYu Xiangning dprint(2, ("socket_vop_close: count %d\n", count));
151*0f1702c5SYu Xiangning return (0);
152*0f1702c5SYu Xiangning }
153*0f1702c5SYu Xiangning
154*0f1702c5SYu Xiangning mutex_enter(&so->so_lock);
155*0f1702c5SYu Xiangning if (--so->so_count == 0) {
156*0f1702c5SYu Xiangning /*
157*0f1702c5SYu Xiangning * Initiate connection shutdown.
158*0f1702c5SYu Xiangning */
159*0f1702c5SYu Xiangning mutex_exit(&so->so_lock);
160*0f1702c5SYu Xiangning error = socket_close_internal(so, flag, cr);
161*0f1702c5SYu Xiangning } else {
162*0f1702c5SYu Xiangning mutex_exit(&so->so_lock);
163*0f1702c5SYu Xiangning }
164*0f1702c5SYu Xiangning
165*0f1702c5SYu Xiangning return (error);
166*0f1702c5SYu Xiangning }
167*0f1702c5SYu Xiangning
168*0f1702c5SYu Xiangning /*ARGSUSED2*/
169*0f1702c5SYu Xiangning static int
socket_vop_read(struct vnode * vp,struct uio * uiop,int ioflag,struct cred * cr,caller_context_t * ct)170*0f1702c5SYu Xiangning socket_vop_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cr,
171*0f1702c5SYu Xiangning caller_context_t *ct)
172*0f1702c5SYu Xiangning {
173*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
174*0f1702c5SYu Xiangning struct nmsghdr lmsg;
175*0f1702c5SYu Xiangning
176*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
177*0f1702c5SYu Xiangning bzero((void *)&lmsg, sizeof (lmsg));
178*0f1702c5SYu Xiangning
179*0f1702c5SYu Xiangning return (socket_recvmsg(so, &lmsg, uiop, cr));
180*0f1702c5SYu Xiangning }
181*0f1702c5SYu Xiangning
182*0f1702c5SYu Xiangning /*ARGSUSED2*/
183*0f1702c5SYu Xiangning static int
socket_vop_write(struct vnode * vp,struct uio * uiop,int ioflag,struct cred * cr,caller_context_t * ct)184*0f1702c5SYu Xiangning socket_vop_write(struct vnode *vp, struct uio *uiop, int ioflag,
185*0f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
186*0f1702c5SYu Xiangning {
187*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
188*0f1702c5SYu Xiangning struct nmsghdr lmsg;
189*0f1702c5SYu Xiangning
190*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
191*0f1702c5SYu Xiangning bzero((void *)&lmsg, sizeof (lmsg));
192*0f1702c5SYu Xiangning
193*0f1702c5SYu Xiangning if (!(so->so_mode & SM_BYTESTREAM)) {
194*0f1702c5SYu Xiangning /*
195*0f1702c5SYu Xiangning * If the socket is not byte stream set MSG_EOR
196*0f1702c5SYu Xiangning */
197*0f1702c5SYu Xiangning lmsg.msg_flags = MSG_EOR;
198*0f1702c5SYu Xiangning }
199*0f1702c5SYu Xiangning
200*0f1702c5SYu Xiangning return (socket_sendmsg(so, &lmsg, uiop, cr));
201*0f1702c5SYu Xiangning }
202*0f1702c5SYu Xiangning
203*0f1702c5SYu Xiangning /*ARGSUSED4*/
204*0f1702c5SYu 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)205*0f1702c5SYu Xiangning socket_vop_ioctl(struct vnode *vp, int cmd, intptr_t arg, int mode,
206*0f1702c5SYu Xiangning struct cred *cr, int32_t *rvalp, caller_context_t *ct)
207*0f1702c5SYu Xiangning {
208*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
209*0f1702c5SYu Xiangning
210*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
211*0f1702c5SYu Xiangning
212*0f1702c5SYu Xiangning return (socket_ioctl(so, cmd, arg, mode, cr, rvalp));
213*0f1702c5SYu Xiangning }
214*0f1702c5SYu Xiangning
215*0f1702c5SYu Xiangning /*
216*0f1702c5SYu Xiangning * Allow any flags. Record FNDELAY and FNONBLOCK so that they can be inherited
217*0f1702c5SYu Xiangning * from listener to acceptor.
218*0f1702c5SYu Xiangning */
219*0f1702c5SYu Xiangning /* ARGSUSED */
220*0f1702c5SYu Xiangning static int
socket_vop_setfl(vnode_t * vp,int oflags,int nflags,cred_t * cr,caller_context_t * ct)221*0f1702c5SYu Xiangning socket_vop_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr,
222*0f1702c5SYu Xiangning caller_context_t *ct)
223*0f1702c5SYu Xiangning {
224*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
225*0f1702c5SYu Xiangning int error = 0;
226*0f1702c5SYu Xiangning
227*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
228*0f1702c5SYu Xiangning
229*0f1702c5SYu Xiangning mutex_enter(&so->so_lock);
230*0f1702c5SYu Xiangning if (nflags & FNDELAY)
231*0f1702c5SYu Xiangning so->so_state |= SS_NDELAY;
232*0f1702c5SYu Xiangning else
233*0f1702c5SYu Xiangning so->so_state &= ~SS_NDELAY;
234*0f1702c5SYu Xiangning if (nflags & FNONBLOCK)
235*0f1702c5SYu Xiangning so->so_state |= SS_NONBLOCK;
236*0f1702c5SYu Xiangning else
237*0f1702c5SYu Xiangning so->so_state &= ~SS_NONBLOCK;
238*0f1702c5SYu Xiangning mutex_exit(&so->so_lock);
239*0f1702c5SYu Xiangning
240*0f1702c5SYu Xiangning if (so->so_state & SS_ASYNC)
241*0f1702c5SYu Xiangning oflags |= FASYNC;
242*0f1702c5SYu Xiangning /*
243*0f1702c5SYu Xiangning * Sets/clears the SS_ASYNC flag based on the presence/absence
244*0f1702c5SYu Xiangning * of the FASYNC flag passed to fcntl(F_SETFL).
245*0f1702c5SYu Xiangning * This exists solely for BSD fcntl() FASYNC compatibility.
246*0f1702c5SYu Xiangning */
247*0f1702c5SYu Xiangning if ((oflags ^ nflags) & FASYNC && so->so_version != SOV_STREAM) {
248*0f1702c5SYu Xiangning int async = nflags & FASYNC;
249*0f1702c5SYu Xiangning int32_t rv;
250*0f1702c5SYu Xiangning
251*0f1702c5SYu Xiangning /*
252*0f1702c5SYu Xiangning * For non-TPI sockets all we have to do is set/remove the
253*0f1702c5SYu Xiangning * SS_ASYNC bit, but for TPI it is more involved. For that
254*0f1702c5SYu Xiangning * reason we delegate the job to the protocol's ioctl handler.
255*0f1702c5SYu Xiangning */
256*0f1702c5SYu Xiangning error = socket_ioctl(so, FIOASYNC, (intptr_t)&async, FKIOCTL,
257*0f1702c5SYu Xiangning cr, &rv);
258*0f1702c5SYu Xiangning }
259*0f1702c5SYu Xiangning return (error);
260*0f1702c5SYu Xiangning }
261*0f1702c5SYu Xiangning
262*0f1702c5SYu Xiangning
263*0f1702c5SYu Xiangning /*
264*0f1702c5SYu Xiangning * Get the made up attributes for the vnode.
265*0f1702c5SYu Xiangning * 4.3BSD returns the current time for all the timestamps.
266*0f1702c5SYu Xiangning * 4.4BSD returns 0 for all the timestamps.
267*0f1702c5SYu Xiangning * Here we use the access and modified times recorded in the sonode.
268*0f1702c5SYu Xiangning *
269*0f1702c5SYu Xiangning * Just like in BSD there is not effect on the underlying file system node
270*0f1702c5SYu Xiangning * bound to an AF_UNIX pathname.
271*0f1702c5SYu Xiangning *
272*0f1702c5SYu Xiangning * When sockmod has been popped this will act just like a stream. Since
273*0f1702c5SYu Xiangning * a socket is always a clone there is no need to inspect the attributes
274*0f1702c5SYu Xiangning * of the "realvp".
275*0f1702c5SYu Xiangning */
276*0f1702c5SYu Xiangning /* ARGSUSED */
277*0f1702c5SYu Xiangning int
socket_vop_getattr(struct vnode * vp,struct vattr * vap,int flags,struct cred * cr,caller_context_t * ct)278*0f1702c5SYu Xiangning socket_vop_getattr(struct vnode *vp, struct vattr *vap, int flags,
279*0f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
280*0f1702c5SYu Xiangning {
281*0f1702c5SYu Xiangning dev_t fsid;
282*0f1702c5SYu Xiangning struct sonode *so;
283*0f1702c5SYu Xiangning static int sonode_shift = 0;
284*0f1702c5SYu Xiangning
285*0f1702c5SYu Xiangning /*
286*0f1702c5SYu Xiangning * Calculate the amount of bitshift to a sonode pointer which will
287*0f1702c5SYu Xiangning * still keep it unique. See below.
288*0f1702c5SYu Xiangning */
289*0f1702c5SYu Xiangning if (sonode_shift == 0)
290*0f1702c5SYu Xiangning sonode_shift = highbit(sizeof (struct sonode));
291*0f1702c5SYu Xiangning ASSERT(sonode_shift > 0);
292*0f1702c5SYu Xiangning
293*0f1702c5SYu Xiangning so = VTOSO(vp);
294*0f1702c5SYu Xiangning fsid = sockdev;
295*0f1702c5SYu Xiangning
296*0f1702c5SYu Xiangning if (so->so_version == SOV_STREAM) {
297*0f1702c5SYu Xiangning /*
298*0f1702c5SYu Xiangning * The imaginary "sockmod" has been popped - act
299*0f1702c5SYu Xiangning * as a stream
300*0f1702c5SYu Xiangning */
301*0f1702c5SYu Xiangning vap->va_type = VCHR;
302*0f1702c5SYu Xiangning vap->va_mode = 0;
303*0f1702c5SYu Xiangning } else {
304*0f1702c5SYu Xiangning vap->va_type = vp->v_type;
305*0f1702c5SYu Xiangning vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
306*0f1702c5SYu Xiangning S_IROTH|S_IWOTH;
307*0f1702c5SYu Xiangning }
308*0f1702c5SYu Xiangning vap->va_uid = vap->va_gid = 0;
309*0f1702c5SYu Xiangning vap->va_fsid = fsid;
310*0f1702c5SYu Xiangning /*
311*0f1702c5SYu Xiangning * If the va_nodeid is > MAX_USHORT, then i386 stats might fail.
312*0f1702c5SYu Xiangning * So we shift down the sonode pointer to try and get the most
313*0f1702c5SYu Xiangning * uniqueness into 16-bits.
314*0f1702c5SYu Xiangning */
315*0f1702c5SYu Xiangning vap->va_nodeid = ((ino_t)so >> sonode_shift) & 0xFFFF;
316*0f1702c5SYu Xiangning vap->va_nlink = 0;
317*0f1702c5SYu Xiangning vap->va_size = 0;
318*0f1702c5SYu Xiangning
319*0f1702c5SYu Xiangning /*
320*0f1702c5SYu Xiangning * We need to zero out the va_rdev to avoid some fstats getting
321*0f1702c5SYu Xiangning * EOVERFLOW. This also mimics SunOS 4.x and BSD behavior.
322*0f1702c5SYu Xiangning */
323*0f1702c5SYu Xiangning vap->va_rdev = (dev_t)0;
324*0f1702c5SYu Xiangning vap->va_blksize = MAXBSIZE;
325*0f1702c5SYu Xiangning vap->va_nblocks = btod(vap->va_size);
326*0f1702c5SYu Xiangning
327*0f1702c5SYu Xiangning if (!SOCK_IS_NONSTR(so)) {
328*0f1702c5SYu Xiangning sotpi_info_t *sti = SOTOTPI(so);
329*0f1702c5SYu Xiangning
330*0f1702c5SYu Xiangning mutex_enter(&so->so_lock);
331*0f1702c5SYu Xiangning vap->va_atime.tv_sec = sti->sti_atime;
332*0f1702c5SYu Xiangning vap->va_mtime.tv_sec = sti->sti_mtime;
333*0f1702c5SYu Xiangning vap->va_ctime.tv_sec = sti->sti_ctime;
334*0f1702c5SYu Xiangning mutex_exit(&so->so_lock);
335*0f1702c5SYu Xiangning } else {
336*0f1702c5SYu Xiangning vap->va_atime.tv_sec = 0;
337*0f1702c5SYu Xiangning vap->va_mtime.tv_sec = 0;
338*0f1702c5SYu Xiangning vap->va_ctime.tv_sec = 0;
339*0f1702c5SYu Xiangning }
340*0f1702c5SYu Xiangning
341*0f1702c5SYu Xiangning vap->va_atime.tv_nsec = 0;
342*0f1702c5SYu Xiangning vap->va_mtime.tv_nsec = 0;
343*0f1702c5SYu Xiangning vap->va_ctime.tv_nsec = 0;
344*0f1702c5SYu Xiangning vap->va_seq = 0;
345*0f1702c5SYu Xiangning
346*0f1702c5SYu Xiangning return (0);
347*0f1702c5SYu Xiangning }
348*0f1702c5SYu Xiangning
349*0f1702c5SYu Xiangning /*
350*0f1702c5SYu Xiangning * Set attributes.
351*0f1702c5SYu Xiangning * Just like in BSD there is not effect on the underlying file system node
352*0f1702c5SYu Xiangning * bound to an AF_UNIX pathname.
353*0f1702c5SYu Xiangning *
354*0f1702c5SYu Xiangning * When sockmod has been popped this will act just like a stream. Since
355*0f1702c5SYu Xiangning * a socket is always a clone there is no need to modify the attributes
356*0f1702c5SYu Xiangning * of the "realvp".
357*0f1702c5SYu Xiangning */
358*0f1702c5SYu Xiangning /* ARGSUSED */
359*0f1702c5SYu Xiangning int
socket_vop_setattr(struct vnode * vp,struct vattr * vap,int flags,struct cred * cr,caller_context_t * ct)360*0f1702c5SYu Xiangning socket_vop_setattr(struct vnode *vp, struct vattr *vap, int flags,
361*0f1702c5SYu Xiangning struct cred *cr, caller_context_t *ct)
362*0f1702c5SYu Xiangning {
363*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
364*0f1702c5SYu Xiangning
365*0f1702c5SYu Xiangning /*
366*0f1702c5SYu Xiangning * If times were changed, and we have a STREAMS socket, then update
367*0f1702c5SYu Xiangning * the sonode.
368*0f1702c5SYu Xiangning */
369*0f1702c5SYu Xiangning if (!SOCK_IS_NONSTR(so)) {
370*0f1702c5SYu Xiangning sotpi_info_t *sti = SOTOTPI(so);
371*0f1702c5SYu Xiangning
372*0f1702c5SYu Xiangning mutex_enter(&so->so_lock);
373*0f1702c5SYu Xiangning if (vap->va_mask & AT_ATIME)
374*0f1702c5SYu Xiangning sti->sti_atime = vap->va_atime.tv_sec;
375*0f1702c5SYu Xiangning if (vap->va_mask & AT_MTIME) {
376*0f1702c5SYu Xiangning sti->sti_mtime = vap->va_mtime.tv_sec;
377*0f1702c5SYu Xiangning sti->sti_ctime = gethrestime_sec();
378*0f1702c5SYu Xiangning }
379*0f1702c5SYu Xiangning mutex_exit(&so->so_lock);
380*0f1702c5SYu Xiangning }
381*0f1702c5SYu Xiangning
382*0f1702c5SYu Xiangning return (0);
383*0f1702c5SYu Xiangning }
384*0f1702c5SYu Xiangning
385*0f1702c5SYu Xiangning /*
386*0f1702c5SYu Xiangning * Check if user is allowed to access vp. For non-STREAMS based sockets,
387*0f1702c5SYu Xiangning * there might not be a device attached to the file system. So for those
388*0f1702c5SYu Xiangning * types of sockets there are no permissions to check.
389*0f1702c5SYu Xiangning *
390*0f1702c5SYu Xiangning * XXX Should there be some other mechanism to check access rights?
391*0f1702c5SYu Xiangning */
392*0f1702c5SYu Xiangning /*ARGSUSED*/
393*0f1702c5SYu Xiangning int
socket_vop_access(struct vnode * vp,int mode,int flags,struct cred * cr,caller_context_t * ct)394*0f1702c5SYu Xiangning socket_vop_access(struct vnode *vp, int mode, int flags, struct cred *cr,
395*0f1702c5SYu Xiangning caller_context_t *ct)
396*0f1702c5SYu Xiangning {
397*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
398*0f1702c5SYu Xiangning
399*0f1702c5SYu Xiangning if (!SOCK_IS_NONSTR(so)) {
400*0f1702c5SYu Xiangning ASSERT(so->so_sockparams->sp_sdev_info.sd_vnode != NULL);
401*0f1702c5SYu Xiangning return (VOP_ACCESS(so->so_sockparams->sp_sdev_info.sd_vnode,
402*0f1702c5SYu Xiangning mode, flags, cr, NULL));
403*0f1702c5SYu Xiangning }
404*0f1702c5SYu Xiangning return (0);
405*0f1702c5SYu Xiangning }
406*0f1702c5SYu Xiangning
407*0f1702c5SYu Xiangning /*
408*0f1702c5SYu Xiangning * 4.3BSD and 4.4BSD fail a fsync on a socket with EINVAL.
409*0f1702c5SYu Xiangning * This code does the same to be compatible and also to not give an
410*0f1702c5SYu Xiangning * application the impression that the data has actually been "synced"
411*0f1702c5SYu Xiangning * to the other end of the connection.
412*0f1702c5SYu Xiangning */
413*0f1702c5SYu Xiangning /* ARGSUSED */
414*0f1702c5SYu Xiangning int
socket_vop_fsync(struct vnode * vp,int syncflag,struct cred * cr,caller_context_t * ct)415*0f1702c5SYu Xiangning socket_vop_fsync(struct vnode *vp, int syncflag, struct cred *cr,
416*0f1702c5SYu Xiangning caller_context_t *ct)
417*0f1702c5SYu Xiangning {
418*0f1702c5SYu Xiangning return (EINVAL);
419*0f1702c5SYu Xiangning }
420*0f1702c5SYu Xiangning
421*0f1702c5SYu Xiangning /*ARGSUSED*/
422*0f1702c5SYu Xiangning static void
socket_vop_inactive(struct vnode * vp,struct cred * cr,caller_context_t * ct)423*0f1702c5SYu Xiangning socket_vop_inactive(struct vnode *vp, struct cred *cr, caller_context_t *ct)
424*0f1702c5SYu Xiangning {
425*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
426*0f1702c5SYu Xiangning
427*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
428*0f1702c5SYu Xiangning
429*0f1702c5SYu Xiangning mutex_enter(&vp->v_lock);
430*0f1702c5SYu Xiangning /*
431*0f1702c5SYu Xiangning * If no one has reclaimed the vnode, remove from the
432*0f1702c5SYu Xiangning * cache now.
433*0f1702c5SYu Xiangning */
434*0f1702c5SYu Xiangning if (vp->v_count < 1)
435*0f1702c5SYu Xiangning cmn_err(CE_PANIC, "socket_inactive: Bad v_count");
436*0f1702c5SYu Xiangning
437*0f1702c5SYu Xiangning /*
438*0f1702c5SYu Xiangning * Drop the temporary hold by vn_rele now
439*0f1702c5SYu Xiangning */
440*0f1702c5SYu Xiangning if (--vp->v_count != 0) {
441*0f1702c5SYu Xiangning mutex_exit(&vp->v_lock);
442*0f1702c5SYu Xiangning return;
443*0f1702c5SYu Xiangning }
444*0f1702c5SYu Xiangning mutex_exit(&vp->v_lock);
445*0f1702c5SYu Xiangning
446*0f1702c5SYu Xiangning
447*0f1702c5SYu Xiangning ASSERT(!vn_has_cached_data(vp));
448*0f1702c5SYu Xiangning
449*0f1702c5SYu Xiangning /* socket specfic clean-up */
450*0f1702c5SYu Xiangning socket_destroy_internal(so, cr);
451*0f1702c5SYu Xiangning }
452*0f1702c5SYu Xiangning
453*0f1702c5SYu Xiangning /* ARGSUSED */
454*0f1702c5SYu Xiangning int
socket_vop_fid(struct vnode * vp,struct fid * fidp,caller_context_t * ct)455*0f1702c5SYu Xiangning socket_vop_fid(struct vnode *vp, struct fid *fidp, caller_context_t *ct)
456*0f1702c5SYu Xiangning {
457*0f1702c5SYu Xiangning return (EINVAL);
458*0f1702c5SYu Xiangning }
459*0f1702c5SYu Xiangning
460*0f1702c5SYu Xiangning /*
461*0f1702c5SYu Xiangning * Sockets are not seekable.
462*0f1702c5SYu Xiangning * (and there is a bug to fix STREAMS to make them fail this as well).
463*0f1702c5SYu Xiangning */
464*0f1702c5SYu Xiangning /*ARGSUSED*/
465*0f1702c5SYu Xiangning int
socket_vop_seek(struct vnode * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)466*0f1702c5SYu Xiangning socket_vop_seek(struct vnode *vp, offset_t ooff, offset_t *noffp,
467*0f1702c5SYu Xiangning caller_context_t *ct)
468*0f1702c5SYu Xiangning {
469*0f1702c5SYu Xiangning return (ESPIPE);
470*0f1702c5SYu Xiangning }
471*0f1702c5SYu Xiangning
472*0f1702c5SYu Xiangning /*ARGSUSED*/
473*0f1702c5SYu Xiangning static int
socket_vop_poll(struct vnode * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)474*0f1702c5SYu Xiangning socket_vop_poll(struct vnode *vp, short events, int anyyet, short *reventsp,
475*0f1702c5SYu Xiangning struct pollhead **phpp, caller_context_t *ct)
476*0f1702c5SYu Xiangning {
477*0f1702c5SYu Xiangning struct sonode *so = VTOSO(vp);
478*0f1702c5SYu Xiangning
479*0f1702c5SYu Xiangning ASSERT(vp->v_type == VSOCK);
480*0f1702c5SYu Xiangning
481*0f1702c5SYu Xiangning return (socket_poll(so, events, anyyet, reventsp, phpp));
482*0f1702c5SYu Xiangning }
483