monitor_fdpass.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* $OpenBSD: monitor_fdpass.c,v 1.21 2016/02/29 20:22:36 jca Exp $ */
  2. /*
  3. * Copyright 2001 Niels Provos <provos@citi.umich.edu>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "includes.h"
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. #include <sys/uio.h>
  30. #ifdef HAVE_SYS_UN_H
  31. #include <sys/un.h>
  32. #endif
  33. #include <errno.h>
  34. #include <string.h>
  35. #include <stdarg.h>
  36. #ifdef HAVE_POLL_H
  37. # include <poll.h>
  38. #else
  39. # ifdef HAVE_SYS_POLL_H
  40. # include <sys/poll.h>
  41. # endif
  42. #endif
  43. #include "log.h"
  44. #include "monitor_fdpass.h"
  45. int
  46. mm_send_fd(int sock, int fd)
  47. {
  48. #if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
  49. struct msghdr msg;
  50. #ifndef HAVE_ACCRIGHTS_IN_MSGHDR
  51. union {
  52. struct cmsghdr hdr;
  53. char buf[CMSG_SPACE(sizeof(int))];
  54. } cmsgbuf;
  55. struct cmsghdr *cmsg;
  56. #endif
  57. struct iovec vec;
  58. char ch = '\0';
  59. ssize_t n;
  60. struct pollfd pfd;
  61. memset(&msg, 0, sizeof(msg));
  62. #ifdef HAVE_ACCRIGHTS_IN_MSGHDR
  63. msg.msg_accrights = (caddr_t)&fd;
  64. msg.msg_accrightslen = sizeof(fd);
  65. #else
  66. memset(&cmsgbuf, 0, sizeof(cmsgbuf));
  67. msg.msg_control = (caddr_t)&cmsgbuf.buf;
  68. msg.msg_controllen = sizeof(cmsgbuf.buf);
  69. cmsg = CMSG_FIRSTHDR(&msg);
  70. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  71. cmsg->cmsg_level = SOL_SOCKET;
  72. cmsg->cmsg_type = SCM_RIGHTS;
  73. *(int *)CMSG_DATA(cmsg) = fd;
  74. #endif
  75. vec.iov_base = &ch;
  76. vec.iov_len = 1;
  77. msg.msg_iov = &vec;
  78. msg.msg_iovlen = 1;
  79. pfd.fd = sock;
  80. pfd.events = POLLOUT;
  81. while ((n = sendmsg(sock, &msg, 0)) == -1 &&
  82. (errno == EAGAIN || errno == EINTR)) {
  83. debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno));
  84. (void)poll(&pfd, 1, -1);
  85. }
  86. if (n == -1) {
  87. error("%s: sendmsg(%d): %s", __func__, fd,
  88. strerror(errno));
  89. return -1;
  90. }
  91. if (n != 1) {
  92. error("%s: sendmsg: expected sent 1 got %zd", __func__, n);
  93. return -1;
  94. }
  95. return 0;
  96. #else
  97. error("%s: file descriptor passing not supported", __func__);
  98. return -1;
  99. #endif
  100. }
  101. int
  102. mm_receive_fd(int sock)
  103. {
  104. #if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
  105. struct msghdr msg;
  106. #ifndef HAVE_ACCRIGHTS_IN_MSGHDR
  107. union {
  108. struct cmsghdr hdr;
  109. char buf[CMSG_SPACE(sizeof(int))];
  110. } cmsgbuf;
  111. struct cmsghdr *cmsg;
  112. #endif
  113. struct iovec vec;
  114. ssize_t n;
  115. char ch;
  116. int fd;
  117. struct pollfd pfd;
  118. memset(&msg, 0, sizeof(msg));
  119. vec.iov_base = &ch;
  120. vec.iov_len = 1;
  121. msg.msg_iov = &vec;
  122. msg.msg_iovlen = 1;
  123. #ifdef HAVE_ACCRIGHTS_IN_MSGHDR
  124. msg.msg_accrights = (caddr_t)&fd;
  125. msg.msg_accrightslen = sizeof(fd);
  126. #else
  127. memset(&cmsgbuf, 0, sizeof(cmsgbuf));
  128. msg.msg_control = &cmsgbuf.buf;
  129. msg.msg_controllen = sizeof(cmsgbuf.buf);
  130. #endif
  131. pfd.fd = sock;
  132. pfd.events = POLLIN;
  133. while ((n = recvmsg(sock, &msg, 0)) == -1 &&
  134. (errno == EAGAIN || errno == EINTR)) {
  135. debug3("%s: recvmsg: %s", __func__, strerror(errno));
  136. (void)poll(&pfd, 1, -1);
  137. }
  138. if (n == -1) {
  139. error("%s: recvmsg: %s", __func__, strerror(errno));
  140. return -1;
  141. }
  142. if (n != 1) {
  143. error("%s: recvmsg: expected received 1 got %zd", __func__, n);
  144. return -1;
  145. }
  146. #ifdef HAVE_ACCRIGHTS_IN_MSGHDR
  147. if (msg.msg_accrightslen != sizeof(fd)) {
  148. error("%s: no fd", __func__);
  149. return -1;
  150. }
  151. #else
  152. cmsg = CMSG_FIRSTHDR(&msg);
  153. if (cmsg == NULL) {
  154. error("%s: no message header", __func__);
  155. return -1;
  156. }
  157. #ifndef BROKEN_CMSG_TYPE
  158. if (cmsg->cmsg_type != SCM_RIGHTS) {
  159. error("%s: expected type %d got %d", __func__,
  160. SCM_RIGHTS, cmsg->cmsg_type);
  161. return -1;
  162. }
  163. #endif
  164. fd = (*(int *)CMSG_DATA(cmsg));
  165. #endif
  166. return fd;
  167. #else
  168. error("%s: file descriptor passing not supported", __func__);
  169. return -1;
  170. #endif
  171. }