xref: /titanic_51/usr/src/lib/libfakekernel/common/ksocket.c (revision a90cf9f29973990687fa61de9f1f6ea22e924e40)
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*a90cf9f2SGordon Ross  * Copyright 2015 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>
35*a90cf9f2SGordon Ross #include <limits.h>
36b819cea2SGordon Ross #include <unistd.h>
37b819cea2SGordon Ross #include <errno.h>
38b819cea2SGordon Ross #include <umem.h>
39b819cea2SGordon Ross 
40b819cea2SGordon Ross #define	_KSOCKET_MAGIC 0xabcdef09
41b819cea2SGordon Ross 
42b819cea2SGordon Ross #define	KSOCKET_VALID(ks) (ks->kso_magic == _KSOCKET_MAGIC)
43b819cea2SGordon Ross #define	KSTOSO(ks) (ks->kso_fd)
44b819cea2SGordon Ross 
45b819cea2SGordon Ross #ifndef	SS_CLOSING
46b819cea2SGordon Ross #define	SS_CLOSING 0x00010000
47b819cea2SGordon Ross #endif
48b819cea2SGordon Ross 
49b819cea2SGordon Ross /*
50b819cea2SGordon Ross  * NB: you can't cast this into a sonode like you can with a normal
51b819cea2SGordon Ross  * ksocket_t, but no correct code should ever do that anyway.
52b819cea2SGordon Ross  * The ksocket_t type is opaque to prevent exactly that.
53b819cea2SGordon Ross  */
54b819cea2SGordon Ross struct __ksocket {
55b819cea2SGordon Ross 	uint32_t kso_magic;
56b819cea2SGordon Ross 	uint32_t kso_count;
57b819cea2SGordon Ross 	uint32_t kso_state;
58b819cea2SGordon Ross 	int kso_fd;
59b819cea2SGordon Ross 	kmutex_t kso_lock;
60b819cea2SGordon Ross 	kcondvar_t kso_closing_cv;
61b819cea2SGordon Ross };
62b819cea2SGordon Ross 
63b819cea2SGordon Ross static umem_cache_t *ksocket_cache = NULL;
64b819cea2SGordon Ross 
65b819cea2SGordon Ross /*ARGSUSED*/
66b819cea2SGordon Ross static int
67b819cea2SGordon Ross _ksocket_ctor(void *buf, void *arg, int flags)
68b819cea2SGordon Ross {
69b819cea2SGordon Ross 	ksocket_t sock = buf;
70b819cea2SGordon Ross 
71b819cea2SGordon Ross 	bzero(sock, sizeof (*sock));
72b819cea2SGordon Ross 	mutex_init(&sock->kso_lock, NULL, MUTEX_DEFAULT, NULL);
73b819cea2SGordon Ross 	cv_init(&sock->kso_closing_cv, NULL, CV_DEFAULT, NULL);
74b819cea2SGordon Ross 	return (0);
75b819cea2SGordon Ross }
76b819cea2SGordon Ross 
77b819cea2SGordon Ross /*ARGSUSED*/
78b819cea2SGordon Ross static void
79b819cea2SGordon Ross _ksocket_dtor(void *buf, void *arg)
80b819cea2SGordon Ross {
81b819cea2SGordon Ross 	ksocket_t sock = buf;
82b819cea2SGordon Ross 
83b819cea2SGordon Ross 	mutex_destroy(&sock->kso_lock);
84b819cea2SGordon Ross 	cv_destroy(&sock->kso_closing_cv);
85b819cea2SGordon Ross }
86b819cea2SGordon Ross 
87b819cea2SGordon Ross #pragma init(_ksocket_init)
88b819cea2SGordon Ross int
89b819cea2SGordon Ross _ksocket_init(void)
90b819cea2SGordon Ross {
91b819cea2SGordon Ross 	ksocket_cache = umem_cache_create("ksocket",
92b819cea2SGordon Ross 	    sizeof (struct __ksocket), 0,
93b819cea2SGordon Ross 	    _ksocket_ctor, _ksocket_dtor, NULL, NULL, NULL, 0);
94b819cea2SGordon Ross 	VERIFY(ksocket_cache != NULL);
95b819cea2SGordon Ross 	return (0);
96b819cea2SGordon Ross }
97b819cea2SGordon Ross 
98b819cea2SGordon Ross #pragma fini(_ksocket_fini)
99b819cea2SGordon Ross int
100b819cea2SGordon Ross _ksocket_fini(void)
101b819cea2SGordon Ross {
102b819cea2SGordon Ross 	umem_cache_destroy(ksocket_cache);
103b819cea2SGordon Ross 	return (0);
104b819cea2SGordon Ross }
105b819cea2SGordon Ross 
106b819cea2SGordon Ross static ksocket_t
107b819cea2SGordon Ross _ksocket_create(int fd)
108b819cea2SGordon Ross {
109b819cea2SGordon Ross 	ksocket_t ks;
110b819cea2SGordon Ross 
111b819cea2SGordon Ross 	ks = umem_cache_alloc(ksocket_cache, 0);
112b819cea2SGordon Ross 	VERIFY(ks != NULL);
113b819cea2SGordon Ross 	ks->kso_magic = _KSOCKET_MAGIC;
114b819cea2SGordon Ross 	ks->kso_count = 1;
115b819cea2SGordon Ross 	ks->kso_fd = fd;
116b819cea2SGordon Ross 	return (ks);
117b819cea2SGordon Ross }
118b819cea2SGordon Ross 
119b819cea2SGordon Ross static void
120b819cea2SGordon Ross _ksocket_destroy(ksocket_t ks)
121b819cea2SGordon Ross {
122b819cea2SGordon Ross 	ASSERT(ks->kso_count == 1);
123b819cea2SGordon Ross 	umem_cache_free(ksocket_cache, ks);
124b819cea2SGordon Ross }
125b819cea2SGordon Ross 
126b819cea2SGordon Ross int
127b819cea2SGordon Ross ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
128b819cea2SGordon Ross     struct cred *cr)
129b819cea2SGordon Ross {
130b819cea2SGordon Ross 	int fd;
131b819cea2SGordon Ross 	ksocket_t ks;
132b819cea2SGordon Ross 
133b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
134b819cea2SGordon Ross 	ASSERT(cr != NULL);
135b819cea2SGordon Ross 
136b819cea2SGordon Ross 	ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
137b819cea2SGordon Ross 
138b819cea2SGordon Ross 	fd = socket(domain, type, protocol);
139b819cea2SGordon Ross 	if (fd < 0) {
140b819cea2SGordon Ross 		*ksp = NULL;
141b819cea2SGordon Ross 		return (errno);
142b819cea2SGordon Ross 	}
143b819cea2SGordon Ross 
144b819cea2SGordon Ross 	ks = _ksocket_create(fd);
145b819cea2SGordon Ross 	*ksp = ks;
146b819cea2SGordon Ross 	return (0);
147b819cea2SGordon Ross }
148b819cea2SGordon Ross 
149b819cea2SGordon Ross /*
150b819cea2SGordon Ross  * This is marked NODIRECT so the main program linking with this library
151b819cea2SGordon Ross  * can provide its own "bind helper" function.  See: fksmbd_ksock.c
152b819cea2SGordon Ross  */
153b819cea2SGordon Ross /* ARGSUSED */
154b819cea2SGordon Ross int
155b819cea2SGordon Ross ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen)
156b819cea2SGordon Ross {
157b819cea2SGordon Ross 	return (EACCES);
158b819cea2SGordon Ross }
159b819cea2SGordon Ross 
160b819cea2SGordon Ross int
161b819cea2SGordon Ross ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
162b819cea2SGordon Ross     struct cred *cr)
163b819cea2SGordon Ross {
164b819cea2SGordon Ross 	int err = 0;
165b819cea2SGordon Ross 
166b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
167b819cea2SGordon Ross 	ASSERT(cr != NULL);
168b819cea2SGordon Ross 
169b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
170b819cea2SGordon Ross 		return (ENOTSOCK);
171b819cea2SGordon Ross 
172b819cea2SGordon Ross 	if (bind(KSTOSO(ks), addr, addrlen) != 0)
173b819cea2SGordon Ross 		err = errno;
174b819cea2SGordon Ross 
175b819cea2SGordon Ross 	if (err == EACCES) {
176b819cea2SGordon Ross 		err = ksocket_bind_helper(KSTOSO(ks), addr, addrlen);
177b819cea2SGordon Ross 	}
178b819cea2SGordon Ross 
179b819cea2SGordon Ross 	return (err);
180b819cea2SGordon Ross }
181b819cea2SGordon Ross 
182b819cea2SGordon Ross int
183b819cea2SGordon Ross ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
184b819cea2SGordon Ross {
185b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
186b819cea2SGordon Ross 	ASSERT(cr != NULL);
187b819cea2SGordon Ross 
188b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
189b819cea2SGordon Ross 		return (ENOTSOCK);
190b819cea2SGordon Ross 
191b819cea2SGordon Ross 	if (listen(KSTOSO(ks), backlog) != 0)
192b819cea2SGordon Ross 		return (errno);
193b819cea2SGordon Ross 
194b819cea2SGordon Ross 	return (0);
195b819cea2SGordon Ross }
196b819cea2SGordon Ross 
197b819cea2SGordon Ross int
198b819cea2SGordon Ross ksocket_accept(ksocket_t ks, struct sockaddr *addr,
199b819cea2SGordon Ross     socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
200b819cea2SGordon Ross {
201b819cea2SGordon Ross 	int fd;
202b819cea2SGordon Ross 
203b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
204b819cea2SGordon Ross 	ASSERT(cr != NULL);
205b819cea2SGordon Ross 
206b819cea2SGordon Ross 	*nks = NULL;
207b819cea2SGordon Ross 
208b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
209b819cea2SGordon Ross 		return (ENOTSOCK);
210b819cea2SGordon Ross 
211b819cea2SGordon Ross 	if (addr != NULL && addrlenp == NULL)
212b819cea2SGordon Ross 		return (EFAULT);
213b819cea2SGordon Ross 
214b819cea2SGordon Ross 	fd = accept(KSTOSO(ks), addr, addrlenp);
215b819cea2SGordon Ross 	if (fd < 0)
216b819cea2SGordon Ross 		return (errno);
217b819cea2SGordon Ross 
218b819cea2SGordon Ross 	*nks = _ksocket_create(fd);
219b819cea2SGordon Ross 
220b819cea2SGordon Ross 	return (0);
221b819cea2SGordon Ross }
222b819cea2SGordon Ross 
223b819cea2SGordon Ross int
224b819cea2SGordon Ross ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
225b819cea2SGordon Ross     struct cred *cr)
226b819cea2SGordon Ross {
227b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
228b819cea2SGordon Ross 	ASSERT(cr != NULL);
229b819cea2SGordon Ross 
230b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
231b819cea2SGordon Ross 		return (ENOTSOCK);
232b819cea2SGordon Ross 
233b819cea2SGordon Ross 	if (connect(KSTOSO(ks), addr, addrlen) != 0)
234b819cea2SGordon Ross 		return (errno);
235b819cea2SGordon Ross 
236b819cea2SGordon Ross 	return (0);
237b819cea2SGordon Ross }
238b819cea2SGordon Ross 
239b819cea2SGordon Ross int
240b819cea2SGordon Ross ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
241b819cea2SGordon Ross     size_t *sent, struct cred *cr)
242b819cea2SGordon Ross {
243b819cea2SGordon Ross 	ssize_t error;
244b819cea2SGordon Ross 
245b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
246b819cea2SGordon Ross 	ASSERT(cr != NULL);
247b819cea2SGordon Ross 
248b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
249b819cea2SGordon Ross 		if (sent != NULL)
250b819cea2SGordon Ross 			*sent = 0;
251b819cea2SGordon Ross 		return (ENOTSOCK);
252b819cea2SGordon Ross 	}
253b819cea2SGordon Ross 
254b819cea2SGordon Ross 	error = send(KSTOSO(ks), msg, msglen, flags);
255b819cea2SGordon Ross 	if (error < 0) {
256b819cea2SGordon Ross 		if (sent != NULL)
257b819cea2SGordon Ross 			*sent = 0;
258b819cea2SGordon Ross 		return (errno);
259b819cea2SGordon Ross 	}
260b819cea2SGordon Ross 
261b819cea2SGordon Ross 	if (sent != NULL)
262b819cea2SGordon Ross 		*sent = (size_t)error;
263b819cea2SGordon Ross 	return (0);
264b819cea2SGordon Ross }
265b819cea2SGordon Ross 
266b819cea2SGordon Ross int
267b819cea2SGordon Ross ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
268b819cea2SGordon Ross     struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
269b819cea2SGordon Ross {
270b819cea2SGordon Ross 	ssize_t error;
271b819cea2SGordon Ross 
272b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
273b819cea2SGordon Ross 	ASSERT(cr != NULL);
274b819cea2SGordon Ross 
275b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
276b819cea2SGordon Ross 		if (sent != NULL)
277b819cea2SGordon Ross 			*sent = 0;
278b819cea2SGordon Ross 		return (ENOTSOCK);
279b819cea2SGordon Ross 	}
280b819cea2SGordon Ross 
281b819cea2SGordon Ross 	error = sendto(KSTOSO(ks), msg, msglen, flags, name, namelen);
282b819cea2SGordon Ross 	if (error < 0) {
283b819cea2SGordon Ross 		if (sent != NULL)
284b819cea2SGordon Ross 			*sent = 0;
285b819cea2SGordon Ross 		return (errno);
286b819cea2SGordon Ross 	}
287b819cea2SGordon Ross 
288b819cea2SGordon Ross 	if (sent != NULL)
289b819cea2SGordon Ross 		*sent = (size_t)error;
290b819cea2SGordon Ross 	return (0);
291b819cea2SGordon Ross }
292b819cea2SGordon Ross 
293b819cea2SGordon Ross int
294b819cea2SGordon Ross ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags,
295b819cea2SGordon Ross     size_t *sent, struct cred *cr)
296b819cea2SGordon Ross {
297*a90cf9f2SGordon Ross 	uio_t uio;
298*a90cf9f2SGordon Ross 	ssize_t len;
299b819cea2SGordon Ross 
300b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
301b819cea2SGordon Ross 	ASSERT(cr != NULL);
302b819cea2SGordon Ross 
303b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
304b819cea2SGordon Ross 		if (sent != NULL)
305b819cea2SGordon Ross 			*sent = 0;
306b819cea2SGordon Ross 		return (ENOTSOCK);
307b819cea2SGordon Ross 	}
308b819cea2SGordon Ross 
309*a90cf9f2SGordon Ross 	/* socksyscalls.c uses MSG_MAXIOVLEN (local macro), both are 16 */
310*a90cf9f2SGordon Ross 	ASSERT3U(msg->msg_iovlen, <=, IOV_MAX);
311*a90cf9f2SGordon Ross 	len = sendmsg(KSTOSO(ks), msg, flags);
312*a90cf9f2SGordon Ross 	if (len < 0) {
313b819cea2SGordon Ross 		if (sent != NULL)
314b819cea2SGordon Ross 			*sent = 0;
315b819cea2SGordon Ross 		return (errno);
316b819cea2SGordon Ross 	}
317b819cea2SGordon Ross 
318*a90cf9f2SGordon Ross 	/*
319*a90cf9f2SGordon Ross 	 * The user-level sendmsg() does NOT update msg->iov like
320*a90cf9f2SGordon Ross 	 * ksocket_sendmsg().  It's unclear whether that's a bug
321*a90cf9f2SGordon Ross 	 * or if that was intentional.  Anyway, update it here.
322*a90cf9f2SGordon Ross 	 */
323*a90cf9f2SGordon Ross 	if (msg->msg_iov != NULL) {
324*a90cf9f2SGordon Ross 		bzero(&uio, sizeof (uio));
325*a90cf9f2SGordon Ross 		uio.uio_iov = msg->msg_iov;
326*a90cf9f2SGordon Ross 		uio.uio_iovcnt = msg->msg_iovlen;
327*a90cf9f2SGordon Ross 		uio.uio_resid = len;
328*a90cf9f2SGordon Ross 
329*a90cf9f2SGordon Ross 		uioskip(&uio, len);
330*a90cf9f2SGordon Ross 		ASSERT(uio.uio_resid == 0);
331*a90cf9f2SGordon Ross 
332*a90cf9f2SGordon Ross 		msg->msg_iov = uio.uio_iov;
333*a90cf9f2SGordon Ross 		msg->msg_iovlen = uio.uio_iovcnt;
334*a90cf9f2SGordon Ross 	}
335*a90cf9f2SGordon Ross 
336b819cea2SGordon Ross 	if (sent != NULL)
337*a90cf9f2SGordon Ross 		*sent = (size_t)len;
338b819cea2SGordon Ross 	return (0);
339b819cea2SGordon Ross }
340b819cea2SGordon Ross 
341b819cea2SGordon Ross int
342b819cea2SGordon Ross ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
343b819cea2SGordon Ross     size_t *recvd, struct cred *cr)
344b819cea2SGordon Ross {
345b819cea2SGordon Ross 	ssize_t error;
346b819cea2SGordon Ross 
347b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
348b819cea2SGordon Ross 	ASSERT(cr != NULL);
349b819cea2SGordon Ross 
350b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
351b819cea2SGordon Ross 		if (recvd != NULL)
352b819cea2SGordon Ross 			*recvd = 0;
353b819cea2SGordon Ross 		return (ENOTSOCK);
354b819cea2SGordon Ross 	}
355b819cea2SGordon Ross 
356b819cea2SGordon Ross 	error = recv(KSTOSO(ks), msg, msglen, flags);
357b819cea2SGordon Ross 	if (error < 0) {
358b819cea2SGordon Ross 		if (recvd != NULL)
359b819cea2SGordon Ross 			*recvd = 0;
360b819cea2SGordon Ross 		return (errno);
361b819cea2SGordon Ross 	}
362b819cea2SGordon Ross 
363b819cea2SGordon Ross 	if (recvd != NULL)
364b819cea2SGordon Ross 		*recvd = (size_t)error;
365b819cea2SGordon Ross 	return (0);
366b819cea2SGordon Ross }
367b819cea2SGordon Ross 
368b819cea2SGordon Ross int
369b819cea2SGordon Ross ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
370b819cea2SGordon Ross     struct sockaddr *name, socklen_t *namelen, size_t *recvd, struct cred *cr)
371b819cea2SGordon Ross {
372b819cea2SGordon Ross 	ssize_t error;
373b819cea2SGordon Ross 
374b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
375b819cea2SGordon Ross 	ASSERT(cr != NULL);
376b819cea2SGordon Ross 
377b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
378b819cea2SGordon Ross 		if (recvd != NULL)
379b819cea2SGordon Ross 			*recvd = 0;
380b819cea2SGordon Ross 		return (ENOTSOCK);
381b819cea2SGordon Ross 	}
382b819cea2SGordon Ross 
383b819cea2SGordon Ross 	error = recvfrom(KSTOSO(ks), msg, msglen, flags, name, namelen);
384b819cea2SGordon Ross 	if (error != 0) {
385b819cea2SGordon Ross 		if (recvd != NULL)
386b819cea2SGordon Ross 			*recvd = 0;
387b819cea2SGordon Ross 		return (errno);
388b819cea2SGordon Ross 	}
389b819cea2SGordon Ross 
390b819cea2SGordon Ross 	if (recvd != NULL)
391b819cea2SGordon Ross 		*recvd = (ssize_t)error;
392b819cea2SGordon Ross 	return (0);
393b819cea2SGordon Ross }
394b819cea2SGordon Ross 
395b819cea2SGordon Ross int
396b819cea2SGordon Ross ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recvd,
397b819cea2SGordon Ross     struct cred *cr)
398b819cea2SGordon Ross {
399b819cea2SGordon Ross 	ssize_t error;
400b819cea2SGordon Ross 
401b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
402b819cea2SGordon Ross 	ASSERT(cr != NULL);
403b819cea2SGordon Ross 
404b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
405b819cea2SGordon Ross 		if (recvd != NULL)
406b819cea2SGordon Ross 			*recvd = 0;
407b819cea2SGordon Ross 		return (ENOTSOCK);
408b819cea2SGordon Ross 	}
409b819cea2SGordon Ross 
410b819cea2SGordon Ross 	error = recvmsg(KSTOSO(ks), msg, flags);
411b819cea2SGordon Ross 	if (error < 0) {
412b819cea2SGordon Ross 		if (recvd != NULL)
413b819cea2SGordon Ross 			*recvd = 0;
414b819cea2SGordon Ross 		return (errno);
415b819cea2SGordon Ross 	}
416b819cea2SGordon Ross 
417b819cea2SGordon Ross 	if (recvd != NULL)
418b819cea2SGordon Ross 		*recvd = (size_t)error;
419b819cea2SGordon Ross 	return (0);
420b819cea2SGordon Ross }
421b819cea2SGordon Ross 
422b819cea2SGordon Ross int
423b819cea2SGordon Ross ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
424b819cea2SGordon Ross {
425b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
426b819cea2SGordon Ross 	ASSERT(cr != NULL);
427b819cea2SGordon Ross 
428b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
429b819cea2SGordon Ross 		return (ENOTSOCK);
430b819cea2SGordon Ross 
431b819cea2SGordon Ross 	if (shutdown(KSTOSO(ks), how) != 0)
432b819cea2SGordon Ross 		return (errno);
433b819cea2SGordon Ross 
434b819cea2SGordon Ross 	return (0);
435b819cea2SGordon Ross }
436b819cea2SGordon Ross 
437b819cea2SGordon Ross int
438b819cea2SGordon Ross ksocket_close(ksocket_t ks, struct cred *cr)
439b819cea2SGordon Ross {
440b819cea2SGordon Ross 	int fd;
441b819cea2SGordon Ross 
442b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
443b819cea2SGordon Ross 	ASSERT(cr != NULL);
444b819cea2SGordon Ross 
445b819cea2SGordon Ross 	mutex_enter(&ks->kso_lock);
446b819cea2SGordon Ross 
447b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks)) {
448b819cea2SGordon Ross 		mutex_exit(&ks->kso_lock);
449b819cea2SGordon Ross 		return (ENOTSOCK);
450b819cea2SGordon Ross 	}
451b819cea2SGordon Ross 
452b819cea2SGordon Ross 	ks->kso_state |= SS_CLOSING;
453b819cea2SGordon Ross 
454b819cea2SGordon Ross 	/*
455b819cea2SGordon Ross 	 * The real ksocket wakes up everything.
456b819cea2SGordon Ross 	 * It seems the only way we can do that
457b819cea2SGordon Ross 	 * is to go ahead and close the FD.
458b819cea2SGordon Ross 	 */
459b819cea2SGordon Ross 	fd = ks->kso_fd;
460b819cea2SGordon Ross 	ks->kso_fd = -1;
461b819cea2SGordon Ross 	(void) close(fd);
462b819cea2SGordon Ross 
463b819cea2SGordon Ross 	while (ks->kso_count > 1)
464b819cea2SGordon Ross 		cv_wait(&ks->kso_closing_cv, &ks->kso_lock);
465b819cea2SGordon Ross 
466b819cea2SGordon Ross 	mutex_exit(&ks->kso_lock);
467b819cea2SGordon Ross 	_ksocket_destroy(ks);
468b819cea2SGordon Ross 
469b819cea2SGordon Ross 	return (0);
470b819cea2SGordon Ross }
471b819cea2SGordon Ross 
472b819cea2SGordon Ross int
473b819cea2SGordon Ross ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
474b819cea2SGordon Ross     struct cred *cr)
475b819cea2SGordon Ross {
476b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
477b819cea2SGordon Ross 	ASSERT(cr != NULL);
478b819cea2SGordon Ross 
479b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
480b819cea2SGordon Ross 		return (ENOTSOCK);
481b819cea2SGordon Ross 
482b819cea2SGordon Ross 	if (addrlen == NULL || (addr == NULL && *addrlen != 0))
483b819cea2SGordon Ross 		return (EFAULT);
484b819cea2SGordon Ross 
485b819cea2SGordon Ross 	if (getsockname(KSTOSO(ks), addr, addrlen) != 0)
486b819cea2SGordon Ross 		return (errno);
487b819cea2SGordon Ross 
488b819cea2SGordon Ross 	return (0);
489b819cea2SGordon Ross }
490b819cea2SGordon Ross 
491b819cea2SGordon Ross int
492b819cea2SGordon Ross ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
493b819cea2SGordon Ross     struct cred *cr)
494b819cea2SGordon Ross {
495b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
496b819cea2SGordon Ross 	ASSERT(cr != NULL);
497b819cea2SGordon Ross 
498b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
499b819cea2SGordon Ross 		return (ENOTSOCK);
500b819cea2SGordon Ross 
501b819cea2SGordon Ross 	if (addrlen == NULL || (addr == NULL && *addrlen != 0))
502b819cea2SGordon Ross 		return (EFAULT);
503b819cea2SGordon Ross 
504b819cea2SGordon Ross 	if (getpeername(KSTOSO(ks), addr, addrlen) != 0)
505b819cea2SGordon Ross 		return (errno);
506b819cea2SGordon Ross 
507b819cea2SGordon Ross 	return (0);
508b819cea2SGordon Ross }
509b819cea2SGordon Ross 
510b819cea2SGordon Ross int
511b819cea2SGordon Ross ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
512b819cea2SGordon Ross     int optlen, struct cred *cr)
513b819cea2SGordon Ross {
514b819cea2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
515b819cea2SGordon Ross 	ASSERT(cr != NULL);
516b819cea2SGordon Ross 
517b819cea2SGordon Ross 	if (!KSOCKET_VALID(ks))
518b819cea2SGordon Ross 		return (ENOTSOCK);
519b819cea2SGordon Ross 
520b819cea2SGordon Ross 	if (optval == NULL)
521b819cea2SGordon Ross 		optlen = 0;
522b819cea2SGordon Ross 
523b819cea2SGordon Ross 	if (setsockopt(KSTOSO(ks), level, optname, optval, optlen) != 0)
524b819cea2SGordon Ross 		return (errno);
525b819cea2SGordon Ross 
526b819cea2SGordon Ross 	return (0);
527b819cea2SGordon Ross }
528b819cea2SGordon Ross 
52968b2bbf2SGordon Ross int
53068b2bbf2SGordon Ross ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvp, struct cred *cr)
53168b2bbf2SGordon Ross {
53268b2bbf2SGordon Ross 	int rval;
53368b2bbf2SGordon Ross 
53468b2bbf2SGordon Ross 	/* All Solaris components should pass a cred for this operation. */
53568b2bbf2SGordon Ross 	ASSERT(cr != NULL);
53668b2bbf2SGordon Ross 
53768b2bbf2SGordon Ross 	if (!KSOCKET_VALID(ks))
53868b2bbf2SGordon Ross 		return (ENOTSOCK);
53968b2bbf2SGordon Ross 
54068b2bbf2SGordon Ross 	rval = ioctl(KSTOSO(ks), cmd, arg);
54168b2bbf2SGordon Ross 	if (rvp != NULL)
54268b2bbf2SGordon Ross 		*rvp = rval;
54368b2bbf2SGordon Ross 
54468b2bbf2SGordon Ross 	if (rval != 0)
54568b2bbf2SGordon Ross 		rval = errno;
54668b2bbf2SGordon Ross 
54768b2bbf2SGordon Ross 	return (rval);
54868b2bbf2SGordon Ross }
54968b2bbf2SGordon Ross 
550b819cea2SGordon Ross void
551b819cea2SGordon Ross ksocket_hold(ksocket_t ks)
552b819cea2SGordon Ross {
553b819cea2SGordon Ross 	if (!mutex_owned(&ks->kso_lock)) {
554b819cea2SGordon Ross 		mutex_enter(&ks->kso_lock);
555b819cea2SGordon Ross 		ks->kso_count++;
556b819cea2SGordon Ross 		mutex_exit(&ks->kso_lock);
557b819cea2SGordon Ross 	} else
558b819cea2SGordon Ross 		ks->kso_count++;
559b819cea2SGordon Ross }
560b819cea2SGordon Ross 
561b819cea2SGordon Ross void
562b819cea2SGordon Ross ksocket_rele(ksocket_t ks)
563b819cea2SGordon Ross {
564b819cea2SGordon Ross 	/*
565b819cea2SGordon Ross 	 * When so_count equals 1 means no thread working on this ksocket
566b819cea2SGordon Ross 	 */
567b819cea2SGordon Ross 	VERIFY3U(ks->kso_count, >, 1);
568b819cea2SGordon Ross 
569b819cea2SGordon Ross 	if (!mutex_owned(&ks->kso_lock)) {
570b819cea2SGordon Ross 		mutex_enter(&ks->kso_lock);
571b819cea2SGordon Ross 		if (--ks->kso_count == 1)
572b819cea2SGordon Ross 			cv_signal(&ks->kso_closing_cv);
573b819cea2SGordon Ross 		mutex_exit(&ks->kso_lock);
574b819cea2SGordon Ross 	} else {
575b819cea2SGordon Ross 		if (--ks->kso_count == 1)
576b819cea2SGordon Ross 			cv_signal(&ks->kso_closing_cv);
577b819cea2SGordon Ross 	}
578b819cea2SGordon Ross }
579