2 * vi: set autoindent tabstop=4 shiftwidth=4 :
4 * Copyright (c) 2002-2006 MontaVista Software, Inc.
5 * Copyright (c) 2006 Sun Microsystems, Inc.
9 * Author: Steven Dake (sdake@mvista.com)
11 * This software licensed under BSD license, the text of which follows:
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
16 * - Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * - Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 * - Neither the name of the MontaVista Software, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
44 #include <sys/ioctl.h>
45 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <sys/select.h>
52 #include <arpa/inet.h>
53 #include <netinet/in.h>
60 enum SA_HANDLE_STATE
{
61 SA_HANDLE_STATE_EMPTY
,
62 SA_HANDLE_STATE_PENDINGREMOVAL
,
63 SA_HANDLE_STATE_ACTIVE
73 #ifdef OPENAIS_SOLARIS
74 #define MSG_NOSIGNAL 0
77 #if defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS)
78 /* SUN_LEN is broken for abstract namespace
80 #define AIS_SUN_LEN(a) sizeof(*(a))
82 #define AIS_SUN_LEN(a) SUN_LEN(a)
86 static char *socketname
= "libais.socket";
88 static char *socketname
= "/var/run/libais.socket";
92 void socket_nosigpipe(int s
)
95 setsockopt(s
, SOL_SOCKET
, SO_NOSIGPIPE
, (void *)&on
, sizeof(on
));
103 enum service_types service
)
108 struct sockaddr_un address
;
109 mar_req_lib_response_init_t req_lib_response_init
;
110 mar_res_lib_response_init_t res_lib_response_init
;
111 mar_req_lib_dispatch_init_t req_lib_dispatch_init
;
112 mar_res_lib_dispatch_init_t res_lib_dispatch_init
;
117 * Allow set group id binaries to be authenticated
122 memset (&address
, 0, sizeof (struct sockaddr_un
));
123 #if defined(OPENAIS_BSD) || defined(OPENAIS_DARWIN)
124 address
.sun_len
= sizeof(struct sockaddr_un
);
126 address
.sun_family
= PF_UNIX
;
127 #if defined(OPENAIS_LINUX)
128 strcpy (address
.sun_path
+ 1, socketname
);
130 strcpy (address
.sun_path
, socketname
);
132 responseFD
= socket (PF_UNIX
, SOCK_STREAM
, 0);
133 if (responseFD
== -1) {
134 return (SA_AIS_ERR_NO_RESOURCES
);
137 socket_nosigpipe (responseFD
);
139 result
= connect (responseFD
, (struct sockaddr
*)&address
, AIS_SUN_LEN(&address
));
142 return (SA_AIS_ERR_TRY_AGAIN
);
145 req_lib_response_init
.resdis_header
.size
= sizeof (req_lib_response_init
);
146 req_lib_response_init
.resdis_header
.id
= MESSAGE_REQ_RESPONSE_INIT
;
147 req_lib_response_init
.resdis_header
.service
= service
;
149 error
= saSendRetry (responseFD
, &req_lib_response_init
,
150 sizeof (mar_req_lib_response_init_t
));
151 if (error
!= SA_AIS_OK
) {
154 error
= saRecvRetry (responseFD
, &res_lib_response_init
,
155 sizeof (mar_res_lib_response_init_t
));
156 if (error
!= SA_AIS_OK
) {
161 * Check for security errors
163 if (res_lib_response_init
.header
.error
!= SA_AIS_OK
) {
164 error
= res_lib_response_init
.header
.error
;
168 *responseOut
= responseFD
;
170 /* if I comment out the 4 lines below the executive crashes */
171 callbackFD
= socket (PF_UNIX
, SOCK_STREAM
, 0);
172 if (callbackFD
== -1) {
174 return (SA_AIS_ERR_NO_RESOURCES
);
177 socket_nosigpipe (callbackFD
);
179 result
= connect (callbackFD
, (struct sockaddr
*)&address
, AIS_SUN_LEN(&address
));
183 return (SA_AIS_ERR_TRY_AGAIN
);
186 req_lib_dispatch_init
.resdis_header
.size
= sizeof (req_lib_dispatch_init
);
187 req_lib_dispatch_init
.resdis_header
.id
= MESSAGE_REQ_DISPATCH_INIT
;
188 req_lib_dispatch_init
.resdis_header
.service
= service
;
190 req_lib_dispatch_init
.conn_info
= res_lib_response_init
.conn_info
;
192 error
= saSendRetry (callbackFD
, &req_lib_dispatch_init
,
193 sizeof (mar_req_lib_dispatch_init_t
));
194 if (error
!= SA_AIS_OK
) {
197 error
= saRecvRetry (callbackFD
, &res_lib_dispatch_init
,
198 sizeof (mar_res_lib_dispatch_init_t
));
199 if (error
!= SA_AIS_OK
) {
204 * Check for security errors
206 if (res_lib_dispatch_init
.header
.error
!= SA_AIS_OK
) {
207 error
= res_lib_dispatch_init
.header
.error
;
211 *callbackOut
= callbackFD
;
227 SaAisErrorT error
= SA_AIS_OK
;
229 struct msghdr msg_recv
;
230 struct iovec iov_recv
;
231 char *rbuf
= (char *)msg
;
234 msg_recv
.msg_iov
= &iov_recv
;
235 msg_recv
.msg_iovlen
= 1;
236 msg_recv
.msg_name
= 0;
237 msg_recv
.msg_namelen
= 0;
238 #ifndef OPENAIS_SOLARIS
239 msg_recv
.msg_control
= 0;
240 msg_recv
.msg_controllen
= 0;
241 msg_recv
.msg_flags
= 0;
243 msg_recv
.msg_accrights
= NULL
;
244 msg_recv
.msg_accrightslen
= 0;
248 iov_recv
.iov_base
= (void *)&rbuf
[processed
];
249 iov_recv
.iov_len
= len
- processed
;
251 result
= recvmsg (s
, &msg_recv
, MSG_NOSIGNAL
);
252 if (result
== -1 && errno
== EINTR
) {
255 if (result
== -1 && errno
== EAGAIN
) {
258 #if defined(OPENAIS_SOLARIS) || defined(OPENAIS_BSD) || defined(OPENAIS_DARWIN)
259 /* On many OS poll never return POLLHUP or POLLERR.
260 * EOF is detected when recvmsg return 0.
263 error
= SA_AIS_ERR_LIBRARY
;
267 if (result
== -1 || result
== 0) {
268 error
= SA_AIS_ERR_LIBRARY
;
272 if (processed
!= len
) {
275 assert (processed
== len
);
286 SaAisErrorT error
= SA_AIS_OK
;
288 struct msghdr msg_send
;
289 struct iovec iov_send
;
290 char *rbuf
= (char *)msg
;
293 msg_send
.msg_iov
= &iov_send
;
294 msg_send
.msg_iovlen
= 1;
295 msg_send
.msg_name
= 0;
296 msg_send
.msg_namelen
= 0;
297 #ifndef OPENAIS_SOLARIS
298 msg_send
.msg_control
= 0;
299 msg_send
.msg_controllen
= 0;
300 msg_send
.msg_flags
= 0;
302 msg_send
.msg_accrights
= NULL
;
303 msg_send
.msg_accrightslen
= 0;
307 iov_send
.iov_base
= (void *)&rbuf
[processed
];
308 iov_send
.iov_len
= len
- processed
;
310 result
= sendmsg (s
, &msg_send
, MSG_NOSIGNAL
);
313 * return immediately on any kind of syscall error that maps to
314 * SA_AIS_ERR if no part of message has been sent
316 if (result
== -1 && processed
== 0) {
317 if (errno
== EINTR
) {
318 error
= SA_AIS_ERR_TRY_AGAIN
;
321 if (errno
== EAGAIN
) {
322 error
= SA_AIS_ERR_TRY_AGAIN
;
325 if (errno
== EFAULT
) {
326 error
= SA_AIS_ERR_INVALID_PARAM
;
332 * retry read operations that are already started except
333 * for fault in that case, return ERR_LIBRARY
335 if (result
== -1 && processed
> 0) {
336 if (errno
== EINTR
) {
339 if (errno
== EAGAIN
) {
342 if (errno
== EFAULT
) {
343 error
= SA_AIS_ERR_LIBRARY
;
349 * return ERR_LIBRARY on any other syscall error
352 error
= SA_AIS_ERR_LIBRARY
;
357 if (processed
!= len
) {
365 SaAisErrorT
saSendMsgRetry (
370 SaAisErrorT error
= SA_AIS_OK
;
377 int iov_len_sendmsg
= iov_len
;
378 struct iovec
*iov_sendmsg
= iov
;
379 struct iovec iovec_save
;
380 int iovec_saved_position
= -1;
382 struct msghdr msg_send
;
384 for (i
= 0; i
< iov_len
; i
++) {
385 total_size
+= iov
[i
].iov_len
;
387 msg_send
.msg_iov
= iov_sendmsg
;
388 msg_send
.msg_iovlen
= iov_len_sendmsg
;
389 msg_send
.msg_name
= 0;
390 msg_send
.msg_namelen
= 0;
391 #ifndef OPENAIS_SOLARIS
392 msg_send
.msg_control
= 0;
393 msg_send
.msg_controllen
= 0;
394 msg_send
.msg_flags
= 0;
396 msg_send
.msg_accrights
= NULL
;
397 msg_send
.msg_accrightslen
= 0;
401 result
= sendmsg (s
, &msg_send
, MSG_NOSIGNAL
);
403 * Can't send now, and message not committed, so don't retry send
405 if (result
== -1 && iovec_saved_position
== -1) {
406 if (errno
== EINTR
) {
407 error
= SA_AIS_ERR_TRY_AGAIN
;
410 if (errno
== EAGAIN
) {
411 error
= SA_AIS_ERR_TRY_AGAIN
;
414 if (errno
== EFAULT
) {
415 error
= SA_AIS_ERR_INVALID_PARAM
;
421 * Retry (and block) if portion of message has already been written
423 if (result
== -1 && iovec_saved_position
!= -1) {
424 if (errno
== EINTR
) {
427 if (errno
== EAGAIN
) {
430 if (errno
== EFAULT
) {
431 error
= SA_AIS_ERR_LIBRARY
;
437 * ERR_LIBRARY for any other syscall error
440 error
= SA_AIS_ERR_LIBRARY
;
444 if (iovec_saved_position
!= -1) {
445 memcpy (&iov
[iovec_saved_position
], &iovec_save
, sizeof (struct iovec
));
448 total_sent
+= result
;
449 if (total_sent
!= total_size
) {
450 for (i
= 0, csize
= 0, csize_cntr
= 0; i
< iov_len
; i
++) {
451 csize
+= iov
[i
].iov_len
;
452 if (csize
> total_sent
) {
456 csize_cntr
+= iov
[i
].iov_len
;
458 memcpy (&iovec_save
, &iov
[i
], sizeof (struct iovec
));
459 iovec_saved_position
= i
;
460 iov
[i
].iov_base
= ((char *)(iov
[i
].iov_base
)) +
461 (total_sent
- csize_cntr
);
462 iov
[i
].iov_len
= total_size
- total_sent
;
463 msg_send
.msg_iov
= &iov
[i
];
464 msg_send
.msg_iovlen
= iov_len
- i
;
473 SaAisErrorT
saSendMsgReceiveReply (
477 void *responseMessage
,
480 SaAisErrorT error
= SA_AIS_OK
;
482 error
= saSendMsgRetry (s
, iov
, iov_len
);
483 if (error
!= SA_AIS_OK
) {
487 error
= saRecvRetry (s
, responseMessage
, responseLen
);
488 if (error
!= SA_AIS_OK
) {
496 SaAisErrorT
saSendReceiveReply (
498 void *requestMessage
,
500 void *responseMessage
,
503 SaAisErrorT error
= SA_AIS_OK
;
505 error
= saSendRetry (s
, requestMessage
, requestLen
);
506 if (error
!= SA_AIS_OK
) {
510 error
= saRecvRetry (s
, responseMessage
, responseLen
);
511 if (error
!= SA_AIS_OK
) {
525 SaAisErrorT error
= SA_AIS_OK
;
529 result
= poll (ufds
, nfds
, timeout
);
530 if (result
== -1 && errno
== EINTR
) {
534 error
= SA_AIS_ERR_LIBRARY
;
543 struct saHandleDatabase
*handleDatabase
,
545 SaUint64T
*handleOut
)
554 pthread_mutex_lock (&handleDatabase
->mutex
);
556 for (handle
= 0; handle
< handleDatabase
->handleCount
; handle
++) {
557 if (handleDatabase
->handles
[handle
].state
== SA_HANDLE_STATE_EMPTY
) {
564 handleDatabase
->handleCount
+= 1;
565 newHandles
= (struct saHandle
*)realloc (handleDatabase
->handles
,
566 sizeof (struct saHandle
) * handleDatabase
->handleCount
);
567 if (newHandles
== NULL
) {
568 pthread_mutex_unlock (&handleDatabase
->mutex
);
569 return (SA_AIS_ERR_NO_MEMORY
);
571 handleDatabase
->handles
= newHandles
;
574 instance
= malloc (instanceSize
);
577 pthread_mutex_unlock (&handleDatabase
->mutex
);
578 return (SA_AIS_ERR_NO_MEMORY
);
583 * This code makes sure the random number isn't zero
584 * We use 0 to specify an invalid handle out of the 1^64 address space
585 * If we get 0 200 times in a row, the RNG may be broken
587 for (i
= 0; i
< 200; i
++) {
594 memset (instance
, 0, instanceSize
);
596 handleDatabase
->handles
[handle
].state
= SA_HANDLE_STATE_ACTIVE
;
598 handleDatabase
->handles
[handle
].instance
= instance
;
600 handleDatabase
->handles
[handle
].refCount
= 1;
602 handleDatabase
->handles
[handle
].check
= check
;
604 *handleOut
= (SaUint64T
)((uint64_t)check
<< 32 | handle
);
606 pthread_mutex_unlock (&handleDatabase
->mutex
);
614 struct saHandleDatabase
*handleDatabase
,
617 SaAisErrorT error
= SA_AIS_OK
;
618 uint32_t check
= inHandle
>> 32;
619 uint32_t handle
= inHandle
& 0xffffffff;
621 pthread_mutex_lock (&handleDatabase
->mutex
);
623 if (check
!= handleDatabase
->handles
[handle
].check
) {
624 pthread_mutex_unlock (&handleDatabase
->mutex
);
625 error
= SA_AIS_ERR_BAD_HANDLE
;
629 handleDatabase
->handles
[handle
].state
= SA_HANDLE_STATE_PENDINGREMOVAL
;
631 pthread_mutex_unlock (&handleDatabase
->mutex
);
633 saHandleInstancePut (handleDatabase
, inHandle
);
640 saHandleInstanceGet (
641 struct saHandleDatabase
*handleDatabase
,
645 uint32_t check
= inHandle
>> 32;
646 uint32_t handle
= inHandle
& 0xffffffff;
648 SaAisErrorT error
= SA_AIS_OK
;
649 pthread_mutex_lock (&handleDatabase
->mutex
);
651 if (handle
>= (SaUint64T
)handleDatabase
->handleCount
) {
652 error
= SA_AIS_ERR_BAD_HANDLE
;
655 if (handleDatabase
->handles
[handle
].state
!= SA_HANDLE_STATE_ACTIVE
) {
656 error
= SA_AIS_ERR_BAD_HANDLE
;
659 if (check
!= handleDatabase
->handles
[handle
].check
) {
660 error
= SA_AIS_ERR_BAD_HANDLE
;
665 *instance
= handleDatabase
->handles
[handle
].instance
;
667 handleDatabase
->handles
[handle
].refCount
+= 1;
670 pthread_mutex_unlock (&handleDatabase
->mutex
);
677 saHandleInstancePut (
678 struct saHandleDatabase
*handleDatabase
,
682 SaAisErrorT error
= SA_AIS_OK
;
683 uint32_t check
= inHandle
>> 32;
684 uint32_t handle
= inHandle
& 0xffffffff;
686 pthread_mutex_lock (&handleDatabase
->mutex
);
688 if (check
!= handleDatabase
->handles
[handle
].check
) {
689 error
= SA_AIS_ERR_BAD_HANDLE
;
693 handleDatabase
->handles
[handle
].refCount
-= 1;
694 assert (handleDatabase
->handles
[handle
].refCount
>= 0);
696 if (handleDatabase
->handles
[handle
].refCount
== 0) {
697 instance
= (handleDatabase
->handles
[handle
].instance
);
698 handleDatabase
->handleInstanceDestructor (instance
);
700 memset (&handleDatabase
->handles
[handle
], 0, sizeof (struct saHandle
));
704 pthread_mutex_unlock (&handleDatabase
->mutex
);
712 struct saVersionDatabase
*versionDatabase
,
716 SaAisErrorT error
= SA_AIS_ERR_VERSION
;
719 return (SA_AIS_ERR_INVALID_PARAM
);
723 * Look for a release code that we support. If we find it then
724 * make sure that the supported major version is >= to the required one.
725 * In any case we return what we support in the version structure.
727 for (i
= 0; i
< versionDatabase
->versionCount
; i
++) {
730 * Check if the caller requires and old release code that we don't support.
732 if (version
->releaseCode
< versionDatabase
->versionsSupported
[i
].releaseCode
) {
737 * Check if we can support this release code.
739 if (version
->releaseCode
== versionDatabase
->versionsSupported
[i
].releaseCode
) {
742 * Check if we can support the major version requested.
744 if (versionDatabase
->versionsSupported
[i
].majorVersion
>= version
->majorVersion
) {
750 * We support the release code, but not the major version.
757 * If we fall out of the if loop, the caller requires a release code
758 * beyond what we support.
760 if (i
== versionDatabase
->versionCount
) {
761 i
= versionDatabase
->versionCount
- 1;
765 * Tell the caller what we support
767 memcpy(version
, &versionDatabase
->versionsSupported
[i
], sizeof(*version
));
772 * Get the time of day and convert to nanoseconds
774 SaTimeT
clustTimeNow(void)
779 if (gettimeofday(&tv
, 0)) {
783 time_now
= (SaTimeT
)(tv
.tv_sec
) * 1000000000ULL;
784 time_now
+= (SaTimeT
)(tv
.tv_usec
) * 1000ULL;