*/
#include "dlmclient.h"
+
+#include "dlm-protocol.h"
#include "log.h"
#include "socket-path.h"
if (!sockaddr_set_lease_server_path(&sa, name))
return false;
- int dlm_server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ int dlm_server_sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (dlm_server_sock < 0) {
DEBUG_LOG("Socket creation failed: %s\n", strerror(errno));
return false;
return true;
}
-static bool lease_recv_fd(struct dlm_lease *lease)
+static bool lease_send_request(struct dlm_lease *lease, enum dlm_opcode opcode)
{
- char ctrl_buf[CMSG_SPACE(sizeof(int))] = {0};
- char data[1] = {0};
-
- struct iovec iov[1];
- iov[0].iov_base = data;
- iov[0].iov_len = sizeof(data);
-
- struct msghdr msg = {
- .msg_control = ctrl_buf,
- .msg_controllen = CMSG_SPACE(sizeof(int)),
- .msg_iov = iov,
- .msg_iovlen = 1,
+ struct dlm_client_request request = {
+ .opcode = opcode,
};
- int ret;
- while ((ret = recvmsg(lease->dlm_server_sock, &msg, 0)) <= 0) {
- if (ret == 0) {
- errno = EACCES;
- DEBUG_LOG("Request rejected by DRM lease manager\n");
- // TODO: Report why the request was rejected.
- return false;
- }
- if (errno != EINTR) {
- DEBUG_LOG("Socket data receive error: %s\n",
- strerror(errno));
- return false;
- }
+ if (!send_dlm_client_request(lease->dlm_server_sock, &request)) {
+ DEBUG_LOG("Socket data send error: %s\n", strerror(errno));
+ return false;
}
+ return true;
+}
- lease->lease_fd = -1;
- struct cmsghdr *cmsg;
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- int nfds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
- int *fds = (int *)CMSG_DATA(cmsg);
-
- if (nfds == 1) {
- lease->lease_fd = fds[0];
- break;
- }
-
- DEBUG_LOG(
- "Expected 1 fd from lease manager. Received %d\n",
- nfds);
- /* Close any unexpected fds so we don't leak them. */
- for (int i = 0; i < nfds; i++)
- close(fds[i]);
- break;
- }
- }
+static bool lease_recv_fd(struct dlm_lease *lease)
+{
+ lease->lease_fd = receive_lease_fd(lease->dlm_server_sock);
- if (lease->lease_fd < 0) {
- DEBUG_LOG("Expected data not received from lease manager\n");
- errno = EPROTO;
- return false;
- }
+ if (lease->lease_fd < 0)
+ goto err;
return true;
+
+err:
+ switch (errno) {
+ case EACCES:
+ DEBUG_LOG("Lease request rejected by DRM lease manager\n");
+ break;
+ case EPROTO:
+ DEBUG_LOG("Unexpected data received from lease manager\n");
+ break;
+ default:
+ DEBUG_LOG("Lease manager receive data error: %s\n",
+ strerror(errno));
+ break;
+ }
+ return false;
}
struct dlm_lease *dlm_get_lease(const char *name)
{
+ int saved_errno;
struct dlm_lease *lease = calloc(1, sizeof(struct dlm_lease));
if (!lease) {
DEBUG_LOG("can't allocate memory : %s\n", strerror(errno));
return NULL;
}
- if (!lease_recv_fd(lease)) {
- close(lease->dlm_server_sock);
- free(lease);
- return NULL;
- }
+ if (!lease_send_request(lease, DLM_GET_LEASE))
+ goto err_request;
+
+ if (!lease_recv_fd(lease))
+ goto err;
return lease;
+
+err:
+ saved_errno = errno;
+ lease_send_request(lease, DLM_RELEASE_LEASE);
+ errno = saved_errno;
+err_request:
+ close(lease->dlm_server_sock);
+ free(lease);
+ return NULL;
}
void dlm_release_lease(struct dlm_lease *lease)
if (!lease)
return;
+ lease_send_request(lease, DLM_RELEASE_LEASE);
close(lease->lease_fd);
close(lease->dlm_server_sock);
free(lease);