// SPDX-License-Identifier: GPL-2.0
/*
 * Container Security Monitor module
 *
 * Copyright (c) 2018 Google, Inc
 */

#include "monitor.h"

#include <linux/string.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <net/ipv6.h>

bool pb_encode_string_field(pb_ostream_t *stream, const pb_field_t *field,
			    void * const *arg)
{
	const uint8_t *str = (const uint8_t *)*arg;

	/* If the string is not set, skip this string. */
	if (!str)
		return true;

	if (!pb_encode_tag_for_field(stream, field))
		return false;

	return pb_encode_string(stream, str, strlen(str));
}

bool pb_decode_string_field(pb_istream_t *stream, const pb_field_t *field,
			    void **arg)
{
	size_t size;
	void *data;

	*arg = NULL;

	size = stream->bytes_left;

	/* Ensure a null-byte at the end */
	if (size + 1 < size)
		return false;

	data = kzalloc(size + 1, GFP_KERNEL);
	if (!data)
		return false;

	if (!pb_read(stream, data, size)) {
		kfree(data);
		return false;
	}

	*arg = data;

	return true;
}

bool pb_encode_string_array(pb_ostream_t *stream, const pb_field_t *field,
			    void * const *arg)
{
	char *strs = (char *)*arg;

	/* If the string array is not set, skip this string array. */
	if (!strs)
		return true;

	do {
		if (!pb_encode_string_field(stream, field,
					    (void * const *) &strs))
			return false;

		strs += strlen(strs) + 1;
	} while (*strs != 0);

	return true;
}

/* Limit the encoded string size and return how many characters were added. */
ssize_t pb_encode_string_field_limit(pb_ostream_t *stream,
				     const pb_field_t *field,
				     void * const *arg, size_t limit)
{
	char *str = (char *)*arg;
	size_t length;

	/* If the string is not set, skip this string. */
	if (!str)
		return 0;

	if (!pb_encode_tag_for_field(stream, field))
		return -EINVAL;

	length = strlen(str);
	if (length > limit)
		length = limit;

	if (!pb_encode_string(stream, (uint8_t *)str, length))
		return -EINVAL;

	return length;
}

bool pb_decode_string_array(pb_istream_t *stream, const pb_field_t *field,
			    void **arg)
{
	size_t needed, used = 0;
	char *data, *strs;

	/* String length, and two null-bytes for the end of the list. */
	needed = stream->bytes_left + 2;
	if (needed < stream->bytes_left)
		return false;

	if (*arg) {
		/* Calculate used space from the current list. */
		strs = (char *)*arg;
		do {
			used += strlen(strs + used) + 1;
		} while (strs[used] != 0);

		if (used + needed < needed)
			return false;
	}

	data = krealloc(*arg, used + needed, GFP_KERNEL);
	if (!data)
		return false;

	/* Will always be freed by the caller */
	*arg = data;

	/* Reset the new part of the buffer. */
	memset(data + used, 0, needed);

	/* Read what's in the stream buffer only. */
	if (!pb_read(stream, data + used, stream->bytes_left))
		return false;

	return true;
}

bool pb_encode_fixed_string(pb_ostream_t *stream, const pb_field_t *field,
			    const uint8_t *data, size_t length)
{
	/* If the data is not set, skip this string. */
	if (!data)
		return true;

	if (!pb_encode_tag_for_field(stream, field))
		return false;

	return pb_encode_string(stream, data, length);
}


bool pb_encode_uuid_field(pb_ostream_t *stream, const pb_field_t *field,
			  void * const *arg)
{
	return pb_encode_fixed_string(stream, field, (const uint8_t *)*arg,
				      PROCESS_UUID_SIZE);
}

bool pb_encode_ip4(pb_ostream_t *stream, const pb_field_t *field,
		   void * const *arg)
{
	return pb_encode_fixed_string(stream, field, (const uint8_t *)*arg,
				      sizeof(struct in_addr));
}

bool pb_encode_ip6(pb_ostream_t *stream, const pb_field_t *field,
		   void * const *arg)
{
	return pb_encode_fixed_string(stream, field, (const uint8_t *)*arg,
				      sizeof(struct in6_addr));
}
