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