SHA256
1
0
forked from pool/open-iscsi
open-iscsi/iscsi-iname.c

141 lines
4.0 KiB
C

/*
* iSCSI InitiatorName creation utility
* Copyright (C) 2001 Cisco Systems, Inc.
* maintained by linux-iscsi-devel@lists.sourceforge.net
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* See the file COPYING included with this distribution for more details.
*
* $Id: iscsi-iname.c,v 1.4 2004/12/03 19:36:13 mikenc Exp $
*
* iscsi-iname.c - Compute an iSCSI InitiatorName for this host.
* Note that to ensure uniqueness, the system time is
* a factor. This name must be cached and only regenerated
* if there is no cached value.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include "md5.h"
#define TARGET_NAME_MAXLEN 255
#define RANDOM_NUM_GENERATOR "/dev/urandom"
int
main(int argc, char *argv[])
{
char iname[TARGET_NAME_MAXLEN + 1];
struct timeval time;
struct utsname system_info;
long hostid;
struct MD5Context context;
unsigned char digest[16];
unsigned char *bytes = digest;
unsigned char entropy[16];
int e;
int fd;
char *prefix;
/* initialize */
memset(iname, 0, sizeof (iname));
memset(digest, 0, sizeof (digest));
memset(&context, 0, sizeof (context));
MD5Init(&context);
/* take a prefix if given, otherwise use a default. */
if (argc > 1 && argv[1]) {
prefix = argv[1];
if (( strcmp(prefix, "-h") == 0 ) ||
( strcmp(prefix, "--help") == 0 )) {
printf("\nDisplays the iSCSI initiator name\n");
return 0;
} else if ( strcmp(prefix, "-p") == 0 ) {
prefix = argv[2];
} else {
printf("\nUsage: iscsi-iname [-h | --help | "
"-p <prefix>]\n");
return 0;
}
} else {
prefix = "iqn.1987-05.com.cisco:01";
}
/* try to feed some entropy from the pool to MD5 in order to get
* uniqueness properties
*/
if ((fd = open(RANDOM_NUM_GENERATOR, O_RDONLY))) {
e = read(fd, &entropy, 16);
if (e >= 1)
MD5Update(&context, (md5byte *)entropy, e);
close(fd);
}
/* time the name is created is a factor in order to get
* uniqueness properties
*/
if (gettimeofday(&time, NULL) < 0) {
perror("error: gettimeofday failed");
return 1;
}
MD5Update(&context, (md5byte *) & time.tv_sec, sizeof (time.tv_sec));
MD5Update(&context, (md5byte *) & time.tv_usec, sizeof (time.tv_usec));
/* hostid */
hostid = gethostid();
MD5Update(&context, (md5byte *) & hostid, sizeof (hostid));
/* get the hostname and system name */
if (uname(&system_info) < 0) {
perror("error: uname failed");
return 1;
}
MD5Update(&context, (md5byte *) system_info.sysname,
sizeof (system_info.sysname));
MD5Update(&context, (md5byte *) system_info.nodename,
sizeof (system_info.nodename));
MD5Update(&context, (md5byte *) system_info.release,
sizeof (system_info.release));
MD5Update(&context, (md5byte *) system_info.version,
sizeof (system_info.version));
MD5Update(&context, (md5byte *) system_info.machine,
sizeof (system_info.machine));
/* compute the md5 hash of all the bits we just collected */
MD5Final(digest, &context);
/* vary which md5 bytes we pick (though we probably don't need to do
* this, since hopefully MD5 produces results such that each byte is as
* good as any other).
*/
if ((fd = open(RANDOM_NUM_GENERATOR, O_RDONLY))) {
if (read(fd, entropy, 1) == 1)
bytes = &digest[(entropy[0] % (sizeof(digest) - 6))];
close(fd);
}
/* print the prefix followed by 6 bytes of the MD5 hash */
sprintf(iname, "%s.%x%x%x%x%x%x", prefix,
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]);
iname[sizeof (iname) - 1] = '\0';
printf("%s\n", iname);
return 0;
}