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