Example #1
0
/* Initialization of group */
void sbuxton_set_group(char *group, char *layer)
{
	if (!_client_connection()) {
		errno = ENOTCONN;
		return;
	}
	saved_errno = errno;
	int status = 0;
	/* strcpy the name of the layer and group*/
	strncpy(_layer, layer, MAX_LG_LEN-1);
	strncpy(_group, group, MAX_LG_LEN-1);
	/* In case a string is longer than MAX_LG_LEN, set the last byte to null */
	_layer[MAX_LG_LEN -1] = '\0';
	_group[MAX_LG_LEN -1] = '\0';
	BuxtonKey g = buxton_key_create(_group, NULL, _layer, BUXTON_TYPE_STRING);
	buxton_debug("buxton key group = %s\n", buxton_key_get_group(g));
	if (buxton_create_group(client, g, _cg_cb, &status, true)
		|| !status) {
		buxton_debug("Create group call failed.\n");
		errno = EBADMSG;
	} else {
		buxton_debug("Switched to group: %s, layer: %s.\n", buxton_key_get_group(g),
	buxton_key_get_layer(g));
		errno = saved_errno;
	}
	_client_disconnect();
}
Example #2
0
int32_t sbuxton_get_int32(char *key)
{
	/* make sure client connection is open */
	if (!_client_connection()) {
		errno = ENOTCONN;
		return -1;
	}
	/* create key */
	BuxtonKey _key = buxton_key_create(_group, key, _layer, BUXTON_TYPE_INT32);
	/* return value */
	vstatus ret;
	ret.type = BUXTON_TYPE_INT32;
	saved_errno = errno;
	/* get value */
	if (buxton_get_value(client, _key, _bg_cb, &ret, true)) {
		buxton_debug("Get int32_t call failed.\n");
	}
	if (!ret.status) {
		errno = EACCES;
	} else {
		errno = saved_errno;
	}
	_client_disconnect();
	return ret.val.i32val;
}
Example #3
0
/* Set and get int32_t value for buxton key with type BUXTON_TYPE_INT32 */
void sbuxton_set_int32(char *key, int32_t value)
{
	/* make sure client connection is open */
	if (!_client_connection()) {
		errno = ENOTCONN;
		return;
	}
	/* create key  */
	BuxtonKey _key = buxton_key_create(_group, key, _layer, BUXTON_TYPE_INT32);
	/* return value and status */
	vstatus ret;
	ret.type = BUXTON_TYPE_INT32;
	ret.val.i32val = value;
	saved_errno = errno;
	/* call buxton_set_value for type BUXTON_TYPE_INT32 */
	if (buxton_set_value(client, _key, &value, _bs_cb, &ret, true)) {
		buxton_debug("Set int32_t call failed.\n");
		return;
	}
	if (!ret.status) {
		errno = EACCES;
	} else {
		errno = saved_errno;
	}
	_client_disconnect();
}
Example #4
0
/* Set and get char * value for buxton key with type BUXTON_TYPE_STRING */
void sbuxton_set_string(char *key, char *value )
{
	/* make sure client connection is open */
	if (!_client_connection()) {
		errno = ENOTCONN;
		return;
	}
	/* create key */
	BuxtonKey _key = buxton_key_create(_group, key, _layer, BUXTON_TYPE_STRING);
	/* return value and status */
	vstatus ret;
	ret.type = BUXTON_TYPE_STRING;
	ret.val.sval = value;
	saved_errno = errno;
	/* set value */
	if (buxton_set_value(client, _key, value, _bs_cb, &ret, true)) {
		buxton_debug("Set string call failed.\n");
	}
	if (!ret.status) {
		errno = EACCES;
	} else {
		errno = saved_errno;
	}
	_client_disconnect();
}
Example #5
0
/* Remove group given its name and layer */
void sbuxton_remove_group(char *group_name, char *layer)
{
	/* make sure client connection is open */
	if (!_client_connection()) {
		errno = ENOTCONN;
		return;
	}
	saved_errno = errno;
	BuxtonKey group = _buxton_group_create(group_name, layer);
	int status;
	if (buxton_remove_group(client, group, _rg_cb, &status, true)) {
		buxton_debug("Remove group call failed.\n");
	}
	if (!status) {
		errno = EACCES;
	} else {
		errno = saved_errno;
	}
	_client_disconnect();
}
Example #6
0
bool buxton_cache_smack_rules(void)
{
	smack_check();

	FILE *load_file = NULL;
	char *rule_pair = NULL;
	int ret = true;
	bool have_rules = false;
	struct stat buf;

	if (_smackrules) {
		hashmap_free(_smackrules);
	}

	_smackrules = hashmap_new(string_hash_func, string_compare_func);

	if (!_smackrules) {
		abort();
	}

	//FIXME: should check for a proper mount point instead
	if ((stat(SMACK_MOUNT_DIR, &buf) == -1) || !S_ISDIR(buf.st_mode)) {
		buxton_log("Smack filesystem not detected; disabling Smack checks\n");
		have_smack = false;
		goto end;
	}

	load_file = fopen(buxton_smack_load_file(), "r");

	if (!load_file) {
		switch (errno) {
		case ENOENT:
			buxton_log("Smackfs load2 file not found; disabling Smack checks\n");
			have_smack = false;
			goto end;
		default:
			buxton_log("fopen(): %m\n");
			ret = false;
			goto end;
		}
	}

	do {
		int r;
		int chars;
		BuxtonKeyAccessType *accesstype;

		char subject[SMACK_LABEL_LEN+1] = { 0, };
		char object[SMACK_LABEL_LEN+1] = { 0, };
		char access[ACC_LEN] = { 0, };

		/* read contents from load2 */
		chars = fscanf(load_file, "%s %s %s\n", subject, object, access);

		if (ferror(load_file)) {
			buxton_log("fscanf(): %m\n");
			ret = false;
			goto end;
		}

		if (!have_rules && chars == EOF && feof(load_file)) {
			buxton_debug("No loaded Smack rules found\n");
			goto end;
		}

		if (chars != 3) {
			buxton_log("Corrupt load file detected\n");
			ret = false;
			goto end;
		}

		have_rules = true;

		r = asprintf(&rule_pair, "%s %s", subject, object);
		if (r == -1) {
			abort();
		}

		accesstype = malloc0(sizeof(BuxtonKeyAccessType));
		if (!accesstype) {
			abort();
		}

		*accesstype = ACCESS_NONE;

		if (strchr(access, 'r')) {
			*accesstype |= ACCESS_READ;
		}

		if (strchr(access, 'w')) {
			*accesstype |= ACCESS_WRITE;
		}

		hashmap_put(_smackrules, rule_pair, accesstype);

	} while (!feof(load_file));

end:
	if (load_file) {
		fclose(load_file);
	}

	return ret;
}
Example #7
0
bool buxton_check_smack_access(BuxtonString *subject, BuxtonString *object, BuxtonKeyAccessType request)
{
	smack_check();

	_cleanup_free_ char *key = NULL;
	int r;
	BuxtonKeyAccessType *access;

	assert(subject);
	assert(object);
	assert((request == ACCESS_READ) || (request == ACCESS_WRITE));
	assert(_smackrules);

	buxton_debug("Subject: %s\n", subject->value);
	buxton_debug("Object: %s\n", object->value);

	/* check the builtin Smack rules first */
	if (streq(subject->value, "*")) {
		return false;
	}

	if (streq(object->value, "@") || streq(subject->value, "@")) {
		return true;
	}

	if (streq(object->value, "*")) {
		return true;
	}

	if (streq(subject->value, object->value)) {
		return true;
	}

	if (request == ACCESS_READ) {
		if (streq(object->value, "_")) {
			return true;
		}
		if (streq(subject->value, "^")) {
			return true;
		}
	}

	/* finally, check the loaded rules */
	r = asprintf(&key, "%s %s", subject->value, object->value);
	if (r == -1) {
		abort();
	}

	buxton_debug("Key: %s\n", key);

	access = hashmap_get(_smackrules, key);
	if (!access) {
		/* A null value is not an error, since clients may try to
		 * read/write keys with labels that are not in the loaded
		 * rule set. In this situation, access is simply denied,
		 * because there are no further rules to consider.
		 */
		buxton_debug("Value of key '%s' is NULL\n", key);
		return false;
	}

	/* After debugging, change this code to: */
	/* return ((*access) & request); */
	if (access) {
		buxton_debug("Value: %x\n", *access);
	}

	if (request == ACCESS_READ && (*access) & request) {
		buxton_debug("Read access granted!\n");
		return true;
	}

	if (request == ACCESS_WRITE && ((*access) & ACCESS_READ && (*access) & ACCESS_WRITE)) {
		buxton_debug("Write access granted!\n");
		return true;
	}

	buxton_debug("Access denied!\n");
	return false;
}
Example #8
0
/**
 * Entry point into bt-daemon
 * @param argc Number of arguments passed
 * @param argv An array of string arguments
 * @returns EXIT_SUCCESS if the operation succeeded, otherwise EXIT_FAILURE
 */
int main(int argc, char *argv[])
{
	int fd;
	int smackfd = -1;
	socklen_t addr_len;
	struct sockaddr_un remote;
	int descriptors;
	int ret;
	bool manual_start = false;
	struct sigaction sa;

	if (!buxton_cache_smack_rules())
		exit(EXIT_FAILURE);
	smackfd = buxton_watch_smack_rules();
	if (smackfd < 0 && errno)
		exit(EXIT_FAILURE);

	self.nfds_alloc = 0;
	self.accepting_alloc = 0;
	self.nfds = 0;
	self.buxton.client.direct = true;
	self.buxton.client.uid = geteuid();
	if (!buxton_direct_open(&self.buxton))
		exit(EXIT_FAILURE);

	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	sa.sa_handler = my_handler;
	ret = sigaction(SIGINT, &sa, NULL);
	if (ret == -1)
		exit(EXIT_FAILURE);
	ret = sigaction(SIGTERM, &sa, NULL);
	if (ret == -1)
		exit(EXIT_FAILURE);

	/* For client notifications */
	self.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
	/* Store a list of connected clients */
	LIST_HEAD_INIT(client_list_item, self.client_list);

	descriptors = sd_listen_fds(0);
	if (descriptors < 0) {
		buxton_log("sd_listen_fds: %m\n");
		exit(EXIT_FAILURE);
	} else if (descriptors == 0) {
		/* Manual invocation */
		manual_start = true;
		union {
			struct sockaddr sa;
			struct sockaddr_un un;
		} sa;

		fd = socket(AF_UNIX, SOCK_STREAM, 0);
		if (fd < 0) {
			buxton_log("socket(): %m\n");
			exit(EXIT_FAILURE);
		}

		memset(&sa, 0, sizeof(sa));
		sa.un.sun_family = AF_UNIX;
		strncpy(sa.un.sun_path, BUXTON_SOCKET, sizeof(sa.un.sun_path) - 1);
		sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0;

		ret = unlink(sa.un.sun_path);
		if (ret == -1 && errno != ENOENT) {
			exit(EXIT_FAILURE);
		}

		if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
			buxton_log("bind(): %m\n");
			exit(EXIT_FAILURE);
		}

		chmod(sa.un.sun_path, 0666);

		if (listen(fd, SOMAXCONN) < 0) {
			buxton_log("listen(): %m\n");
			exit(EXIT_FAILURE);
		}
		add_pollfd(&self, fd, POLLIN | POLLPRI, true);
	} else {
		/* systemd socket activation */
		for (fd = SD_LISTEN_FDS_START + 0; fd < SD_LISTEN_FDS_START + descriptors; fd++) {
			if (sd_is_fifo(fd, NULL)) {
				add_pollfd(&self, fd, POLLIN, false);
				buxton_debug("Added fd %d type FIFO\n", fd);
			} else if (sd_is_socket_unix(fd, SOCK_STREAM, -1, BUXTON_SOCKET, 0)) {
				add_pollfd(&self, fd, POLLIN | POLLPRI, true);
				buxton_debug("Added fd %d type UNIX\n", fd);
			} else if (sd_is_socket(fd, AF_UNSPEC, 0, -1)) {
				add_pollfd(&self, fd, POLLIN | POLLPRI, true);
				buxton_debug("Added fd %d type SOCKET\n", fd);
			}
		}
	}

	if (smackfd >= 0) {
		/* add Smack rule fd to pollfds */
		add_pollfd(&self, smackfd, POLLIN | POLLPRI, false);
	}

	buxton_log("%s: Started\n", argv[0]);

	/* Enter loop to accept clients */
	for (;;) {
		ret = poll(self.pollfds, self.nfds, -1);

		if (ret < 0) {
			buxton_log("poll(): %m\n");
			if (errno == EINTR) {
				if (do_shutdown)
					break;
				else
					continue;
			}
			break;
		}
		if (ret == 0)
			continue;

		for (nfds_t i=0; i<self.nfds; i++) {
			client_list_item *cl = NULL;
			char discard[256];

			if (self.pollfds[i].revents == 0)
				continue;

			if (self.pollfds[i].fd == -1) {
				/* TODO: Remove client from list  */
				buxton_debug("Removing / Closing client for fd %d\n", self.pollfds[i].fd);
				del_pollfd(&self, i);
				continue;
			}

			if (smackfd >= 0) {
				if (self.pollfds[i].fd == smackfd) {
					if (!buxton_cache_smack_rules())
						exit(EXIT_FAILURE);
					buxton_log("Reloaded Smack access rules\n");
					/* discard inotify data itself */
					while (read(smackfd, &discard, 256) == 256);
					continue;
				}
			}

			if (self.accepting[i] == true) {
				struct timeval tv;
				int fd;
				int on = 1;

				addr_len = sizeof(remote);

				if ((fd = accept(self.pollfds[i].fd,
				    (struct sockaddr *)&remote, &addr_len)) == -1) {
					buxton_log("accept(): %m\n");
					break;
				}

				buxton_debug("New client fd %d connected through fd %d\n", fd, self.pollfds[i].fd);

				cl = malloc0(sizeof(client_list_item));
				if (!cl)
					exit(EXIT_FAILURE);

				LIST_INIT(client_list_item, item, cl);

				cl->fd = fd;
				cl->cred = (struct ucred) {0, 0, 0};
				LIST_PREPEND(client_list_item, item, self.client_list, cl);

				/* poll for data on this new client as well */
				add_pollfd(&self, cl->fd, POLLIN | POLLPRI, false);

				/* Mark our packets as high prio */
				if (setsockopt(cl->fd, SOL_SOCKET, SO_PRIORITY, &on, sizeof(on)) == -1)
					buxton_log("setsockopt(SO_PRIORITY): %m\n");

				/* Set socket recv timeout */
				tv.tv_sec = SOCKET_TIMEOUT;
				tv.tv_usec = 0;
				if (setsockopt(cl->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
					       sizeof(struct timeval)) == -1)
					buxton_log("setsockopt(SO_RCVTIMEO): %m\n");

				/* check if this is optimal or not */
				break;
			}

			assert(self.accepting[i] == 0);
			if (smackfd >= 0)
				assert(self.pollfds[i].fd != smackfd);

			/* handle data on any connection */
			/* TODO: Replace with hash table lookup */
			LIST_FOREACH(item, cl, self.client_list)
				if (self.pollfds[i].fd == cl->fd)
					break;

			assert(cl);
			handle_client(&self, cl, i);
		}
	}

	buxton_log("%s: Closing all connections\n", argv[0]);

	if (manual_start)
		unlink(BUXTON_SOCKET);
	for (int i = 0; i < self.nfds; i++) {
		close(self.pollfds[i].fd);
	}
	for (client_list_item *i = self.client_list; i;) {
		client_list_item *j = i->item_next;
		free(i);
		i = j;
	}
	hashmap_free(self.notify_mapping);
	buxton_direct_close(&self.buxton);
	return EXIT_SUCCESS;
}
Example #9
0
ssize_t buxton_deserialize_message(uint8_t *data,
				  BuxtonControlMessage *r_message,
				  size_t size, uint32_t *r_msgid,
				  BuxtonData **list)
{
	size_t offset = 0;
	ssize_t ret = -1;
	size_t min_length = BUXTON_MESSAGE_HEADER_LENGTH;
	uint16_t control, message;
	size_t n_params, c_param, c_length;
	BuxtonDataType c_type = 0;
	BuxtonData *k_list = NULL;
	BuxtonData c_data;
	uint32_t msgid;

	assert(data);
	assert(r_message);
	assert(list);

	buxton_debug("Deserializing message...\n");
	buxton_debug("size=%lu\n", size);

	if (size < min_length) {
		errno = EINVAL;
		goto end;
	}

	/* Copy the control code */
	control = *(uint16_t*)data;
	offset += sizeof(uint16_t);

	/* Check this is a valid buxton message */
	if (control != BUXTON_CONTROL_CODE) {
		errno = EINVAL;
		goto end;
	}

	/* Obtain the control message */
	message = *(BuxtonControlMessage*)(data+offset);
	offset += sizeof(uint16_t);

	/* Ensure control message is in valid range */
	if (message <= BUXTON_CONTROL_MIN || message >= BUXTON_CONTROL_MAX) {
		errno = EINVAL;
		goto end;
	}

	/* Skip size since our caller got this already */
	offset += sizeof(uint32_t);

	/* Obtain the message id */
	msgid = *(uint32_t*)(data+offset);
	offset += sizeof(uint32_t);

	/* Obtain number of parameters */
	n_params = *(uint32_t*)(data+offset);
	offset += sizeof(uint32_t);
	buxton_debug("total params: %d\n", n_params);

	if (n_params > BUXTON_MESSAGE_MAX_PARAMS) {
		errno = EINVAL;
		goto end;
	}

	k_list = malloc0(sizeof(BuxtonData)*n_params);
	if (n_params && !k_list) {
		errno = ENOMEM;
		goto end;
	}

	memzero(&c_data, sizeof(BuxtonData));

	for (c_param = 0; c_param < n_params; c_param++) {
		buxton_debug("param: %d\n", c_param + 1);
		buxton_debug("offset=%lu\n", offset);
		/* Don't read past the end of the buffer */
		if (offset + sizeof(uint16_t) + sizeof(uint32_t) > size) {
			errno = EINVAL;
			goto end;
		}

		/* Now unpack type */
		memcpy(&c_type, data+offset, sizeof(uint16_t));
		offset += sizeof(uint16_t);

		if (c_type >= BUXTON_TYPE_MAX || c_type <= BUXTON_TYPE_MIN) {
			errno = EINVAL;
			goto end;
		}

		/* Retrieve the length of the value */
		c_length = *(uint32_t*)(data+offset);
		if (c_length == 0 && c_type != BUXTON_TYPE_STRING) {
			errno = EINVAL;
			goto end;
		}
		offset += sizeof(uint32_t);
		buxton_debug("value length: %lu\n", c_length);

		/* Don't try to read past the end of our buffer */
		if (offset + c_length > size) {
			errno = EINVAL;
			goto end;
		}

		switch (c_type) {
		case BUXTON_TYPE_STRING:
			if (c_length) {
				c_data.store.d_string.value = malloc(c_length);
				if (!c_data.store.d_string.value) {
					errno = ENOMEM;
					goto end;
				}
				memcpy(c_data.store.d_string.value, data+offset, c_length);
				c_data.store.d_string.length = (uint32_t)c_length;
				if (c_data.store.d_string.value[c_length-1] != 0x00) {
					errno = EINVAL;
					buxton_debug("buxton_deserialize_message(): Garbage message\n");
					free(c_data.store.d_string.value);
					goto end;
				}
			} else {
				c_data.store.d_string.value = NULL;
				c_data.store.d_string.length = 0;
			}
			break;
		case BUXTON_TYPE_INT32:
			c_data.store.d_int32 = *(int32_t*)(data+offset);
			break;
		case BUXTON_TYPE_UINT32:
			c_data.store.d_uint32 = *(uint32_t*)(data+offset);
			break;
		case BUXTON_TYPE_INT64:
			c_data.store.d_int64 = *(int64_t*)(data+offset);
			break;
		case BUXTON_TYPE_UINT64:
			c_data.store.d_uint64 = *(uint64_t*)(data+offset);
			break;
		case BUXTON_TYPE_FLOAT:
			c_data.store.d_float = *(float*)(data+offset);
			break;
		case BUXTON_TYPE_DOUBLE:
			memcpy(&c_data.store.d_double, data + offset, sizeof(double));
			break;
		case BUXTON_TYPE_BOOLEAN:
			c_data.store.d_boolean = *(bool*)(data+offset);
			break;
		default:
			errno = EINVAL;
			goto end;
		}
		c_data.type = c_type;
		k_list[c_param] = c_data;
		memzero(&c_data, sizeof(BuxtonData));
		offset += c_length;
	}
	*r_message = message;
	*r_msgid = msgid;
	if (n_params == 0) {
		*list = NULL;
		free(k_list);
		k_list = NULL;
	} else {
		*list = k_list;
	}
	ret = (ssize_t)n_params;
end:
	if (ret <= 0) {
		free(k_list);
	}

	buxton_debug("Deserializing returned:%i\n", ret);
	return ret;
}
Example #10
0
size_t buxton_serialize_message(uint8_t **dest, BuxtonControlMessage message,
				uint32_t msgid, BuxtonArray *list)
{
	uint16_t i = 0;
	uint8_t *data = NULL;
	size_t ret = 0;
	size_t offset = 0;
	size_t size = 0;
	size_t curSize = 0;
	uint16_t control, msg;

	assert(dest);
	assert(list);

	buxton_debug("Serializing message...\n");

	if (list->len > BUXTON_MESSAGE_MAX_PARAMS) {
		errno = EINVAL;
		return ret;
	}

	if (message >= BUXTON_CONTROL_MAX || message < BUXTON_CONTROL_SET) {
		errno = EINVAL;
		return ret;
	}

	/*
	 * initial size =
	 * control code + control message (uint16_t * 2) +
	 * message size (uint32_t) +
	 * message id (uint32_t) +
	 * param count (uint32_t)
	 */
	data = malloc0(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) +
		       sizeof(uint32_t));
	if (!data) {
		errno = ENOMEM;
		goto end;
	}

	control = BUXTON_CONTROL_CODE;
	memcpy(data, &control, sizeof(uint16_t));
	offset += sizeof(uint16_t);

	msg = (uint16_t)message;
	memcpy(data+offset, &msg, sizeof(uint16_t));
	offset += sizeof(uint16_t);

	/* Save room for final size */
	offset += sizeof(uint32_t);

	memcpy(data+offset, &msgid, sizeof(uint32_t));
	offset += sizeof(uint32_t);

	/* Now write the parameter count */
	memcpy(data+offset, &(list->len), sizeof(uint32_t));
	offset += sizeof(uint32_t);

	size = offset;

	/* Deal with parameters */
	BuxtonData *param;
	size_t p_length = 0;
	for (i=0; i < list->len; i++) {
		param = buxton_array_get(list, i);
		if (!param) {
			errno = EINVAL;
			goto fail;
		}

		switch (param->type) {
		case BUXTON_TYPE_STRING:
			p_length = param->store.d_string.length;
			break;
		case BUXTON_TYPE_INT32:
			p_length = sizeof(int32_t);
			break;
		case BUXTON_TYPE_UINT32:
			p_length = sizeof(uint32_t);
			break;
		case BUXTON_TYPE_INT64:
			p_length = sizeof(int64_t);
			break;
		case BUXTON_TYPE_UINT64:
			p_length = sizeof(uint64_t);
			break;
		case BUXTON_TYPE_FLOAT:
			p_length = sizeof(float);
			break;
		case BUXTON_TYPE_DOUBLE:
			p_length = sizeof(double);
			break;
		case BUXTON_TYPE_BOOLEAN:
			p_length = sizeof(bool);
			break;
		default:
			errno = EINVAL;
			buxton_log("Invalid parameter type %lu\n", param->type);
			goto fail;
		};

		buxton_debug("offset: %lu\n", offset);
		buxton_debug("value length: %lu\n", p_length);

		/* Need to allocate enough room to hold this data */
		size += sizeof(uint16_t) + sizeof(uint32_t) + p_length;

		if (curSize < size) {
			if (!(data = greedy_realloc((void**)&data, &curSize, size))) {
				errno = ENOMEM;
				goto fail;
			}
			memzero(data+offset, size - offset);
		}

		/* Copy data type */
		memcpy(data+offset, &(param->type), sizeof(uint16_t));
		offset += sizeof(uint16_t);

		/* Write out the length of value */
		memcpy(data+offset, &p_length, sizeof(uint32_t));
		offset += sizeof(uint32_t);

		switch (param->type) {
		case BUXTON_TYPE_STRING:
			memcpy(data+offset, param->store.d_string.value, p_length);
			break;
		case BUXTON_TYPE_INT32:
			memcpy(data+offset, &(param->store.d_int32), sizeof(int32_t));
			break;
		case BUXTON_TYPE_UINT32:
			memcpy(data+offset, &(param->store.d_uint32), sizeof(uint32_t));
			break;
		case BUXTON_TYPE_INT64:
			memcpy(data+offset, &(param->store.d_int64), sizeof(int64_t));
			break;
		case BUXTON_TYPE_UINT64:
			memcpy(data+offset, &(param->store.d_uint64), sizeof(uint64_t));
			break;
		case BUXTON_TYPE_FLOAT:
			memcpy(data+offset, &(param->store.d_float), sizeof(float));
			break;
		case BUXTON_TYPE_DOUBLE:
			memcpy(data+offset, &(param->store.d_double), sizeof(double));
			break;
		case BUXTON_TYPE_BOOLEAN:
			memcpy(data+offset, &(param->store.d_boolean), sizeof(bool));
			break;
		default:
			/* already tested this above, can't get here
			 * normally */
			assert(0);
		};
		offset += p_length;
		p_length = 0;
	}

	memcpy(data+BUXTON_LENGTH_OFFSET, &offset, sizeof(uint32_t));

	ret = offset;
	*dest = data;

fail:
	/* Clean up */
	if (ret == 0) {
		free(data);
	}
end:
	buxton_debug("Serializing returned:%lu\n", ret);
	return ret;
}
Example #11
0
void buxton_deserialize(uint8_t *source, BuxtonData *target,
			BuxtonString *label)
{
	size_t offset = 0;
	size_t length = 0;
	BuxtonDataType type;

	assert(source);
	assert(target);
	assert(label);

	/* Retrieve the BuxtonDataType */
	type = *(BuxtonDataType*)source;
	offset += sizeof(BuxtonDataType);

	/* Retrieve the length of the label */
	label->length = *(uint32_t*)(source+offset);
	offset += sizeof(uint32_t);

	/* Retrieve the length of the value */
	length = *(uint32_t*)(source+offset);
	offset += sizeof(uint32_t);

	/* Retrieve the label */
	label->value = malloc(label->length);
	if (label->length > 0 && !label->value) {
		abort();
	}
	memcpy(label->value, source+offset, label->length);
	offset += label->length;

	switch (type) {
	case BUXTON_TYPE_STRING:
		/* User must free the string */
		target->store.d_string.value = malloc(length);
		if (!target->store.d_string.value) {
			abort();
		}
		memcpy(target->store.d_string.value, source+offset, length);
		target->store.d_string.length = (uint32_t)length;
		break;
	case BUXTON_TYPE_INT32:
		target->store.d_int32 = *(int32_t*)(source+offset);
		break;
	case BUXTON_TYPE_UINT32:
		target->store.d_uint32 = *(uint32_t*)(source+offset);
		break;
	case BUXTON_TYPE_INT64:
		target->store.d_int64 = *(int64_t*)(source+offset);
		break;
	case BUXTON_TYPE_UINT64:
		target->store.d_uint64 = *(uint64_t*)(source+offset);
		break;
	case BUXTON_TYPE_FLOAT:
		target->store.d_float = *(float*)(source+offset);
		break;
	case BUXTON_TYPE_DOUBLE:
		memcpy(&target->store.d_double, source + offset, sizeof(double));
		break;
	case BUXTON_TYPE_BOOLEAN:
		target->store.d_boolean = *(bool*)(source+offset);
		break;
	default:
		buxton_debug("Invalid BuxtonDataType: %lu\n", type);
		abort();
	}

	/* Successful */
	target->type = type;
}