⬢ DragonFlyBSD Kernel Audit
DF-2249 / dfarm.c
← back to finding ↓ download raw
/*
 * dfarm.c -- DF harness charset-pair armer.  Registers crafted charset
 * pairs through the REAL kern.iconv.add sysctl path (same wire format
 * as lib/libkiconv), for the kernel-compiled libiconv framework
 * (options LIBICONV).
 *
 * usage:
 *   dfarm ucs  <to> <from>                       (UCS pair, datalen 0)
 *   dfarm xlat <to> <from> <datalen> <fillhex> [idx:val ...]
 *       registers an "xlat" pair whose table is <datalen> bytes, filled
 *       with <fillhex>, then patched at the given indices (idx:valhex).
 */
#include <sys/types.h>
#include <sys/iconv.h>
#include <sys/sysctl.h>

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

static void
add_pair(const char *conv, const char *to, const char *from,
    const void *data, size_t datalen)
{
	struct iconv_add_in din;
	struct iconv_add_out dout;
	size_t olen = sizeof(dout);

	memset(&din, 0, sizeof(din));
	din.ia_version = ICONV_ADD_VER;
	strlcpy(din.ia_converter, conv, sizeof(din.ia_converter));
	strlcpy(din.ia_to, to, sizeof(din.ia_to));
	strlcpy(din.ia_from, from, sizeof(din.ia_from));
	din.ia_data = data;
	din.ia_datalen = (int)datalen;

	if (sysctlbyname("kern.iconv.add", &dout, &olen, &din,
	    sizeof(din)) == -1) {
		if (errno == EEXIST) {
			printf("already registered %s <- %s (%s)\n", to, from,
			    conv);
			return;
		}
		err(1, "sysctl kern.iconv.add %s <- %s", to, from);
	}
	printf("registered %s <- %s conv=%s csid=%d datalen=%zu\n", to, from,
	    conv, dout.ia_csid, datalen);
}

int
main(int argc, char **argv)
{
	unsigned char *tbl;
	unsigned long fill;
	size_t len, i;
	char *spec, *col;

	if (argc == 4 && strcmp(argv[1], "ucs") == 0) {
		/* the UCS converter registers under ENCODING_UNICODE */
		add_pair("UTF-16BE", argv[2], argv[3], NULL, 0);
		return (0);
	}
	if (argc >= 6 && strcmp(argv[1], "xlat") == 0) {
		len = strtoul(argv[4], NULL, 0);
		fill = strtoul(argv[5], NULL, 16);
		tbl = malloc(len ? len : 1);
		if (tbl == NULL)
			err(1, "malloc");
		memset(tbl, fill & 0xff, len ? len : 1);
		for (i = 6; i < (size_t)argc; i++) {
			unsigned long idx, val;
			idx = strtoul(argv[i], &col, 16);
			if (col == NULL || *col != ':' || idx >= len)
				errx(2, "bad spec %s", argv[i]);
			val = strtoul(col + 1, NULL, 16);
			tbl[idx] = val & 0xff;
		}
		add_pair("xlat", argv[2], argv[3], tbl, len);
		free(tbl);
		return (0);
	}
	errx(2, "usage: dfarm ucs <to> <from> | "
	    "dfarm xlat <to> <from> <datalen> <fillhex> [idx:val ...]");
}