2 * iSCSI InitiatorName creation utility
3 * Copyright (C) 2001 Cisco Systems, Inc.
4 * maintained by linux-iscsi-devel@lists.sourceforge.net
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * See the file COPYING included with this distribution for more details.
18 * $Id: iscsi-iname.c,v 1.1.2.3 2005/03/15 06:33:44 wysochanski Exp $
20 * iscsi-iname.c - Compute an iSCSI InitiatorName for this host.
21 * Note that to ensure uniqueness, the system time is
22 * a factor. This name must be cached and only regenerated
23 * if there is no cached value.
32 #include <sys/utsname.h>
37 #define RANDOM_NUM_GENERATOR "/dev/urandom"
40 main(int argc
, char *argv
[])
44 struct utsname system_info
;
46 struct MD5Context context
;
47 unsigned char digest
[16];
48 unsigned char *bytes
= digest
;
49 unsigned char entropy
[16];
55 memset(iname
, 0, sizeof (iname
));
56 memset(digest
, 0, sizeof (digest
));
57 memset(&context
, 0, sizeof (context
));
60 /* take a prefix if given, otherwise use a default. */
61 if (argc
> 1 && argv
[1]) {
63 if (( strcmp(prefix
, "-h") == 0 ) ||
64 ( strcmp(prefix
, "--help") == 0 )) {
65 printf("\nGenerates a unique iSCSI node name "
66 "on every invocation.\n");
68 } else if ( strcmp(prefix
, "-p") == 0 ) {
71 printf("\nUsage: iscsi-iname [-h | --help | "
76 prefix
= "iqn.2005-03.org.open-iscsi";
79 /* try to feed some entropy from the pool to MD5 in order to get
80 * uniqueness properties
83 if ((fd
= open(RANDOM_NUM_GENERATOR
, O_RDONLY
))) {
84 e
= read(fd
, &entropy
, 16);
86 MD5Update(&context
, (md5byte
*)entropy
, e
);
90 /* time the name is created is a factor in order to get
91 * uniqueness properties
93 if (gettimeofday(&time
, NULL
) < 0) {
94 perror("error: gettimeofday failed");
97 MD5Update(&context
, (md5byte
*) & time
.tv_sec
, sizeof (time
.tv_sec
));
98 MD5Update(&context
, (md5byte
*) & time
.tv_usec
, sizeof (time
.tv_usec
));
101 hostid
= gethostid();
102 MD5Update(&context
, (md5byte
*) & hostid
, sizeof (hostid
));
104 /* get the hostname and system name */
105 if (uname(&system_info
) < 0) {
106 perror("error: uname failed");
109 MD5Update(&context
, (md5byte
*) system_info
.sysname
,
110 sizeof (system_info
.sysname
));
111 MD5Update(&context
, (md5byte
*) system_info
.nodename
,
112 sizeof (system_info
.nodename
));
113 MD5Update(&context
, (md5byte
*) system_info
.release
,
114 sizeof (system_info
.release
));
115 MD5Update(&context
, (md5byte
*) system_info
.version
,
116 sizeof (system_info
.version
));
117 MD5Update(&context
, (md5byte
*) system_info
.machine
,
118 sizeof (system_info
.machine
));
120 /* compute the md5 hash of all the bits we just collected */
121 MD5Final(digest
, &context
);
123 /* vary which md5 bytes we pick (though we probably don't need to do
124 * this, since hopefully MD5 produces results such that each byte is as
125 * good as any other).
128 if ((fd
= open(RANDOM_NUM_GENERATOR
, O_RDONLY
))) {
129 if (read(fd
, entropy
, 1) == 1)
130 bytes
= &digest
[(entropy
[0] % (sizeof(digest
) - 6))];
134 /* print the prefix followed by 6 bytes of the MD5 hash */
135 sprintf(iname
, "%s:%x%x%x%x%x%x", prefix
,
136 bytes
[0], bytes
[1], bytes
[2], bytes
[3], bytes
[4], bytes
[5]);
138 iname
[sizeof (iname
) - 1] = '\0';
139 printf("%s\n", iname
);