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