Blame utils/iscsi-iname.c

Packit Service 646995
/*
Packit Service 646995
 * iSCSI InitiatorName creation utility
Packit Service 646995
 * Copyright (C) 2001 Cisco Systems, Inc.
Packit Service 646995
 * maintained by linux-iscsi-devel@lists.sourceforge.net
Packit Service 646995
 *
Packit Service 646995
 * This program is free software; you can redistribute it and/or modify
Packit Service 646995
 * it under the terms of the GNU General Public License as published
Packit Service 646995
 * by the Free Software Foundation; either version 2 of the License, or
Packit Service 646995
 * (at your option) any later version.
Packit Service 646995
 *
Packit Service 646995
 * This program is distributed in the hope that it will be useful, but
Packit Service 646995
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 646995
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit Service 646995
 * General Public License for more details.
Packit Service 646995
 *
Packit Service 646995
 * See the file COPYING included with this distribution for more details.
Packit Service 646995
 *
Packit Service 646995
 * $Id: iscsi-iname.c,v 1.1.2.3 2005/03/15 06:33:44 wysochanski Exp $
Packit Service 646995
 *
Packit Service 646995
 * iscsi-iname.c - Compute an iSCSI InitiatorName for this host.
Packit Service 646995
 * Note that to ensure uniqueness, the system time is
Packit Service 646995
 * a factor.  This name must be cached and only regenerated
Packit Service 646995
 * if there is no cached value.
Packit Service 646995
 */
Packit Service 646995
Packit Service 646995
#include <stdint.h>
Packit Service 646995
#include <fcntl.h>
Packit Service 646995
#include <unistd.h>
Packit Service 646995
#include <stdlib.h>
Packit Service 646995
#include <stdio.h>
Packit Service 646995
#include <string.h>
Packit Service 646995
#include <sys/utsname.h>
Packit Service 646995
#include <sys/time.h>
Packit Service 646995
Packit Service 646995
#include "md5.h"
Packit Service 646995
Packit Service 646995
#define RANDOM_NUM_GENERATOR	"/dev/urandom"
Packit Service 646995
Packit Service 646995
/* iSCSI names have a maximum length of 223 characters, we reserve 13 to append
Packit Service 646995
 * a seperator and 12 characters (6 random bytes in hex representation) */
Packit Service 646995
#define PREFIX_MAX_LEN 210
Packit Service 646995
Packit Service 646995
static void usage(void)
Packit Service 646995
{
Packit Service 646995
	fprintf(stderr, "Usage: iscsi-iname [-h | --help | -p <prefix>]\n");
Packit Service 646995
	fprintf(stderr, "where <prefix> has max length of %d\n",
Packit Service 646995
		PREFIX_MAX_LEN);
Packit Service 646995
}
Packit Service 646995
Packit Service 646995
int
Packit Service 646995
main(int argc, char *argv[])
Packit Service 646995
{
Packit Service 646995
	struct timeval time;
Packit Service 646995
	struct utsname system_info;
Packit Service 646995
	long hostid;
Packit Service 646995
	struct MD5Context context;
Packit Service 646995
	unsigned char digest[16];
Packit Service 646995
	unsigned char *bytes = digest;
Packit Service 646995
	unsigned char entropy[16];
Packit Service 646995
	int e;
Packit Service 646995
	int fd;
Packit Service 646995
	char *prefix;
Packit Service 646995
Packit Service 646995
	/* initialize */
Packit Service 646995
	memset(digest, 0, sizeof (digest));
Packit Service 646995
	memset(&context, 0, sizeof (context));
Packit Service 646995
	MD5Init(&context);
Packit Service 646995
Packit Service 646995
	/* take a prefix if given, otherwise use a default. */
Packit Service 646995
	if (argc > 1 && argv[1]) {
Packit Service 646995
		prefix = argv[1];
Packit Service 646995
		if (( strcmp(prefix, "-h") == 0 ) ||
Packit Service 646995
		    ( strcmp(prefix, "--help") == 0 )) {
Packit Service 646995
			printf("\nGenerates a unique iSCSI node name "
Packit Service 646995
			       "on every invocation.\n");
Packit Service 646995
			exit(0);
Packit Service 646995
		} else if ( strcmp(prefix, "-p") == 0 ) {
Packit Service 646995
			if (argc != 3) {
Packit Service 646995
				usage();
Packit Service 646995
				exit(1);
Packit Service 646995
			}
Packit Service 646995
			prefix = argv[2];
Packit Service 646995
			if (strnlen(prefix, PREFIX_MAX_LEN + 1) > PREFIX_MAX_LEN) {
Packit Service 646995
				usage();
Packit Service 646995
				exit(1);
Packit Service 646995
			}
Packit Service 646995
		} else {
Packit Service 646995
			usage();
Packit Service 646995
			exit(0);
Packit Service 646995
		}
Packit Service 646995
	} else {
Packit Service f80f6b
		prefix = "iqn.2016-04.com.open-iscsi";
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* try to feed some entropy from the pool to MD5 in order to get
Packit Service 646995
	 * uniqueness properties
Packit Service 646995
	 */
Packit Service 646995
Packit Service 646995
	if ((fd = open(RANDOM_NUM_GENERATOR, O_RDONLY))) {
Packit Service 646995
		e = read(fd, &entropy, 16);
Packit Service 646995
		if (e >= 1)
Packit Service 646995
			MD5Update(&context, (md5byte *)entropy, e);
Packit Service 646995
		close(fd);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* time the name is created is a factor in order to get
Packit Service 646995
	 * uniqueness properties
Packit Service 646995
	 */
Packit Service 646995
	if (gettimeofday(&time, NULL) < 0) {
Packit Service 646995
		perror("error: gettimeofday failed");
Packit Service 646995
		return 1;
Packit Service 646995
	}
Packit Service 646995
	MD5Update(&context, (md5byte *) & time.tv_sec, sizeof (time.tv_sec));
Packit Service 646995
	MD5Update(&context, (md5byte *) & time.tv_usec, sizeof (time.tv_usec));
Packit Service 646995
Packit Service 646995
	/* hostid */
Packit Service 646995
	hostid = gethostid();
Packit Service 646995
	MD5Update(&context, (md5byte *) & hostid, sizeof (hostid));
Packit Service 646995
Packit Service 646995
	/* get the hostname and system name */
Packit Service 646995
	if (uname(&system_info) < 0) {
Packit Service 646995
		perror("error: uname failed");
Packit Service 646995
		return 1;
Packit Service 646995
	}
Packit Service 646995
	MD5Update(&context, (md5byte *) system_info.sysname,
Packit Service 646995
		  sizeof (system_info.sysname));
Packit Service 646995
	MD5Update(&context, (md5byte *) system_info.nodename,
Packit Service 646995
		  sizeof (system_info.nodename));
Packit Service 646995
	MD5Update(&context, (md5byte *) system_info.release,
Packit Service 646995
		  sizeof (system_info.release));
Packit Service 646995
	MD5Update(&context, (md5byte *) system_info.version,
Packit Service 646995
		  sizeof (system_info.version));
Packit Service 646995
	MD5Update(&context, (md5byte *) system_info.machine,
Packit Service 646995
		  sizeof (system_info.machine));
Packit Service 646995
Packit Service 646995
	/* compute the md5 hash of all the bits we just collected */
Packit Service 646995
	MD5Final(digest, &context);
Packit Service 646995
Packit Service 646995
	/* vary which md5 bytes we pick (though we probably don't need to do
Packit Service 646995
	 * this, since hopefully MD5 produces results such that each byte is as
Packit Service 646995
	 * good as any other).
Packit Service 646995
	 */
Packit Service 646995
Packit Service 646995
	if ((fd = open(RANDOM_NUM_GENERATOR, O_RDONLY))) {
Packit Service 646995
		if (read(fd, entropy, 1) == 1)
Packit Service 646995
			bytes = &digest[(entropy[0] % (sizeof(digest) - 6))];
Packit Service 646995
		close(fd);
Packit Service 646995
	}
Packit Service 646995
Packit Service 646995
	/* print the prefix followed by 6 bytes of the MD5 hash */
Packit Service 646995
	printf("%s:%x%x%x%x%x%x\n", prefix,
Packit Service 646995
		bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]);
Packit Service 646995
	return 0;
Packit Service 646995
}