Exemple #1
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;
}
Exemple #2
0
void
qb_ipcc_disconnect(struct qb_ipcc_connection *c)
{
	struct qb_ipc_one_way *ow = NULL;
	int32_t res = 0;

	qb_util_log(LOG_DEBUG, "%s()", __func__);

	if (c == NULL) {
		return;
	}

	ow = _event_sock_one_way_get(c);
	if (ow) {
		res = qb_ipc_us_recv_ready(ow, 0);
		_check_connection_state(c, res);
		qb_ipcc_us_sock_close(ow->u.us.sock);
	}

	if (c->funcs.disconnect) {
		c->funcs.disconnect(c);
	}
	free(c->receive_buf);
	free(c);
}
Exemple #3
0
static void
qb_ipcs_us_disconnect(struct qb_ipcs_connection *c)
{
#if !(defined(QB_LINUX) || defined(QB_CYGWIN))
	struct sockaddr_un un_addr;
	socklen_t un_addr_len = sizeof(struct sockaddr_un);
	char *base_name;
	char sock_name[PATH_MAX];
	size_t length;
#endif
	qb_enter();

	if (c->state == QB_IPCS_CONNECTION_ESTABLISHED ||
	    c->state == QB_IPCS_CONNECTION_ACTIVE) {
		_sock_rm_from_mainloop(c);

#if !(defined(QB_LINUX) || defined(QB_CYGWIN))
		if (getsockname(c->response.u.us.sock, (struct sockaddr *)&un_addr, &un_addr_len) == 0) {
			length = strlen(un_addr.sun_path);
			base_name = strndup(un_addr.sun_path,length-8);
			qb_util_log(LOG_DEBUG, "unlinking socket bound files with base_name=%s length=%d",base_name,length);
			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"request");
			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
			unlink(sock_name);
			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"event");
			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
			unlink(sock_name);
			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"event-tx");
			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
			unlink(sock_name);
			snprintf(sock_name,PATH_MAX,"%s-%s",base_name,"response");
			qb_util_log(LOG_DEBUG, "unlink sock_name=%s",sock_name);
			unlink(sock_name);
		}
#endif
		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		qb_ipcc_us_sock_close(c->request.u.us.sock);
		qb_ipcc_us_sock_close(c->event.u.us.sock);
	}
	if (c->state == QB_IPCS_CONNECTION_SHUTTING_DOWN ||
	    c->state == QB_IPCS_CONNECTION_ACTIVE) {
		munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
		unlink(c->request.u.us.shared_file_name);
	}
}
Exemple #4
0
static void
qb_ipcs_us_disconnect(struct qb_ipcs_connection *c)
{
	qb_enter();

	if (c->state == QB_IPCS_CONNECTION_ESTABLISHED ||
	    c->state == QB_IPCS_CONNECTION_ACTIVE) {
		_sock_rm_from_mainloop(c);

		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		qb_ipcc_us_sock_close(c->request.u.us.sock);
		qb_ipcc_us_sock_close(c->event.u.us.sock);
	}
	if (c->state == QB_IPCS_CONNECTION_SHUTTING_DOWN ||
	    c->state == QB_IPCS_CONNECTION_ACTIVE) {
		munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
		unlink(c->request.u.us.shared_file_name);
	}
}
Exemple #5
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;
}
Exemple #6
0
void
qb_ipcc_disconnect(struct qb_ipcc_connection *c)
{
	struct qb_ipc_one_way *ow = NULL;

	qb_util_log(LOG_DEBUG, "%s()", __func__);

	if (c == NULL) {
		return;
	}

	ow = _event_sock_one_way_get(c);
	(void)_check_connection_state_with(c, -EAGAIN, ow, 0, POLLIN);
	qb_ipcc_us_sock_close(ow->u.us.sock);

	if (c->funcs.disconnect) {
		c->funcs.disconnect(c);
	}
	free(c->receive_buf);
	free(c);
}
Exemple #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;
}
Exemple #8
0
qb_ipcc_connection_t *
qb_ipcc_connect(const char *name, size_t max_msg_size)
{
	int32_t res;
	qb_ipcc_connection_t *c = NULL;
	struct qb_ipc_connection_response response;

	c = calloc(1, sizeof(struct qb_ipcc_connection));
	if (c == NULL) {
		return NULL;
	}

	c->setup.max_msg_size = QB_MAX(max_msg_size,
				       sizeof(struct qb_ipc_connection_response));
	(void)strlcpy(c->name, name, NAME_MAX);
	res = qb_ipcc_us_setup_connect(c, &response);
	if (res < 0) {
		goto disconnect_and_cleanup;
	}
	c->response.type = response.connection_type;
	c->request.type = response.connection_type;
	c->event.type = response.connection_type;
	c->setup.type = response.connection_type;

	c->response.max_msg_size = response.max_msg_size;
	c->request.max_msg_size = response.max_msg_size;
	c->event.max_msg_size = response.max_msg_size;
	c->receive_buf = calloc(1, response.max_msg_size);
	c->fc_enable_max = 1;
	if (c->receive_buf == NULL) {
		res = -ENOMEM;
		goto disconnect_and_cleanup;
	}

	switch (c->request.type) {
	case QB_IPC_SHM:
		res = qb_ipcc_shm_connect(c, &response);
		break;
	case QB_IPC_SOCKET:
		res = qb_ipcc_us_connect(c, &response);
		break;
	case QB_IPC_POSIX_MQ:
	case QB_IPC_SYSV_MQ:
		res = -ENOTSUP;
		break;
	default:
		res = -EINVAL;
		break;
	}
	if (res != 0) {
		goto disconnect_and_cleanup;
	}
	c->is_connected = QB_TRUE;
	return c;

disconnect_and_cleanup:
	qb_ipcc_us_sock_close(c->setup.u.us.sock);
	free(c->receive_buf);
	free(c);
	errno = -res;
	return NULL;
}