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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 #include <sys/types.h>
28 #include <sys/systm.h>
30 #include <sys/errno.h>
31 #include <sys/socket.h>
32 #include <sys/ksocket.h>
33 #include <sys/debug.h>
39 #define _KSOCKET_MAGIC 0xabcdef09
41 #define KSOCKET_VALID(ks) (ks->kso_magic == _KSOCKET_MAGIC)
42 #define KSTOSO(ks) (ks->kso_fd)
45 #define SS_CLOSING 0x00010000
49 * NB: you can't cast this into a sonode like you can with a normal
50 * ksocket_t, but no correct code should ever do that anyway.
51 * The ksocket_t type is opaque to prevent exactly that.
59 kcondvar_t kso_closing_cv
;
62 static umem_cache_t
*ksocket_cache
= NULL
;
66 _ksocket_ctor(void *buf
, void *arg
, int flags
)
70 bzero(sock
, sizeof (*sock
));
71 mutex_init(&sock
->kso_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
72 cv_init(&sock
->kso_closing_cv
, NULL
, CV_DEFAULT
, NULL
);
78 _ksocket_dtor(void *buf
, void *arg
)
82 mutex_destroy(&sock
->kso_lock
);
83 cv_destroy(&sock
->kso_closing_cv
);
86 #pragma init(_ksocket_init)
90 ksocket_cache
= umem_cache_create("ksocket",
91 sizeof (struct __ksocket
), 0,
92 _ksocket_ctor
, _ksocket_dtor
, NULL
, NULL
, NULL
, 0);
93 VERIFY(ksocket_cache
!= NULL
);
97 #pragma fini(_ksocket_fini)
101 umem_cache_destroy(ksocket_cache
);
106 _ksocket_create(int fd
)
110 ks
= umem_cache_alloc(ksocket_cache
, 0);
112 ks
->kso_magic
= _KSOCKET_MAGIC
;
119 _ksocket_destroy(ksocket_t ks
)
121 ASSERT(ks
->kso_count
== 1);
122 umem_cache_free(ksocket_cache
, ks
);
126 ksocket_socket(ksocket_t
*ksp
, int domain
, int type
, int protocol
, int flags
,
132 /* All Solaris components should pass a cred for this operation. */
135 ASSERT(flags
== KSOCKET_SLEEP
|| flags
== KSOCKET_NOSLEEP
);
137 fd
= socket(domain
, type
, protocol
);
143 ks
= _ksocket_create(fd
);
149 * This is marked NODIRECT so the main program linking with this library
150 * can provide its own "bind helper" function. See: fksmbd_ksock.c
154 ksocket_bind_helper(int fd
, struct sockaddr
*addr
, uint_t addrlen
)
160 ksocket_bind(ksocket_t ks
, struct sockaddr
*addr
, socklen_t addrlen
,
165 /* All Solaris components should pass a cred for this operation. */
168 if (!KSOCKET_VALID(ks
))
171 if (bind(KSTOSO(ks
), addr
, addrlen
) != 0)
175 err
= ksocket_bind_helper(KSTOSO(ks
), addr
, addrlen
);
182 ksocket_listen(ksocket_t ks
, int backlog
, struct cred
*cr
)
184 /* All Solaris components should pass a cred for this operation. */
187 if (!KSOCKET_VALID(ks
))
190 if (listen(KSTOSO(ks
), backlog
) != 0)
197 ksocket_accept(ksocket_t ks
, struct sockaddr
*addr
,
198 socklen_t
*addrlenp
, ksocket_t
*nks
, struct cred
*cr
)
202 /* All Solaris components should pass a cred for this operation. */
207 if (!KSOCKET_VALID(ks
))
210 if (addr
!= NULL
&& addrlenp
== NULL
)
213 fd
= accept(KSTOSO(ks
), addr
, addrlenp
);
217 *nks
= _ksocket_create(fd
);
223 ksocket_connect(ksocket_t ks
, struct sockaddr
*addr
, socklen_t addrlen
,
226 /* All Solaris components should pass a cred for this operation. */
229 if (!KSOCKET_VALID(ks
))
232 if (connect(KSTOSO(ks
), addr
, addrlen
) != 0)
239 ksocket_send(ksocket_t ks
, void *msg
, size_t msglen
, int flags
,
240 size_t *sent
, struct cred
*cr
)
244 /* All Solaris components should pass a cred for this operation. */
247 if (!KSOCKET_VALID(ks
)) {
253 error
= send(KSTOSO(ks
), msg
, msglen
, flags
);
261 *sent
= (size_t)error
;
266 ksocket_sendto(ksocket_t ks
, void *msg
, size_t msglen
, int flags
,
267 struct sockaddr
*name
, socklen_t namelen
, size_t *sent
, struct cred
*cr
)
271 /* All Solaris components should pass a cred for this operation. */
274 if (!KSOCKET_VALID(ks
)) {
280 error
= sendto(KSTOSO(ks
), msg
, msglen
, flags
, name
, namelen
);
288 *sent
= (size_t)error
;
293 ksocket_sendmsg(ksocket_t ks
, struct nmsghdr
*msg
, int flags
,
294 size_t *sent
, struct cred
*cr
)
298 /* All Solaris components should pass a cred for this operation. */
301 if (!KSOCKET_VALID(ks
)) {
307 error
= sendmsg(KSTOSO(ks
), msg
, flags
);
315 *sent
= (size_t)error
;
320 ksocket_recv(ksocket_t ks
, void *msg
, size_t msglen
, int flags
,
321 size_t *recvd
, struct cred
*cr
)
325 /* All Solaris components should pass a cred for this operation. */
328 if (!KSOCKET_VALID(ks
)) {
334 error
= recv(KSTOSO(ks
), msg
, msglen
, flags
);
342 *recvd
= (size_t)error
;
347 ksocket_recvfrom(ksocket_t ks
, void *msg
, size_t msglen
, int flags
,
348 struct sockaddr
*name
, socklen_t
*namelen
, size_t *recvd
, struct cred
*cr
)
352 /* All Solaris components should pass a cred for this operation. */
355 if (!KSOCKET_VALID(ks
)) {
361 error
= recvfrom(KSTOSO(ks
), msg
, msglen
, flags
, name
, namelen
);
369 *recvd
= (ssize_t
)error
;
374 ksocket_recvmsg(ksocket_t ks
, struct nmsghdr
*msg
, int flags
, size_t *recvd
,
379 /* All Solaris components should pass a cred for this operation. */
382 if (!KSOCKET_VALID(ks
)) {
388 error
= recvmsg(KSTOSO(ks
), msg
, flags
);
396 *recvd
= (size_t)error
;
401 ksocket_shutdown(ksocket_t ks
, int how
, struct cred
*cr
)
403 /* All Solaris components should pass a cred for this operation. */
406 if (!KSOCKET_VALID(ks
))
409 if (shutdown(KSTOSO(ks
), how
) != 0)
416 ksocket_close(ksocket_t ks
, struct cred
*cr
)
420 /* All Solaris components should pass a cred for this operation. */
423 mutex_enter(&ks
->kso_lock
);
425 if (!KSOCKET_VALID(ks
)) {
426 mutex_exit(&ks
->kso_lock
);
430 ks
->kso_state
|= SS_CLOSING
;
433 * The real ksocket wakes up everything.
434 * It seems the only way we can do that
435 * is to go ahead and close the FD.
441 while (ks
->kso_count
> 1)
442 cv_wait(&ks
->kso_closing_cv
, &ks
->kso_lock
);
444 mutex_exit(&ks
->kso_lock
);
445 _ksocket_destroy(ks
);
451 ksocket_getsockname(ksocket_t ks
, struct sockaddr
*addr
, socklen_t
*addrlen
,
454 /* All Solaris components should pass a cred for this operation. */
457 if (!KSOCKET_VALID(ks
))
460 if (addrlen
== NULL
|| (addr
== NULL
&& *addrlen
!= 0))
463 if (getsockname(KSTOSO(ks
), addr
, addrlen
) != 0)
470 ksocket_getpeername(ksocket_t ks
, struct sockaddr
*addr
, socklen_t
*addrlen
,
473 /* All Solaris components should pass a cred for this operation. */
476 if (!KSOCKET_VALID(ks
))
479 if (addrlen
== NULL
|| (addr
== NULL
&& *addrlen
!= 0))
482 if (getpeername(KSTOSO(ks
), addr
, addrlen
) != 0)
489 ksocket_setsockopt(ksocket_t ks
, int level
, int optname
, const void *optval
,
490 int optlen
, struct cred
*cr
)
492 /* All Solaris components should pass a cred for this operation. */
495 if (!KSOCKET_VALID(ks
))
501 if (setsockopt(KSTOSO(ks
), level
, optname
, optval
, optlen
) != 0)
508 ksocket_hold(ksocket_t ks
)
510 if (!mutex_owned(&ks
->kso_lock
)) {
511 mutex_enter(&ks
->kso_lock
);
513 mutex_exit(&ks
->kso_lock
);
519 ksocket_rele(ksocket_t ks
)
522 * When so_count equals 1 means no thread working on this ksocket
524 VERIFY3U(ks
->kso_count
, >, 1);
526 if (!mutex_owned(&ks
->kso_lock
)) {
527 mutex_enter(&ks
->kso_lock
);
528 if (--ks
->kso_count
== 1)
529 cv_signal(&ks
->kso_closing_cv
);
530 mutex_exit(&ks
->kso_lock
);
532 if (--ks
->kso_count
== 1)
533 cv_signal(&ks
->kso_closing_cv
);