/* 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; }
/* 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; }