aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/dlm-protocol.c83
-rw-r--r--common/dlm-protocol.h2
2 files changed, 85 insertions, 0 deletions
diff --git a/common/dlm-protocol.c b/common/dlm-protocol.c
index 4fc87b2..79aa86f 100644
--- a/common/dlm-protocol.c
+++ b/common/dlm-protocol.c
@@ -64,3 +64,86 @@ bool send_dlm_client_request(int socket, struct dlm_client_request *request)
}
return true;
}
+
+int receive_lease_fd(int socket)
+{
+ int lease_fd = -1;
+ char ctrl_buf[CMSG_SPACE(sizeof(lease_fd))];
+
+ char data;
+ struct iovec iov = {.iov_base = &data, .iov_len = sizeof(data)};
+ struct msghdr msg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = ctrl_buf,
+ .msg_controllen = sizeof(ctrl_buf),
+ };
+
+ ssize_t len;
+ while ((len = recvmsg(socket, &msg, 0)) <= 0) {
+ if (len == 0) {
+ errno = EACCES;
+ goto err;
+ }
+
+ if (errno != EINTR)
+ goto err;
+ }
+
+ 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_fd = fds[0];
+ break;
+ }
+
+ /* Close any unexpected fds so we don't leak them. */
+ for (int i = 0; i < nfds; i++)
+ close(fds[i]);
+ break;
+ }
+ }
+
+ if (lease_fd < 0) {
+ errno = EPROTO;
+ goto err;
+ }
+
+err:
+ return lease_fd;
+}
+
+bool send_lease_fd(int socket, int lease)
+{
+ char data;
+ struct iovec iov = {
+ .iov_base = &data,
+ .iov_len = sizeof(data),
+ };
+
+ char ctrl_buf[CMSG_SPACE(sizeof(lease))] = {0};
+
+ struct msghdr msg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_controllen = sizeof(ctrl_buf),
+ .msg_control = ctrl_buf,
+ };
+
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(lease));
+ *((int *)CMSG_DATA(cmsg)) = lease;
+
+ if (sendmsg(socket, &msg, 0) < 0)
+ return false;
+
+ return true;
+}
diff --git a/common/dlm-protocol.h b/common/dlm-protocol.h
index 44785e5..c7e1327 100644
--- a/common/dlm-protocol.h
+++ b/common/dlm-protocol.h
@@ -29,4 +29,6 @@ struct dlm_client_request {
bool receive_dlm_client_request(int socket, struct dlm_client_request *request);
bool send_dlm_client_request(int socket, struct dlm_client_request *request);
+int receive_lease_fd(int socket);
+bool send_lease_fd(int socket, int lease);
#endif