1*10946SSangeeta.Misra@Sun.COM /*
2*10946SSangeeta.Misra@Sun.COM * CDDL HEADER START
3*10946SSangeeta.Misra@Sun.COM *
4*10946SSangeeta.Misra@Sun.COM * The contents of this file are subject to the terms of the
5*10946SSangeeta.Misra@Sun.COM * Common Development and Distribution License (the "License").
6*10946SSangeeta.Misra@Sun.COM * You may not use this file except in compliance with the License.
7*10946SSangeeta.Misra@Sun.COM *
8*10946SSangeeta.Misra@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10946SSangeeta.Misra@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*10946SSangeeta.Misra@Sun.COM * See the License for the specific language governing permissions
11*10946SSangeeta.Misra@Sun.COM * and limitations under the License.
12*10946SSangeeta.Misra@Sun.COM *
13*10946SSangeeta.Misra@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*10946SSangeeta.Misra@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10946SSangeeta.Misra@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*10946SSangeeta.Misra@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*10946SSangeeta.Misra@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*10946SSangeeta.Misra@Sun.COM *
19*10946SSangeeta.Misra@Sun.COM * CDDL HEADER END
20*10946SSangeeta.Misra@Sun.COM */
21*10946SSangeeta.Misra@Sun.COM
22*10946SSangeeta.Misra@Sun.COM /*
23*10946SSangeeta.Misra@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*10946SSangeeta.Misra@Sun.COM * Use is subject to license terms.
25*10946SSangeeta.Misra@Sun.COM */
26*10946SSangeeta.Misra@Sun.COM
27*10946SSangeeta.Misra@Sun.COM #include <stdlib.h>
28*10946SSangeeta.Misra@Sun.COM #include <strings.h>
29*10946SSangeeta.Misra@Sun.COM #include <unistd.h>
30*10946SSangeeta.Misra@Sun.COM #include <stddef.h>
31*10946SSangeeta.Misra@Sun.COM #include <assert.h>
32*10946SSangeeta.Misra@Sun.COM #include <sys/types.h>
33*10946SSangeeta.Misra@Sun.COM #include <sys/socket.h>
34*10946SSangeeta.Misra@Sun.COM #include <thread.h>
35*10946SSangeeta.Misra@Sun.COM #include <synch.h>
36*10946SSangeeta.Misra@Sun.COM #include <libilb_impl.h>
37*10946SSangeeta.Misra@Sun.COM #include <libilb.h>
38*10946SSangeeta.Misra@Sun.COM
39*10946SSangeeta.Misra@Sun.COM /* Assertion: the calling thread has a hold on the handle */
40*10946SSangeeta.Misra@Sun.COM static void
i_ilb_socket_set_err(ilb_handle_t h,ilb_status_t err)41*10946SSangeeta.Misra@Sun.COM i_ilb_socket_set_err(ilb_handle_t h, ilb_status_t err)
42*10946SSangeeta.Misra@Sun.COM {
43*10946SSangeeta.Misra@Sun.COM ilb_handle_impl_t *hi = (ilb_handle_impl_t *)h;
44*10946SSangeeta.Misra@Sun.COM
45*10946SSangeeta.Misra@Sun.COM if (h == ILB_INVALID_HANDLE)
46*10946SSangeeta.Misra@Sun.COM return;
47*10946SSangeeta.Misra@Sun.COM hi->h_valid = B_FALSE;
48*10946SSangeeta.Misra@Sun.COM hi->h_error = err;
49*10946SSangeeta.Misra@Sun.COM }
50*10946SSangeeta.Misra@Sun.COM
51*10946SSangeeta.Misra@Sun.COM ilb_status_t
ilb_open(ilb_handle_t * hp)52*10946SSangeeta.Misra@Sun.COM ilb_open(ilb_handle_t *hp)
53*10946SSangeeta.Misra@Sun.COM {
54*10946SSangeeta.Misra@Sun.COM ilb_handle_impl_t *hi = NULL;
55*10946SSangeeta.Misra@Sun.COM int s = -1;
56*10946SSangeeta.Misra@Sun.COM struct sockaddr_un sa = {AF_UNIX, SOCKET_PATH};
57*10946SSangeeta.Misra@Sun.COM ilb_status_t rc = ILB_STATUS_OK;
58*10946SSangeeta.Misra@Sun.COM int sobufsz;
59*10946SSangeeta.Misra@Sun.COM
60*10946SSangeeta.Misra@Sun.COM if (hp == NULL)
61*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_EINVAL);
62*10946SSangeeta.Misra@Sun.COM
63*10946SSangeeta.Misra@Sun.COM hi = calloc(sizeof (*hi), 1);
64*10946SSangeeta.Misra@Sun.COM if (hi == NULL)
65*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_ENOMEM);
66*10946SSangeeta.Misra@Sun.COM
67*10946SSangeeta.Misra@Sun.COM if (cond_init(&hi->h_cv, USYNC_THREAD, NULL) != 0) {
68*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_INTERNAL;
69*10946SSangeeta.Misra@Sun.COM goto out;
70*10946SSangeeta.Misra@Sun.COM }
71*10946SSangeeta.Misra@Sun.COM
72*10946SSangeeta.Misra@Sun.COM if (mutex_init(&hi->h_lock, USYNC_THREAD | LOCK_ERRORCHECK, NULL)
73*10946SSangeeta.Misra@Sun.COM != 0) {
74*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_INTERNAL;
75*10946SSangeeta.Misra@Sun.COM goto out;
76*10946SSangeeta.Misra@Sun.COM }
77*10946SSangeeta.Misra@Sun.COM
78*10946SSangeeta.Misra@Sun.COM hi->h_busy = B_FALSE;
79*10946SSangeeta.Misra@Sun.COM
80*10946SSangeeta.Misra@Sun.COM if ((s = socket(PF_UNIX, SOCK_SEQPACKET, 0)) == -1 ||
81*10946SSangeeta.Misra@Sun.COM connect(s, (struct sockaddr *)&sa, sizeof (sa.sun_path))
82*10946SSangeeta.Misra@Sun.COM == -1) {
83*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_SOCKET;
84*10946SSangeeta.Misra@Sun.COM goto out;
85*10946SSangeeta.Misra@Sun.COM }
86*10946SSangeeta.Misra@Sun.COM
87*10946SSangeeta.Misra@Sun.COM /* The socket buffer must be at least the max size of a message */
88*10946SSangeeta.Misra@Sun.COM sobufsz = ILBD_MSG_SIZE;
89*10946SSangeeta.Misra@Sun.COM if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sobufsz,
90*10946SSangeeta.Misra@Sun.COM sizeof (sobufsz)) != 0) {
91*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_SOCKET;
92*10946SSangeeta.Misra@Sun.COM (void) close(s);
93*10946SSangeeta.Misra@Sun.COM goto out;
94*10946SSangeeta.Misra@Sun.COM }
95*10946SSangeeta.Misra@Sun.COM if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sobufsz,
96*10946SSangeeta.Misra@Sun.COM sizeof (sobufsz)) != 0) {
97*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_SOCKET;
98*10946SSangeeta.Misra@Sun.COM (void) close(s);
99*10946SSangeeta.Misra@Sun.COM goto out;
100*10946SSangeeta.Misra@Sun.COM }
101*10946SSangeeta.Misra@Sun.COM
102*10946SSangeeta.Misra@Sun.COM hi->h_socket = s;
103*10946SSangeeta.Misra@Sun.COM hi->h_valid = B_TRUE;
104*10946SSangeeta.Misra@Sun.COM
105*10946SSangeeta.Misra@Sun.COM out:
106*10946SSangeeta.Misra@Sun.COM if (rc != ILB_STATUS_OK && s != -1)
107*10946SSangeeta.Misra@Sun.COM (void) close(s);
108*10946SSangeeta.Misra@Sun.COM
109*10946SSangeeta.Misra@Sun.COM if (rc == ILB_STATUS_OK) {
110*10946SSangeeta.Misra@Sun.COM *hp = (ilb_handle_t)hi;
111*10946SSangeeta.Misra@Sun.COM } else {
112*10946SSangeeta.Misra@Sun.COM free(hi);
113*10946SSangeeta.Misra@Sun.COM *hp = ILB_INVALID_HANDLE;
114*10946SSangeeta.Misra@Sun.COM }
115*10946SSangeeta.Misra@Sun.COM return (rc);
116*10946SSangeeta.Misra@Sun.COM }
117*10946SSangeeta.Misra@Sun.COM
118*10946SSangeeta.Misra@Sun.COM ilb_status_t
ilb_close(ilb_handle_t h)119*10946SSangeeta.Misra@Sun.COM ilb_close(ilb_handle_t h)
120*10946SSangeeta.Misra@Sun.COM {
121*10946SSangeeta.Misra@Sun.COM ilb_handle_impl_t *hi = (ilb_handle_impl_t *)h;
122*10946SSangeeta.Misra@Sun.COM
123*10946SSangeeta.Misra@Sun.COM if (h == ILB_INVALID_HANDLE)
124*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_EINVAL);
125*10946SSangeeta.Misra@Sun.COM
126*10946SSangeeta.Misra@Sun.COM if (mutex_lock(&hi->h_lock) != 0)
127*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_INTERNAL);
128*10946SSangeeta.Misra@Sun.COM
129*10946SSangeeta.Misra@Sun.COM /* Somebody has done a close, no need to do anything. */
130*10946SSangeeta.Misra@Sun.COM if (hi->h_closing) {
131*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_OK);
132*10946SSangeeta.Misra@Sun.COM } else {
133*10946SSangeeta.Misra@Sun.COM hi->h_closing = B_TRUE;
134*10946SSangeeta.Misra@Sun.COM hi->h_error = ILB_STATUS_HANDLE_CLOSING;
135*10946SSangeeta.Misra@Sun.COM }
136*10946SSangeeta.Misra@Sun.COM
137*10946SSangeeta.Misra@Sun.COM /* Wait until there is nobody waiting. */
138*10946SSangeeta.Misra@Sun.COM while (hi->h_waiter > 0) {
139*10946SSangeeta.Misra@Sun.COM if (cond_wait(&hi->h_cv, &hi->h_lock) != 0) {
140*10946SSangeeta.Misra@Sun.COM (void) mutex_unlock(&hi->h_lock);
141*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_INTERNAL);
142*10946SSangeeta.Misra@Sun.COM }
143*10946SSangeeta.Misra@Sun.COM }
144*10946SSangeeta.Misra@Sun.COM /* No one is waiting, proceed to free the handle. */
145*10946SSangeeta.Misra@Sun.COM
146*10946SSangeeta.Misra@Sun.COM (void) close(hi->h_socket);
147*10946SSangeeta.Misra@Sun.COM (void) mutex_destroy(&hi->h_lock);
148*10946SSangeeta.Misra@Sun.COM (void) cond_destroy(&hi->h_cv);
149*10946SSangeeta.Misra@Sun.COM free(hi);
150*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_OK);
151*10946SSangeeta.Misra@Sun.COM }
152*10946SSangeeta.Misra@Sun.COM
153*10946SSangeeta.Misra@Sun.COM /*
154*10946SSangeeta.Misra@Sun.COM * Unified routine to communicate with ilbd.
155*10946SSangeeta.Misra@Sun.COM *
156*10946SSangeeta.Misra@Sun.COM * If ic is non-NULL, it means that the caller wants to send something
157*10946SSangeeta.Misra@Sun.COM * to ilbd and expects a reply. If ic is NULL, it means that the caller
158*10946SSangeeta.Misra@Sun.COM * only expects to receive from ilbd.
159*10946SSangeeta.Misra@Sun.COM *
160*10946SSangeeta.Misra@Sun.COM * The rbuf is the buffer supplied by the caller for receiving. If it
161*10946SSangeeta.Misra@Sun.COM * is NULL, it means that there is no reply expected.
162*10946SSangeeta.Misra@Sun.COM *
163*10946SSangeeta.Misra@Sun.COM * This function will not close() the socket to kernel unless there is
164*10946SSangeeta.Misra@Sun.COM * an error. If the transaction only consists of one exchange, the caller
165*10946SSangeeta.Misra@Sun.COM * can use i_ilb_close_comm() to close() the socket when done.
166*10946SSangeeta.Misra@Sun.COM */
167*10946SSangeeta.Misra@Sun.COM ilb_status_t
i_ilb_do_comm(ilb_handle_t h,ilb_comm_t * ic,size_t ic_sz,ilb_comm_t * rbuf,size_t * rbufsz)168*10946SSangeeta.Misra@Sun.COM i_ilb_do_comm(ilb_handle_t h, ilb_comm_t *ic, size_t ic_sz, ilb_comm_t *rbuf,
169*10946SSangeeta.Misra@Sun.COM size_t *rbufsz)
170*10946SSangeeta.Misra@Sun.COM {
171*10946SSangeeta.Misra@Sun.COM ilb_status_t rc = ILB_STATUS_OK;
172*10946SSangeeta.Misra@Sun.COM int r, s;
173*10946SSangeeta.Misra@Sun.COM ilb_handle_impl_t *hi = (ilb_handle_impl_t *)h;
174*10946SSangeeta.Misra@Sun.COM
175*10946SSangeeta.Misra@Sun.COM assert(rbuf != NULL);
176*10946SSangeeta.Misra@Sun.COM if (h == ILB_INVALID_HANDLE)
177*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_EINVAL);
178*10946SSangeeta.Misra@Sun.COM
179*10946SSangeeta.Misra@Sun.COM if (mutex_lock(&hi->h_lock) != 0)
180*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_INTERNAL);
181*10946SSangeeta.Misra@Sun.COM
182*10946SSangeeta.Misra@Sun.COM hi->h_waiter++;
183*10946SSangeeta.Misra@Sun.COM while (hi->h_busy) {
184*10946SSangeeta.Misra@Sun.COM if (cond_wait(&hi->h_cv, &hi->h_lock) != 0) {
185*10946SSangeeta.Misra@Sun.COM hi->h_waiter--;
186*10946SSangeeta.Misra@Sun.COM (void) cond_signal(&hi->h_cv);
187*10946SSangeeta.Misra@Sun.COM (void) mutex_unlock(&hi->h_lock);
188*10946SSangeeta.Misra@Sun.COM return (ILB_STATUS_INTERNAL);
189*10946SSangeeta.Misra@Sun.COM }
190*10946SSangeeta.Misra@Sun.COM }
191*10946SSangeeta.Misra@Sun.COM
192*10946SSangeeta.Misra@Sun.COM if (!hi->h_valid || hi->h_closing) {
193*10946SSangeeta.Misra@Sun.COM hi->h_waiter--;
194*10946SSangeeta.Misra@Sun.COM (void) cond_signal(&hi->h_cv);
195*10946SSangeeta.Misra@Sun.COM (void) mutex_unlock(&hi->h_lock);
196*10946SSangeeta.Misra@Sun.COM return (hi->h_error);
197*10946SSangeeta.Misra@Sun.COM }
198*10946SSangeeta.Misra@Sun.COM
199*10946SSangeeta.Misra@Sun.COM hi->h_busy = B_TRUE;
200*10946SSangeeta.Misra@Sun.COM (void) mutex_unlock(&hi->h_lock);
201*10946SSangeeta.Misra@Sun.COM
202*10946SSangeeta.Misra@Sun.COM s = hi->h_socket;
203*10946SSangeeta.Misra@Sun.COM
204*10946SSangeeta.Misra@Sun.COM r = send(s, ic, ic_sz, 0);
205*10946SSangeeta.Misra@Sun.COM if (r < ic_sz) {
206*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_WRITE;
207*10946SSangeeta.Misra@Sun.COM goto socket_error;
208*10946SSangeeta.Misra@Sun.COM }
209*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_OK;
210*10946SSangeeta.Misra@Sun.COM
211*10946SSangeeta.Misra@Sun.COM if ((r = recv(s, rbuf, *rbufsz, 0)) <= 0) {
212*10946SSangeeta.Misra@Sun.COM rc = ILB_STATUS_READ;
213*10946SSangeeta.Misra@Sun.COM } else {
214*10946SSangeeta.Misra@Sun.COM *rbufsz = r;
215*10946SSangeeta.Misra@Sun.COM goto out;
216*10946SSangeeta.Misra@Sun.COM }
217*10946SSangeeta.Misra@Sun.COM
218*10946SSangeeta.Misra@Sun.COM socket_error:
219*10946SSangeeta.Misra@Sun.COM i_ilb_socket_set_err(h, rc);
220*10946SSangeeta.Misra@Sun.COM
221*10946SSangeeta.Misra@Sun.COM out:
222*10946SSangeeta.Misra@Sun.COM (void) mutex_lock(&hi->h_lock);
223*10946SSangeeta.Misra@Sun.COM hi->h_busy = B_FALSE;
224*10946SSangeeta.Misra@Sun.COM hi->h_waiter--;
225*10946SSangeeta.Misra@Sun.COM (void) cond_signal(&hi->h_cv);
226*10946SSangeeta.Misra@Sun.COM (void) mutex_unlock(&hi->h_lock);
227*10946SSangeeta.Misra@Sun.COM
228*10946SSangeeta.Misra@Sun.COM return (rc);
229*10946SSangeeta.Misra@Sun.COM }
230*10946SSangeeta.Misra@Sun.COM
231*10946SSangeeta.Misra@Sun.COM void
i_ilb_close_comm(ilb_handle_t h)232*10946SSangeeta.Misra@Sun.COM i_ilb_close_comm(ilb_handle_t h)
233*10946SSangeeta.Misra@Sun.COM {
234*10946SSangeeta.Misra@Sun.COM (void) ilb_close(h);
235*10946SSangeeta.Misra@Sun.COM }
236