Beispiel #1
0
ssize_t py_recv(int fd, void *buf, size_t len, int *cdata)
{
	struct msghdr msg = {0};
	struct iovec iov = {0};
	size_t cmsglen = CMSG_SPACE(sizeof(int));
	char control[CMSG_SPACE(sizeof(int))];
	struct cmsghdr *cmsg;
	ssize_t ret;

	iov.iov_base = buf;
	iov.iov_len = len;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	if (cdata != NULL) {
		msg.msg_control = control;
		msg.msg_controllen = cmsglen;
	}

	ret = recvmsg(fd, &msg, 0);
	if (ret == -1 || cdata == NULL) {
		return ret;
	}

	cmsg = CMSG_FIRSTHDR(&msg);
	if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int))
	    || cmsg->cmsg_level != SOL_SOCKET
	    || cmsg->cmsg_type != SCM_RIGHTS) {
		*cdata = -1;
	} else {
		*cdata = get_unaligned_int(CMSG_DATA(cmsg));
	}

	return ret;
}
Beispiel #2
0
/* receives a fd and data_len data
 * params: unix_socket
 *         data
 *         data_len
 *         fd         - will be set to the passed fd value or -1 if no fd
 *                      was passed
 *         flags      - 0, MSG_DONTWAIT, MSG_WAITALL; same as recv_all flags
 * returns: bytes read on success, -1 on error (and sets errno) */
int receive_fd(int unix_socket, void* data, int data_len, int* fd, int flags)
{
	struct msghdr msg;
	struct iovec iov[1];
	int new_fd;
	int ret;
	int n;
#ifdef HAVE_MSGHDR_MSG_CONTROL
	struct cmsghdr* cmsg;
	union{
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(new_fd))];
	}control_un;

	msg.msg_control=control_un.control;
	msg.msg_controllen=sizeof(control_un.control);
#else
	msg.msg_accrights=(caddr_t) &new_fd;
	msg.msg_accrightslen=sizeof(int);
#endif

	msg.msg_name=0;
	msg.msg_namelen=0;

	iov[0].iov_base=data;
	iov[0].iov_len=data_len;
	msg.msg_iov=iov;
	msg.msg_iovlen=1;

again:
	ret=recvmsg(unix_socket, &msg, flags);
	if (ret<0){
		if (errno==EINTR) goto again;
		if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) goto error;
		LM_CRIT("recvmsg on %d failed: %s\n", unix_socket, strerror(errno));
		goto error;
	}
	if (ret==0){
		/* EOF */
		LM_CRIT("EOF on %d\n", unix_socket);
		goto error;
	}
	if (ret<data_len){
		LM_WARN("too few bytes read (%d from %d) trying to fix...\n",
				ret, data_len);
		/* blocking recv_all */
		n=recv_all(unix_socket, (char*)data+ret, data_len-ret, MSG_WAITALL);
		if (n>=0) ret+=n;
		else{
			ret=n;
			goto error;
		}
	}

#ifdef HAVE_MSGHDR_MSG_CONTROL
	cmsg=CMSG_FIRSTHDR(&msg);
	if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
		if (cmsg->cmsg_type!= SCM_RIGHTS){
			LM_ERR("msg control type != SCM_RIGHTS\n");
			ret=-1;
			goto error;
		}
		if (cmsg->cmsg_level!= SOL_SOCKET){
			LM_ERR("msg level != SOL_SOCKET\n");
			ret=-1;
			goto error;
		}
		*fd = get_unaligned_int(CMSG_DATA(cmsg));
	}else{
		/*
		LM_ERR("no descriptor passed, cmsg=%p,len=%d\n",
			cmsg, (unsigned)cmsg->cmsg_len); */
		*fd=-1;
		/* it's not really an error */
	}
#else
	if (msg.msg_accrightslen==sizeof(int)){
		*fd=new_fd;
	}else{
		/*LM_ERR("no descriptor passed, accrightslen=%d\n",
			msg.msg_accrightslen); */
		*fd=-1;
	}
#endif

error:
	return ret;
}