free(b->auth_uid);
free(b->address);
+ close_many(b->fds, b->n_fds);
+ free(b->fds);
+
for (i = 0; i < b->rqueue_size; i++)
sd_bus_message_unref(b->rqueue[i]);
free(b->rqueue);
k = recvmsg(b->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
if (k < 0)
return errno == EAGAIN ? 0 : -errno;
+ if (k == 0)
+ return -ECONNRESET;
b->rbuffer_size += k;
if (*idx >= m->size)
return 0;
+ zero(mh);
+
+ if (m->n_fds > 0) {
+ struct cmsghdr *control;
+ control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
+
+ mh.msg_control = control;
+ control->cmsg_level = SOL_SOCKET;
+ control->cmsg_type = SCM_RIGHTS;
+ mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
+ memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
+ }
n = m->n_iovec * sizeof(struct iovec);
iov = alloca(n);
j = 0;
iovec_advance(iov, &j, *idx);
- zero(mh);
mh.msg_iov = iov;
mh.msg_iovlen = m->n_iovec;
static int message_make(sd_bus *bus, size_t size, sd_bus_message **m) {
sd_bus_message *t;
- void *b = NULL;
+ void *b;
int r;
assert(bus);
bus->rbuffer_size - size);
if (!b)
return -ENOMEM;
- }
+ } else
+ b = NULL;
r = bus_message_from_malloc(bus->rbuffer, size,
+ bus->fds, bus->n_fds,
bus->ucred_valid ? &bus->ucred : NULL,
- bus->label[0] ? bus->label : NULL, &t);
+ bus->label[0] ? bus->label : NULL,
+ &t);
if (r < 0) {
free(b);
return r;
bus->rbuffer = b;
bus->rbuffer_size -= size;
+ bus->fds = NULL;
+ bus->n_fds = 0;
+
*m = t;
return 1;
}
void *b;
union {
struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
+ uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) +
+ CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(NAME_MAX)]; /*selinux label */
} control;
struct cmsghdr *cmsg;
k = recvmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
if (k < 0)
return errno == EAGAIN ? 0 : -errno;
+ if (k == 0)
+ return -ECONNRESET;
bus->rbuffer_size += k;
- bus->ucred_valid = false;
- bus->label[0] = 0;
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS) {
+ int n, *f;
+
+ n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+
+ f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
+ if (!f) {
+ close_many((int*) CMSG_DATA(cmsg), n);
+ return -ENOMEM;
+ }
+
+ memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
+ bus->fds = f;
+ bus->n_fds += n;
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
return -ENOTCONN;
if (!m)
return -EINVAL;
+ if (m->n_fds > 0 && !bus->can_fds)
+ return -ENOTSUP;
/* If the serial number isn't kept, then we know that no reply
* is expected */