Example #1
0
File: ipcs.c Project: ip1981/libqb
static int32_t
new_event_notification(struct qb_ipcs_connection * c)
{
	ssize_t res = 0;

	if (!c->service->needs_sock_for_poll) {
		return res;
	}

	assert(c->outstanding_notifiers >= 0);
	if (c->outstanding_notifiers > 0) {
		c->outstanding_notifiers++;
	} else {
		res = qb_ipc_us_send(&c->setup, &c->outstanding_notifiers, 1);
		if (res == 1) {
			return res;
		}
		/*
		 * notify the client later, when we can.
		 */
		c->outstanding_notifiers++;
		c->poll_events = POLLOUT | POLLIN | POLLPRI | POLLNVAL;
		(void)_modify_dispatch_descriptor_(c);
	}
	return res;
}
Example #2
0
int32_t
qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
			 struct qb_ipc_connection_response *r)
{
	int32_t res;
	struct qb_ipc_connection_request request;
	struct ipc_auth_data *data;
#ifdef QB_LINUX
	int off = 0;
	int on = 1;
#endif

	res = qb_ipcc_stream_sock_connect(c->name, &c->setup.u.us.sock);
	if (res != 0) {
		return res;
	}
#ifdef QB_LINUX
	setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &on,
		   sizeof(on));
#endif

	memset(&request, 0, sizeof(request));
	request.hdr.id = QB_IPC_MSG_AUTHENTICATE;
	request.hdr.size = sizeof(request);
	request.max_msg_size = c->setup.max_msg_size;
	res = qb_ipc_us_send(&c->setup, &request, request.hdr.size);
	if (res < 0) {
		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		return res;
	}

	data = init_ipc_auth_data(c->setup.u.us.sock, sizeof(struct qb_ipc_connection_response));
	if (data == NULL) {
		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		return -ENOMEM;
	}

	qb_ipc_us_ready(&c->setup, NULL, -1, POLLIN);
	res = qb_ipc_us_recv_msghdr(data);

#ifdef QB_LINUX
	setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &off,
		   sizeof(off));
#endif

	if (res != data->len) {
		destroy_ipc_auth_data(data);
		return res;
	}

	memcpy(r, &data->msg.res, sizeof(struct qb_ipc_connection_response));

	qb_ipc_auth_creds(data);
	c->egid = data->ugp.gid;
	c->server_pid = data->ugp.pid;

	destroy_ipc_auth_data(data);
	return r->hdr.error;
}
Example #3
0
int32_t
qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
			 struct qb_ipc_connection_response *r)
{
	int32_t res;
	struct qb_ipc_connection_request request;
#ifdef QB_LINUX
	int off = 0;
	int on = 1;
#endif

	res = qb_ipcc_stream_sock_connect(c->name, &c->setup.u.us.sock);
	if (res != 0) {
		return res;
	}
#ifdef QB_LINUX
	setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &on,
		   sizeof(on));
#endif

	memset(&request, 0, sizeof(request));
	request.hdr.id = QB_IPC_MSG_AUTHENTICATE;
	request.hdr.size = sizeof(request);
	request.max_msg_size = c->setup.max_msg_size;
	res = qb_ipc_us_send(&c->setup, &request, request.hdr.size);
	if (res < 0) {
		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		return res;
	}
#ifdef QB_LINUX
	setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &off,
		   sizeof(off));
#endif

	res =
	    qb_ipc_us_recv(&c->setup, r,
			   sizeof(struct qb_ipc_connection_response), -1);
	if (res < 0) {
		return res;
	}

	if (r->hdr.error != 0) {
		return r->hdr.error;
	}
	return 0;
}
Example #4
0
File: ipcc.c Project: krig/libqb
ssize_t
qb_ipcc_sendv(struct qb_ipcc_connection * c, const struct iovec * iov,
	      size_t iov_len)
{
	int32_t total_size = 0;
	int32_t i;
	int32_t res;
	int32_t res2;

	for (i = 0; i < iov_len; i++) {
		total_size += iov[i].iov_len;
	}
	if (c == NULL) {
		return -EINVAL;
	}
	if (total_size > c->request.max_msg_size) {
		return -EMSGSIZE;
	}

	if (c->funcs.fc_get) {
		res = c->funcs.fc_get(&c->request);
		if (res < 0) {
			return res;
		} else if (res > 0 && res <= c->fc_enable_max) {
			return -EAGAIN;
		} else {
			/*
			 * we can transmit
			 */
		}
	}

	res = c->funcs.sendv(&c->request, iov, iov_len);
	if (res > 0 && c->needs_sock_for_poll) {
		do {
			res2 = qb_ipc_us_send(&c->setup, &res, 1);
		} while (res2 == -EAGAIN);
		if (res2 == -EPIPE) {
			res2 = -ENOTCONN;
		}
		if (res2 != 1) {
			res = res2;
		}
	}
	return _check_connection_state(c, res);
}
Example #5
0
File: ipcs.c Project: ip1981/libqb
static int32_t
resend_event_notifications(struct qb_ipcs_connection *c)
{
	ssize_t res = 0;

	if (c->outstanding_notifiers > 0) {
		res = qb_ipc_us_send(&c->setup, &c->outstanding_notifiers,
				     c->outstanding_notifiers);
	}
	if (res > 0) {
		c->outstanding_notifiers -= res;
	}
	assert(c->outstanding_notifiers >= 0);
	if (c->outstanding_notifiers == 0) {
		c->poll_events = POLLIN | POLLPRI | POLLNVAL;
		(void)_modify_dispatch_descriptor_(c);
	}
	return res;
}
Example #6
0
File: ipcc.c Project: krig/libqb
ssize_t
qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, size_t msg_len)
{
	ssize_t res;
	ssize_t res2;

	if (c == NULL) {
		return -EINVAL;
	}
	if (msg_len > c->request.max_msg_size) {
		return -EMSGSIZE;
	}
	if (c->funcs.fc_get) {
		res = c->funcs.fc_get(&c->request);
		if (res < 0) {
			return res;
		} else if (res > 0 && res <= c->fc_enable_max) {
			return -EAGAIN;
		} else {
			/*
			 * we can transmit
			 */
		}
	}

	res = c->funcs.send(&c->request, msg_ptr, msg_len);
	if (res == msg_len && c->needs_sock_for_poll) {
		do {
			res2 = qb_ipc_us_send(&c->setup, msg_ptr, 1);
		} while (res2 == -EAGAIN);
		if (res2 == -EPIPE) {
			res2 = -ENOTCONN;
		}
		if (res2 != 1) {
			res = res2;
		}
	}
	return _check_connection_state(c, res);
}
Example #7
0
static int32_t
handle_new_connection(struct qb_ipcs_service *s,
		      int32_t auth_result,
		      int32_t sock,
		      void *msg, size_t len, struct ipc_auth_ugp *ugp)
{
	struct qb_ipcs_connection *c = NULL;
	struct qb_ipc_connection_request *req = msg;
	int32_t res = auth_result;
	int32_t res2 = 0;
	struct qb_ipc_connection_response response;

	c = qb_ipcs_connection_alloc(s);
	if (c == NULL) {
		qb_ipcc_us_sock_close(sock);
		return -ENOMEM;
	}

	c->receive_buf = calloc(1, req->max_msg_size);
	if (c->receive_buf == NULL) {
		free(c);
		qb_ipcc_us_sock_close(sock);
		return -ENOMEM;
	}
	c->setup.u.us.sock = sock;
	c->request.max_msg_size = req->max_msg_size;
	c->response.max_msg_size = req->max_msg_size;
	c->event.max_msg_size = req->max_msg_size;
	c->pid = ugp->pid;
	c->auth.uid = c->euid = ugp->uid;
	c->auth.gid = c->egid = ugp->gid;
	c->auth.mode = 0600;
	c->stats.client_pid = ugp->pid;
	snprintf(c->description, CONNECTION_DESCRIPTION,
		 "%d-%d-%d", s->pid, ugp->pid, c->setup.u.us.sock);

	if (auth_result == 0 && c->service->serv_fns.connection_accept) {
		res = c->service->serv_fns.connection_accept(c,
							     c->euid, c->egid);
	}
	if (res != 0) {
		goto send_response;
	}

	qb_util_log(LOG_DEBUG, "IPC credentials authenticated (%s)",
		    c->description);

	memset(&response, 0, sizeof(response));
	if (s->funcs.connect) {
		res = s->funcs.connect(s, c, &response);
		if (res != 0) {
			goto send_response;
		}
	}
	/*
	 * The connection is good, add it to the active connection list
	 */
	c->state = QB_IPCS_CONNECTION_ACTIVE;
	qb_list_add(&c->list, &s->connections);

send_response:
	response.hdr.id = QB_IPC_MSG_AUTHENTICATE;
	response.hdr.size = sizeof(response);
	response.hdr.error = res;
	if (res == 0) {
		response.connection = (intptr_t) c;
		response.connection_type = s->type;
		response.max_msg_size = c->request.max_msg_size;
		s->stats.active_connections++;
	}

	res2 = qb_ipc_us_send(&c->setup, &response, response.hdr.size);
	if (res == 0 && res2 != response.hdr.size) {
		res = res2;
	}

	if (res == 0) {
		qb_ipcs_connection_ref(c);
		if (s->serv_fns.connection_created) {
			s->serv_fns.connection_created(c);
		}
		if (c->state == QB_IPCS_CONNECTION_ACTIVE) {
			c->state = QB_IPCS_CONNECTION_ESTABLISHED;
		}
		qb_ipcs_connection_unref(c);
	} else {
		if (res == -EACCES) {
			qb_util_log(LOG_ERR, "Invalid IPC credentials (%s).",
				    c->description);
		} else {
			errno = -res;
			qb_util_perror(LOG_ERR,
				       "Error in connection setup (%s)",
				       c->description);
		}
		qb_ipcs_disconnect(c);
	}
	return res;
}