/*
 * Copyright (c) 2019 Antmicro Ltd
 *
 * Copyright (c) 2019 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_socks, CONFIG_SOCKS_LOG_LEVEL);

#include <zephyr/kernel.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/net_pkt.h>

#include "socks.h"
#include "socks_internal.h"

static void socks5_method_rsp_cb(struct net_context *ctx,
				 struct net_pkt *pkt,
				 union net_ip_header *ip_hdr,
				 union net_proto_header *proto_hdr,
				 int status,
				 void *user_data)
{
	struct socks5_method_response *method_rsp =
			(struct socks5_method_response *)user_data;

	if (!pkt || status) {
		memset(method_rsp, 0, sizeof(struct socks5_method_response));
		goto end;
	}

	if (net_pkt_read(pkt, (uint8_t *)method_rsp,
			 sizeof(struct socks5_method_response))) {
		memset(method_rsp, 0, sizeof(struct socks5_method_response));
	}

end:
	net_pkt_unref(pkt);
}

static void socks5_cmd_rsp_cb(struct net_context *ctx,
			      struct net_pkt *pkt,
			      union net_ip_header *ip_hdr,
			      union net_proto_header *proto_hdr,
			      int status,
			      void *user_data)
{
	struct socks5_command_response *cmd_rsp =
			(struct socks5_command_response *)user_data;
	int size;

	if (!pkt || status) {
		memset(cmd_rsp, 0,
		       sizeof(struct socks5_command_request_common));
		goto end;
	}

	size = sizeof(struct socks5_command_request_common);

	if (net_pkt_read(pkt, (uint8_t *)cmd_rsp, size)) {
		memset(cmd_rsp, 0,
		       sizeof(struct socks5_command_request_common));
	}

end:
	net_pkt_unref(pkt);
}

static int socks5_tcp_connect(struct net_context *ctx,
			      const struct sockaddr *proxy,
			      socklen_t proxy_len,
			      const struct sockaddr *dest,
			      socklen_t dest_len)
{
	struct socks5_method_request method_req;
	struct socks5_method_response method_rsp;
	struct socks5_command_request cmd_req;
	struct socks5_command_response cmd_rsp;
	int size;
	int ret;

	/* Negotiate authentication method */
	method_req.r.ver = SOCKS5_PKT_MAGIC;

	/* We only support NOAUTH at the moment */
	method_req.r.nmethods = 1U;
	method_req.methods[0] = SOCKS5_AUTH_METHOD_NOAUTH;

	/* size + 1 because just one method is supported */
	size = sizeof(struct socks5_method_request_common) + 1;

	ret = net_context_sendto(ctx, (uint8_t *)&method_req, size,
				 proxy, proxy_len, NULL, K_NO_WAIT,
				 ctx->user_data);
	if (ret < 0) {
		LOG_ERR("Could not send negotiation packet");
		return ret;
	}

	ret = net_context_recv(ctx, socks5_method_rsp_cb,
			       K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
			       &method_rsp);
	if (ret < 0) {
		LOG_ERR("Could not receive negotiation response");
		return ret;
	}

	if (method_rsp.ver != SOCKS5_PKT_MAGIC) {
		LOG_ERR("Invalid negotiation response magic");
		return -EINVAL;
	}

	if (method_rsp.method != SOCKS5_AUTH_METHOD_NOAUTH) {
		LOG_ERR("Invalid negotiation response");
		return -ENOTSUP;
	}

	/* Negotiation complete - now connect to destination */
	cmd_req.r.ver = SOCKS5_PKT_MAGIC;
	cmd_req.r.cmd = SOCKS5_CMD_CONNECT;
	cmd_req.r.rsv = SOCKS5_PKT_RSV;

	if (proxy->sa_family == AF_INET) {
		const struct sockaddr_in *d4 =
			(struct sockaddr_in *)dest;

		cmd_req.r.atyp = SOCKS5_ATYP_IPV4;

		memcpy(&cmd_req.ipv4_addr.addr,
		       (uint8_t *)&d4->sin_addr,
		       sizeof(cmd_req.ipv4_addr.addr));

		cmd_req.ipv4_addr.port = d4->sin_port;

		size = sizeof(struct socks5_command_request_common)
			+ sizeof(struct socks5_ipv4_addr);
	} else if (proxy->sa_family == AF_INET6) {
		const struct sockaddr_in6 *d6 =
			(struct sockaddr_in6 *)dest;

		cmd_req.r.atyp = SOCKS5_ATYP_IPV6;

		memcpy(&cmd_req.ipv6_addr.addr,
		       (uint8_t *)&d6->sin6_addr,
		       sizeof(cmd_req.ipv6_addr.addr));

		cmd_req.ipv6_addr.port = d6->sin6_port;

		size = sizeof(struct socks5_command_request_common)
			+ sizeof(struct socks5_ipv6_addr);
	}

	ret = net_context_sendto(ctx, (uint8_t *)&cmd_req, size,
				 proxy, proxy_len, NULL, K_NO_WAIT,
				 ctx->user_data);
	if (ret < 0) {
		LOG_ERR("Could not send CONNECT command");
		return ret;
	}

	ret = net_context_recv(ctx, socks5_cmd_rsp_cb,
			       K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
			       &cmd_rsp);
	if (ret < 0) {
		LOG_ERR("Could not receive CONNECT response");
		return ret;
	}

	if (cmd_rsp.r.ver != SOCKS5_PKT_MAGIC) {
		LOG_ERR("Invalid CONNECT response");
		return -EINVAL;
	}

	if (cmd_rsp.r.rep != SOCKS5_CMD_RESP_SUCCESS) {
		LOG_ERR("Unable to connect to destination");
		return -EINVAL;
	}

	/* Verifying the rest is not required */

	LOG_DBG("Connection through SOCKS5 proxy successful");

	return 0;
}

int net_socks5_connect(struct net_context *ctx, const struct sockaddr *addr,
		       socklen_t addrlen)
{
	struct sockaddr proxy;
	socklen_t proxy_len;
	int type;
	int ret;

	type = net_context_get_type(ctx);
	/* TODO: Only TCP and TLS supported, UDP and DTLS yet to support. */
	if (type != SOCK_STREAM) {
		return -ENOTSUP;
	}

	ret = net_context_get_option(ctx, NET_OPT_SOCKS5, &proxy, &proxy_len);
	if (ret < 0) {
		return ret;
	}

	/* Connect to Proxy Server */
	ret = net_context_connect(ctx, &proxy, proxy_len, NULL,
				  K_MSEC(CONFIG_NET_SOCKETS_CONNECT_TIMEOUT),
				  NULL);
	if (ret < 0) {
		return ret;
	}

	return socks5_tcp_connect(ctx, &proxy, proxy_len, addr, addrlen);
}
