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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
32 #include <sys/types.h>
33 #include <sys/socket.h>
36 #include <libilb_impl.h>
39 /* Assertion: the calling thread has a hold on the handle */
41 i_ilb_socket_set_err(ilb_handle_t h
, ilb_status_t err
)
43 ilb_handle_impl_t
*hi
= (ilb_handle_impl_t
*)h
;
45 if (h
== ILB_INVALID_HANDLE
)
47 hi
->h_valid
= B_FALSE
;
52 ilb_open(ilb_handle_t
*hp
)
54 ilb_handle_impl_t
*hi
= NULL
;
56 struct sockaddr_un sa
= {AF_UNIX
, SOCKET_PATH
};
57 ilb_status_t rc
= ILB_STATUS_OK
;
61 return (ILB_STATUS_EINVAL
);
63 hi
= calloc(sizeof (*hi
), 1);
65 return (ILB_STATUS_ENOMEM
);
67 if (cond_init(&hi
->h_cv
, USYNC_THREAD
, NULL
) != 0) {
68 rc
= ILB_STATUS_INTERNAL
;
72 if (mutex_init(&hi
->h_lock
, USYNC_THREAD
| LOCK_ERRORCHECK
, NULL
)
74 rc
= ILB_STATUS_INTERNAL
;
80 if ((s
= socket(PF_UNIX
, SOCK_SEQPACKET
, 0)) == -1 ||
81 connect(s
, (struct sockaddr
*)&sa
, sizeof (sa
.sun_path
))
83 rc
= ILB_STATUS_SOCKET
;
87 /* The socket buffer must be at least the max size of a message */
88 sobufsz
= ILBD_MSG_SIZE
;
89 if (setsockopt(s
, SOL_SOCKET
, SO_SNDBUF
, &sobufsz
,
90 sizeof (sobufsz
)) != 0) {
91 rc
= ILB_STATUS_SOCKET
;
95 if (setsockopt(s
, SOL_SOCKET
, SO_RCVBUF
, &sobufsz
,
96 sizeof (sobufsz
)) != 0) {
97 rc
= ILB_STATUS_SOCKET
;
103 hi
->h_valid
= B_TRUE
;
106 if (rc
!= ILB_STATUS_OK
&& s
!= -1)
109 if (rc
== ILB_STATUS_OK
) {
110 *hp
= (ilb_handle_t
)hi
;
113 *hp
= ILB_INVALID_HANDLE
;
119 ilb_close(ilb_handle_t h
)
121 ilb_handle_impl_t
*hi
= (ilb_handle_impl_t
*)h
;
123 if (h
== ILB_INVALID_HANDLE
)
124 return (ILB_STATUS_EINVAL
);
126 if (mutex_lock(&hi
->h_lock
) != 0)
127 return (ILB_STATUS_INTERNAL
);
129 /* Somebody has done a close, no need to do anything. */
131 return (ILB_STATUS_OK
);
133 hi
->h_closing
= B_TRUE
;
134 hi
->h_error
= ILB_STATUS_HANDLE_CLOSING
;
137 /* Wait until there is nobody waiting. */
138 while (hi
->h_waiter
> 0) {
139 if (cond_wait(&hi
->h_cv
, &hi
->h_lock
) != 0) {
140 (void) mutex_unlock(&hi
->h_lock
);
141 return (ILB_STATUS_INTERNAL
);
144 /* No one is waiting, proceed to free the handle. */
146 (void) close(hi
->h_socket
);
147 (void) mutex_destroy(&hi
->h_lock
);
148 (void) cond_destroy(&hi
->h_cv
);
150 return (ILB_STATUS_OK
);
154 * Unified routine to communicate with ilbd.
156 * If ic is non-NULL, it means that the caller wants to send something
157 * to ilbd and expects a reply. If ic is NULL, it means that the caller
158 * only expects to receive from ilbd.
160 * The rbuf is the buffer supplied by the caller for receiving. If it
161 * is NULL, it means that there is no reply expected.
163 * This function will not close() the socket to kernel unless there is
164 * an error. If the transaction only consists of one exchange, the caller
165 * can use i_ilb_close_comm() to close() the socket when done.
168 i_ilb_do_comm(ilb_handle_t h
, ilb_comm_t
*ic
, size_t ic_sz
, ilb_comm_t
*rbuf
,
171 ilb_status_t rc
= ILB_STATUS_OK
;
173 ilb_handle_impl_t
*hi
= (ilb_handle_impl_t
*)h
;
175 assert(rbuf
!= NULL
);
176 if (h
== ILB_INVALID_HANDLE
)
177 return (ILB_STATUS_EINVAL
);
179 if (mutex_lock(&hi
->h_lock
) != 0)
180 return (ILB_STATUS_INTERNAL
);
184 if (cond_wait(&hi
->h_cv
, &hi
->h_lock
) != 0) {
186 (void) cond_signal(&hi
->h_cv
);
187 (void) mutex_unlock(&hi
->h_lock
);
188 return (ILB_STATUS_INTERNAL
);
192 if (!hi
->h_valid
|| hi
->h_closing
) {
194 (void) cond_signal(&hi
->h_cv
);
195 (void) mutex_unlock(&hi
->h_lock
);
196 return (hi
->h_error
);
200 (void) mutex_unlock(&hi
->h_lock
);
204 r
= send(s
, ic
, ic_sz
, 0);
206 rc
= ILB_STATUS_WRITE
;
211 if ((r
= recv(s
, rbuf
, *rbufsz
, 0)) <= 0) {
212 rc
= ILB_STATUS_READ
;
219 i_ilb_socket_set_err(h
, rc
);
222 (void) mutex_lock(&hi
->h_lock
);
223 hi
->h_busy
= B_FALSE
;
225 (void) cond_signal(&hi
->h_cv
);
226 (void) mutex_unlock(&hi
->h_lock
);
232 i_ilb_close_comm(ilb_handle_t h
)