pass_fd.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (C) 2001-2003 FhG Fokus
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /*!
  21. * \file
  22. * \brief Kamailio core ::
  23. * \ingroup core
  24. * Module: \ref core
  25. */
  26. #ifdef USE_TCP
  27. #include "pass_fd.h"
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <sys/uio.h>
  31. #include <stdlib.h> /* for NULL definition on openbsd */
  32. #include <errno.h>
  33. #include <string.h>
  34. #ifdef NO_MSG_WAITALL
  35. #include <poll.h>
  36. #endif /* NO_MSG_WAITALL */
  37. #include "dprint.h"
  38. /** receive all the data or returns error (handles EINTR etc.)
  39. * params: socket
  40. * data - buffer for the results
  41. * data_len -
  42. * flags - recv flags for the first recv (see recv(2)), only
  43. * 0, MSG_WAITALL and MSG_DONTWAIT make sense
  44. * if flags is set to MSG_DONWAIT (or to 0 and the socket fd is non-blocking),
  45. * and if no data is queued on the fd, recv_all will not wait (it will
  46. * return error and set errno to EAGAIN/EWOULDBLOCK). However if even 1 byte
  47. * is queued, the call will block until the whole data_len was read or an
  48. * error or eof occured ("semi-nonblocking" behaviour, some tcp code
  49. * counts on it).
  50. * if flags is set to MSG_WAITALL it will block even if no byte is available.
  51. *
  52. * returns: bytes read or error (<0)
  53. * can return < data_len if EOF */
  54. int recv_all(int socket, void* data, int data_len, int flags)
  55. {
  56. int b_read;
  57. int n;
  58. #ifdef NO_MSG_WAITALL
  59. struct pollfd pfd;
  60. #endif /* NO_MSG_WAITALL */
  61. b_read=0;
  62. again:
  63. #ifdef NO_MSG_WAITALL
  64. if (flags & MSG_WAITALL){
  65. n=-1;
  66. goto poll_recv; /* simulate MSG_WAITALL */
  67. }
  68. #endif /* NO_MSG_WAITALL */
  69. n=recv(socket, (char*)data, data_len, flags);
  70. if (n<0){
  71. /* error */
  72. if (errno==EINTR) goto again; /* signal, try again */
  73. /* on EAGAIN just return (let the caller know) */
  74. if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) return n;
  75. LM_CRIT("1st recv on %d failed: %s\n",
  76. socket, strerror(errno));
  77. return n;
  78. }
  79. b_read+=n;
  80. while( (b_read!=data_len) && (n)){
  81. #ifdef NO_MSG_WAITALL
  82. /* cygwin & win do not support MSG_WAITALL => workaround using poll */
  83. poll_recv:
  84. n=recv(socket, (char*)data+b_read, data_len-b_read, 0);
  85. #else /* NO_MSG_WAITALL */
  86. n=recv(socket, (char*)data+b_read, data_len-b_read, MSG_WAITALL);
  87. #endif /* NO_MSG_WAITALL */
  88. if (n<0){
  89. /* error */
  90. if (errno==EINTR) continue; /* signal, try again */
  91. #ifdef NO_MSG_WAITALL
  92. if (errno==EAGAIN || errno==EWOULDBLOCK){
  93. /* emulate MSG_WAITALL using poll */
  94. pfd.fd=socket;
  95. pfd.events=POLLIN;
  96. poll_retry:
  97. n=poll(&pfd, 1, -1);
  98. if (n<0){
  99. if (errno==EINTR) goto poll_retry;
  100. LM_CRIT("poll on %d failed: %s\n",
  101. socket, strerror(errno));
  102. return n;
  103. } else continue; /* try recv again */
  104. }
  105. #endif /* NO_MSG_WAITALL */
  106. LM_CRIT("2nd recv on %d failed: %s\n",
  107. socket, strerror(errno));
  108. return n;
  109. }
  110. b_read+=n;
  111. }
  112. return b_read;
  113. }
  114. /** sends all data (takes care of signals) (assumes blocking fd)
  115. * returns number of bytes sent or < 0 for an error */
  116. int send_all(int socket, void* data, int data_len)
  117. {
  118. int n;
  119. again:
  120. n=send(socket, data, data_len, 0);
  121. if (n<0){
  122. /* error */
  123. if (errno==EINTR) goto again; /* signal, try again */
  124. if ((errno!=EAGAIN) &&(errno!=EWOULDBLOCK))
  125. LM_CRIT("send on %d failed: %s\n",
  126. socket, strerror(errno));
  127. }
  128. return n;
  129. }
  130. /** at least 1 byte must be sent! */
  131. int send_fd(int unix_socket, void* data, int data_len, int fd)
  132. {
  133. struct msghdr msg;
  134. struct iovec iov[1];
  135. int ret;
  136. #ifdef HAVE_MSGHDR_MSG_CONTROL
  137. int* pi;
  138. struct cmsghdr* cmsg;
  139. /* make sure msg_control will point to properly aligned data */
  140. union {
  141. struct cmsghdr cm;
  142. char control[CMSG_SPACE(sizeof(fd))];
  143. }control_un;
  144. msg.msg_control=control_un.control;
  145. /* openbsd doesn't like "more space", msg_controllen must not
  146. * include the end padding */
  147. msg.msg_controllen=CMSG_LEN(sizeof(fd));
  148. cmsg=CMSG_FIRSTHDR(&msg);
  149. cmsg->cmsg_level = SOL_SOCKET;
  150. cmsg->cmsg_type = SCM_RIGHTS;
  151. cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
  152. pi=(int*)CMSG_DATA(cmsg);
  153. *pi=fd;
  154. msg.msg_flags=0;
  155. #else
  156. msg.msg_accrights=(caddr_t) &fd;
  157. msg.msg_accrightslen=sizeof(fd);
  158. #endif
  159. msg.msg_name=0;
  160. msg.msg_namelen=0;
  161. iov[0].iov_base=data;
  162. iov[0].iov_len=data_len;
  163. msg.msg_iov=iov;
  164. msg.msg_iovlen=1;
  165. again:
  166. ret=sendmsg(unix_socket, &msg, 0);
  167. if (ret<0){
  168. if (errno==EINTR) goto again;
  169. if ((errno!=EAGAIN) && (errno!=EWOULDBLOCK))
  170. LM_CRIT("sendmsg failed sending %d on %d: %s (%d)\n",
  171. fd, unix_socket, strerror(errno), errno);
  172. }
  173. return ret;
  174. }
  175. /** receives a fd and data_len data
  176. * params: unix_socket
  177. * data
  178. * data_len
  179. * fd - will be set to the passed fd value or -1 if no fd
  180. * was passed
  181. * flags - 0, MSG_DONTWAIT, MSG_WAITALL; same as recv_all flags
  182. * returns: bytes read on success, -1 on error (and sets errno) */
  183. int receive_fd(int unix_socket, void* data, int data_len, int* fd, int flags)
  184. {
  185. struct msghdr msg;
  186. struct iovec iov[1];
  187. int new_fd;
  188. int ret;
  189. int n;
  190. #ifdef NO_MSG_WAITALL
  191. struct pollfd pfd;
  192. int f;
  193. #endif /*NO_MSG_WAITALL */
  194. #ifdef HAVE_MSGHDR_MSG_CONTROL
  195. int* pi;
  196. struct cmsghdr* cmsg;
  197. union{
  198. struct cmsghdr cm;
  199. char control[CMSG_SPACE(sizeof(new_fd))];
  200. }control_un;
  201. msg.msg_control=control_un.control;
  202. msg.msg_controllen=sizeof(control_un.control);
  203. #else
  204. msg.msg_accrights=(caddr_t) &new_fd;
  205. msg.msg_accrightslen=sizeof(int);
  206. #endif
  207. msg.msg_name=0;
  208. msg.msg_namelen=0;
  209. iov[0].iov_base=data;
  210. iov[0].iov_len=data_len;
  211. msg.msg_iov=iov;
  212. msg.msg_iovlen=1;
  213. #ifdef NO_MSG_WAITALL
  214. f=flags & ~MSG_WAITALL;
  215. #endif /* NO_MSG_WAITALL */
  216. again:
  217. #ifdef NO_MSG_WAITALL
  218. ret=recvmsg(unix_socket, &msg, f);
  219. #else /* NO_MSG_WAITALL */
  220. ret=recvmsg(unix_socket, &msg, flags);
  221. #endif /* NO_MSG_WAITALL */
  222. if (ret<0){
  223. if (errno==EINTR) goto again;
  224. if ((errno==EAGAIN)||(errno==EWOULDBLOCK)){
  225. #ifdef NO_MSG_WAITALL
  226. if (flags & MSG_WAITALL){
  227. /* emulate MSG_WAITALL using poll */
  228. pfd.fd=unix_socket;
  229. pfd.events=POLLIN;
  230. poll_again:
  231. ret=poll(&pfd, 1, -1);
  232. if (ret>=0) goto again;
  233. else if (errno==EINTR) goto poll_again;
  234. LM_CRIT("poll on %d failed: %s\n",
  235. unix_socket, strerror(errno));
  236. }
  237. #endif /* NO_MSG_WAITALL */
  238. goto error;
  239. }
  240. LM_CRIT("recvmsg on %d failed: %s\n",
  241. unix_socket, strerror(errno));
  242. goto error;
  243. }
  244. if (ret==0){
  245. /* EOF */
  246. LM_CRIT("EOF on %d\n", unix_socket);
  247. goto error;
  248. }
  249. if (ret<data_len){
  250. LM_WARN("too few bytes read (%d from %d) trying to fix...\n",
  251. ret, data_len);
  252. /* blocking recv_all */
  253. n=recv_all(unix_socket, (char*)data+ret, data_len-ret, MSG_WAITALL);
  254. if (n>=0) ret+=n;
  255. else{
  256. ret=n;
  257. goto error;
  258. }
  259. }
  260. #ifdef HAVE_MSGHDR_MSG_CONTROL
  261. cmsg=CMSG_FIRSTHDR(&msg);
  262. if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
  263. if (cmsg->cmsg_type!= SCM_RIGHTS){
  264. LM_ERR("msg control type != SCM_RIGHTS\n");
  265. ret=-1;
  266. goto error;
  267. }
  268. if (cmsg->cmsg_level!= SOL_SOCKET){
  269. LM_ERR("msg level != SOL_SOCKET\n");
  270. ret=-1;
  271. goto error;
  272. }
  273. pi=(int*) CMSG_DATA(cmsg);
  274. *fd=*pi;
  275. }else{
  276. /*LM_ERR("no descriptor passed, cmsg=%p, len=%d\n",
  277. cmsg, (unsigned)cmsg->cmsg_len); */
  278. *fd=-1;
  279. /* it's not really an error */
  280. }
  281. #else
  282. if (msg.msg_accrightslen==sizeof(int)){
  283. *fd=new_fd;
  284. }else{
  285. /*LM_ERR("no descriptor passed, accrightslen=%d\n",
  286. msg.msg_accrightslen); */
  287. *fd=-1;
  288. }
  289. #endif
  290. error:
  291. return ret;
  292. }
  293. #endif