4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright (c) 2017 by Delphix. All rights reserved.
30 #include <sys/types.h>
31 #include <sys/t_lock.h>
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bitmap.h>
35 #include <sys/debug.h>
36 #include <sys/errno.h>
37 #include <sys/strsubr.h>
38 #include <sys/cmn_err.h>
39 #include <sys/sysmacros.h>
40 #include <sys/filio.h>
41 #include <sys/flock.h>
43 #include <sys/share.h>
44 #include <sys/fs_subr.h>
48 #include <sys/sockio.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/strsun.h>
53 #include "sockcommon.h"
59 static int socket_vop_open(struct vnode
**, int, struct cred
*,
61 static int socket_vop_close(struct vnode
*, int, int, offset_t
,
62 struct cred
*, caller_context_t
*);
63 static int socket_vop_read(struct vnode
*, struct uio
*, int,
64 struct cred
*, caller_context_t
*);
65 static int socket_vop_write(struct vnode
*, struct uio
*, int,
66 struct cred
*, caller_context_t
*);
67 static int socket_vop_ioctl(struct vnode
*, int, intptr_t, int,
68 struct cred
*, int32_t *, caller_context_t
*);
69 static int socket_vop_setfl(struct vnode
*, int, int, cred_t
*,
71 static int socket_vop_getattr(struct vnode
*, struct vattr
*, int,
72 struct cred
*, caller_context_t
*);
73 static int socket_vop_setattr(struct vnode
*, struct vattr
*, int,
74 struct cred
*, caller_context_t
*);
75 static int socket_vop_access(struct vnode
*, int, int, struct cred
*,
77 static int socket_vop_fsync(struct vnode
*, int, struct cred
*,
79 static void socket_vop_inactive(struct vnode
*, struct cred
*,
81 static int socket_vop_fid(struct vnode
*, struct fid
*,
83 static int socket_vop_seek(struct vnode
*, offset_t
, offset_t
*,
85 static int socket_vop_poll(struct vnode
*, short, int, short *,
86 struct pollhead
**, caller_context_t
*);
88 extern int socket_close_internal(struct sonode
*, int, cred_t
*);
89 extern void socket_destroy_internal(struct sonode
*, cred_t
*);
91 const struct vnodeops socket_vnodeops
= {
92 .vnop_name
= "sockfs",
93 .vop_open
= socket_vop_open
,
94 .vop_close
= socket_vop_close
,
95 .vop_read
= socket_vop_read
,
96 .vop_write
= socket_vop_write
,
97 .vop_ioctl
= socket_vop_ioctl
,
98 .vop_setfl
= socket_vop_setfl
,
99 .vop_getattr
= socket_vop_getattr
,
100 .vop_setattr
= socket_vop_setattr
,
101 .vop_access
= socket_vop_access
,
102 .vop_fsync
= socket_vop_fsync
,
103 .vop_inactive
= socket_vop_inactive
,
104 .vop_fid
= socket_vop_fid
,
105 .vop_seek
= socket_vop_seek
,
106 .vop_poll
= socket_vop_poll
,
107 .vop_dispose
= fs_nodispose
,
117 socket_vop_open(struct vnode
**vpp
, int flag
, struct cred
*cr
,
118 caller_context_t
*ct
)
120 struct vnode
*vp
= *vpp
;
121 struct sonode
*so
= VTOSO(vp
);
123 flag
&= ~FCREAT
; /* paranoia */
124 mutex_enter(&so
->so_lock
);
126 mutex_exit(&so
->so_lock
);
128 ASSERT(so
->so_count
!= 0); /* wraparound */
129 ASSERT(vp
->v_type
== VSOCK
);
136 socket_vop_close(struct vnode
*vp
, int flag
, int count
, offset_t offset
,
137 struct cred
*cr
, caller_context_t
*ct
)
143 ASSERT(vp
->v_type
== VSOCK
);
145 cleanlocks(vp
, ttoproc(curthread
)->p_pid
, 0);
146 cleanshares(vp
, ttoproc(curthread
)->p_pid
);
152 dprint(2, ("socket_vop_close: count %d\n", count
));
156 mutex_enter(&so
->so_lock
);
157 if (--so
->so_count
== 0) {
159 * Initiate connection shutdown.
161 mutex_exit(&so
->so_lock
);
162 error
= socket_close_internal(so
, flag
, cr
);
164 mutex_exit(&so
->so_lock
);
172 socket_vop_read(struct vnode
*vp
, struct uio
*uiop
, int ioflag
, struct cred
*cr
,
173 caller_context_t
*ct
)
175 struct sonode
*so
= VTOSO(vp
);
178 ASSERT(vp
->v_type
== VSOCK
);
179 bzero((void *)&lmsg
, sizeof (lmsg
));
181 return (socket_recvmsg(so
, &lmsg
, uiop
, cr
));
186 socket_vop_write(struct vnode
*vp
, struct uio
*uiop
, int ioflag
,
187 struct cred
*cr
, caller_context_t
*ct
)
189 struct sonode
*so
= VTOSO(vp
);
192 ASSERT(vp
->v_type
== VSOCK
);
193 bzero((void *)&lmsg
, sizeof (lmsg
));
195 if (!(so
->so_mode
& SM_BYTESTREAM
)) {
197 * If the socket is not byte stream set MSG_EOR
199 lmsg
.msg_flags
= MSG_EOR
;
202 return (socket_sendmsg(so
, &lmsg
, uiop
, cr
));
207 socket_vop_ioctl(struct vnode
*vp
, int cmd
, intptr_t arg
, int mode
,
208 struct cred
*cr
, int32_t *rvalp
, caller_context_t
*ct
)
210 struct sonode
*so
= VTOSO(vp
);
212 ASSERT(vp
->v_type
== VSOCK
);
214 return (socket_ioctl(so
, cmd
, arg
, mode
, cr
, rvalp
));
218 * Allow any flags. Record FNDELAY and FNONBLOCK so that they can be inherited
219 * from listener to acceptor.
223 socket_vop_setfl(vnode_t
*vp
, int oflags
, int nflags
, cred_t
*cr
,
224 caller_context_t
*ct
)
226 struct sonode
*so
= VTOSO(vp
);
229 ASSERT(vp
->v_type
== VSOCK
);
231 mutex_enter(&so
->so_lock
);
232 if (nflags
& FNDELAY
)
233 so
->so_state
|= SS_NDELAY
;
235 so
->so_state
&= ~SS_NDELAY
;
236 if (nflags
& FNONBLOCK
)
237 so
->so_state
|= SS_NONBLOCK
;
239 so
->so_state
&= ~SS_NONBLOCK
;
240 mutex_exit(&so
->so_lock
);
242 if (so
->so_state
& SS_ASYNC
)
245 * Sets/clears the SS_ASYNC flag based on the presence/absence
246 * of the FASYNC flag passed to fcntl(F_SETFL).
247 * This exists solely for BSD fcntl() FASYNC compatibility.
249 if ((oflags
^ nflags
) & FASYNC
&& !so
->so_is_stream
) {
250 int async
= nflags
& FASYNC
;
254 * For non-TPI sockets all we have to do is set/remove the
255 * SS_ASYNC bit, but for TPI it is more involved. For that
256 * reason we delegate the job to the protocol's ioctl handler.
258 error
= socket_ioctl(so
, FIOASYNC
, (intptr_t)&async
, FKIOCTL
,
266 * Get the made up attributes for the vnode.
267 * 4.3BSD returns the current time for all the timestamps.
268 * 4.4BSD returns 0 for all the timestamps.
269 * Here we use the access and modified times recorded in the sonode.
271 * Just like in BSD there is not effect on the underlying file system node
272 * bound to an AF_UNIX pathname.
274 * When sockmod has been popped this will act just like a stream. Since
275 * a socket is always a clone there is no need to inspect the attributes
280 socket_vop_getattr(struct vnode
*vp
, struct vattr
*vap
, int flags
,
281 struct cred
*cr
, caller_context_t
*ct
)
285 static int sonode_shift
= 0;
288 * Calculate the amount of bitshift to a sonode pointer which will
289 * still keep it unique. See below.
291 if (sonode_shift
== 0)
292 sonode_shift
= highbit(sizeof (struct sonode
));
293 ASSERT(sonode_shift
> 0);
298 if (so
->so_is_stream
) {
300 * The imaginary "sockmod" has been popped - act
306 vap
->va_type
= vp
->v_type
;
307 vap
->va_mode
= S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|
310 vap
->va_uid
= vap
->va_gid
= 0;
313 * If the va_nodeid is > MAX_USHORT, then i386 stats might fail.
314 * So we shift down the sonode pointer to try and get the most
315 * uniqueness into 16-bits.
317 vap
->va_nodeid
= ((ino_t
)so
>> sonode_shift
) & 0xFFFF;
322 * We need to zero out the va_rdev to avoid some fstats getting
323 * EOVERFLOW. This also mimics SunOS 4.x and BSD behavior.
325 vap
->va_rdev
= (dev_t
)0;
326 vap
->va_blksize
= MAXBSIZE
;
327 vap
->va_nblocks
= btod(vap
->va_size
);
329 if (!SOCK_IS_NONSTR(so
)) {
330 sotpi_info_t
*sti
= SOTOTPI(so
);
332 mutex_enter(&so
->so_lock
);
333 vap
->va_atime
.tv_sec
= sti
->sti_atime
;
334 vap
->va_mtime
.tv_sec
= sti
->sti_mtime
;
335 vap
->va_ctime
.tv_sec
= sti
->sti_ctime
;
336 mutex_exit(&so
->so_lock
);
338 vap
->va_atime
.tv_sec
= 0;
339 vap
->va_mtime
.tv_sec
= 0;
340 vap
->va_ctime
.tv_sec
= 0;
343 vap
->va_atime
.tv_nsec
= 0;
344 vap
->va_mtime
.tv_nsec
= 0;
345 vap
->va_ctime
.tv_nsec
= 0;
353 * Just like in BSD there is not effect on the underlying file system node
354 * bound to an AF_UNIX pathname.
356 * When sockmod has been popped this will act just like a stream. Since
357 * a socket is always a clone there is no need to modify the attributes
362 socket_vop_setattr(struct vnode
*vp
, struct vattr
*vap
, int flags
,
363 struct cred
*cr
, caller_context_t
*ct
)
365 struct sonode
*so
= VTOSO(vp
);
368 * If times were changed, and we have a STREAMS socket, then update
371 if (!SOCK_IS_NONSTR(so
)) {
372 sotpi_info_t
*sti
= SOTOTPI(so
);
374 mutex_enter(&so
->so_lock
);
375 if (vap
->va_mask
& AT_ATIME
)
376 sti
->sti_atime
= vap
->va_atime
.tv_sec
;
377 if (vap
->va_mask
& AT_MTIME
) {
378 sti
->sti_mtime
= vap
->va_mtime
.tv_sec
;
379 sti
->sti_ctime
= gethrestime_sec();
381 mutex_exit(&so
->so_lock
);
388 * Check if user is allowed to access vp. For non-STREAMS based sockets,
389 * there might not be a device attached to the file system. So for those
390 * types of sockets there are no permissions to check.
392 * XXX Should there be some other mechanism to check access rights?
396 socket_vop_access(struct vnode
*vp
, int mode
, int flags
, struct cred
*cr
,
397 caller_context_t
*ct
)
399 struct sonode
*so
= VTOSO(vp
);
401 if (!SOCK_IS_NONSTR(so
)) {
402 ASSERT(so
->so_sockparams
->sp_sdev_info
.sd_vnode
!= NULL
);
403 return (fop_access(so
->so_sockparams
->sp_sdev_info
.sd_vnode
,
404 mode
, flags
, cr
, NULL
));
410 * 4.3BSD and 4.4BSD fail a fsync on a socket with EINVAL.
411 * This code does the same to be compatible and also to not give an
412 * application the impression that the data has actually been "synced"
413 * to the other end of the connection.
417 socket_vop_fsync(struct vnode
*vp
, int syncflag
, struct cred
*cr
,
418 caller_context_t
*ct
)
425 socket_vop_inactive(struct vnode
*vp
, struct cred
*cr
, caller_context_t
*ct
)
427 struct sonode
*so
= VTOSO(vp
);
429 ASSERT(vp
->v_type
== VSOCK
);
431 mutex_enter(&vp
->v_lock
);
433 * If no one has reclaimed the vnode, remove from the
437 cmn_err(CE_PANIC
, "socket_inactive: Bad v_count");
440 if (vp
->v_count
!= 0) {
441 mutex_exit(&vp
->v_lock
);
444 mutex_exit(&vp
->v_lock
);
447 ASSERT(!vn_has_cached_data(vp
));
449 /* socket specfic clean-up */
450 socket_destroy_internal(so
, cr
);
455 socket_vop_fid(struct vnode
*vp
, struct fid
*fidp
, caller_context_t
*ct
)
461 * Sockets are not seekable.
462 * (and there is a bug to fix STREAMS to make them fail this as well).
466 socket_vop_seek(struct vnode
*vp
, offset_t ooff
, offset_t
*noffp
,
467 caller_context_t
*ct
)
474 socket_vop_poll(struct vnode
*vp
, short events
, int anyyet
, short *reventsp
,
475 struct pollhead
**phpp
, caller_context_t
*ct
)
477 struct sonode
*so
= VTOSO(vp
);
479 ASSERT(vp
->v_type
== VSOCK
);
481 return (socket_poll(so
, events
, anyyet
, reventsp
, phpp
));