penguin/tinyproxy

An L4 proxy designed to act as a tiny transparent shim

src/x_builtins.c

raw ยท 1813 bytes

#include "x_builtins.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>

int x_builtin_parse(const char *s, enum x_builtin_upstream *out)
{
	if (s == NULL || out == NULL) {
		return -EINVAL;
	}

	if (strcmp(s, "client_addr") == 0 || strcmp(s, "X_CLIENT_ADDR") == 0) {
		*out = X_BUILTIN_CLIENT_ADDR;
		return 0;
	}

	if (strcmp(s, "discard") == 0 || strcmp(s, "X_DISCARD") == 0) {
		*out = X_BUILTIN_DISCARD;
		return 0;
	}

	if (strcmp(s, "hang") == 0 || strcmp(s, "X_HANG") == 0) {
		*out = X_BUILTIN_HANG;
		return 0;
	}

	if (strcmp(s, "close") == 0 || strcmp(s, "X_CLOSE") == 0) {
		*out = X_BUILTIN_CLOSE;
		return 0;
	}

	return -EINVAL;
}

const char *x_builtin_name(enum x_builtin_upstream builtin)
{
	switch (builtin) {
	case X_BUILTIN_CLIENT_ADDR:
		return "client_addr";
	case X_BUILTIN_DISCARD:
		return "discard";
	case X_BUILTIN_HANG:
		return "hang";
	case X_BUILTIN_CLOSE:
		return "close";
	case X_BUILTIN_NONE:
	default:
		return "none";
	}
}

int x_builtin_handle(
	const struct x_builtin_request *req,
	struct x_builtin_response *res
) {
	int n;

	if (req == NULL || res == NULL) {
		return -EINVAL;
	}

	memset(res, 0, sizeof(*res));

	switch (req->builtin) {
	case X_BUILTIN_CLIENT_ADDR:
		if (req->client_addr == NULL) {
			return -EINVAL;
		}

		n = snprintf(res->data, sizeof(res->data), "%s\n", req->client_addr);
		if (n < 0 || (size_t)n >= sizeof(res->data)) {
			return -ENOSPC;
		}

		res->data_len = (size_t)n;
		res->action = X_BUILTIN_ACTION_CLOSE;
		return 0;

	case X_BUILTIN_DISCARD:
		res->action = X_BUILTIN_ACTION_DISCARD;
		return 0;

	case X_BUILTIN_CLOSE:
		res->data_len = 0;
		res->action = X_BUILTIN_ACTION_CLOSE;
		return 0;

	case X_BUILTIN_HANG:
		res->action = X_BUILTIN_ACTION_HANG;
		return 0;

	case X_BUILTIN_NONE:
	default:
		return -EINVAL;
	}
}