1b819cea2SGordon Ross /*
2b819cea2SGordon Ross * CDDL HEADER START
3b819cea2SGordon Ross *
4b819cea2SGordon Ross * The contents of this file are subject to the terms of the
5b819cea2SGordon Ross * Common Development and Distribution License (the "License").
6b819cea2SGordon Ross * You may not use this file except in compliance with the License.
7b819cea2SGordon Ross *
8b819cea2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9b819cea2SGordon Ross * or http://www.opensolaris.org/os/licensing.
10b819cea2SGordon Ross * See the License for the specific language governing permissions
11b819cea2SGordon Ross * and limitations under the License.
12b819cea2SGordon Ross *
13b819cea2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14b819cea2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15b819cea2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16b819cea2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17b819cea2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18b819cea2SGordon Ross *
19b819cea2SGordon Ross * CDDL HEADER END
20b819cea2SGordon Ross */
21b819cea2SGordon Ross
22b819cea2SGordon Ross /*
23b819cea2SGordon Ross * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24*68b2bbf2SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25b819cea2SGordon Ross */
26b819cea2SGordon Ross
27b819cea2SGordon Ross #include <sys/types.h>
28b819cea2SGordon Ross #include <sys/systm.h>
29b819cea2SGordon Ross #include <sys/cred.h>
30b819cea2SGordon Ross #include <sys/errno.h>
31b819cea2SGordon Ross #include <sys/socket.h>
32b819cea2SGordon Ross #include <sys/ksocket.h>
33b819cea2SGordon Ross #include <sys/debug.h>
34b819cea2SGordon Ross #include <sys/kmem.h>
35b819cea2SGordon Ross #include <unistd.h>
36b819cea2SGordon Ross #include <errno.h>
37b819cea2SGordon Ross #include <umem.h>
38b819cea2SGordon Ross
39b819cea2SGordon Ross #define _KSOCKET_MAGIC 0xabcdef09
40b819cea2SGordon Ross
41b819cea2SGordon Ross #define KSOCKET_VALID(ks) (ks->kso_magic == _KSOCKET_MAGIC)
42b819cea2SGordon Ross #define KSTOSO(ks) (ks->kso_fd)
43b819cea2SGordon Ross
44b819cea2SGordon Ross #ifndef SS_CLOSING
45b819cea2SGordon Ross #define SS_CLOSING 0x00010000
46b819cea2SGordon Ross #endif
47b819cea2SGordon Ross
48b819cea2SGordon Ross /*
49b819cea2SGordon Ross * NB: you can't cast this into a sonode like you can with a normal
50b819cea2SGordon Ross * ksocket_t, but no correct code should ever do that anyway.
51b819cea2SGordon Ross * The ksocket_t type is opaque to prevent exactly that.
52b819cea2SGordon Ross */
53b819cea2SGordon Ross struct __ksocket {
54b819cea2SGordon Ross uint32_t kso_magic;
55b819cea2SGordon Ross uint32_t kso_count;
56b819cea2SGordon Ross uint32_t kso_state;
57b819cea2SGordon Ross int kso_fd;
58b819cea2SGordon Ross kmutex_t kso_lock;
59b819cea2SGordon Ross kcondvar_t kso_closing_cv;
60b819cea2SGordon Ross };
61b819cea2SGordon Ross
62b819cea2SGordon Ross static umem_cache_t *ksocket_cache = NULL;
63b819cea2SGordon Ross
64b819cea2SGordon Ross /*ARGSUSED*/
65b819cea2SGordon Ross static int
_ksocket_ctor(void * buf,void * arg,int flags)66b819cea2SGordon Ross _ksocket_ctor(void *buf, void *arg, int flags)
67b819cea2SGordon Ross {
68b819cea2SGordon Ross ksocket_t sock = buf;
69b819cea2SGordon Ross
70b819cea2SGordon Ross bzero(sock, sizeof (*sock));
71b819cea2SGordon Ross mutex_init(&sock->kso_lock, NULL, MUTEX_DEFAULT, NULL);
72b819cea2SGordon Ross cv_init(&sock->kso_closing_cv, NULL, CV_DEFAULT, NULL);
73b819cea2SGordon Ross return (0);
74b819cea2SGordon Ross }
75b819cea2SGordon Ross
76b819cea2SGordon Ross /*ARGSUSED*/
77b819cea2SGordon Ross static void
_ksocket_dtor(void * buf,void * arg)78b819cea2SGordon Ross _ksocket_dtor(void *buf, void *arg)
79b819cea2SGordon Ross {
80b819cea2SGordon Ross ksocket_t sock = buf;
81b819cea2SGordon Ross
82b819cea2SGordon Ross mutex_destroy(&sock->kso_lock);
83b819cea2SGordon Ross cv_destroy(&sock->kso_closing_cv);
84b819cea2SGordon Ross }
85b819cea2SGordon Ross
86b819cea2SGordon Ross #pragma init(_ksocket_init)
87b819cea2SGordon Ross int
_ksocket_init(void)88b819cea2SGordon Ross _ksocket_init(void)
89b819cea2SGordon Ross {
90b819cea2SGordon Ross ksocket_cache = umem_cache_create("ksocket",
91b819cea2SGordon Ross sizeof (struct __ksocket), 0,
92b819cea2SGordon Ross _ksocket_ctor, _ksocket_dtor, NULL, NULL, NULL, 0);
93b819cea2SGordon Ross VERIFY(ksocket_cache != NULL);
94b819cea2SGordon Ross return (0);
95b819cea2SGordon Ross }
96b819cea2SGordon Ross
97b819cea2SGordon Ross #pragma fini(_ksocket_fini)
98b819cea2SGordon Ross int
_ksocket_fini(void)99b819cea2SGordon Ross _ksocket_fini(void)
100b819cea2SGordon Ross {
101b819cea2SGordon Ross umem_cache_destroy(ksocket_cache);
102b819cea2SGordon Ross return (0);
103b819cea2SGordon Ross }
104b819cea2SGordon Ross
105b819cea2SGordon Ross static ksocket_t
_ksocket_create(int fd)106b819cea2SGordon Ross _ksocket_create(int fd)
107b819cea2SGordon Ross {
108b819cea2SGordon Ross ksocket_t ks;
109b819cea2SGordon Ross
110b819cea2SGordon Ross ks = umem_cache_alloc(ksocket_cache, 0);
111b819cea2SGordon Ross VERIFY(ks != NULL);
112b819cea2SGordon Ross ks->kso_magic = _KSOCKET_MAGIC;
113b819cea2SGordon Ross ks->kso_count = 1;
114b819cea2SGordon Ross ks->kso_fd = fd;
115b819cea2SGordon Ross return (ks);
116b819cea2SGordon Ross }
117b819cea2SGordon Ross
118b819cea2SGordon Ross static void
_ksocket_destroy(ksocket_t ks)119b819cea2SGordon Ross _ksocket_destroy(ksocket_t ks)
120b819cea2SGordon Ross {
121b819cea2SGordon Ross ASSERT(ks->kso_count == 1);
122b819cea2SGordon Ross umem_cache_free(ksocket_cache, ks);
123b819cea2SGordon Ross }
124b819cea2SGordon Ross
125b819cea2SGordon Ross int
ksocket_socket(ksocket_t * ksp,int domain,int type,int protocol,int flags,struct cred * cr)126b819cea2SGordon Ross ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
127b819cea2SGordon Ross struct cred *cr)
128b819cea2SGordon Ross {
129b819cea2SGordon Ross int fd;
130b819cea2SGordon Ross ksocket_t ks;
131b819cea2SGordon Ross
132b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
133b819cea2SGordon Ross ASSERT(cr != NULL);
134b819cea2SGordon Ross
135b819cea2SGordon Ross ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
136b819cea2SGordon Ross
137b819cea2SGordon Ross fd = socket(domain, type, protocol);
138b819cea2SGordon Ross if (fd < 0) {
139b819cea2SGordon Ross *ksp = NULL;
140b819cea2SGordon Ross return (errno);
141b819cea2SGordon Ross }
142b819cea2SGordon Ross
143b819cea2SGordon Ross ks = _ksocket_create(fd);
144b819cea2SGordon Ross *ksp = ks;
145b819cea2SGordon Ross return (0);
146b819cea2SGordon Ross }
147b819cea2SGordon Ross
148b819cea2SGordon Ross /*
149b819cea2SGordon Ross * This is marked NODIRECT so the main program linking with this library
150b819cea2SGordon Ross * can provide its own "bind helper" function. See: fksmbd_ksock.c
151b819cea2SGordon Ross */
152b819cea2SGordon Ross /* ARGSUSED */
153b819cea2SGordon Ross int
ksocket_bind_helper(int fd,struct sockaddr * addr,uint_t addrlen)154b819cea2SGordon Ross ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen)
155b819cea2SGordon Ross {
156b819cea2SGordon Ross return (EACCES);
157b819cea2SGordon Ross }
158b819cea2SGordon Ross
159b819cea2SGordon Ross int
ksocket_bind(ksocket_t ks,struct sockaddr * addr,socklen_t addrlen,struct cred * cr)160b819cea2SGordon Ross ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
161b819cea2SGordon Ross struct cred *cr)
162b819cea2SGordon Ross {
163b819cea2SGordon Ross int err = 0;
164b819cea2SGordon Ross
165b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
166b819cea2SGordon Ross ASSERT(cr != NULL);
167b819cea2SGordon Ross
168b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
169b819cea2SGordon Ross return (ENOTSOCK);
170b819cea2SGordon Ross
171b819cea2SGordon Ross if (bind(KSTOSO(ks), addr, addrlen) != 0)
172b819cea2SGordon Ross err = errno;
173b819cea2SGordon Ross
174b819cea2SGordon Ross if (err == EACCES) {
175b819cea2SGordon Ross err = ksocket_bind_helper(KSTOSO(ks), addr, addrlen);
176b819cea2SGordon Ross }
177b819cea2SGordon Ross
178b819cea2SGordon Ross return (err);
179b819cea2SGordon Ross }
180b819cea2SGordon Ross
181b819cea2SGordon Ross int
ksocket_listen(ksocket_t ks,int backlog,struct cred * cr)182b819cea2SGordon Ross ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
183b819cea2SGordon Ross {
184b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
185b819cea2SGordon Ross ASSERT(cr != NULL);
186b819cea2SGordon Ross
187b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
188b819cea2SGordon Ross return (ENOTSOCK);
189b819cea2SGordon Ross
190b819cea2SGordon Ross if (listen(KSTOSO(ks), backlog) != 0)
191b819cea2SGordon Ross return (errno);
192b819cea2SGordon Ross
193b819cea2SGordon Ross return (0);
194b819cea2SGordon Ross }
195b819cea2SGordon Ross
196b819cea2SGordon Ross int
ksocket_accept(ksocket_t ks,struct sockaddr * addr,socklen_t * addrlenp,ksocket_t * nks,struct cred * cr)197b819cea2SGordon Ross ksocket_accept(ksocket_t ks, struct sockaddr *addr,
198b819cea2SGordon Ross socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
199b819cea2SGordon Ross {
200b819cea2SGordon Ross int fd;
201b819cea2SGordon Ross
202b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
203b819cea2SGordon Ross ASSERT(cr != NULL);
204b819cea2SGordon Ross
205b819cea2SGordon Ross *nks = NULL;
206b819cea2SGordon Ross
207b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
208b819cea2SGordon Ross return (ENOTSOCK);
209b819cea2SGordon Ross
210b819cea2SGordon Ross if (addr != NULL && addrlenp == NULL)
211b819cea2SGordon Ross return (EFAULT);
212b819cea2SGordon Ross
213b819cea2SGordon Ross fd = accept(KSTOSO(ks), addr, addrlenp);
214b819cea2SGordon Ross if (fd < 0)
215b819cea2SGordon Ross return (errno);
216b819cea2SGordon Ross
217b819cea2SGordon Ross *nks = _ksocket_create(fd);
218b819cea2SGordon Ross
219b819cea2SGordon Ross return (0);
220b819cea2SGordon Ross }
221b819cea2SGordon Ross
222b819cea2SGordon Ross int
ksocket_connect(ksocket_t ks,struct sockaddr * addr,socklen_t addrlen,struct cred * cr)223b819cea2SGordon Ross ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
224b819cea2SGordon Ross struct cred *cr)
225b819cea2SGordon Ross {
226b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
227b819cea2SGordon Ross ASSERT(cr != NULL);
228b819cea2SGordon Ross
229b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
230b819cea2SGordon Ross return (ENOTSOCK);
231b819cea2SGordon Ross
232b819cea2SGordon Ross if (connect(KSTOSO(ks), addr, addrlen) != 0)
233b819cea2SGordon Ross return (errno);
234b819cea2SGordon Ross
235b819cea2SGordon Ross return (0);
236b819cea2SGordon Ross }
237b819cea2SGordon Ross
238b819cea2SGordon Ross int
ksocket_send(ksocket_t ks,void * msg,size_t msglen,int flags,size_t * sent,struct cred * cr)239b819cea2SGordon Ross ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
240b819cea2SGordon Ross size_t *sent, struct cred *cr)
241b819cea2SGordon Ross {
242b819cea2SGordon Ross ssize_t error;
243b819cea2SGordon Ross
244b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
245b819cea2SGordon Ross ASSERT(cr != NULL);
246b819cea2SGordon Ross
247b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
248b819cea2SGordon Ross if (sent != NULL)
249b819cea2SGordon Ross *sent = 0;
250b819cea2SGordon Ross return (ENOTSOCK);
251b819cea2SGordon Ross }
252b819cea2SGordon Ross
253b819cea2SGordon Ross error = send(KSTOSO(ks), msg, msglen, flags);
254b819cea2SGordon Ross if (error < 0) {
255b819cea2SGordon Ross if (sent != NULL)
256b819cea2SGordon Ross *sent = 0;
257b819cea2SGordon Ross return (errno);
258b819cea2SGordon Ross }
259b819cea2SGordon Ross
260b819cea2SGordon Ross if (sent != NULL)
261b819cea2SGordon Ross *sent = (size_t)error;
262b819cea2SGordon Ross return (0);
263b819cea2SGordon Ross }
264b819cea2SGordon Ross
265b819cea2SGordon Ross int
ksocket_sendto(ksocket_t ks,void * msg,size_t msglen,int flags,struct sockaddr * name,socklen_t namelen,size_t * sent,struct cred * cr)266b819cea2SGordon Ross ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
267b819cea2SGordon Ross struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
268b819cea2SGordon Ross {
269b819cea2SGordon Ross ssize_t error;
270b819cea2SGordon Ross
271b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
272b819cea2SGordon Ross ASSERT(cr != NULL);
273b819cea2SGordon Ross
274b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
275b819cea2SGordon Ross if (sent != NULL)
276b819cea2SGordon Ross *sent = 0;
277b819cea2SGordon Ross return (ENOTSOCK);
278b819cea2SGordon Ross }
279b819cea2SGordon Ross
280b819cea2SGordon Ross error = sendto(KSTOSO(ks), msg, msglen, flags, name, namelen);
281b819cea2SGordon Ross if (error < 0) {
282b819cea2SGordon Ross if (sent != NULL)
283b819cea2SGordon Ross *sent = 0;
284b819cea2SGordon Ross return (errno);
285b819cea2SGordon Ross }
286b819cea2SGordon Ross
287b819cea2SGordon Ross if (sent != NULL)
288b819cea2SGordon Ross *sent = (size_t)error;
289b819cea2SGordon Ross return (0);
290b819cea2SGordon Ross }
291b819cea2SGordon Ross
292b819cea2SGordon Ross int
ksocket_sendmsg(ksocket_t ks,struct nmsghdr * msg,int flags,size_t * sent,struct cred * cr)293b819cea2SGordon Ross ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags,
294b819cea2SGordon Ross size_t *sent, struct cred *cr)
295b819cea2SGordon Ross {
296b819cea2SGordon Ross ssize_t error;
297b819cea2SGordon Ross
298b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
299b819cea2SGordon Ross ASSERT(cr != NULL);
300b819cea2SGordon Ross
301b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
302b819cea2SGordon Ross if (sent != NULL)
303b819cea2SGordon Ross *sent = 0;
304b819cea2SGordon Ross return (ENOTSOCK);
305b819cea2SGordon Ross }
306b819cea2SGordon Ross
307b819cea2SGordon Ross error = sendmsg(KSTOSO(ks), msg, flags);
308b819cea2SGordon Ross if (error < 0) {
309b819cea2SGordon Ross if (sent != NULL)
310b819cea2SGordon Ross *sent = 0;
311b819cea2SGordon Ross return (errno);
312b819cea2SGordon Ross }
313b819cea2SGordon Ross
314b819cea2SGordon Ross if (sent != NULL)
315b819cea2SGordon Ross *sent = (size_t)error;
316b819cea2SGordon Ross return (0);
317b819cea2SGordon Ross }
318b819cea2SGordon Ross
319b819cea2SGordon Ross int
ksocket_recv(ksocket_t ks,void * msg,size_t msglen,int flags,size_t * recvd,struct cred * cr)320b819cea2SGordon Ross ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
321b819cea2SGordon Ross size_t *recvd, struct cred *cr)
322b819cea2SGordon Ross {
323b819cea2SGordon Ross ssize_t error;
324b819cea2SGordon Ross
325b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
326b819cea2SGordon Ross ASSERT(cr != NULL);
327b819cea2SGordon Ross
328b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
329b819cea2SGordon Ross if (recvd != NULL)
330b819cea2SGordon Ross *recvd = 0;
331b819cea2SGordon Ross return (ENOTSOCK);
332b819cea2SGordon Ross }
333b819cea2SGordon Ross
334b819cea2SGordon Ross error = recv(KSTOSO(ks), msg, msglen, flags);
335b819cea2SGordon Ross if (error < 0) {
336b819cea2SGordon Ross if (recvd != NULL)
337b819cea2SGordon Ross *recvd = 0;
338b819cea2SGordon Ross return (errno);
339b819cea2SGordon Ross }
340b819cea2SGordon Ross
341b819cea2SGordon Ross if (recvd != NULL)
342b819cea2SGordon Ross *recvd = (size_t)error;
343b819cea2SGordon Ross return (0);
344b819cea2SGordon Ross }
345b819cea2SGordon Ross
346b819cea2SGordon Ross int
ksocket_recvfrom(ksocket_t ks,void * msg,size_t msglen,int flags,struct sockaddr * name,socklen_t * namelen,size_t * recvd,struct cred * cr)347b819cea2SGordon Ross ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
348b819cea2SGordon Ross struct sockaddr *name, socklen_t *namelen, size_t *recvd, struct cred *cr)
349b819cea2SGordon Ross {
350b819cea2SGordon Ross ssize_t error;
351b819cea2SGordon Ross
352b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
353b819cea2SGordon Ross ASSERT(cr != NULL);
354b819cea2SGordon Ross
355b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
356b819cea2SGordon Ross if (recvd != NULL)
357b819cea2SGordon Ross *recvd = 0;
358b819cea2SGordon Ross return (ENOTSOCK);
359b819cea2SGordon Ross }
360b819cea2SGordon Ross
361b819cea2SGordon Ross error = recvfrom(KSTOSO(ks), msg, msglen, flags, name, namelen);
362b819cea2SGordon Ross if (error != 0) {
363b819cea2SGordon Ross if (recvd != NULL)
364b819cea2SGordon Ross *recvd = 0;
365b819cea2SGordon Ross return (errno);
366b819cea2SGordon Ross }
367b819cea2SGordon Ross
368b819cea2SGordon Ross if (recvd != NULL)
369b819cea2SGordon Ross *recvd = (ssize_t)error;
370b819cea2SGordon Ross return (0);
371b819cea2SGordon Ross }
372b819cea2SGordon Ross
373b819cea2SGordon Ross int
ksocket_recvmsg(ksocket_t ks,struct nmsghdr * msg,int flags,size_t * recvd,struct cred * cr)374b819cea2SGordon Ross ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recvd,
375b819cea2SGordon Ross struct cred *cr)
376b819cea2SGordon Ross {
377b819cea2SGordon Ross ssize_t error;
378b819cea2SGordon Ross
379b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
380b819cea2SGordon Ross ASSERT(cr != NULL);
381b819cea2SGordon Ross
382b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
383b819cea2SGordon Ross if (recvd != NULL)
384b819cea2SGordon Ross *recvd = 0;
385b819cea2SGordon Ross return (ENOTSOCK);
386b819cea2SGordon Ross }
387b819cea2SGordon Ross
388b819cea2SGordon Ross error = recvmsg(KSTOSO(ks), msg, flags);
389b819cea2SGordon Ross if (error < 0) {
390b819cea2SGordon Ross if (recvd != NULL)
391b819cea2SGordon Ross *recvd = 0;
392b819cea2SGordon Ross return (errno);
393b819cea2SGordon Ross }
394b819cea2SGordon Ross
395b819cea2SGordon Ross if (recvd != NULL)
396b819cea2SGordon Ross *recvd = (size_t)error;
397b819cea2SGordon Ross return (0);
398b819cea2SGordon Ross }
399b819cea2SGordon Ross
400b819cea2SGordon Ross int
ksocket_shutdown(ksocket_t ks,int how,struct cred * cr)401b819cea2SGordon Ross ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
402b819cea2SGordon Ross {
403b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
404b819cea2SGordon Ross ASSERT(cr != NULL);
405b819cea2SGordon Ross
406b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
407b819cea2SGordon Ross return (ENOTSOCK);
408b819cea2SGordon Ross
409b819cea2SGordon Ross if (shutdown(KSTOSO(ks), how) != 0)
410b819cea2SGordon Ross return (errno);
411b819cea2SGordon Ross
412b819cea2SGordon Ross return (0);
413b819cea2SGordon Ross }
414b819cea2SGordon Ross
415b819cea2SGordon Ross int
ksocket_close(ksocket_t ks,struct cred * cr)416b819cea2SGordon Ross ksocket_close(ksocket_t ks, struct cred *cr)
417b819cea2SGordon Ross {
418b819cea2SGordon Ross int fd;
419b819cea2SGordon Ross
420b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
421b819cea2SGordon Ross ASSERT(cr != NULL);
422b819cea2SGordon Ross
423b819cea2SGordon Ross mutex_enter(&ks->kso_lock);
424b819cea2SGordon Ross
425b819cea2SGordon Ross if (!KSOCKET_VALID(ks)) {
426b819cea2SGordon Ross mutex_exit(&ks->kso_lock);
427b819cea2SGordon Ross return (ENOTSOCK);
428b819cea2SGordon Ross }
429b819cea2SGordon Ross
430b819cea2SGordon Ross ks->kso_state |= SS_CLOSING;
431b819cea2SGordon Ross
432b819cea2SGordon Ross /*
433b819cea2SGordon Ross * The real ksocket wakes up everything.
434b819cea2SGordon Ross * It seems the only way we can do that
435b819cea2SGordon Ross * is to go ahead and close the FD.
436b819cea2SGordon Ross */
437b819cea2SGordon Ross fd = ks->kso_fd;
438b819cea2SGordon Ross ks->kso_fd = -1;
439b819cea2SGordon Ross (void) close(fd);
440b819cea2SGordon Ross
441b819cea2SGordon Ross while (ks->kso_count > 1)
442b819cea2SGordon Ross cv_wait(&ks->kso_closing_cv, &ks->kso_lock);
443b819cea2SGordon Ross
444b819cea2SGordon Ross mutex_exit(&ks->kso_lock);
445b819cea2SGordon Ross _ksocket_destroy(ks);
446b819cea2SGordon Ross
447b819cea2SGordon Ross return (0);
448b819cea2SGordon Ross }
449b819cea2SGordon Ross
450b819cea2SGordon Ross int
ksocket_getsockname(ksocket_t ks,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)451b819cea2SGordon Ross ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
452b819cea2SGordon Ross struct cred *cr)
453b819cea2SGordon Ross {
454b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
455b819cea2SGordon Ross ASSERT(cr != NULL);
456b819cea2SGordon Ross
457b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
458b819cea2SGordon Ross return (ENOTSOCK);
459b819cea2SGordon Ross
460b819cea2SGordon Ross if (addrlen == NULL || (addr == NULL && *addrlen != 0))
461b819cea2SGordon Ross return (EFAULT);
462b819cea2SGordon Ross
463b819cea2SGordon Ross if (getsockname(KSTOSO(ks), addr, addrlen) != 0)
464b819cea2SGordon Ross return (errno);
465b819cea2SGordon Ross
466b819cea2SGordon Ross return (0);
467b819cea2SGordon Ross }
468b819cea2SGordon Ross
469b819cea2SGordon Ross int
ksocket_getpeername(ksocket_t ks,struct sockaddr * addr,socklen_t * addrlen,struct cred * cr)470b819cea2SGordon Ross ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
471b819cea2SGordon Ross struct cred *cr)
472b819cea2SGordon Ross {
473b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
474b819cea2SGordon Ross ASSERT(cr != NULL);
475b819cea2SGordon Ross
476b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
477b819cea2SGordon Ross return (ENOTSOCK);
478b819cea2SGordon Ross
479b819cea2SGordon Ross if (addrlen == NULL || (addr == NULL && *addrlen != 0))
480b819cea2SGordon Ross return (EFAULT);
481b819cea2SGordon Ross
482b819cea2SGordon Ross if (getpeername(KSTOSO(ks), addr, addrlen) != 0)
483b819cea2SGordon Ross return (errno);
484b819cea2SGordon Ross
485b819cea2SGordon Ross return (0);
486b819cea2SGordon Ross }
487b819cea2SGordon Ross
488b819cea2SGordon Ross int
ksocket_setsockopt(ksocket_t ks,int level,int optname,const void * optval,int optlen,struct cred * cr)489b819cea2SGordon Ross ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
490b819cea2SGordon Ross int optlen, struct cred *cr)
491b819cea2SGordon Ross {
492b819cea2SGordon Ross /* All Solaris components should pass a cred for this operation. */
493b819cea2SGordon Ross ASSERT(cr != NULL);
494b819cea2SGordon Ross
495b819cea2SGordon Ross if (!KSOCKET_VALID(ks))
496b819cea2SGordon Ross return (ENOTSOCK);
497b819cea2SGordon Ross
498b819cea2SGordon Ross if (optval == NULL)
499b819cea2SGordon Ross optlen = 0;
500b819cea2SGordon Ross
501b819cea2SGordon Ross if (setsockopt(KSTOSO(ks), level, optname, optval, optlen) != 0)
502b819cea2SGordon Ross return (errno);
503b819cea2SGordon Ross
504b819cea2SGordon Ross return (0);
505b819cea2SGordon Ross }
506b819cea2SGordon Ross
507*68b2bbf2SGordon Ross int
ksocket_ioctl(ksocket_t ks,int cmd,intptr_t arg,int * rvp,struct cred * cr)508*68b2bbf2SGordon Ross ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvp, struct cred *cr)
509*68b2bbf2SGordon Ross {
510*68b2bbf2SGordon Ross int rval;
511*68b2bbf2SGordon Ross
512*68b2bbf2SGordon Ross /* All Solaris components should pass a cred for this operation. */
513*68b2bbf2SGordon Ross ASSERT(cr != NULL);
514*68b2bbf2SGordon Ross
515*68b2bbf2SGordon Ross if (!KSOCKET_VALID(ks))
516*68b2bbf2SGordon Ross return (ENOTSOCK);
517*68b2bbf2SGordon Ross
518*68b2bbf2SGordon Ross rval = ioctl(KSTOSO(ks), cmd, arg);
519*68b2bbf2SGordon Ross if (rvp != NULL)
520*68b2bbf2SGordon Ross *rvp = rval;
521*68b2bbf2SGordon Ross
522*68b2bbf2SGordon Ross if (rval != 0)
523*68b2bbf2SGordon Ross rval = errno;
524*68b2bbf2SGordon Ross
525*68b2bbf2SGordon Ross return (rval);
526*68b2bbf2SGordon Ross }
527*68b2bbf2SGordon Ross
528b819cea2SGordon Ross void
ksocket_hold(ksocket_t ks)529b819cea2SGordon Ross ksocket_hold(ksocket_t ks)
530b819cea2SGordon Ross {
531b819cea2SGordon Ross if (!mutex_owned(&ks->kso_lock)) {
532b819cea2SGordon Ross mutex_enter(&ks->kso_lock);
533b819cea2SGordon Ross ks->kso_count++;
534b819cea2SGordon Ross mutex_exit(&ks->kso_lock);
535b819cea2SGordon Ross } else
536b819cea2SGordon Ross ks->kso_count++;
537b819cea2SGordon Ross }
538b819cea2SGordon Ross
539b819cea2SGordon Ross void
ksocket_rele(ksocket_t ks)540b819cea2SGordon Ross ksocket_rele(ksocket_t ks)
541b819cea2SGordon Ross {
542b819cea2SGordon Ross /*
543b819cea2SGordon Ross * When so_count equals 1 means no thread working on this ksocket
544b819cea2SGordon Ross */
545b819cea2SGordon Ross VERIFY3U(ks->kso_count, >, 1);
546b819cea2SGordon Ross
547b819cea2SGordon Ross if (!mutex_owned(&ks->kso_lock)) {
548b819cea2SGordon Ross mutex_enter(&ks->kso_lock);
549b819cea2SGordon Ross if (--ks->kso_count == 1)
550b819cea2SGordon Ross cv_signal(&ks->kso_closing_cv);
551b819cea2SGordon Ross mutex_exit(&ks->kso_lock);
552b819cea2SGordon Ross } else {
553b819cea2SGordon Ross if (--ks->kso_count == 1)
554b819cea2SGordon Ross cv_signal(&ks->kso_closing_cv);
555b819cea2SGordon Ross }
556b819cea2SGordon Ross }
557