Example #1
0
/* not return sent size, but success: 0 or failure: -1 */
static int py_send_nlmsg(int fd, struct nlmsghdr *nlh, int cdata)
{
	struct msghdr msg = {0};
	struct iovec iov;
	size_t cmsglen = CMSG_SPACE(sizeof(int));
	char control[CMSG_SPACE(sizeof(int))];
	struct cmsghdr *cmsg;
	ssize_t nsent;

	iov.iov_base = nlh;
	iov.iov_len = nlh->nlmsg_len;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	if (cdata) {
		msg.msg_control = control;
		msg.msg_controllen = cmsglen;
		cmsg = CMSG_FIRSTHDR(&msg);
		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		put_unaligned_int(CMSG_DATA(cmsg), cdata);
	}

	nsent = sendmsg(fd, &msg, MSG_NOSIGNAL);
	if (nsent == -1)
		return -1;
	if (nsent != nlh->nlmsg_len) {
		errno = EMSGSIZE;
		return -1;
	}

	return 0;
}
Example #2
0
/* at least 1 byte must be sent! */
int send_fd(int unix_socket, void* data, int data_len, int fd)
{
	struct msghdr msg;
	struct iovec iov[1];
	int ret;
#ifdef HAVE_MSGHDR_MSG_CONTROL
	struct cmsghdr* cmsg;
	/* make sure msg_control will point to properly aligned data */
	union {
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(fd))];
	}control_un;

	msg.msg_control=control_un.control;
	/* openbsd doesn't like "more space", msg_controllen must not
	 * include the end padding */
	msg.msg_controllen=CMSG_LEN(sizeof(fd));

	cmsg=CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;
	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
	put_unaligned_int(CMSG_DATA(cmsg), fd);
	msg.msg_flags=0;
#else
	msg.msg_accrights=(caddr_t) &fd;
	msg.msg_accrightslen=sizeof(fd);
#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=sendmsg(unix_socket, &msg, 0);
	if (ret<0){
		if (errno==EINTR) goto again;
		if (errno==EAGAIN || errno==EWOULDBLOCK) {
			LM_ERR("sendmsg would block on %d: %s\n",
				unix_socket, strerror(errno));
		} else {
			LM_CRIT("sendmsg failed on %d: %s\n",
				unix_socket, strerror(errno));
		}
	}

	return ret;
}