/*
 * misc.c	Miscellaneous TIPC helper functions.
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 *
 * Authors:	Richard Alpe <richard.alpe@ericsson.com>
 */

#include <stdio.h>
#include <stdint.h>
#include <linux/tipc.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include "misc.h"

#define IN_RANGE(val, low, high) ((val) <= (high) && (val) >= (low))

uint32_t str2addr(char *str)
{
	unsigned int z, c, n;
	char dummy;

	if (sscanf(str, "%u.%u.%u%c", &z, &c, &n, &dummy) != 3) {
		fprintf(stderr, "invalid network address, syntax: Z.C.N\n");
		return 0;
	}

	if (IN_RANGE(z, 0, 255) && IN_RANGE(c, 0, 4095) && IN_RANGE(n, 0, 4095))
		return tipc_addr(z, c, n);

	fprintf(stderr, "invalid network address \"%s\"\n", str);
	return 0;
}

static int is_hex(char *arr, int last)
{
	int i;

	while (!arr[last])
		last--;

	for (i = 0; i <= last; i++) {
		if (!IN_RANGE(arr[i], '0', '9') &&
		    !IN_RANGE(arr[i], 'a', 'f') &&
		    !IN_RANGE(arr[i], 'A', 'F'))
			return 0;
	}
	return 1;
}

static int is_name(char *arr, int last)
{
	int i;
	char c;

	while (!arr[last])
		last--;

	if (last > 15)
		return 0;

	for (i = 0; i <= last; i++) {
		c = arr[i];
		if (!IN_RANGE(c, '0', '9') && !IN_RANGE(c, 'a', 'z') &&
		    !IN_RANGE(c, 'A', 'Z') && c != '-' && c != '_' &&
		    c != '.' && c != ':' && c != '@')
			return 0;
	}
	return 1;
}

int str2nodeid(char *str, uint8_t *id)
{
	int len = strlen(str);
	int i;

	if (len > 32)
		return -1;

	if (is_name(str, len - 1)) {
		memcpy(id, str, len);
		return 0;
	}
	if (!is_hex(str, len - 1))
		return -1;

	str[len] = '0';
	for (i = 0; i < 16; i++) {
		if (sscanf(&str[2 * i], "%2hhx", &id[i]) != 1)
			break;
	}
	return 0;
}

int str2key(char *str, struct tipc_aead_key *key)
{
	int len = strlen(str);
	int ishex = 0;
	int i;

	/* Check if the input is a hex string (i.e. 0x...) */
	if (len > 2 && strncmp(str, "0x", 2) == 0) {
	    ishex = is_hex(str + 2, len - 2 - 1);
	    if (ishex) {
		len -= 2;
		str += 2;
	    }
	}

	if (len > TIPC_AEAD_KEYLEN_MAX)
		return -1;

	/* Obtain key: */
	if (!ishex) {
		key->keylen = len;
		memcpy(key->key, str, len);
	} else {
		/* Convert hex string to key */
		key->keylen = (len + 1) / 2;
		for (i = 0; i < key->keylen; i++) {
			if (i == 0 && len % 2 != 0) {
				if (sscanf(str, "%1hhx", &key->key[0]) != 1)
					return -1;
				str += 1;
				continue;
			}
			if (sscanf(str, "%2hhx", &key->key[i]) != 1)
				return -1;
			str += 2;
		}
	}

	return 0;
}

void nodeid2str(uint8_t *id, char *str)
{
	int i;

	if (is_name((char *)id, 15)) {
		memcpy(str, id, 16);
		return;
	}

	for (i = 0; i < 16; i++)
		sprintf(&str[2 * i], "%02x", id[i]);

	for (i = 31; str[i] == '0'; i--)
		str[i] = 0;
}

void hash2nodestr(uint32_t hash, char *str)
{
	struct tipc_sioc_nodeid_req nr = {};
	int sd;

	sd = socket(AF_TIPC, SOCK_RDM, 0);
	if (sd < 0) {
		fprintf(stderr, "opening TIPC socket: %s\n", strerror(errno));
		return;
	}
	nr.peer = hash;
	if (!ioctl(sd, SIOCGETNODEID, &nr))
		nodeid2str((uint8_t *)nr.node_id, str);
	close(sd);
}
