xref: /illumos-gate/usr/src/cmd/iscsiadm/iscsiadm_main.c (revision bbf215553c7233fbab8a0afdf1fac74c44781867)
1  /*
2   * CDDL HEADER START
3   *
4   * The contents of this file are subject to the terms of the
5   * Common Development and Distribution License (the "License").
6   * You may not use this file except in compliance with the License.
7   *
8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9   * or http://www.opensolaris.org/os/licensing.
10   * See the License for the specific language governing permissions
11   * and limitations under the License.
12   *
13   * When distributing Covered Code, include this CDDL HEADER in each
14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15   * If applicable, add the following below this CDDL HEADER, with the
16   * fields enclosed by brackets "[]" replaced with your own identifying
17   * information: Portions Copyright [yyyy] [name of copyright owner]
18   *
19   * CDDL HEADER END
20   */
21  /*
22   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23   */
24  
25  #include <stdlib.h>
26  #include <stdio.h>
27  #include <wchar.h>
28  #include <widec.h>
29  #include <sys/types.h>
30  #include <sys/socket.h>
31  #include <arpa/inet.h>
32  #include <netdb.h>
33  #include <unistd.h>
34  #include <libintl.h>
35  #include <limits.h>
36  #include <string.h>
37  #include <strings.h>
38  #include <syslog.h>
39  #include <errno.h>
40  #include <netinet/in.h>
41  #include <sys/socket.h>
42  #include <arpa/inet.h>
43  #include <wctype.h>
44  #include <assert.h>
45  
46  #include <ima.h>
47  #include <libsun_ima.h>
48  #include <sys/iscsi_protocol.h>
49  #include <sys/scsi/adapters/iscsi_if.h>
50  
51  #include "cmdparse.h"
52  #include "sun_ima.h"
53  #include "iscsiadm.h"
54  
55  #define	VERSION_STRING_MAX_LEN	10
56  #define	MAX_LONG_CHAR_LEN 19
57  
58  #define	MAX_AUTH_METHODS 5
59  /*
60   * Version number:
61   *  MAJOR - This should only change when there is an incompatible change made
62   *  to the interfaces or the output.
63   *
64   *  MINOR - This should change whenever there is a new command or new feature
65   *  with no incompatible change.
66   */
67  #define	VERSION_STRING_MAJOR	    "1"
68  #define	VERSION_STRING_MINOR	    "0"
69  
70  #define	OPTIONSTRING1	"yes|no"
71  #define	OPTIONSTRING2	"initiator node name"
72  #define	OPTIONSTRING3	"initiator node alias"
73  #define	OPTIONSTRING4	"enable|disable"
74  #define	OPTIONSTRING5	"key=value,..."
75  #define	OPTIONSTRING6	"none|CRC32"
76  #define	OPTIONSTRING7	"CHAP name"
77  #define	OPTIONSTRING8	"<# sessions>|<IP Address>[,<IP Address>]*"
78  #define	OPTIONSTRING9	"tunable-prop=value"
79  #define	OPTIONVAL1	"0 to 3600"
80  #define	OPTIONVAL2	"512 to 2**24 - 1"
81  #define	OPTIONVAL3	"1 to 65535"
82  #define	OPTIONVAL4	"<IP address>[:port]"
83  
84  #define	MAX_ISCSI_NAME_LEN	    223
85  #define	MAX_ADDRESS_LEN		    255
86  #define	MIN_CHAP_SECRET_LEN	    12
87  #define	MAX_CHAP_SECRET_LEN	    16
88  #define	DEFAULT_ISCSI_PORT	    3260
89  #define	ISNS_DEFAULT_SERVER_PORT    3205
90  #define	DEFAULT_RADIUS_PORT	    1812
91  #define	MAX_CHAP_NAME_LEN	    512
92  #define	ISCSI_DEFAULT_RX_TIMEOUT_VALUE		"60"
93  #define	ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX	"180"
94  #define	ISCSI_DEFAULT_LOGIN_POLLING_DELAY	"60"
95  
96  /* For listNode */
97  #define	INF_ERROR		1
98  #define	INVALID_NODE_NAME	2
99  
100  #define	IMABOOLPRINT(prop, option)	 \
101  	if ((option) == PRINT_CONFIGURED_PARAMS) { \
102  		(void) fprintf(stdout, "%s/%s\n", \
103  		(prop).defaultValue == IMA_TRUE ? gettext("yes") : \
104  			gettext("no"), \
105  		(prop).currentValueValid == IMA_TRUE ? \
106  			((prop).currentValue == IMA_TRUE ? \
107  			gettext("yes"): gettext("no")) : "-"); \
108  	} else if ((option) == PRINT_NEGOTIATED_PARAMS) { \
109  		(void) fprintf(stdout, "%s\n", \
110  		(prop).currentValueValid == IMA_TRUE ? \
111  		(((prop).currentValue == IMA_TRUE) ? gettext("yes") : \
112  		gettext("no")) : "-"); \
113  	}
114  
115  #define	IMAMINMAXPRINT(prop, option) \
116  	if ((option) == PRINT_CONFIGURED_PARAMS) { \
117  		(void) fprintf(stdout, "%d/", (prop).defaultValue); \
118  		if ((prop).currentValueValid == IMA_TRUE) { \
119  			(void) fprintf(stdout, "%d\n", (prop).currentValue); \
120  		} else if ((prop).currentValueValid == IMA_FALSE) { \
121  			(void) fprintf(stdout, "%s\n", "-"); \
122  		} \
123  	} else if ((option) == PRINT_NEGOTIATED_PARAMS) { \
124  		if ((prop).currentValueValid == IMA_TRUE) { \
125  			(void) fprintf(stdout, "%d\n", (prop).currentValue); \
126  		} else if ((prop).currentValueValid == IMA_FALSE) { \
127  			(void) fprintf(stdout, "%s\n", "-"); \
128  		} \
129  	}
130  
131  /* forward declarations */
132  #define	PARSE_ADDR_OK				0
133  #define	PARSE_ADDR_MISSING_CLOSING_BRACKET	1
134  #define	PARSE_ADDR_PORT_OUT_OF_RANGE		2
135  #define	PARSE_TARGET_OK				0
136  #define	PARSE_TARGET_INVALID_TPGT		1
137  #define	PARSE_TARGET_INVALID_ADDR		2
138  
139  #define	PRINT_CONFIGURED_PARAMS			1
140  #define	PRINT_NEGOTIATED_PARAMS			2
141  
142  typedef enum iSCSINameCheckStatus {
143  	iSCSINameCheckOK,
144  	iSCSINameLenZero,
145  	iSCSINameLenExceededMax,
146  	iSCSINameUnknownType,
147  	iSCSINameInvalidCharacter,
148  	iSCSINameIqnFormatError,
149  	iSCSINameEUIFormatError,
150  	iSCSINameIqnDateFormatError,
151  	iSCSINameIqnSubdomainFormatError,
152  	iSCSINameIqnInvalidYearError,
153  	iSCSINameIqnInvalidMonthError,
154  	iSCSINameIqnFQDNError
155  } iSCSINameCheckStatusType;
156  
157  /* Utility functions */
158  iSCSINameCheckStatusType iSCSINameStringProfileCheck(wchar_t *name);
159  boolean_t isNaturalNumber(char *numberStr, uint32_t upperBound);
160  static int parseAddress(char *address_port_str, uint16_t defaultPort,
161      char *address_str, size_t address_str_len,
162      uint16_t *port, boolean_t *isIpv6);
163  int parseTarget(char *targetStr,
164      wchar_t *targetNameStr,
165      size_t targetNameStrLen,
166      boolean_t *targetAddressSpecified,
167      wchar_t *targetAddressStr,
168      size_t targetAddressStrLen,
169      uint16_t *port,
170      boolean_t *tpgtSpecified,
171      uint16_t *tpgt,
172      boolean_t *isIpv6);
173  static int chkConnLoginMaxPollingLoginDelay(IMA_OID oid,
174      int key, int uintValue);
175  
176  /* subcommand functions */
177  static int addFunc(int, char **, int, cmdOptions_t *, void *, int *);
178  static int listFunc(int, char **, int, cmdOptions_t *, void *, int *);
179  static int modifyFunc(int, char **, int, cmdOptions_t *, void *, int *);
180  static int removeFunc(int, char **, int, cmdOptions_t *, void *, int *);
181  
182  /* helper functions */
183  static char *getExecBasename(char *);
184  static int getNodeProps(IMA_NODE_PROPERTIES *);
185  static int getSecret(char *, int *, int, int);
186  static int getTargetAddress(int, char *, IMA_TARGET_ADDRESS *);
187  static int printLoginParameters(char *, IMA_OID, int);
188  static void printDiscoveryMethod(char *, IMA_UINT32);
189  static void printTargetLuns(IMA_OID_LIST *);
190  static void printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *);
191  static void printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE *, int);
192  static int setLoginParameter(IMA_OID, int, char *);
193  static int setLoginParameters(IMA_OID, char *);
194  static int setTunableParameters(IMA_OID, char *);
195  static void printLibError(IMA_STATUS);
196  /* LINTED E_STATIC_UNUSED */
197  static int sunPluginChk(IMA_OID, boolean_t *);
198  static int sunInitiatorFind(IMA_OID *);
199  static int getAuthMethodValue(char *, IMA_AUTHMETHOD *);
200  static int getLoginParam(char *);
201  static int getTunableParam(char *);
202  static void iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status);
203  static int modifyIndividualTargetParam(cmdOptions_t *optionList,
204      IMA_OID targetOid, int *);
205  static void listCHAPName(IMA_OID oid);
206  static int printConfiguredSessions(IMA_OID);
207  static int printTunableParameters(IMA_OID oid);
208  
209  /* object functions per subcommand */
210  static int addAddress(int, int, char *[], int *);
211  static int addStaticConfig(int, char *[], int *);
212  static int listDiscovery(int *);
213  static int listDiscoveryAddress(int, char *[], cmdOptions_t *, int *);
214  static int listISNSServerAddress(int, char *[], cmdOptions_t *, int *);
215  static int listNode(int *);
216  static int listStaticConfig(int, char *[], int *);
217  static int listTarget(int, char *[], cmdOptions_t *, int *);
218  static int listTargetParam(int, char *[], cmdOptions_t *, int *);
219  static int modifyDiscovery(cmdOptions_t *, int *);
220  static int modifyNodeAuthMethod(IMA_OID, char *, int *);
221  static int modifyNodeAuthParam(IMA_OID oid, int, char *, int *);
222  static int modifyNodeRadiusConfig(IMA_OID, char *, int *);
223  static int modifyNodeRadiusAccess(IMA_OID, char *, int *);
224  static int modifyNodeRadiusSharedSecret(IMA_OID, int *);
225  static int modifyNode(cmdOptions_t *, int *);
226  static int modifyTargetAuthMethod(IMA_OID, char *, int *);
227  static int modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *);
228  static int modifyTargetParam(cmdOptions_t *, char *, int *);
229  static int removeAddress(int, int, char *[], int *);
230  static int removeStaticConfig(int, char *[], int *);
231  static int removeTargetParam(int, char *[], int *);
232  static int modifyTargetBidirAuthFlag(IMA_OID, char *, int *);
233  static int modifyConfiguredSessions(IMA_OID targetOid, char *optarg);
234  
235  /* LINTED E_STATIC_UNUSED */
236  static IMA_STATUS getISCSINodeParameter(int paramType,
237      IMA_OID *oid,
238      void *pProps,
239      uint32_t paramIndex);
240  /* LINTED E_STATIC_UNUSED */
241  static IMA_STATUS setISCSINodeParameter(int paramType,
242      IMA_OID *oid,
243      void *pProps,
244      uint32_t paramIndex);
245  /* LINTED E_STATIC_UNUSED */
246  static IMA_STATUS getDigest(IMA_OID oid, int ioctlCmd,
247      SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm);
248  
249  IMA_STATUS getNegotiatedDigest(int digestType,
250  	SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm,
251  	SUN_IMA_CONN_PROPERTIES *connProps);
252  
253  /* globals */
254  static char *cmdName;
255  
256  /*
257   * Available option letters:
258   *
259   * befgijklmnoquwxyz
260   *
261   * DEFGHIJKLMOQUVWXYZ
262   */
263  
264  /*
265   * Add new options here
266   */
267  optionTbl_t longOptions[] = {
268  	{"static", required_arg, 's', OPTIONSTRING4},
269  	{"sendtargets", required_arg, 't', OPTIONSTRING4},
270  	{"iSNS", required_arg, 'i', OPTIONSTRING4},
271  	{"headerdigest", required_arg, 'h', OPTIONSTRING6},
272  	{"datadigest", required_arg, 'd', OPTIONSTRING6},
273  	{"login-param", required_arg, 'p', OPTIONSTRING5},
274  	{"authentication", required_arg, 'a', "CHAP|none"},
275  	{"bi-directional-authentication", required_arg, 'B', OPTIONSTRING4},
276  	{"CHAP-secret", no_arg, 'C', NULL},
277  	{"CHAP-name", required_arg, 'H', OPTIONSTRING7},
278  	{"node-name", required_arg, 'N', OPTIONSTRING2},
279  	{"node-alias", required_arg, 'A', OPTIONSTRING3},
280  	{"radius-server", required_arg, 'r', OPTIONVAL4},
281  	{"radius-access", required_arg, 'R', OPTIONSTRING4},
282  	{"radius-shared-secret", no_arg, 'P', NULL},
283  	{"verbose", no_arg, 'v', NULL},
284  	{"scsi-target", no_arg, 'S', NULL},
285  	{"configured-sessions", required_arg, 'c', OPTIONSTRING8},
286  	{"tunable-param", required_arg, 'T', OPTIONSTRING9},
287  	{NULL, 0, 0, 0}
288  };
289  
290  parameterTbl_t loginParams[] = {
291  	{"dataseqinorder", DATA_SEQ_IN_ORDER},
292  	{"defaulttime2retain", DEFAULT_TIME_2_RETAIN},
293  	{"defaulttime2wait", DEFAULT_TIME_2_WAIT},
294  	{"firstburstlength", FIRST_BURST_LENGTH},
295  	{"immediatedata", IMMEDIATE_DATA},
296  	{"initialr2t", INITIAL_R2T},
297  	{"maxburstlength", MAX_BURST_LENGTH},
298  	{"datapduinorder", DATA_PDU_IN_ORDER},
299  	{"maxoutstandingr2t", MAX_OUTSTANDING_R2T},
300  	{"maxrecvdataseglen", MAX_RECV_DATA_SEG_LEN},
301  	{"maxconnections", MAX_CONNECTIONS},
302  	{"errorrecoverylevel", ERROR_RECOVERY_LEVEL},
303  	{NULL, 0}
304  };
305  
306  parameterTbl_t tunableParams[] = {
307  	{"recv-login-rsp-timeout", RECV_LOGIN_RSP_TIMEOUT},
308  	{"conn-login-max", CONN_LOGIN_MAX},
309  	{"polling-login-delay", POLLING_LOGIN_DELAY},
310  	{NULL, 0}
311  };
312  
313  /*
314   * Add new subcommands here
315   */
316  subcommand_t subcommands[] = {
317  	{"add", ADD, addFunc},
318  	{"list", LIST, listFunc},
319  	{"modify", MODIFY, modifyFunc},
320  	{"remove", REMOVE, removeFunc},
321  	{NULL, 0, NULL}
322  };
323  
324  /*
325   * Add objects here
326   */
327  object_t objects[] = {
328  	{"discovery", DISCOVERY},
329  	{"discovery-address", DISCOVERY_ADDRESS},
330  	{"isns-server", ISNS_SERVER_ADDRESS},
331  	{"initiator-node", NODE},
332  	{"static-config", STATIC_CONFIG},
333  	{"target", TARGET},
334  	{"target-param", TARGET_PARAM},
335  	{NULL, 0}
336  };
337  
338  /*
339   * Rules for subcommands and objects
340   */
341  objectRules_t objectRules[] = {
342  	{TARGET, 0, LIST, 0, ADD|REMOVE|MODIFY, LIST,
343  	"target-name"},
344  	{TARGET_PARAM, MODIFY|REMOVE, LIST, 0, ADD, MODIFY,
345  	"target-name"},
346  	{DISCOVERY, 0, 0, LIST|MODIFY, ADD|REMOVE, 0, NULL},
347  	{NODE, 0, 0, MODIFY|LIST, ADD|REMOVE, 0, NULL},
348  	{STATIC_CONFIG, ADD|REMOVE, LIST, 0, MODIFY, ADD|REMOVE|LIST,
349  	"target-name,target-address[:port-number][,tpgt]"},
350  	{DISCOVERY_ADDRESS, ADD|REMOVE, LIST, 0, MODIFY,
351  	ADD|REMOVE|LIST, "IP-address[:port-number]"},
352  	{ISNS_SERVER_ADDRESS, ADD|REMOVE, LIST, 0, MODIFY,
353  	ADD|REMOVE|LIST, "IP-address[:port-number]"},
354  	{0, 0, 0, 0, 0, 0}
355  };
356  
357  /*
358   * list of objects, subcommands, valid short options, required flag and
359   * exclusive option string
360   *
361   * If it's not here, there are no options for that object.
362   */
363  optionRules_t optionRules[] = {
364  	{DISCOVERY, MODIFY, "sti", B_TRUE, NULL},
365  	{DISCOVERY_ADDRESS, LIST, "v", B_FALSE, NULL},
366  	{ISNS_SERVER_ADDRESS, LIST, "v", B_FALSE, NULL},
367  	{TARGET, LIST, "vS", B_FALSE, NULL},
368  	{NODE, MODIFY, "NAhdCaRrPHcT", B_TRUE, "CP"},
369  	{TARGET_PARAM, MODIFY, "ahdBCpcHT", B_TRUE, "C"},
370  	{TARGET_PARAM, LIST, "v", B_FALSE, NULL},
371  	{0, 0, 0, 0, 0}
372  };
373  
374  
375  static boolean_t
targetNamesEqual(wchar_t * name1,wchar_t * name2)376  targetNamesEqual(wchar_t *name1, wchar_t *name2)
377  {
378  	int i;
379  	wchar_t wchar1, wchar2;
380  
381  	if (name1 == NULL || name2 == NULL) {
382  		return (B_FALSE);
383  	}
384  
385  	if (wcslen(name1) != wcslen(name2)) {
386  		return (B_FALSE);
387  	}
388  
389  	/*
390  	 * Convert names to lower case and compare
391  	 */
392  	for (i = 0; i < wcslen(name1); i++) {
393  		wchar1 = towctrans((wint_t)name1[i], wctrans("tolower"));
394  		wchar2 = towctrans((wint_t)name2[i], wctrans("tolower"));
395  
396  		if (wchar1 != wchar2) {
397  			return (B_FALSE);
398  		}
399  	}
400  
401  	return (B_TRUE);
402  }
403  
404  static boolean_t
ipAddressesEqual(IMA_TARGET_ADDRESS addr1,IMA_TARGET_ADDRESS addr2)405  ipAddressesEqual(IMA_TARGET_ADDRESS addr1, IMA_TARGET_ADDRESS addr2)
406  {
407  #define	IPV4_ADDR_BYTES 4
408  #define	IPV6_ADDR_BYTES 16
409  
410  	int compSize;
411  
412  	if (addr1.hostnameIpAddress.id.ipAddress.ipv4Address !=
413  	    addr2.hostnameIpAddress.id.ipAddress.ipv4Address) {
414  		return (B_FALSE);
415  	}
416  
417  	compSize = IPV6_ADDR_BYTES;
418  	if (addr1.hostnameIpAddress.id.ipAddress.ipv4Address) {
419  		compSize = IPV4_ADDR_BYTES;
420  	}
421  
422  	if (bcmp(addr1.hostnameIpAddress.id.ipAddress.ipAddress,
423  	    addr2.hostnameIpAddress.id.ipAddress.ipAddress, compSize) == 0) {
424  		return (B_TRUE);
425  	}
426  
427  	return (B_FALSE);
428  }
429  
430  static int
getLoginParam(char * arg)431  getLoginParam(char *arg)
432  {
433  	parameterTbl_t *paramp;
434  	int len;
435  
436  	for (paramp = loginParams; paramp->name; paramp++) {
437  		len = strlen(arg);
438  		if (len == strlen(paramp->name) &&
439  		    strncasecmp(arg, paramp->name, len) == 0) {
440  			return (paramp->val);
441  		}
442  	}
443  	return (-1);
444  }
445  
446  static int
getTunableParam(char * arg)447  getTunableParam(char *arg)
448  {
449  	parameterTbl_t *paramp;
450  	int len;
451  
452  	for (paramp = tunableParams; paramp->name != NULL; paramp++) {
453  		len = strlen(arg);
454  		if (len == strlen(paramp->name) &&
455  		    strncasecmp(arg, paramp->name, len) == 0) {
456  			return (paramp->val);
457  		}
458  	}
459  	return (-1);
460  }
461  
462  static void
printLibError(IMA_STATUS status)463  printLibError(IMA_STATUS status)
464  {
465  	char *errorString;
466  	switch (status) {
467  	case IMA_ERROR_NOT_SUPPORTED:
468  		errorString =
469  		gettext("Operation currently not supported");
470  		break;
471  	case IMA_ERROR_INSUFFICIENT_MEMORY:
472  		errorString = gettext("Insufficient memory");
473  		break;
474  	case IMA_ERROR_UNEXPECTED_OS_ERROR:
475  		errorString = gettext("unexpected OS error");
476  		break;
477  	case IMA_ERROR_UNKNOWN_ERROR:
478  		errorString = gettext("Unknown error");
479  		break;
480  	case IMA_ERROR_LU_IN_USE:
481  		errorString = gettext("Logical unit in use");
482  		break;
483  	case IMA_ERROR_INVALID_PARAMETER:
484  		errorString = gettext("Invalid parameter specified");
485  		break;
486  	case IMA_ERROR_INVALID_OBJECT_TYPE:
487  		errorString =
488  		gettext("Internal library error: Invalid oid type specified");
489  		break;
490  	case IMA_ERROR_INCORRECT_OBJECT_TYPE:
491  		errorString =
492  		gettext("Internal library error: Incorrect oid type specified");
493  		break;
494  	case IMA_ERROR_OBJECT_NOT_FOUND:
495  		errorString = gettext("Internal library error: Oid not found");
496  		break;
497  	case IMA_ERROR_NAME_TOO_LONG:
498  		errorString = gettext("Name too long");
499  		break;
500  	default:
501  		errorString = gettext("Unknown error");
502  	}
503  	(void) fprintf(stderr, "%s: %s\n", cmdName, errorString);
504  }
505  
506  /*
507   * input:
508   *  execFullName - exec name of program (argv[0])
509   *
510   * Returns:
511   *  command name portion of execFullName
512   */
513  static char *
getExecBasename(char * execFullname)514  getExecBasename(char *execFullname)
515  {
516  	char *lastSlash, *execBasename;
517  
518  	/* guard against '/' at end of command invocation */
519  	for (;;) {
520  		lastSlash = strrchr(execFullname, '/');
521  		if (lastSlash == NULL) {
522  			execBasename = execFullname;
523  			break;
524  		} else {
525  			execBasename = lastSlash + 1;
526  			if (*execBasename == '\0') {
527  				*lastSlash = '\0';
528  				continue;
529  			}
530  			break;
531  		}
532  	}
533  	return (execBasename);
534  }
535  
536  
537  /*
538   * input:
539   *  nodeProps - pointer to caller allocated IMA_NODE_PROPERTIES
540   *
541   * returns:
542   *  zero on success
543   *  non-zero otherwise
544   */
545  static int
getNodeProps(IMA_NODE_PROPERTIES * nodeProps)546  getNodeProps(IMA_NODE_PROPERTIES *nodeProps)
547  {
548  	IMA_OID sharedNodeOid;
549  
550  	IMA_STATUS status = IMA_GetSharedNodeOid(&sharedNodeOid);
551  	if (!(IMA_SUCCESS(status))) {
552  		printLibError(status);
553  		return (INF_ERROR);
554  	}
555  
556  	status = IMA_GetNodeProperties(sharedNodeOid, nodeProps);
557  	if (!IMA_SUCCESS(status)) {
558  		printLibError(status);
559  		return (INF_ERROR);
560  	}
561  
562  	return (0);
563  }
564  
565  /*
566   * sunInitiatorFind
567   * Purpose:
568   *  Finds the Sun iSCSI initiator (LHBA). This CLI currently supports only
569   *  one initiator.
570   *
571   * output:
572   *  oid of initiator
573   *
574   * Returns:
575   *  zero on success with initiator found
576   *  > 0 on success with no initiator found
577   *  < 0 on failure
578   */
579  static int
sunInitiatorFind(IMA_OID * oid)580  sunInitiatorFind(IMA_OID *oid)
581  {
582  	IMA_OID_LIST *lhbaList = NULL;
583  
584  	IMA_STATUS status = IMA_GetLhbaOidList(&lhbaList);
585  	if (!IMA_SUCCESS(status)) {
586  		printLibError(status);
587  		return (-1);
588  	}
589  
590  	if ((lhbaList == NULL) || (lhbaList->oidCount == 0)) {
591  		printLibError(IMA_ERROR_OBJECT_NOT_FOUND);
592  		if (lhbaList != NULL)
593  			(void) IMA_FreeMemory(lhbaList);
594  		return (-1);
595  	}
596  
597  	*oid = lhbaList->oids[0];
598  	(void) IMA_FreeMemory(lhbaList);
599  
600  	return (0);
601  }
602  
603  /*
604   * input:
605   *  wcInput - wide character string containing discovery address
606   * output:
607   *  address - IMA_TARGET_ADDRESS structure containing valid
608   *	discovery address
609   * returns:
610   *  zero on success
611   *  non-zero on failure
612   */
613  
614  static int
getTargetAddress(int addrType,char * ipStr,IMA_TARGET_ADDRESS * address)615  getTargetAddress(int addrType, char *ipStr, IMA_TARGET_ADDRESS *address)
616  {
617  	char cCol = ':';
618  	char cBracketL = '['; /* Open Bracket '[' */
619  	char cBracketR = ']'; /* Close Bracket ']' */
620  	char *colPos;
621  	char *startPos;
622  	unsigned long inputPort;
623  	int addressType = AF_INET;
624  	char *tmpStrPtr, tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN];
625  	int rval;
626  
627  	/* Check if this is a ipv6 address */
628  	if (ipStr[0] == cBracketL) {
629  		addressType = AF_INET6;
630  		startPos = strchr(ipStr, cBracketR);
631  		if (!startPos) {
632  			(void) fprintf(stderr, "%s: %s: ']' %s\n",
633  			    cmdName, ipStr, gettext("missing"));
634  			return (1);
635  		}
636  		(void) strlcpy(tmpStr, ipStr+1, startPos-ipStr);
637  		address->hostnameIpAddress.id.ipAddress.ipv4Address = IMA_FALSE;
638  		tmpStrPtr = tmpStr;
639  	} else {
640  		/* set start position to beginning of input object */
641  		addressType = AF_INET;
642  		startPos = ipStr;
643  		address->hostnameIpAddress.id.ipAddress.ipv4Address = IMA_TRUE;
644  		tmpStrPtr = ipStr;
645  	}
646  	/* wcschr for ':'. If not there, use default port */
647  	colPos = strchr(startPos, cCol);
648  
649  	if (!colPos) {
650  		if (addrType == DISCOVERY_ADDRESS) {
651  			inputPort = DEFAULT_ISCSI_PORT;
652  		} else if (addrType == ISNS_SERVER_ADDRESS) {
653  			inputPort = ISNS_DEFAULT_SERVER_PORT;
654  		} else {
655  			*colPos = '\0';
656  		}
657  	} else {
658  		*colPos = '\0';
659  	}
660  
661  	rval = inet_pton(addressType, tmpStrPtr,
662  	    address->hostnameIpAddress.id.ipAddress.ipAddress);
663  	/* inet_pton returns 1 on success */
664  	if (rval != 1) {
665  		(void) fprintf(stderr, "%s: %s: %s\n", cmdName, ipStr,
666  		    gettext("invalid IP address"));
667  		return (1);
668  	}
669  
670  
671  	if (colPos) {
672  		char *errchr;
673  
674  		colPos++;
675  		if (*colPos == '\0') {
676  			(void) fprintf(stderr, "%s: %s: %s\n",
677  			    cmdName, ipStr,
678  			    gettext("port number missing"));
679  			return (1);
680  		}
681  
682  		/*
683  		 * convert port string to unsigned value
684  		 * Note:  Don't remove errno = 0 as you may get false failures.
685  		 */
686  		errno = 0;
687  		inputPort = strtol(colPos, &errchr, 10);
688  		if (errno != 0 || inputPort == 0 && errchr != NULL) {
689  			(void) fprintf(stderr, "%s: %s:%s %s\n",
690  			    cmdName, ipStr, colPos,
691  			    gettext("port number invalid"));
692  			return (1);
693  		}
694  		/* make sure it's in the range */
695  		if (inputPort > USHRT_MAX) {
696  			(void) fprintf(stderr, "%s: %s: %s\n",
697  			    cmdName, ipStr,
698  			    gettext("port number out of range"));
699  			return (1);
700  		}
701  	}
702  	address->portNumber  = inputPort;
703  
704  	return (0);
705  }
706  
707  /*
708   * Print results of send targets command
709   */
710  static void
printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES * pList)711  printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList)
712  {
713  	char outBuf[INET6_ADDRSTRLEN];
714  	int inetSize;
715  	int af;
716  	int i;
717  
718  	for (i = 0; i < pList->keyCount; i++) {
719  		if (pList->keys[i].address.ipAddress.ipv4Address == IMA_TRUE) {
720  			af = AF_INET;
721  			inetSize = INET_ADDRSTRLEN;
722  		} else {
723  			af = AF_INET6;
724  			inetSize = INET6_ADDRSTRLEN;
725  		}
726  		(void) fprintf(stdout, gettext("\tTarget name: %ws\n"),
727  		    pList->keys[i].name);
728  		(void) fprintf(stdout, "\t\t%s: %15s:%d", "Target address",
729  		    inet_ntop(af, &(pList->keys[i].address.ipAddress.ipAddress),
730  		    outBuf, inetSize), pList->keys[i].address.portNumber);
731  		(void) fprintf(stdout, ", %d", pList->keys[i].tpgt);
732  		(void) fprintf(stdout, "\n");
733  	}
734  }
735  
736  
737  /*
738   * Print all login parameters
739   */
740  static int
printLoginParameters(char * prefix,IMA_OID oid,int printOption)741  printLoginParameters(char *prefix, IMA_OID oid, int printOption)
742  {
743  	IMA_STATUS status;
744  	IMA_BOOL_VALUE propBool;
745  	IMA_MIN_MAX_VALUE propMinMax;
746  	char longString[MAX_LONG_CHAR_LEN + 1];
747  	SUN_IMA_CONN_PROPERTIES	*connProps = NULL;
748  	IMA_OID_LIST *pConnList;
749  
750  	(void) memset(longString, 0, sizeof (longString));
751  
752  	switch (printOption) {
753  		case PRINT_CONFIGURED_PARAMS:
754  			(void) fprintf(stdout, "%s%s:\n",
755  			    prefix,
756  			    gettext("Login Parameters (Default/Configured)"));
757  			break;
758  		case PRINT_NEGOTIATED_PARAMS:
759  			(void) fprintf(stdout, "%s%s:\n",
760  			    prefix,
761  			    gettext("Login Parameters (Negotiated)"));
762  			status = SUN_IMA_GetConnOidList(
763  			    &oid,
764  			    &pConnList);
765  
766  			if (!IMA_SUCCESS(status)) {
767  				printLibError(status);
768  				return (1);
769  			}
770  
771  			status = SUN_IMA_GetConnProperties(&pConnList->oids[0],
772  			    &connProps);
773  			propBool.currentValueValid = connProps->valuesValid;
774  			propMinMax.currentValueValid = connProps->valuesValid;
775  			break;
776  		default:
777  			return (1);
778  	}
779  
780  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
781  		propBool.currentValue = connProps->dataSequenceInOrder;
782  	} else {
783  		status = IMA_GetDataSequenceInOrderProperties(oid, &propBool);
784  	}
785  	if (!IMA_SUCCESS(status)) {
786  		printLibError(status);
787  		(void) IMA_FreeMemory(connProps);
788  		return (1);
789  	}
790  	(void) fprintf(stdout, "%s\t%s: ", prefix,
791  	    gettext("Data Sequence In Order"));
792  	IMABOOLPRINT(propBool, printOption);
793  
794  
795  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
796  		propBool.currentValue = connProps->dataPduInOrder;
797  	} else {
798  		status = IMA_GetDataPduInOrderProperties(oid, &propBool);
799  	}
800  	if (!IMA_SUCCESS(status)) {
801  		printLibError(status);
802  		(void) IMA_FreeMemory(connProps);
803  		return (1);
804  	}
805  	(void) fprintf(stdout, "%s\t%s: ", prefix,
806  	    gettext("Data PDU In Order"));
807  	IMABOOLPRINT(propBool, printOption);
808  
809  
810  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
811  		propMinMax.currentValue = connProps->defaultTime2Retain;
812  	} else {
813  		status = IMA_GetDefaultTime2RetainProperties(oid, &propMinMax);
814  	}
815  	if (!IMA_SUCCESS(status)) {
816  		printLibError(status);
817  		(void) IMA_FreeMemory(connProps);
818  		return (1);
819  	}
820  	(void) fprintf(stdout, "%s\t%s: ", prefix,
821  	    gettext("Default Time To Retain"));
822  	IMAMINMAXPRINT(propMinMax, printOption);
823  
824  
825  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
826  		propMinMax.currentValue = connProps->defaultTime2Wait;
827  	} else {
828  		status = IMA_GetDefaultTime2WaitProperties(oid, &propMinMax);
829  	}
830  	if (!IMA_SUCCESS(status)) {
831  		printLibError(status);
832  		(void) IMA_FreeMemory(connProps);
833  		return (1);
834  	}
835  	(void) fprintf(stdout, "%s\t%s: ", prefix,
836  	    gettext("Default Time To Wait"));
837  	IMAMINMAXPRINT(propMinMax, printOption);
838  
839  
840  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
841  		propMinMax.currentValue = connProps->errorRecoveryLevel;
842  	} else {
843  		status = IMA_GetErrorRecoveryLevelProperties(oid, &propMinMax);
844  	}
845  	if (!IMA_SUCCESS(status)) {
846  		printLibError(status);
847  		(void) IMA_FreeMemory(connProps);
848  		return (1);
849  	}
850  	(void) fprintf(stdout, "%s\t%s: ", prefix,
851  	    gettext("Error Recovery Level"));
852  	IMAMINMAXPRINT(propMinMax, printOption);
853  
854  
855  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
856  		propMinMax.currentValue = connProps->firstBurstLength;
857  	} else {
858  		status = IMA_GetFirstBurstLengthProperties(oid,
859  		    &propMinMax);
860  	}
861  	if (!IMA_SUCCESS(status)) {
862  		printLibError(status);
863  		(void) IMA_FreeMemory(connProps);
864  		return (1);
865  	}
866  	(void) fprintf(stdout, "%s\t%s: ",
867  	    prefix, gettext("First Burst Length"));
868  	IMAMINMAXPRINT(propMinMax, printOption);
869  
870  
871  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
872  		propBool.currentValue = connProps->immediateData;
873  	} else {
874  		status = IMA_GetImmediateDataProperties(oid, &propBool);
875  	}
876  	if (!IMA_SUCCESS(status)) {
877  		printLibError(status);
878  		(void) IMA_FreeMemory(connProps);
879  		return (1);
880  	}
881  	(void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Immediate Data"));
882  	IMABOOLPRINT(propBool, printOption);
883  
884  
885  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
886  		propBool.currentValue = connProps->initialR2T;
887  	} else {
888  		status = IMA_GetInitialR2TProperties(oid, &propBool);
889  	}
890  	if (!IMA_SUCCESS(status)) {
891  		printLibError(status);
892  		(void) IMA_FreeMemory(connProps);
893  		return (1);
894  	}
895  	(void) fprintf(stdout, "%s\t%s: ", prefix,
896  	    gettext("Initial Ready To Transfer (R2T)"));
897  	IMABOOLPRINT(propBool, printOption);
898  
899  
900  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
901  		propMinMax.currentValue = connProps->maxBurstLength;
902  	} else {
903  		status = IMA_GetMaxBurstLengthProperties(oid, &propMinMax);
904  	}
905  	if (!IMA_SUCCESS(status)) {
906  		printLibError(status);
907  		(void) IMA_FreeMemory(connProps);
908  		return (1);
909  	}
910  	(void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Max Burst Length"));
911  	IMAMINMAXPRINT(propMinMax, printOption);
912  
913  
914  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
915  		propMinMax.currentValue = connProps->maxOutstandingR2T;
916  	} else {
917  		status = IMA_GetMaxOutstandingR2TProperties(oid, &propMinMax);
918  	}
919  	if (!IMA_SUCCESS(status)) {
920  		printLibError(status);
921  		(void) IMA_FreeMemory(connProps);
922  		return (1);
923  	}
924  	(void) fprintf(stdout, "%s\t%s: ", prefix,
925  	    gettext("Max Outstanding R2T"));
926  	IMAMINMAXPRINT(propMinMax, printOption);
927  
928  
929  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
930  		propMinMax.currentValue = connProps->maxRecvDataSegmentLength;
931  	} else {
932  		status = IMA_GetMaxRecvDataSegmentLengthProperties(oid,
933  		    &propMinMax);
934  	}
935  	if (!IMA_SUCCESS(status)) {
936  		printLibError(status);
937  		(void) IMA_FreeMemory(connProps);
938  		return (1);
939  	}
940  	(void) fprintf(stdout, "%s\t%s: ", prefix,
941  	    gettext("Max Receive Data Segment Length"));
942  	IMAMINMAXPRINT(propMinMax, printOption);
943  
944  
945  	if (printOption == PRINT_NEGOTIATED_PARAMS) {
946  		propMinMax.currentValue = connProps->maxConnections;
947  	} else {
948  		status = IMA_GetMaxConnectionsProperties(oid, &propMinMax);
949  	}
950  	if (!IMA_SUCCESS(status)) {
951  		printLibError(status);
952  		(void) IMA_FreeMemory(connProps);
953  		return (1);
954  	}
955  	(void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Max Connections"));
956  	IMAMINMAXPRINT(propMinMax, printOption);
957  
958  	(void) IMA_FreeMemory(connProps);
959  	return (0);
960  }
961  
962  /*
963   * Print discovery information.
964   */
965  static void
printDiscoveryMethod(char * prefix,IMA_UINT32 discoveryMethodFlags)966  printDiscoveryMethod(char *prefix, IMA_UINT32 discoveryMethodFlags)
967  {
968  	(void) fprintf(stdout, "%s%s: ", prefix, gettext("Discovery Method"));
969  	if (discoveryMethodFlags == IMA_TARGET_DISCOVERY_METHOD_UNKNOWN) {
970  		(void) fprintf(stdout, "%s\n", gettext("NA"));
971  	} else {
972  		if (!((discoveryMethodFlags &
973  		    IMA_TARGET_DISCOVERY_METHOD_STATIC) ^
974  		    IMA_TARGET_DISCOVERY_METHOD_STATIC)) {
975  			(void) fprintf(stdout, "%s ", gettext("Static"));
976  		}
977  		if (!((discoveryMethodFlags &
978  		    IMA_TARGET_DISCOVERY_METHOD_SENDTARGETS) ^
979  		    IMA_TARGET_DISCOVERY_METHOD_SENDTARGETS)) {
980  			(void) fprintf(stdout, "%s ", gettext("SendTargets"));
981  		}
982  		if (!((discoveryMethodFlags &
983  		    IMA_TARGET_DISCOVERY_METHOD_ISNS) ^
984  		    IMA_TARGET_DISCOVERY_METHOD_ISNS)) {
985  			(void) fprintf(stdout, "%s ", gettext("iSNS"));
986  		}
987  		(void) fprintf(stdout, "\n");
988  	}
989  }
990  
991  /*
992   * printConnectionList - Prints the conection list provided
993   */
994  static void
printConnectionList(char * prefix,IMA_OID_LIST * pConnList)995  printConnectionList(char *prefix, IMA_OID_LIST *pConnList)
996  {
997  	IMA_STATUS		imaStatus;
998  	int			i;
999  	SUN_IMA_CONN_PROPERTIES	*connProps;
1000  	union {
1001  		char	ipv4[INET_ADDRSTRLEN+1];
1002  		char	ipv6[INET6_ADDRSTRLEN+1];
1003  	} tmp;
1004  
1005  	for (i = 0; i < pConnList->oidCount; i++) {
1006  		imaStatus = SUN_IMA_GetConnProperties(&pConnList->oids[i],
1007  		    &connProps);
1008  
1009  		if (imaStatus != IMA_STATUS_SUCCESS) {
1010  			continue;
1011  		}
1012  
1013  		(void) fprintf(stdout, "%sCID: %d\n", prefix,
1014  		    connProps->connectionID);
1015  
1016  		(void) memset(&tmp, 0, sizeof (tmp));
1017  		if (connProps->local.ipAddress.ipv4Address == IMA_TRUE) {
1018  			if (inet_ntop(AF_INET,
1019  			    &connProps->local.ipAddress.ipAddress[0],
1020  			    &tmp.ipv4[0],
1021  			    INET_ADDRSTRLEN)) {
1022  				(void) fprintf(stdout,
1023  				    "%s  %s: %s:%u\n",
1024  				    prefix,
1025  				    gettext("IP address (Local)"),
1026  				    &tmp.ipv4[0],
1027  				    ntohs(connProps->local.portNumber));
1028  			}
1029  		} else {
1030  			if (inet_ntop(AF_INET6,
1031  			    &connProps->local.ipAddress.ipAddress[0],
1032  			    &tmp.ipv6[0],
1033  			    INET6_ADDRSTRLEN)) {
1034  				(void) fprintf(stdout,
1035  				    "%s  %s: [%s]:%u\n",
1036  				    prefix,
1037  				    gettext("IP address (Local)"),
1038  				    &tmp.ipv6[0],
1039  				    ntohs(connProps->local.portNumber));
1040  			}
1041  		}
1042  		if (connProps->peer.ipAddress.ipv4Address == IMA_TRUE) {
1043  			if (inet_ntop(AF_INET,
1044  			    &connProps->peer.ipAddress.ipAddress[0],
1045  			    &tmp.ipv4[0],
1046  			    INET_ADDRSTRLEN)) {
1047  				(void) fprintf(stdout,
1048  				    "%s  %s: %s:%u\n",
1049  				    prefix,
1050  				    gettext("IP address (Peer)"),
1051  				    &tmp.ipv4[0],
1052  				    ntohs(connProps->peer.portNumber));
1053  			}
1054  		} else {
1055  			if (inet_ntop(AF_INET6,
1056  			    &connProps->peer.ipAddress.ipAddress[0],
1057  			    &tmp.ipv6[0],
1058  			    INET6_ADDRSTRLEN)) {
1059  				(void) fprintf(stdout,
1060  				    "%s  %s: [%s]:%u\n",
1061  				    prefix,
1062  				    gettext("IP address (Peer)"),
1063  				    &tmp.ipv6[0],
1064  				    ntohs(connProps->peer.portNumber));
1065  			}
1066  		}
1067  
1068  		(void) IMA_FreeMemory(connProps);
1069  	}
1070  }
1071  
1072  /*
1073   * Set login parameters on a target or initiator
1074   */
1075  static int
setLoginParameter(IMA_OID oid,int optval,char * optarg)1076  setLoginParameter(IMA_OID oid, int optval, char *optarg)
1077  {
1078  	IMA_STATUS status = IMA_STATUS_SUCCESS;
1079  	IMA_UINT uintValue;
1080  	IMA_BOOL boolValue;
1081  	SUN_IMA_DIGEST_ALGORITHM digestAlgList[1];
1082  	IMA_MIN_MAX_VALUE propMinMax;
1083  	char *endptr;
1084  
1085  	/*
1086  	 * for clarity, there are two switch statements
1087  	 * The first loads the variable and the second
1088  	 * calls the appropriate API
1089  	 */
1090  	switch (optval) {
1091  		case DATA_SEQ_IN_ORDER:
1092  		case IMMEDIATE_DATA:
1093  		case INITIAL_R2T:
1094  		case DATA_PDU_IN_ORDER:
1095  			/* implement 'default'? */
1096  			if (strcasecmp(optarg, "yes") == 0) {
1097  				boolValue = IMA_TRUE;
1098  			} else if (strcasecmp(optarg, "no") == 0) {
1099  				boolValue = IMA_FALSE;
1100  			} else {
1101  				(void) fprintf(stderr, "%s: %s - %s\n",
1102  				    cmdName,
1103  				    gettext("invalid option argument"),
1104  				    optarg);
1105  				return (1);
1106  			}
1107  			break;
1108  		case DEFAULT_TIME_2_RETAIN:
1109  		case DEFAULT_TIME_2_WAIT:
1110  			errno = 0;
1111  			uintValue = strtoul(optarg, &endptr, 0);
1112  			if (*endptr != '\0' || errno != 0) {
1113  				(void) fprintf(stderr, "%s: %s - %s\n",
1114  				    cmdName,
1115  				    gettext("invalid option argument"),
1116  				    optarg);
1117  				return (1);
1118  			}
1119  			if (uintValue > 3600) {
1120  				(void) fprintf(stderr, "%s: %s\n",
1121  				    cmdName,
1122  gettext("value must be between 0 and 3600"));
1123  				return (1);
1124  			}
1125  			break;
1126  		case FIRST_BURST_LENGTH:
1127  		case MAX_BURST_LENGTH:
1128  		case MAX_RECV_DATA_SEG_LEN:
1129  			errno = 0;
1130  			/* implement 'default'? */
1131  			uintValue = strtoul(optarg, &endptr, 0);
1132  			if (*endptr != '\0' || errno != 0) {
1133  				(void) fprintf(stderr, "%s: %s - %s\n",
1134  				    cmdName,
1135  				    gettext("invalid option argument"),
1136  				    optarg);
1137  				return (1);
1138  			}
1139  			if (uintValue < 512 || uintValue > 16777215) {
1140  				(void) fprintf(stderr, "%s: %s\n",
1141  				    cmdName,
1142  gettext("value must be between 512 and 16777215"));
1143  				return (1);
1144  			}
1145  			break;
1146  		case MAX_OUTSTANDING_R2T:
1147  			errno = 0;
1148  			uintValue = strtoul(optarg, &endptr, 0);
1149  			if (*endptr != '\0' || errno != 0) {
1150  				(void) fprintf(stderr, "%s: %s - %s\n",
1151  				    cmdName,
1152  				    gettext("invalid option argument"),
1153  				    optarg);
1154  				return (1);
1155  			}
1156  			if (uintValue < 1 || uintValue > 65535) {
1157  				(void) fprintf(stderr, "%s: %s\n",
1158  				    cmdName,
1159  gettext("value must be between 1 and 65535"));
1160  				return (1);
1161  			}
1162  			break;
1163  		case HEADER_DIGEST:
1164  		case DATA_DIGEST:
1165  			if (strcasecmp(optarg, "none") == 0) {
1166  				digestAlgList[0] = SUN_IMA_DIGEST_NONE;
1167  			} else if (strcasecmp(optarg, "CRC32") == 0) {
1168  				digestAlgList[0] = SUN_IMA_DIGEST_CRC32;
1169  			} else {
1170  				(void) fprintf(stderr, "%s: %s - %s\n",
1171  				    cmdName,
1172  				    gettext("invalid option argument"),
1173  				    optarg);
1174  				return (1);
1175  			}
1176  			break;
1177  		case MAX_CONNECTIONS:
1178  			errno = 0;
1179  			uintValue = strtoul(optarg, &endptr, 0);
1180  			if (*endptr != '\0' || errno != 0) {
1181  				(void) fprintf(stderr, "%s: %s - %s\n",
1182  				    cmdName,
1183  				    gettext("invalid option argument"),
1184  				    optarg);
1185  				return (1);
1186  			}
1187  			if (uintValue < 1 || uintValue > 256) {
1188  				(void) fprintf(stderr, "%s: %s\n",
1189  				    cmdName,
1190  gettext("value must be between 1 and 256"));
1191  				return (1);
1192  			}
1193  			break;
1194  		case ERROR_RECOVERY_LEVEL:
1195  			errno = 0;
1196  			uintValue = strtoul(optarg, &endptr, 0);
1197  			if (*endptr != '\0' || errno != 0) {
1198  				(void) fprintf(stderr, "%s: %s - %s\n",
1199  				    cmdName,
1200  				    gettext("invalid option argument"),
1201  				    optarg);
1202  				return (1);
1203  			}
1204  			if (uintValue > 2) {
1205  				(void) fprintf(stderr, "%s: %s\n",
1206  				    cmdName,
1207  gettext("value must be between 0 and 2"));
1208  				return (1);
1209  			}
1210  			break;
1211  		default:
1212  			(void) fprintf(stderr, "%s: %c: %s\n",
1213  			    cmdName, optval, gettext("unknown option"));
1214  			return (1);
1215  	}
1216  
1217  	switch (optval) {
1218  		case DATA_PDU_IN_ORDER:
1219  			status = IMA_SetDataPduInOrder(oid, boolValue);
1220  			break;
1221  		case DATA_SEQ_IN_ORDER:
1222  			status = IMA_SetDataSequenceInOrder(oid, boolValue);
1223  			break;
1224  		case DEFAULT_TIME_2_RETAIN:
1225  			status = IMA_SetDefaultTime2Retain(oid, uintValue);
1226  			break;
1227  		case DEFAULT_TIME_2_WAIT:
1228  			status = IMA_SetDefaultTime2Wait(oid, uintValue);
1229  			break;
1230  		case FIRST_BURST_LENGTH:
1231  			status = IMA_SetFirstBurstLength(oid, uintValue);
1232  
1233  			/*
1234  			 * If this call fails check to see if it's because
1235  			 * the requested value is > than maxBurstLength
1236  			 */
1237  			if (!IMA_SUCCESS(status)) {
1238  				status = IMA_GetMaxBurstLengthProperties(oid,
1239  				    &propMinMax);
1240  				if (!IMA_SUCCESS(status)) {
1241  					printLibError(status);
1242  					return (1);
1243  				}
1244  				if (uintValue > propMinMax.currentValue) {
1245  					(void) fprintf(stderr,
1246  					    "%s: %s\n", cmdName,
1247  					    gettext("firstBurstLength must " \
1248  					    "be less than or equal to than " \
1249  					    "maxBurstLength"));
1250  				}
1251  				return (1);
1252  			}
1253  
1254  			break;
1255  		case IMMEDIATE_DATA:
1256  			status = IMA_SetImmediateData(oid, boolValue);
1257  			break;
1258  		case INITIAL_R2T:
1259  			status = IMA_SetInitialR2T(oid, boolValue);
1260  			break;
1261  		case MAX_BURST_LENGTH:
1262  			status = IMA_SetMaxBurstLength(oid, uintValue);
1263  			/*
1264  			 * If this call fails check to see if it's because
1265  			 * the requested value is < than firstBurstLength
1266  			 */
1267  			if (!IMA_SUCCESS(status)) {
1268  				status = IMA_GetFirstBurstLengthProperties(oid,
1269  				    &propMinMax);
1270  				if (!IMA_SUCCESS(status)) {
1271  					printLibError(status);
1272  					return (1);
1273  				}
1274  				if (uintValue < propMinMax.currentValue) {
1275  					(void) fprintf(stderr, "%s: %s\n",
1276  					    cmdName,
1277  					    gettext("maxBurstLength must be " \
1278  					    "greater than or equal to " \
1279  					    "firstBurstLength"));
1280  				}
1281  				return (1);
1282  			}
1283  			break;
1284  
1285  		case MAX_OUTSTANDING_R2T:
1286  			status = IMA_SetMaxOutstandingR2T(oid, uintValue);
1287  			break;
1288  		case MAX_RECV_DATA_SEG_LEN:
1289  			status = IMA_SetMaxRecvDataSegmentLength(oid,
1290  			    uintValue);
1291  			break;
1292  		case HEADER_DIGEST:
1293  			status = SUN_IMA_SetHeaderDigest(oid, 1,
1294  			    &digestAlgList[0]);
1295  			break;
1296  		case DATA_DIGEST:
1297  			status = SUN_IMA_SetDataDigest(oid, 1,
1298  			    &digestAlgList[0]);
1299  			break;
1300  		case MAX_CONNECTIONS:
1301  			status = IMA_SetMaxConnections(oid, uintValue);
1302  			break;
1303  		case ERROR_RECOVERY_LEVEL:
1304  			status = IMA_SetErrorRecoveryLevel(oid, uintValue);
1305  			break;
1306  	}
1307  	if (!IMA_SUCCESS(status)) {
1308  		printLibError(status);
1309  		return (1);
1310  	}
1311  	return (0);
1312  }
1313  
1314  static void
printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE * digestAlgorithms,int printOption)1315  printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE *digestAlgorithms,
1316      int printOption)
1317  {
1318  	int i;
1319  
1320  	if (printOption == PRINT_CONFIGURED_PARAMS) {
1321  		for (i = 0; i < digestAlgorithms->defaultAlgorithmCount; i++) {
1322  			if (i > 0) {
1323  				(void) fprintf(stdout, "|");
1324  			}
1325  			switch (digestAlgorithms->defaultAlgorithms[i]) {
1326  				case SUN_IMA_DIGEST_NONE:
1327  					(void) fprintf(stdout,
1328  					    gettext("NONE"));
1329  					break;
1330  				case SUN_IMA_DIGEST_CRC32:
1331  					(void) fprintf(stdout,
1332  					    gettext("CRC32"));
1333  					break;
1334  				default:
1335  					(void) fprintf(stdout,
1336  					    gettext("Unknown"));
1337  					break;
1338  			}
1339  		}
1340  		(void) fprintf(stdout, "/");
1341  		if (digestAlgorithms->currentValid == IMA_TRUE) {
1342  			for (i = 0;
1343  			    i < digestAlgorithms->currentAlgorithmCount; i++) {
1344  				if (i > 0) {
1345  					(void) fprintf(stdout, "|");
1346  				}
1347  				switch (digestAlgorithms->
1348  				    currentAlgorithms[i]) {
1349  					case SUN_IMA_DIGEST_NONE:
1350  						(void) fprintf(stdout,
1351  						    gettext("NONE"));
1352  						break;
1353  					case SUN_IMA_DIGEST_CRC32:
1354  						(void) fprintf(stdout,
1355  						    gettext("CRC32"));
1356  						break;
1357  					default:
1358  						(void) fprintf(stdout,
1359  						    gettext("Unknown"));
1360  						break;
1361  				}
1362  			}
1363  		} else {
1364  			(void) fprintf(stdout, "-");
1365  		}
1366  		(void) fprintf(stdout, "\n");
1367  	} else if (printOption == PRINT_NEGOTIATED_PARAMS) {
1368  
1369  		if (digestAlgorithms->negotiatedValid == IMA_TRUE) {
1370  			for (i = 0;
1371  			    i < digestAlgorithms->negotiatedAlgorithmCount;
1372  			    i++) {
1373  				if (i > 0) {
1374  					(void) fprintf(stdout, "|");
1375  				}
1376  				switch (digestAlgorithms->
1377  				    negotiatedAlgorithms[i]) {
1378  					case SUN_IMA_DIGEST_NONE:
1379  						(void) fprintf(stdout,
1380  						    gettext("NONE"));
1381  						break;
1382  					case SUN_IMA_DIGEST_CRC32:
1383  						(void) fprintf(stdout,
1384  						    gettext("CRC32"));
1385  						break;
1386  					default:
1387  						(void) fprintf(stdout,
1388  						    gettext("Unknown"));
1389  						break;
1390  				}
1391  			}
1392  		} else {
1393  			(void) fprintf(stdout, "-");
1394  		}
1395  		(void) fprintf(stdout, "\n");
1396  	}
1397  }
1398  
1399  static int
setLoginParameters(IMA_OID oid,char * optarg)1400  setLoginParameters(IMA_OID oid, char *optarg)
1401  {
1402  	char keyp[MAXOPTARGLEN];
1403  	char valp[MAXOPTARGLEN];
1404  	int key;
1405  	char *nameValueString, *indexp, *delim = NULL;
1406  
1407  	if ((nameValueString = strdup(optarg)) == NULL) {
1408  		if (errno == ENOMEM) {
1409  			(void) fprintf(stderr, "%s: %s\n",
1410  			    cmdName, strerror(errno));
1411  		} else {
1412  			(void) fprintf(stderr, "%s: %s\n", cmdName,
1413  			    gettext("unknown error"));
1414  		}
1415  		return (1);
1416  	}
1417  
1418  	indexp = nameValueString;
1419  
1420  	/*
1421  	 * Retrieve all login params from option argument
1422  	 * Syntax <key=value,...>
1423  	 */
1424  	while (indexp) {
1425  		if (delim = strchr(indexp, ',')) {
1426  			delim[0] = '\0';
1427  		}
1428  		(void) memset(keyp, 0, sizeof (keyp));
1429  		(void) memset(valp, 0, sizeof (valp));
1430  		if (sscanf(indexp, gettext("%[^=]=%s"), keyp, valp) != 2) {
1431  			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1432  			    gettext("Unknown param"), indexp);
1433  			if (nameValueString) {
1434  				free(nameValueString);
1435  				nameValueString = NULL;
1436  			}
1437  			return (1);
1438  		}
1439  		if ((key = getLoginParam(keyp)) == -1) {
1440  			(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
1441  			    gettext("Unknown key"), keyp);
1442  			if (nameValueString) {
1443  				free(nameValueString);
1444  				nameValueString = NULL;
1445  			}
1446  			return (1);
1447  		}
1448  		if (setLoginParameter(oid, key, valp) != 0) {
1449  			if (nameValueString) {
1450  				free(nameValueString);
1451  				nameValueString = NULL;
1452  			}
1453  			return (1);
1454  		}
1455  		if (delim) {
1456  			indexp = delim + 1;
1457  		} else {
1458  			indexp = NULL;
1459  		}
1460  	}
1461  
1462  	if (nameValueString) {
1463  		free(nameValueString);
1464  		nameValueString = NULL;
1465  	}
1466  	return (0);
1467  }
1468  
1469  /*
1470   * Print logical unit information for a specific target
1471   */
1472  static void
printTargetLuns(IMA_OID_LIST * lunList)1473  printTargetLuns(IMA_OID_LIST * lunList)
1474  {
1475  	int	j;
1476  	IMA_STATUS status;
1477  	SUN_IMA_LU_PROPERTIES	lunProps;
1478  
1479  	for (j = 0; j < lunList->oidCount; j++) {
1480  		status = SUN_IMA_GetLuProperties(lunList->oids[j],
1481  		    &lunProps);
1482  		if (!IMA_SUCCESS(status)) {
1483  			printLibError(status);
1484  			return;
1485  		}
1486  
1487  		(void) fprintf(stdout, "\tLUN: %lld\n",
1488  		    lunProps.imaProps.targetLun);
1489  		(void) fprintf(stdout, "\t     Vendor:  %s\n",
1490  		    lunProps.vendorId);
1491  		(void) fprintf(stdout, "\t     Product: %s\n",
1492  		    lunProps.productId);
1493  		/*
1494  		 * The lun is valid though the os Device Name is not.
1495  		 * Give this information to users for judgement.
1496  		 */
1497  		if (lunProps.imaProps.osDeviceNameValid == IMA_TRUE) {
1498  			(void) fprintf(stdout,
1499  			    gettext("\t     OS Device Name: %ws\n"),
1500  			    lunProps.imaProps.osDeviceName);
1501  		} else {
1502  			(void) fprintf(stdout,
1503  			    gettext("\t     OS Device Name: Not"
1504  			    " Available\n"));
1505  		}
1506  	}
1507  }
1508  
1509  /*
1510   * Retrieve CHAP secret from input
1511   */
1512  static int
getSecret(char * secret,int * secretLen,int minSecretLen,int maxSecretLen)1513  getSecret(char *secret, int *secretLen, int minSecretLen, int maxSecretLen)
1514  {
1515  	char *chapSecret;
1516  
1517  	/* get password */
1518  	chapSecret = getpassphrase(gettext("Enter secret:"));
1519  
1520  	if (chapSecret == NULL) {
1521  		(void) fprintf(stderr, "%s: %s\n", cmdName,
1522  		    gettext("Unable to get secret"));
1523  		*secret = '\0';
1524  		return (1);
1525  	}
1526  
1527  	if (strlen(chapSecret) > maxSecretLen) {
1528  		(void) fprintf(stderr, "%s: %s %d\n", cmdName,
1529  		    gettext("secret too long, maximum length is"),
1530  		    maxSecretLen);
1531  		*secret = '\0';
1532  		return (1);
1533  	}
1534  
1535  	if (strlen(chapSecret) < minSecretLen) {
1536  		(void) fprintf(stderr, "%s: %s %d\n", cmdName,
1537  		    gettext("secret too short, minimum length is"),
1538  		    minSecretLen);
1539  		*secret = '\0';
1540  		return (1);
1541  	}
1542  
1543  	(void) strcpy(secret, chapSecret);
1544  
1545  	chapSecret = getpassphrase(gettext("Re-enter secret:"));
1546  
1547  	if (chapSecret == NULL) {
1548  		(void) fprintf(stderr, "%s: %s\n", cmdName,
1549  		    gettext("Unable to get secret"));
1550  		*secret = '\0';
1551  		return (1);
1552  	}
1553  
1554  	if (strcmp(secret, chapSecret) != 0) {
1555  		(void) fprintf(stderr, "%s: %s\n", cmdName,
1556  		    gettext("secrets do not match, secret not changed"));
1557  		*secret = '\0';
1558  		return (1);
1559  	}
1560  	*secretLen = strlen(chapSecret);
1561  	return (0);
1562  }
1563  
1564  /*
1565   * Lists the discovery attributes
1566   */
1567  static int
listDiscovery(int * funcRet)1568  listDiscovery(int *funcRet)
1569  {
1570  	IMA_OID	initiatorOid;
1571  	IMA_DISCOVERY_PROPERTIES discProps;
1572  	int ret;
1573  	IMA_STATUS status;
1574  
1575  	assert(funcRet != NULL);
1576  
1577  
1578  	/* Find Sun initiator */
1579  	ret = sunInitiatorFind(&initiatorOid);
1580  	if (ret > 0) {
1581  		(void) fprintf(stderr, "%s: %s\n",
1582  		    cmdName, gettext("no initiator found"));
1583  	}
1584  
1585  	if (ret != 0) {
1586  		return (ret);
1587  	}
1588  
1589  	/* Get discovery attributes from IMA */
1590  	status = IMA_GetDiscoveryProperties(initiatorOid, &discProps);
1591  	if (!IMA_SUCCESS(status)) {
1592  		printLibError(status);
1593  		*funcRet = 1;
1594  		return (ret);
1595  	}
1596  
1597  
1598  	(void) fprintf(stdout, "%s:\n", "Discovery");
1599  	(void) fprintf(stdout, "\tStatic: %s\n",
1600  	    discProps.staticDiscoveryEnabled == IMA_TRUE ? \
1601  	    gettext("enabled") : gettext("disabled"));
1602  	(void) fprintf(stdout, "\tSend Targets: %s\n",
1603  	    discProps.sendTargetsDiscoveryEnabled == IMA_TRUE ? \
1604  	    gettext("enabled") : gettext("disabled"));
1605  	(void) fprintf(stdout, "\tiSNS: %s\n",
1606  	    discProps.iSnsDiscoveryEnabled == IMA_TRUE ? \
1607  	    gettext("enabled") : gettext("disabled"));
1608  
1609  	return (0);
1610  }
1611  
1612  /*
1613   * Print all initiator node attributes
1614   */
1615  static int
listNode(int * funcRet)1616  listNode(int *funcRet)
1617  {
1618  	IMA_OID	initiatorOid;
1619  	IMA_NODE_PROPERTIES nodeProps;
1620  	IMA_STATUS status;
1621  	int ret;
1622  	IMA_UINT maxEntries = MAX_AUTH_METHODS;
1623  	IMA_AUTHMETHOD	methodList[MAX_AUTH_METHODS];
1624  	SUN_IMA_RADIUS_CONFIG radiusConfig;
1625  	SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms;
1626  	IMA_BOOL radiusAccess;
1627  
1628  	int i;
1629  
1630  	assert(funcRet != NULL);
1631  
1632  	ret = getNodeProps(&nodeProps);
1633  	if (ret != 0) {
1634  		return (ret);
1635  	}
1636  
1637  	if (nodeProps.nameValid == IMA_FALSE) {
1638  		return (INVALID_NODE_NAME);
1639  	}
1640  
1641  	/* Find Sun initiator */
1642  	ret = sunInitiatorFind(&initiatorOid);
1643  	if (ret > 0) {
1644  		(void) fprintf(stderr, "%s: %s\n",
1645  		    cmdName, gettext("no initiator found"));
1646  	}
1647  
1648  	if (ret != 0) {
1649  		return (ret);
1650  	}
1651  	/* Begin output */
1652  	(void) fprintf(stdout, gettext("%s: %ws\n"),
1653  	    gettext("Initiator node name"),
1654  	    nodeProps.name);
1655  	(void) fprintf(stdout, gettext("Initiator node alias: "));
1656  	if (nodeProps.aliasValid == IMA_TRUE) {
1657  		(void) fprintf(stdout, gettext("%ws\n"), nodeProps.alias);
1658  	} else {
1659  		(void) fprintf(stdout, "%s\n", "-");
1660  	}
1661  	(void) fprintf(stdout, "\t%s:\n",
1662  	    gettext("Login Parameters (Default/Configured)"));
1663  
1664  	/* Get Digest configuration */
1665  	status = SUN_IMA_GetHeaderDigest(initiatorOid, &digestAlgorithms);
1666  	if (IMA_SUCCESS(status)) {
1667  		(void) fprintf(stdout, "\t\t%s: ", gettext("Header Digest"));
1668  		printDigestAlgorithm(&digestAlgorithms,
1669  		    PRINT_CONFIGURED_PARAMS);
1670  	} else {
1671  		printLibError(status);
1672  		*funcRet = 1;
1673  		return (ret);
1674  	}
1675  
1676  	status = SUN_IMA_GetDataDigest(initiatorOid, &digestAlgorithms);
1677  	if (IMA_SUCCESS(status)) {
1678  		(void) fprintf(stdout, "\t\t%s: ", gettext("Data Digest"));
1679  		printDigestAlgorithm(&digestAlgorithms,
1680  		    PRINT_CONFIGURED_PARAMS);
1681  	} else {
1682  		printLibError(status);
1683  		*funcRet = 1;
1684  		return (ret);
1685  	}
1686  
1687  	/* Get authentication type for this lhba */
1688  	status = IMA_GetInUseInitiatorAuthMethods(initiatorOid, &maxEntries,
1689  	    &methodList[0]);
1690  	(void) fprintf(stdout, "\t%s: ", gettext("Authentication Type"));
1691  	if (!IMA_SUCCESS(status)) {
1692  		/* No authentication method set - default is NONE */
1693  		(void) fprintf(stdout, gettext("NONE"));
1694  	} else {
1695  		for (i = 0; i < maxEntries; i++) {
1696  			if (i > 0) {
1697  				(void) fprintf(stdout, "|");
1698  			}
1699  			switch (methodList[i]) {
1700  				case IMA_AUTHMETHOD_NONE:
1701  					(void) fprintf(stdout, gettext("NONE"));
1702  					break;
1703  				case IMA_AUTHMETHOD_CHAP:
1704  					(void) fprintf(stdout, gettext("CHAP"));
1705  					listCHAPName(initiatorOid);
1706  					break;
1707  				default:
1708  					(void) fprintf(stdout,
1709  					    gettext("unknown type"));
1710  					break;
1711  			}
1712  		}
1713  	}
1714  	(void) fprintf(stdout, "\n");
1715  
1716  
1717  	/* Get RADIUS configuration */
1718  	status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig);
1719  	(void) fprintf(stdout, "\t%s: ", gettext("RADIUS Server"));
1720  	if (IMA_SUCCESS(status)) {
1721  		if (strlen(radiusConfig.hostnameIpAddress) > 0) {
1722  			(void) fprintf(stdout, "%s:%d",
1723  			    radiusConfig.hostnameIpAddress,
1724  			    radiusConfig.port);
1725  		} else {
1726  			(void) fprintf(stdout, "%s", gettext("NONE"));
1727  		}
1728  	} else {
1729  		(void) fprintf(stdout, "%s", gettext("NONE"));
1730  	}
1731  	(void) fprintf(stdout, "\n");
1732  
1733  	status = SUN_IMA_GetInitiatorRadiusAccess(initiatorOid,
1734  	    &radiusAccess);
1735  	(void) fprintf(stdout, "\t%s: ", gettext("RADIUS Access"));
1736  	if (IMA_SUCCESS(status)) {
1737  		if (radiusAccess == IMA_TRUE) {
1738  			(void) fprintf(stdout, "%s", gettext("enabled"));
1739  		} else {
1740  			(void) fprintf(stdout, "%s", gettext("disabled"));
1741  		}
1742  	} else if (status == IMA_ERROR_OBJECT_NOT_FOUND) {
1743  		(void) fprintf(stdout, "%s", gettext("disabled"));
1744  	} else {
1745  		(void) fprintf(stdout, "%s", gettext("unknown"));
1746  	}
1747  	(void) fprintf(stdout, "\n");
1748  
1749  	/* print tunable parameters information. */
1750  	ret = printTunableParameters(initiatorOid);
1751  
1752  	/* print configured session information. */
1753  	ret = printConfiguredSessions(initiatorOid);
1754  
1755  	return (ret);
1756  }
1757  
1758  /*
1759   * Print discovery addresses
1760   */
1761  static int
listDiscoveryAddress(int objectLen,char * objects[],cmdOptions_t * options,int * funcRet)1762  listDiscoveryAddress(int objectLen, char *objects[], cmdOptions_t *options,
1763      int *funcRet)
1764  {
1765  	IMA_OID	initiatorOid;
1766  	SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList;
1767  	IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps;
1768  	IMA_TARGET_ADDRESS address;
1769  	SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList;
1770  	IMA_STATUS status;
1771  	wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
1772  	int ret;
1773  	boolean_t object = B_FALSE;
1774  	int outerLoop;
1775  	boolean_t found;
1776  	boolean_t verbose = B_FALSE;
1777  	int i, j;
1778  	cmdOptions_t *optionList = options;
1779  	char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
1780  
1781  	assert(funcRet != NULL);
1782  
1783  	/* Find Sun initiator */
1784  	ret = sunInitiatorFind(&initiatorOid);
1785  	if (ret > 0) {
1786  		(void) fprintf(stderr, "%s: %s\n",
1787  		    cmdName, gettext("no initiator found"));
1788  	}
1789  
1790  	if (ret != 0) {
1791  		return (ret);
1792  	}
1793  
1794  	for (; optionList->optval; optionList++) {
1795  		switch (optionList->optval) {
1796  			case 'v':
1797  				verbose = B_TRUE;
1798  				break;
1799  			default:
1800  				(void) fprintf(stderr, "%s: %c: %s\n",
1801  				    cmdName, optionList->optval,
1802  				    gettext("unknown option"));
1803  				return (1);
1804  		}
1805  	}
1806  
1807  	/*
1808  	 * If there are multiple objects, execute outer 'for' loop that
1809  	 * many times for each target detail, otherwise, execute it only
1810  	 * once with summaries only
1811  	 */
1812  	if (objectLen > 0) {
1813  		object = B_TRUE;
1814  		outerLoop = objectLen;
1815  	} else {
1816  		object = B_FALSE;
1817  		outerLoop = 1;
1818  	}
1819  
1820  	status = SUN_IMA_GetDiscoveryAddressPropertiesList(
1821  	    &discoveryAddressPropertiesList);
1822  	if (!IMA_SUCCESS(status)) {
1823  		printLibError(status);
1824  		*funcRet = 1;
1825  		return (ret);
1826  	}
1827  
1828  	for (i = 0; i < outerLoop; i++) {
1829  		if (object) {
1830  			/* initialize */
1831  			(void) memset(&wcInputObject[0], 0,
1832  			    sizeof (wcInputObject));
1833  			(void) memset(&address, 0, sizeof (address));
1834  			if (mbstowcs(wcInputObject, objects[i],
1835  			    (MAX_ADDRESS_LEN + 1)) == (size_t)-1) {
1836  				(void) fprintf(stderr, "%s: %s\n",
1837  				    cmdName,
1838  				    gettext("conversion error"));
1839  				ret = 1;
1840  				continue;
1841  			}
1842  
1843  			/*
1844  			 * if one or more objects were input,
1845  			 * get the values
1846  			 */
1847  			if (getTargetAddress(DISCOVERY_ADDRESS,
1848  			    objects[i], &address) != 0) {
1849  				ret = 1;
1850  				continue;
1851  			}
1852  		}
1853  		for (found = B_FALSE, j = 0;
1854  		    j < discoveryAddressPropertiesList->discAddrCount;
1855  		    j++) {
1856  			discAddrProps =
1857  			    discoveryAddressPropertiesList->props[j];
1858  
1859  			/*
1860  			 * Compare the discovery address with the input if
1861  			 * one was input
1862  			 */
1863  			if (object &&
1864  			    ipAddressesEqual(discAddrProps.discoveryAddress,
1865  			    address) && (discAddrProps.discoveryAddress.
1866  			    portNumber == address.portNumber)) {
1867  				found = B_TRUE;
1868  			}
1869  
1870  			if (!object || found) {
1871  				/* Print summary - always */
1872  				if (discAddrProps.discoveryAddress.
1873  				    hostnameIpAddress.id.ipAddress.
1874  				    ipv4Address) {
1875  					(void) inet_ntop(AF_INET, discAddrProps.
1876  					    discoveryAddress.hostnameIpAddress.
1877  					    id.ipAddress.ipAddress, sAddr,
1878  					    sizeof (sAddr));
1879  					(void) fprintf(stdout,
1880  					    "Discovery Address: %s:%u\n",
1881  					    sAddr, discAddrProps.
1882  					    discoveryAddress.portNumber);
1883  				} else {
1884  					(void) inet_ntop(AF_INET6,
1885  					    discAddrProps.
1886  					    discoveryAddress.hostnameIpAddress.
1887  					    id.ipAddress.ipAddress, sAddr,
1888  					    sizeof (sAddr));
1889  					(void) fprintf(stdout,
1890  					    "DiscoveryAddress: [%s]:%u\n",
1891  					    sAddr, discAddrProps.
1892  					    discoveryAddress.portNumber);
1893  				}
1894  			}
1895  
1896  			if ((!object || found) && verbose) {
1897  				IMA_NODE_PROPERTIES nodeProps;
1898  
1899  				if (getNodeProps(&nodeProps) != 0) {
1900  					break;
1901  				}
1902  
1903  				/*
1904  				 * Issue sendTargets only when an addr is
1905  				 * specified.
1906  				 */
1907  				status = SUN_IMA_SendTargets(nodeProps.name,
1908  				    discAddrProps.discoveryAddress, &pList);
1909  				if (!IMA_SUCCESS(status)) {
1910  					(void) fprintf(stderr, "%s\n",
1911  					    gettext("\tUnable to get "\
1912  					    "targets."));
1913  					*funcRet = 1;
1914  					continue;
1915  				}
1916  				printSendTargets(pList);
1917  			}
1918  
1919  			if (found) {
1920  				/* we found the discovery address - break */
1921  				break;
1922  			}
1923  		}
1924  		/*
1925  		 * There was an object entered but we didn't
1926  		 * find it.
1927  		 */
1928  		if (object && !found) {
1929  			(void) fprintf(stdout, "%s: %s\n",
1930  			    objects[i], gettext("not found"));
1931  		}
1932  	}
1933  	return (ret);
1934  }
1935  
1936  /*
1937   * Print ISNS Server addresses
1938   */
1939  static int
listISNSServerAddress(int objectLen,char * objects[],cmdOptions_t * options,int * funcRet)1940  listISNSServerAddress(int objectLen, char *objects[], cmdOptions_t *options,
1941      int *funcRet)
1942  {
1943  	IMA_OID	initiatorOid;
1944  	SUN_IMA_DISC_ADDR_PROP_LIST	    *discoveryAddressPropertiesList;
1945  	IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps;
1946  	IMA_TARGET_ADDRESS address;
1947  	SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList;
1948  	IMA_STATUS status;
1949  	wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
1950  	int ret;
1951  	boolean_t object = B_FALSE;
1952  	int outerLoop;
1953  	boolean_t found;
1954  	boolean_t showTarget = B_FALSE;
1955  	int i, j;
1956  	cmdOptions_t *optionList = options;
1957  	char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
1958  
1959  	assert(funcRet != NULL);
1960  
1961  	/* Find Sun initiator */
1962  	ret = sunInitiatorFind(&initiatorOid);
1963  	if (ret > 0) {
1964  		(void) fprintf(stderr, "%s: %s\n",
1965  		    cmdName, gettext("no initiator found"));
1966  	}
1967  
1968  	if (ret != 0) {
1969  		return (ret);
1970  	}
1971  
1972  	for (; optionList->optval; optionList++) {
1973  		switch (optionList->optval) {
1974  			case 'v':
1975  				showTarget = B_TRUE;
1976  				break;
1977  			default:
1978  				(void) fprintf(stderr, "%s: %c: %s\n",
1979  				    cmdName, optionList->optval,
1980  				    gettext("unknown option"));
1981  				return (1);
1982  		}
1983  	}
1984  
1985  	/*
1986  	 * If there are multiple objects, execute outer 'for' loop that
1987  	 * many times for each target detail, otherwise, execute it only
1988  	 * once with summaries only
1989  	 */
1990  	if (objectLen > 0) {
1991  		object = B_TRUE;
1992  		outerLoop = objectLen;
1993  	} else {
1994  		object = B_FALSE;
1995  		outerLoop = 1;
1996  	}
1997  
1998  	status = SUN_IMA_GetISNSServerAddressPropertiesList(
1999  	    &discoveryAddressPropertiesList);
2000  	if (!IMA_SUCCESS(status)) {
2001  		printLibError(status);
2002  		*funcRet = 1;
2003  		return (ret);
2004  	}
2005  
2006  	for (i = 0; i < outerLoop; i++) {
2007  		if (object) {
2008  			/* initialize */
2009  			(void) memset(&wcInputObject[0], 0,
2010  			    sizeof (wcInputObject));
2011  			(void) memset(&address, 0, sizeof (address));
2012  			if (mbstowcs(wcInputObject, objects[i],
2013  			    (MAX_ADDRESS_LEN + 1)) == (size_t)-1) {
2014  				(void) fprintf(stderr, "%s: %s\n",
2015  				    cmdName,
2016  				    gettext("conversion error"));
2017  				ret = 1;
2018  				continue;
2019  			}
2020  
2021  			/*
2022  			 * if one or more objects were input,
2023  			 * get the values
2024  			 */
2025  			if (getTargetAddress(ISNS_SERVER_ADDRESS,
2026  			    objects[i], &address) != 0) {
2027  				ret = 1;
2028  				continue;
2029  			}
2030  		}
2031  		for (found = B_FALSE, j = 0;
2032  		    j < discoveryAddressPropertiesList->discAddrCount;
2033  		    j++) {
2034  			discAddrProps =
2035  			    discoveryAddressPropertiesList->props[j];
2036  
2037  			/*
2038  			 * Compare the discovery address with the input if
2039  			 * one was input
2040  			 */
2041  			if (object &&
2042  			    ipAddressesEqual(discAddrProps.discoveryAddress,
2043  			    address) &&
2044  			    (discAddrProps.discoveryAddress.portNumber ==
2045  			    address.portNumber)) {
2046  				found = B_TRUE;
2047  			}
2048  
2049  			if (!object || found) {
2050  				/* Print summary - always */
2051  				if (discAddrProps.discoveryAddress.
2052  				    hostnameIpAddress.id.ipAddress.
2053  				    ipv4Address) {
2054  					(void) inet_ntop(AF_INET, discAddrProps.
2055  					    discoveryAddress.hostnameIpAddress.
2056  					    id.ipAddress.ipAddress, sAddr,
2057  					    sizeof (sAddr));
2058  				} else {
2059  					(void) inet_ntop(AF_INET6,
2060  					    discAddrProps.
2061  					    discoveryAddress.hostnameIpAddress.
2062  					    id.ipAddress.ipAddress, sAddr,
2063  					    sizeof (sAddr));
2064  				}
2065  				(void) fprintf(stdout,
2066  				    "iSNS Server IP Address: %s:%u\n",
2067  				    sAddr,
2068  				    discAddrProps.discoveryAddress.portNumber);
2069  			}
2070  
2071  			if ((!object || found) && showTarget) {
2072  				IMA_NODE_PROPERTIES nodeProps;
2073  
2074  				if (getNodeProps(&nodeProps) != 0) {
2075  					break;
2076  				}
2077  
2078  				/*
2079  				 * Issue sendTargets only when an addr is
2080  				 * specified.
2081  				 */
2082  				status = SUN_IMA_RetrieveISNSServerTargets(
2083  				    discAddrProps.discoveryAddress,
2084  				    &pList);
2085  				if (!IMA_SUCCESS(status)) {
2086  					/*
2087  					 * Check if the discovery mode is
2088  					 * disabled.
2089  					 */
2090  					if (status ==
2091  					    IMA_ERROR_OBJECT_NOT_FOUND) {
2092  						(void) fprintf(stderr, "%s\n",
2093  						    gettext("\tiSNS "\
2094  						    "discovery "\
2095  						    "mode "\
2096  						    "disabled. "\
2097  						    "No targets "\
2098  						    "to report."));
2099  
2100  					} else {
2101  						(void) fprintf(stderr, "%s\n",
2102  						    gettext("\tUnable "\
2103  						    "to get "\
2104  						    "targets."));
2105  					}
2106  					continue;
2107  				}
2108  				printSendTargets(pList);
2109  			}
2110  
2111  			if (found) {
2112  				/* we found the discovery address - break */
2113  				break;
2114  			}
2115  		}
2116  		/*
2117  		 * There was an object entered but we didn't
2118  		 * find it.
2119  		 */
2120  		if (object && !found) {
2121  			(void) fprintf(stdout, "%s: %s\n",
2122  			    objects[i], gettext("not found"));
2123  		}
2124  	}
2125  	return (ret);
2126  }
2127  
2128  /*
2129   * Print static configuration targets
2130   */
2131  static int
listStaticConfig(int operandLen,char * operand[],int * funcRet)2132  listStaticConfig(int operandLen, char *operand[], int *funcRet)
2133  {
2134  	IMA_STATUS status;
2135  	IMA_OID	initiatorOid;
2136  	IMA_OID_LIST *staticTargetList;
2137  	SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps;
2138  	wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1];
2139  	wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
2140  	wchar_t wcCol;
2141  	char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
2142  	int ret;
2143  	boolean_t object = B_FALSE;
2144  	int outerLoop;
2145  	boolean_t found; /* B_TRUE if a target name is found */
2146  	boolean_t matched; /* B_TRUE if a specific target is found */
2147  	boolean_t targetAddressSpecified = B_FALSE;
2148  	boolean_t tpgtSpecified = B_FALSE;
2149  	boolean_t isIpv6;
2150  	int i, j;
2151  	IMA_UINT16 port = 0;
2152  	IMA_UINT16 tpgt = 0;
2153  	char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN];
2154  	wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
2155  
2156  	assert(funcRet != NULL);
2157  
2158  	/* Find Sun initiator */
2159  	ret = sunInitiatorFind(&initiatorOid);
2160  	if (ret > 0) {
2161  		(void) fprintf(stderr, "%s: %s\n",
2162  		    cmdName, gettext("no initiator found"));
2163  	}
2164  
2165  	if (ret != 0) {
2166  		return (ret);
2167  	}
2168  
2169  	/*
2170  	 * If there are multiple objects, execute outer 'for' loop that
2171  	 * many times for each static config detail, otherwise, execute it only
2172  	 * once with summaries only
2173  	 */
2174  	if (operandLen > 0) {
2175  		object = B_TRUE;
2176  		outerLoop = operandLen;
2177  	} else {
2178  		object = B_FALSE;
2179  		outerLoop = 1;
2180  	}
2181  
2182  	/* convert ':' to wide char for wchar string search */
2183  	if (mbtowc(&wcCol, ":", sizeof (wcCol)) == -1) {
2184  		(void) fprintf(stderr, "%s: %s\n",
2185  		    cmdName, gettext("conversion error"));
2186  		return (1);
2187  	}
2188  
2189  	status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid,
2190  	    &staticTargetList);
2191  	if (!IMA_SUCCESS(status)) {
2192  		printLibError(status);
2193  		*funcRet = 1;
2194  		return (ret);
2195  	}
2196  
2197  	for (i = 0; i < outerLoop; i++) {
2198  		if (object) {
2199  			if (parseTarget(operand[i],
2200  			    &staticTargetName[0],
2201  			    MAX_ISCSI_NAME_LEN + 1,
2202  			    &targetAddressSpecified,
2203  			    &staticTargetAddress[0],
2204  			    SUN_IMA_IP_ADDRESS_PORT_LEN,
2205  			    &port,
2206  			    &tpgtSpecified,
2207  			    &tpgt,
2208  			    &isIpv6) != PARSE_TARGET_OK) {
2209  				ret = 1;
2210  				continue;
2211  			}
2212  		}
2213  
2214  		for (found = B_FALSE, j = 0; j < staticTargetList->oidCount;
2215  		    j++) {
2216  			boolean_t isIpv6 = B_FALSE;
2217  			IMA_UINT16 stpgt;
2218  			IMA_BOOL defaultTpgt;
2219  
2220  			matched = B_FALSE;
2221  			(void) memset(&staticTargetProps, 0,
2222  			    sizeof (staticTargetProps));
2223  
2224  			status = SUN_IMA_GetStaticTargetProperties(
2225  			    staticTargetList->oids[j], &staticTargetProps);
2226  			if (!IMA_SUCCESS(status)) {
2227  				printLibError(status);
2228  				(void) IMA_FreeMemory(staticTargetList);
2229  				*funcRet = 1;
2230  				return (ret);
2231  			}
2232  
2233  			stpgt = staticTargetProps.staticTarget.targetAddress.
2234  			    tpgt;
2235  
2236  			defaultTpgt = staticTargetProps.staticTarget.
2237  			    targetAddress.defaultTpgt;
2238  
2239  			isIpv6 = !staticTargetProps.staticTarget.targetAddress.
2240  			    imaStruct.hostnameIpAddress.id.ipAddress.
2241  			    ipv4Address;
2242  
2243  			/*
2244  			 * Compare the static target name with the input if
2245  			 * one was input
2246  			 */
2247  
2248  			if (object &&
2249  			    (targetNamesEqual(
2250  			    staticTargetProps.staticTarget.targetName,
2251  			    staticTargetName) == B_TRUE)) {
2252  				/* targetName found - found = B_TRUE */
2253  				found = B_TRUE;
2254  				if (targetAddressSpecified == B_FALSE) {
2255  					matched = B_TRUE;
2256  				} else {
2257  
2258  				if (staticTargetProps.staticTarget.
2259  				    targetAddress.imaStruct.
2260  				    hostnameIpAddress.id.ipAddress.
2261  				    ipv4Address == IMA_TRUE) {
2262  					(void) inet_ntop(AF_INET,
2263  					    staticTargetProps.
2264  					    staticTarget.targetAddress.
2265  					    imaStruct.hostnameIpAddress.id.
2266  					    ipAddress.ipAddress, tmpStr,
2267  					    sizeof (tmpStr));
2268  				} else {
2269  					(void) inet_ntop(AF_INET6,
2270  					    staticTargetProps.
2271  					    staticTarget.targetAddress.
2272  					    imaStruct.hostnameIpAddress.id.
2273  					    ipAddress.ipAddress, tmpStr,
2274  					    sizeof (tmpStr));
2275  				}
2276  
2277  				if (mbstowcs(tmpTargetAddress, tmpStr,
2278  				    SUN_IMA_IP_ADDRESS_PORT_LEN) ==
2279  				    (size_t)-1) {
2280  					(void) fprintf(stderr, "%s: %s\n",
2281  					    cmdName,
2282  					gettext("conversion error"));
2283  					ret = 1;
2284  					continue;
2285  				}
2286  
2287  				if (wcsncmp(tmpTargetAddress,
2288  				    staticTargetAddress,
2289  				    SUN_IMA_IP_ADDRESS_PORT_LEN)
2290  				    == 0 &&
2291  				    staticTargetProps.
2292  				    staticTarget.targetAddress.
2293  				    imaStruct.portNumber == port) {
2294  					/*
2295  					 * Since an object is
2296  					 * specified, it should also
2297  					 * have a tpgt specified. If
2298  					 * not, that means the object
2299  					 * specified is associated with
2300  					 * the default tpgt. In
2301  					 * either case, a tpgt
2302  					 * comparison should be done
2303  					 * before claiming that a
2304  					 * match is found.
2305  					 */
2306  					if ((tpgt == stpgt &&
2307  					    tpgtSpecified == B_TRUE &&
2308  					    defaultTpgt == IMA_FALSE) ||
2309  					    (tpgt == stpgt &&
2310  					    tpgtSpecified == B_FALSE &&
2311  					    defaultTpgt == IMA_TRUE)) {
2312  						matched = B_TRUE;
2313  					}
2314  				}
2315  
2316  				}
2317  			}
2318  
2319  			if (!object || matched) {
2320  				/* print summary - always */
2321  				(void) fprintf(stdout, gettext("%s: %ws,"),
2322  				    "Static Configuration Target",
2323  				    staticTargetProps.staticTarget.targetName);
2324  
2325  				if (isIpv6 == B_FALSE) {
2326  					(void) inet_ntop(AF_INET,
2327  					    staticTargetProps.
2328  					    staticTarget.targetAddress.
2329  					    imaStruct.hostnameIpAddress.id.
2330  					    ipAddress.ipAddress, sAddr,
2331  					    sizeof (sAddr));
2332  					(void) fprintf(stdout, "%s:%d",
2333  					    sAddr,
2334  					    staticTargetProps.staticTarget.
2335  					    targetAddress.imaStruct.portNumber);
2336  				} else {
2337  					(void) inet_ntop(AF_INET6,
2338  					    staticTargetProps.
2339  					    staticTarget.targetAddress.
2340  					    imaStruct.hostnameIpAddress.id.
2341  					    ipAddress.ipAddress, sAddr,
2342  					    sizeof (sAddr));
2343  					(void) fprintf(stdout, "[%s]:%d",
2344  					    sAddr,
2345  					    staticTargetProps.staticTarget.
2346  					    targetAddress.imaStruct.portNumber);
2347  				}
2348  
2349  				if (staticTargetProps.staticTarget.
2350  				    targetAddress.
2351  				    defaultTpgt == IMA_FALSE) {
2352  					(void) fprintf(stdout, ",%d\n",
2353  					    staticTargetProps.
2354  					    staticTarget.targetAddress.tpgt);
2355  				} else {
2356  					(void) fprintf(stdout, "\n");
2357  				}
2358  			}
2359  
2360  		}
2361  		/*
2362  		 * No details to display, but if there were:
2363  		 *  if (object && found)...
2364  		 *
2365  		 */
2366  
2367  		/*
2368  		 * There was an object entered but we didn't
2369  		 * find it.
2370  		 */
2371  		if (object && !found) {
2372  			(void) fprintf(stdout, "%s: %s\n",
2373  			    operand[i], gettext("not found"));
2374  			ret = 1; /* DIY test fix */
2375  		}
2376  	}
2377  	return (ret);
2378  }
2379  
2380  /*
2381   * Print targets
2382   */
2383  /*ARGSUSED*/
2384  static int
listTarget(int objectLen,char * objects[],cmdOptions_t * options,int * funcRet)2385  listTarget(int objectLen, char *objects[], cmdOptions_t *options, int *funcRet)
2386  {
2387  	IMA_OID	initiatorOid;
2388  	IMA_OID_LIST *targetList;
2389  	IMA_OID_LIST *lunList;
2390  	SUN_IMA_TARGET_PROPERTIES targetProps;
2391  	IMA_STATUS status;
2392  	IMA_OID_LIST *pConnList;
2393  	SUN_IMA_CONN_PROPERTIES *connProps;
2394  
2395  	int ret;
2396  	wchar_t targetName[MAX_ISCSI_NAME_LEN + 1];
2397  	wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
2398  	int outerLoop;
2399  	boolean_t found;
2400  	boolean_t operandEntered = B_FALSE;
2401  	boolean_t verbose = B_FALSE;
2402  	boolean_t scsi_target = B_FALSE;
2403  	boolean_t targetAddressSpecified = B_FALSE;
2404  	boolean_t isIpv6 = B_FALSE;
2405  	int i, j;
2406  	cmdOptions_t *optionList = options;
2407  	boolean_t tpgtSpecified = B_FALSE;
2408  	IMA_UINT16 port = 0;
2409  	uint16_t tpgt;
2410  
2411  	assert(funcRet != NULL);
2412  
2413  	/* Find Sun initiator */
2414  	ret = sunInitiatorFind(&initiatorOid);
2415  	if (ret > 0) {
2416  		(void) fprintf(stderr, "%s: %s\n",
2417  		    cmdName, gettext("no initiator found"));
2418  	}
2419  
2420  	if (ret != 0) {
2421  		return (ret);
2422  	}
2423  
2424  	for (; optionList->optval; optionList++) {
2425  		switch (optionList->optval) {
2426  			case 'S':
2427  				scsi_target = B_TRUE;
2428  				break;
2429  			case 'v':
2430  				verbose = B_TRUE;
2431  				break;
2432  			default:
2433  				(void) fprintf(stderr, "%s: %c: %s\n",
2434  				    cmdName, optionList->optval,
2435  				    gettext("unknown option"));
2436  				return (1);
2437  		}
2438  	}
2439  
2440  	/*
2441  	 * If there are multiple objects, execute outer 'for' loop that
2442  	 * many times for each target detail, otherwise, execute it only
2443  	 * once with summaries only
2444  	 */
2445  	if (objectLen > 0) {
2446  		operandEntered = B_TRUE;
2447  		outerLoop = objectLen;
2448  	} else {
2449  		operandEntered = B_FALSE;
2450  		outerLoop = 1;
2451  	}
2452  
2453  	status = SUN_IMA_GetSessionOidList(initiatorOid, &targetList);
2454  	if (!IMA_SUCCESS(status)) {
2455  		printLibError(status);
2456  		*funcRet = 1;
2457  		return (ret);
2458  	}
2459  
2460  	for (i = 0; i < outerLoop; i++) {
2461  
2462  		tpgtSpecified = B_FALSE;
2463  		if (operandEntered) {
2464  			if (parseTarget(objects[i],
2465  			    &targetName[0],
2466  			    MAX_ISCSI_NAME_LEN + 1,
2467  			    &targetAddressSpecified,
2468  			    &targetAddress[0],
2469  			    SUN_IMA_IP_ADDRESS_PORT_LEN,
2470  			    &port,
2471  			    &tpgtSpecified,
2472  			    &tpgt,
2473  			    &isIpv6) != PARSE_TARGET_OK) {
2474  				ret = 1;
2475  				continue;
2476  			}
2477  		}
2478  		for (found = B_FALSE, j = 0; j < targetList->oidCount; j++) {
2479  			status = SUN_IMA_GetTargetProperties(
2480  			    targetList->oids[j],
2481  			    &targetProps);
2482  			if (!IMA_SUCCESS(status)) {
2483  				printLibError(status);
2484  				(void) IMA_FreeMemory(targetList);
2485  				*funcRet = 1;
2486  				return (ret);
2487  			}
2488  
2489  			/*
2490  			 * Compare the target name with the input if
2491  			 * one was input, if they match, print the target's info
2492  			 *
2493  			 * if no target name was input, continue printing this
2494  			 * target
2495  			 */
2496  			if (operandEntered) {
2497  				if (targetNamesEqual(targetProps.imaProps.name,
2498  				    targetName) == B_TRUE) {
2499  					if (tpgtSpecified == B_TRUE) {
2500  						if (targetProps.
2501  						    defaultTpgtConf ==
2502  						    IMA_FALSE &&
2503  						    targetProps.
2504  						    tpgtConf == tpgt) {
2505  							found = B_TRUE;
2506  						} else {
2507  							/*
2508  							 * tpgt does not match,
2509  							 * move on to next
2510  							 * target
2511  							 */
2512  							continue;
2513  						}
2514  					} else {
2515  						found = B_TRUE;
2516  					}
2517  				} else {
2518  					/*
2519  					 * target name does not match, move on
2520  					 * to next target
2521  					 */
2522  					continue;
2523  				}
2524  			}
2525  
2526  			/* print summary - always */
2527  			(void) fprintf(stdout, gettext("%s: %ws\n"),
2528  			    gettext("Target"), targetProps.imaProps.name);
2529  
2530  			/* Alias */
2531  			(void) fprintf(stdout, "\t%s: ", gettext("Alias"));
2532  			if (wslen(targetProps.imaProps.alias) > (size_t)0) {
2533  				(void) fprintf(stdout, gettext("%ws\n"),
2534  				    targetProps.imaProps.alias);
2535  			} else {
2536  				(void) fprintf(stdout, "%s\n", "-");
2537  			}
2538  
2539  			if (targetProps.defaultTpgtNego != IMA_TRUE) {
2540  				(void) fprintf(stdout, "%s%s: %d\n",
2541  				    "\t", gettext("TPGT"),
2542  				    targetProps.tpgtNego);
2543  			} else if (targetProps.defaultTpgtConf != IMA_TRUE) {
2544  				(void) fprintf(stdout, "%s%s: %d\n",
2545  				    "\t", gettext("TPGT"),
2546  				    targetProps.tpgtConf);
2547  			}
2548  
2549  			(void) fprintf(stdout,
2550  			    "%s%s: %02x%02x%02x%02x%02x%02x\n",
2551  			    "\t", gettext("ISID"),
2552  			    targetProps.isid[0], targetProps.isid[1],
2553  			    targetProps.isid[2], targetProps.isid[3],
2554  			    targetProps.isid[4], targetProps.isid[5]);
2555  
2556  			pConnList = NULL;
2557  			status = SUN_IMA_GetConnOidList(
2558  			    &targetList->oids[j],
2559  			    &pConnList);
2560  
2561  			if (!IMA_SUCCESS(status)) {
2562  				printLibError(status);
2563  				(void) IMA_FreeMemory(targetList);
2564  				*funcRet = 1;
2565  				return (ret);
2566  			}
2567  
2568  			(void) fprintf(stdout, "%s%s: %lu\n",
2569  			    "\t",
2570  			    gettext("Connections"),
2571  			    pConnList->oidCount);
2572  
2573  			if (verbose) {
2574  				SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms;
2575  
2576  				printConnectionList("\t\t", pConnList);
2577  				printDiscoveryMethod(
2578  				    "\t\t  ",
2579  				    targetProps.imaProps.discoveryMethodFlags);
2580  				(void) printLoginParameters(
2581  				    "\t\t  ",
2582  				    targetList->oids[j],
2583  				    PRINT_NEGOTIATED_PARAMS);
2584  
2585  				/* Get Digest configuration */
2586  				status = SUN_IMA_GetConnProperties(
2587  				    &pConnList->oids[0], &connProps);
2588  
2589  				(void) getNegotiatedDigest(
2590  				    ISCSI_LOGIN_PARAM_HEADER_DIGEST,
2591  				    &digestAlgorithms, connProps);
2592  
2593  				if (IMA_SUCCESS(status)) {
2594  					(void) fprintf(stdout, "\t\t  \t%s: ",
2595  					    gettext("Header Digest"));
2596  					printDigestAlgorithm(
2597  					    &digestAlgorithms,
2598  					    PRINT_NEGOTIATED_PARAMS);
2599  				} else {
2600  					(void) IMA_FreeMemory(pConnList);
2601  					(void) IMA_FreeMemory(targetList);
2602  					printLibError(status);
2603  					*funcRet = 1;
2604  					return (ret);
2605  				}
2606  
2607  				(void) getNegotiatedDigest(
2608  				    ISCSI_LOGIN_PARAM_DATA_DIGEST,
2609  				    &digestAlgorithms, connProps);
2610  
2611  				if (IMA_SUCCESS(status)) {
2612  					(void) fprintf(stdout, "\t\t  \t%s: ",
2613  					    gettext("Data Digest"));
2614  					printDigestAlgorithm(
2615  					    &digestAlgorithms,
2616  					    PRINT_NEGOTIATED_PARAMS);
2617  				} else {
2618  					(void) IMA_FreeMemory(pConnList);
2619  					(void) IMA_FreeMemory(targetList);
2620  					printLibError(status);
2621  					*funcRet = 1;
2622  					return (ret);
2623  				}
2624  
2625  				(void) fprintf(stdout, "\n");
2626  			}
2627  
2628  			if (scsi_target) {
2629  				status = SUN_IMA_ReEnumeration(
2630  				    targetList->oids[j]);
2631  				if (!IMA_SUCCESS(status)) {
2632  					/*
2633  					 * Proceeds the listing
2634  					 * but indicates the
2635  					 * error in return value
2636  					 */
2637  					ret = 1;
2638  				}
2639  
2640  				status = IMA_GetLuOidList(
2641  				    targetList->oids[j],
2642  				    &lunList);
2643  				if (!IMA_SUCCESS(status)) {
2644  					printLibError(status);
2645  					(void) IMA_FreeMemory(targetList);
2646  					*funcRet = 1;
2647  					return (ret);
2648  				}
2649  				if (lunList->oidCount != 0) {
2650  					printTargetLuns(lunList);
2651  				}
2652  				(void) fprintf(stdout, "\n");
2653  				(void) IMA_FreeMemory(lunList);
2654  			}
2655  		}
2656  		/*
2657  		 * did we find the object
2658  		 */
2659  
2660  		if (operandEntered && !found) {
2661  			(void) fprintf(stdout, "%s: %s\n",
2662  			    objects[i], gettext("not found"));
2663  		}
2664  	}
2665  
2666  	(void) IMA_FreeMemory(targetList);
2667  	return (ret);
2668  }
2669  
2670  
2671  /*
2672   * Print configured session information
2673   */
2674  static int
printConfiguredSessions(IMA_OID oid)2675  printConfiguredSessions(IMA_OID oid)
2676  {
2677  	IMA_STATUS		status;
2678  	const char		*rtn;
2679  	SUN_IMA_CONFIG_SESSIONS	*pConfigSessions;
2680  	char			address[MAX_ADDRESS_LEN];
2681  	int			out;
2682  
2683  	/* Get configured session information */
2684  	status = SUN_IMA_GetConfigSessions(oid, &pConfigSessions);
2685  
2686  	if (IMA_SUCCESS(status)) {
2687  		(void) fprintf(stdout, "\t%s: ",
2688  		    gettext("Configured Sessions"));
2689  		if (pConfigSessions->bound == IMA_FALSE) {
2690  			/* default binding */
2691  			(void) fprintf(stdout, "%lu\n", pConfigSessions->out);
2692  		} else {
2693  			/* hardcoded binding */
2694  			for (out = 0;
2695  			    out < pConfigSessions->out; out++) {
2696  				if (pConfigSessions->bindings[out].
2697  				    ipAddress.ipv4Address == IMA_TRUE) {
2698  					rtn = inet_ntop(AF_INET,
2699  					    pConfigSessions->bindings[out].
2700  					    ipAddress.ipAddress, address,
2701  					    MAX_ADDRESS_LEN);
2702  				} else {
2703  					rtn = inet_ntop(AF_INET6,
2704  					    pConfigSessions->bindings[out].
2705  					    ipAddress.ipAddress, address,
2706  					    MAX_ADDRESS_LEN);
2707  				}
2708  				if (rtn != NULL) {
2709  					(void) printf("%s ", address);
2710  				}
2711  			}
2712  			(void) fprintf(stdout, "\n");
2713  		}
2714  	} else {
2715  		free(pConfigSessions);
2716  		printLibError(status);
2717  		return (1);
2718  	}
2719  
2720  	free(pConfigSessions);
2721  	return (0);
2722  }
2723  
2724  /*
2725   * Print target parameters
2726   */
2727  static int
listTargetParam(int operandLen,char * operand[],cmdOptions_t * options,int * funcRet)2728  listTargetParam(int operandLen, char *operand[], cmdOptions_t *options,
2729      int *funcRet)
2730  {
2731  	IMA_STATUS status;
2732  	IMA_OID	initiatorOid;
2733  	IMA_OID_LIST *targetList;
2734  	IMA_AUTHMETHOD	methodList[MAX_AUTH_METHODS];
2735  	SUN_IMA_TARGET_PROPERTIES targetProps;
2736  	IMA_UINT maxEntries = MAX_AUTH_METHODS;
2737  	IMA_BOOL bidirAuth;
2738  	int ret;
2739  	wchar_t targetName[MAX_ISCSI_NAME_LEN + 1];
2740  	wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
2741  	boolean_t operandEntered = B_FALSE;
2742  	boolean_t targetAddressSpecified = B_FALSE;
2743  	boolean_t printObject = B_FALSE;
2744  	boolean_t tpgtSpecified = B_FALSE;
2745  	boolean_t isIpv6 = B_FALSE;
2746  	int outerLoop;
2747  	boolean_t found;
2748  	int i, j;
2749  	SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms;
2750  	boolean_t verbose = B_FALSE;
2751  	cmdOptions_t *optionList = options;
2752  	IMA_UINT16 port = 0;
2753  	IMA_UINT16 tpgt = 0;
2754  
2755  	assert(funcRet != NULL);
2756  
2757  	/* Find Sun initiator */
2758  	ret = sunInitiatorFind(&initiatorOid);
2759  	if (ret > 0) {
2760  		(void) fprintf(stderr, "%s: %s\n",
2761  		    cmdName, gettext("no initiator found"));
2762  	}
2763  
2764  	if (ret != 0) {
2765  		return (ret);
2766  	}
2767  
2768  	for (; optionList->optval; optionList++) {
2769  		switch (optionList->optval) {
2770  			case 'v':
2771  				verbose = B_TRUE;
2772  				break;
2773  			default:
2774  				(void) fprintf(stderr, "%s: %c: %s\n",
2775  				    cmdName, optionList->optval,
2776  				    gettext("unknown option"));
2777  				return (1);
2778  		}
2779  	}
2780  
2781  	/*
2782  	 * If there are multiple operands, execute outer 'for' loop that
2783  	 * many times to find each target parameter operand entered, otherwise,
2784  	 * execute it only once for all target parameters returned.
2785  	 */
2786  	if (operandLen > 0) {
2787  		operandEntered = B_TRUE;
2788  		outerLoop = operandLen;
2789  	} else {
2790  		operandEntered = B_FALSE;
2791  		outerLoop = 1;
2792  	}
2793  
2794  	/*
2795  	 * Ideally there should be an interface available for obtaining
2796  	 * the list of target-param objects. Since the driver currently
2797  	 * creates a target OID and the associated session structure when
2798  	 * a target-param object is created, we can leverage the target
2799  	 * OID list and use it to manage the target-param objects. When
2800  	 * we stop creating a session for target-param object in the
2801  	 * driver, we will switch to using a different interface to
2802  	 * obtain target-param objects.
2803  	 */
2804  	status = IMA_GetTargetOidList(initiatorOid, &targetList);
2805  	if (!IMA_SUCCESS(status)) {
2806  		printLibError(status);
2807  		*funcRet = 1;
2808  		return (ret);
2809  	}
2810  
2811  	for (i = 0; i < outerLoop; i++) {
2812  		if (operandEntered) {
2813  			if (parseTarget(operand[i],
2814  			    &targetName[0],
2815  			    MAX_ISCSI_NAME_LEN + 1,
2816  			    &targetAddressSpecified,
2817  			    &targetAddress[0],
2818  			    SUN_IMA_IP_ADDRESS_PORT_LEN,
2819  			    &port,
2820  			    &tpgtSpecified,
2821  			    &tpgt,
2822  			    &isIpv6) != PARSE_TARGET_OK) {
2823  				ret = 1;
2824  				continue;
2825  			}
2826  		}
2827  		for (j = 0; j < targetList->oidCount; j++) {
2828  			found = B_FALSE;
2829  			printObject = B_FALSE;
2830  			status = SUN_IMA_GetTargetProperties(
2831  			    targetList->oids[j],
2832  			    &targetProps);
2833  			if (!IMA_SUCCESS(status)) {
2834  				printLibError(status);
2835  				(void) IMA_FreeMemory(targetList);
2836  				*funcRet = 1;
2837  				return (ret);
2838  			}
2839  
2840  			/*
2841  			 * Compare the target name with the input if
2842  			 * one was input
2843  			 */
2844  			if (operandEntered &&
2845  			    (targetNamesEqual(targetProps.imaProps.name,
2846  			    targetName) == B_TRUE)) {
2847  				/*
2848  				 * For now, regardless of whether a target
2849  				 * address is specified, we return B_TRUE
2850  				 * because IMA_TARGET_PROPERTIES does not
2851  				 * have a field for specifying address.
2852  				 */
2853  				found = B_TRUE;
2854  			}
2855  
2856  			/*
2857  			 * if no operand was entered OR
2858  			 * an operand was entered and it was
2859  			 * found, we want to print
2860  			 */
2861  			if (!operandEntered || found) {
2862  				printObject = B_TRUE;
2863  			}
2864  
2865  			if (printObject) {
2866  				(void) fprintf(stdout, gettext("%s: %ws\n"),
2867  				    gettext("Target"),
2868  				    targetProps.imaProps.name);
2869  
2870  				(void) fprintf(stdout,
2871  				    "\t%s: ", gettext("Alias"));
2872  				if (wslen(targetProps.imaProps.alias) >
2873  				    (size_t)0) {
2874  					(void) fprintf(stdout,
2875  					    gettext("%ws\n"),
2876  					    targetProps.imaProps.alias);
2877  				} else {
2878  					(void) fprintf(stdout, "%s\n", "-");
2879  				}
2880  			}
2881  
2882  			if (printObject && verbose) {
2883  				/* Get bidirectional authentication flag */
2884  				(void) fprintf(stdout, "\t%s: ",
2885  				    gettext("Bi-directional Authentication"));
2886  				status = SUN_IMA_GetTargetBidirAuthFlag(
2887  				    targetList->oids[j],
2888  				    &bidirAuth);
2889  				if (IMA_SUCCESS(status)) {
2890  					if (bidirAuth == IMA_TRUE) {
2891  						(void) fprintf(stdout,
2892  						    gettext("enabled"));
2893  					} else {
2894  						(void) fprintf(stdout,
2895  						    gettext("disabled"));
2896  					}
2897  				} else {
2898  					(void) fprintf(stdout,
2899  					    gettext("disabled"));
2900  				}
2901  				(void) fprintf(stdout, "\n");
2902  
2903  				/* Get authentication type for this target */
2904  				status = SUN_IMA_GetTargetAuthMethods(
2905  				    initiatorOid,
2906  				    targetList->oids[j],
2907  				    &maxEntries,
2908  				    &methodList[0]);
2909  				(void) fprintf(stdout, "\t%s: ",
2910  				    gettext("Authentication Type"));
2911  				if (!IMA_SUCCESS(status)) {
2912  					/*
2913  					 * No authentication method define
2914  					 * NONE by default.
2915  					 */
2916  					(void) fprintf(stdout, gettext("NONE"));
2917  				} else {
2918  					for (i = 0; i < maxEntries; i++) {
2919  						if (i > 0) {
2920  							(void) fprintf(stdout,
2921  							    "|");
2922  						}
2923  						switch (methodList[i]) {
2924  						case IMA_AUTHMETHOD_NONE:
2925  							(void) fprintf(stdout,
2926  							    gettext("NONE"));
2927  							break;
2928  
2929  						case IMA_AUTHMETHOD_CHAP:
2930  							(void) fprintf(stdout,
2931  							    gettext("CHAP"));
2932  							listCHAPName(
2933  							    targetList->
2934  							    oids[j]);
2935  							break;
2936  
2937  						default:
2938  							(void) fprintf(stdout,
2939  							    gettext(
2940  							    "unknown "
2941  							    "type"));
2942  							break;
2943  						}
2944  					}
2945  				}
2946  				(void) fprintf(stdout, "\n");
2947  				if (printLoginParameters("\t",
2948  				    targetList->oids[j],
2949  				    PRINT_CONFIGURED_PARAMS)
2950  				    != 0) {
2951  					(void) IMA_FreeMemory(targetList);
2952  					*funcRet = 1;
2953  					return (ret);
2954  				}
2955  
2956  				/* Get Digest configuration */
2957  				status = SUN_IMA_GetHeaderDigest(
2958  				    targetList->oids[j],
2959  				    &digestAlgorithms);
2960  				if (IMA_SUCCESS(status)) {
2961  					(void) fprintf(stdout, "\t\t%s: ",
2962  					    gettext("Header Digest"));
2963  					printDigestAlgorithm(&digestAlgorithms,
2964  					    PRINT_CONFIGURED_PARAMS);
2965  				} else {
2966  					printLibError(status);
2967  					*funcRet = 1;
2968  					return (ret);
2969  				}
2970  
2971  				status = SUN_IMA_GetDataDigest(
2972  				    targetList->oids[j],
2973  				    &digestAlgorithms);
2974  				if (IMA_SUCCESS(status)) {
2975  					(void) fprintf(stdout, "\t\t%s: ",
2976  					    gettext("Data Digest"));
2977  					printDigestAlgorithm(&digestAlgorithms,
2978  					    PRINT_CONFIGURED_PARAMS);
2979  				} else {
2980  					printLibError(status);
2981  					*funcRet = 1;
2982  					return (ret);
2983  				}
2984  
2985  				/* print tunable parameters infomation */
2986  				if (printTunableParameters(
2987  				    targetList->oids[j]) != 0) {
2988  					*funcRet = 1;
2989  					return (ret);
2990  				}
2991  
2992  				/* print configured session information */
2993  				if (printConfiguredSessions(
2994  				    targetList->oids[j]) != 0) {
2995  					*funcRet = 1;
2996  					return (ret);
2997  				}
2998  
2999  				(void) fprintf(stdout, "\n");
3000  			}
3001  
3002  			if (found) {
3003  				break;
3004  			}
3005  		}
3006  		if (operandEntered && !found) {
3007  			*funcRet = 1; /* DIY message fix */
3008  			(void) fprintf(stdout, "%s: %s\n",
3009  			    operand[i], gettext("not found"));
3010  		}
3011  	}
3012  
3013  	(void) IMA_FreeMemory(targetList);
3014  	return (ret);
3015  }
3016  
3017  /*
3018   * Modify discovery attributes
3019   */
3020  static int
modifyDiscovery(cmdOptions_t * options,int * funcRet)3021  modifyDiscovery(cmdOptions_t *options, int *funcRet)
3022  {
3023  	IMA_OID oid;
3024  	IMA_STATUS status;
3025  	IMA_BOOL setDiscovery;
3026  	IMA_HOST_ID hostId;
3027  
3028  	int ret;
3029  	cmdOptions_t *optionList = options;
3030  
3031  	assert(funcRet != NULL);
3032  
3033  	/* Find Sun initiator */
3034  	ret = sunInitiatorFind(&oid);
3035  	if (ret > 0) {
3036  		(void) fprintf(stderr, "%s: %s\n",
3037  		    cmdName, gettext("no initiator found"));
3038  	}
3039  
3040  	if (ret != 0) {
3041  		return (ret);
3042  	}
3043  
3044  	for (; optionList->optval; optionList++) {
3045  		/* check optarg and set bool accordingly */
3046  		if (strcasecmp(optionList->optarg, ISCSIADM_ARG_ENABLE) == 0) {
3047  			setDiscovery = IMA_TRUE;
3048  		} else if (strcasecmp(optionList->optarg, ISCSIADM_ARG_DISABLE)
3049  		    == 0) {
3050  			setDiscovery = IMA_FALSE;
3051  		} else {
3052  			(void) fprintf(stderr, "%s: %s\n",
3053  			    cmdName, gettext("invalid option argument"));
3054  			return (1);
3055  		}
3056  
3057  		switch (optionList->optval) {
3058  			case 's':
3059  				/* Set static discovery */
3060  				status = IMA_SetStaticDiscovery(oid,
3061  				    setDiscovery);
3062  				if (!IMA_SUCCESS(status)) {
3063  					printLibError(status);
3064  					*funcRet = 1;
3065  					return (ret);
3066  				}
3067  				break;
3068  			case 't':
3069  				/* Set send targets discovery */
3070  				status = IMA_SetSendTargetsDiscovery(oid,
3071  				    setDiscovery);
3072  				if (!IMA_SUCCESS(status)) {
3073  					printLibError(status);
3074  					*funcRet = 1;
3075  					return (ret);
3076  				}
3077  				break;
3078  			case 'i':
3079  				/* Set iSNS discovery */
3080  				(void) memset(&hostId, 0, sizeof (hostId));
3081  				status = IMA_SetIsnsDiscovery(oid, setDiscovery,
3082  				    IMA_ISNS_DISCOVERY_METHOD_STATIC, &hostId);
3083  				if (!IMA_SUCCESS(status)) {
3084  					printLibError(status);
3085  					*funcRet = 1;
3086  					return (ret);
3087  				}
3088  				break;
3089  			default:
3090  				(void) fprintf(stderr, "%s: %c: %s\n",
3091  				    cmdName, optionList->optval,
3092  				    gettext("unknown option"));
3093  				return (1);
3094  		}
3095  	}
3096  
3097  	return (ret);
3098  }
3099  
3100  /*
3101   * Set the initiator node's authentication method
3102   */
3103  static int
modifyNodeAuthParam(IMA_OID oid,int param,char * chapName,int * funcRet)3104  modifyNodeAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet)
3105  {
3106  	IMA_INITIATOR_AUTHPARMS authParams;
3107  	IMA_STATUS status;
3108  	int ret;
3109  	int secretLen = MAX_CHAP_SECRET_LEN;
3110  	int nameLen = 0;
3111  
3112  	IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1];
3113  
3114  	assert(funcRet != NULL);
3115  
3116  	/*
3117  	 * Start with existing parameters and modify with the desired change
3118  	 * before passing along.  We ignore any failures as they probably
3119  	 * are caused by non-existence of auth params for the given node.
3120  	 */
3121  	status = IMA_GetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP,
3122  	    &authParams);
3123  
3124  	switch (param) {
3125  	case AUTH_NAME:
3126  		if (chapName == NULL) {
3127  			(void) fprintf(stderr, "CHAP name cannot be NULL.\n");
3128  			return (1);
3129  		}
3130  		nameLen = strlen(chapName);
3131  		if (nameLen == 0) {
3132  			(void) fprintf(stderr, "CHAP name cannot be empty.\n");
3133  			return (1);
3134  		}
3135  		if (nameLen > ISCSI_MAX_C_USER_LEN) {
3136  			(void) fprintf(stderr, "CHAP name is too long.\n");
3137  			return (1);
3138  		}
3139  		(void) memset(&authParams.chapParms.name, 0,
3140  		    sizeof (authParams.chapParms.name));
3141  		(void) memcpy(&authParams.chapParms.name,
3142  		    &chapName[0], nameLen);
3143  		authParams.chapParms.nameLength = nameLen;
3144  		break;
3145  
3146  	case AUTH_PASSWORD :
3147  		ret = getSecret((char *)&chapSecret[0], &secretLen,
3148  		    MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN);
3149  
3150  		if (ret != 0) {
3151  			return (ret);
3152  		}
3153  
3154  		(void) memset(&authParams.chapParms.challengeSecret, 0,
3155  		    sizeof (authParams.chapParms.challengeSecret));
3156  		(void) memcpy(&authParams.chapParms.challengeSecret,
3157  		    &chapSecret[0], secretLen);
3158  		authParams.chapParms.challengeSecretLength = secretLen;
3159  		break;
3160  
3161  	default:
3162  		(void) fprintf(stderr, "Invalid auth parameter %d\n", param);
3163  		return (1);
3164  	}
3165  
3166  	status = IMA_SetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP,
3167  	    &authParams);
3168  	if (!IMA_SUCCESS(status)) {
3169  		printLibError(status);
3170  		*funcRet = 1;
3171  	}
3172  	return (ret);
3173  }
3174  
3175  /*
3176   * Set the target's authentication method
3177   */
3178  static int
modifyTargetAuthParam(IMA_OID oid,int param,char * chapName,int * funcRet)3179  modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet)
3180  {
3181  	IMA_INITIATOR_AUTHPARMS authParams;
3182  	IMA_STATUS status;
3183  	int ret;
3184  	int secretLen = MAX_CHAP_SECRET_LEN;
3185  	int nameLen = 0;
3186  
3187  	IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1];
3188  
3189  	assert(funcRet != NULL);
3190  
3191  	/*
3192  	 * Start with existing parameters and modify with the desired change
3193  	 * before passing along.  We ignore any get failures as they probably
3194  	 * are caused by non-existence of auth params for the given target.
3195  	 */
3196  	status = SUN_IMA_GetTargetAuthParms(oid, IMA_AUTHMETHOD_CHAP,
3197  	    &authParams);
3198  
3199  	switch (param) {
3200  	case AUTH_NAME:
3201  		if (chapName == NULL) {
3202  			(void) fprintf(stderr, "CHAP name cannot be NULL.\n");
3203  			return (1);
3204  		}
3205  		nameLen = strlen(chapName);
3206  		if (nameLen == 0) {
3207  			(void) fprintf(stderr, "CHAP name cannot be empty.\n");
3208  			return (1);
3209  		}
3210  		if (nameLen > ISCSI_MAX_C_USER_LEN) {
3211  			(void) fprintf(stderr, "CHAP name is too long.\n");
3212  			return (1);
3213  		}
3214  		(void) memset(&authParams.chapParms.name, 0,
3215  		    sizeof (authParams.chapParms.name));
3216  		(void) memcpy(&authParams.chapParms.name,
3217  		    &chapName[0], nameLen);
3218  		authParams.chapParms.nameLength = nameLen;
3219  		break;
3220  
3221  	case AUTH_PASSWORD :
3222  		ret = getSecret((char *)&chapSecret[0], &secretLen,
3223  		    1, MAX_CHAP_SECRET_LEN);
3224  
3225  		if (ret != 0) {
3226  			return (ret);
3227  		}
3228  
3229  		(void) memset(&authParams.chapParms.challengeSecret, 0,
3230  		    sizeof (authParams.chapParms.challengeSecret));
3231  		(void) memcpy(&authParams.chapParms.challengeSecret,
3232  		    &chapSecret[0], secretLen);
3233  		authParams.chapParms.challengeSecretLength = secretLen;
3234  		break;
3235  
3236  	default:
3237  		(void) fprintf(stderr, "Invalid auth parameter %d\n", param);
3238  		return (1);
3239  	}
3240  
3241  	status = SUN_IMA_SetTargetAuthParams(oid, IMA_AUTHMETHOD_CHAP,
3242  	    &authParams);
3243  	if (!IMA_SUCCESS(status)) {
3244  		printLibError(status);
3245  		*funcRet = 1;
3246  	}
3247  	return (0);
3248  }
3249  
3250  static int
modifyTargetBidirAuthFlag(IMA_OID targetOid,char * optarg,int * funcRet)3251  modifyTargetBidirAuthFlag(IMA_OID targetOid, char *optarg, int *funcRet)
3252  {
3253  	IMA_BOOL boolValue;
3254  	IMA_STATUS status;
3255  
3256  	assert(funcRet != NULL);
3257  
3258  	if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) {
3259  		boolValue = IMA_TRUE;
3260  	} else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) {
3261  		boolValue = IMA_FALSE;
3262  	} else {
3263  		(void) fprintf(stderr, "%s: %s %s\n",
3264  		    cmdName, gettext("invalid option argument"), optarg);
3265  		return (1);
3266  	}
3267  
3268  	status = SUN_IMA_SetTargetBidirAuthFlag(targetOid, &boolValue);
3269  	if (!IMA_SUCCESS(status)) {
3270  		printLibError(status);
3271  		*funcRet = 1;
3272  	}
3273  	return (0);
3274  }
3275  
3276  static int
modifyConfiguredSessions(IMA_OID targetOid,char * optarg)3277  modifyConfiguredSessions(IMA_OID targetOid, char *optarg)
3278  {
3279  	SUN_IMA_CONFIG_SESSIONS *pConfigSessions;
3280  	IMA_STATUS		status;
3281  	int			sessions;
3282  	int			size;
3283  	char			tmp[1024];
3284  	boolean_t		isIpv6 = B_FALSE;
3285  	uint16_t		port;
3286  	char			address[MAX_ADDRESS_LEN];
3287  	char			*commaPos;
3288  	char			*addressPos;
3289  	int			rtn;
3290  
3291  	/*
3292  	 * Strip the first int value from the string.  If we sprintf
3293  	 * this back to a string and it matches the original string
3294  	 * then this command is using default binding.  If not a
3295  	 * match we have hard coded binding or a usage error.
3296  	 */
3297  	sessions = atoi(optarg);
3298  	(void) sprintf(tmp, "%d", sessions);
3299  	if (strcmp(optarg, tmp) == 0) {
3300  		/* default binding */
3301  
3302  		/* allocate the required pConfigSessions */
3303  		size = sizeof (SUN_IMA_CONFIG_SESSIONS);
3304  		pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size);
3305  		if (pConfigSessions == NULL) {
3306  			return (1);
3307  		}
3308  
3309  		/* setup pConfigSessions */
3310  		pConfigSessions->bound	= IMA_FALSE;
3311  		pConfigSessions->in	= sessions;
3312  		pConfigSessions->out	= 0;
3313  	} else {
3314  		/* hardcoded binding */
3315  
3316  		/*
3317  		 * First we need to determine how many bindings
3318  		 * are available.  This can be done by scanning
3319  		 * for the number of ',' + 1.
3320  		 */
3321  		sessions = 1;
3322  		commaPos = strchr(optarg, ',');
3323  		while (commaPos != NULL) {
3324  			sessions++;
3325  			commaPos = strchr(++commaPos, ',');
3326  		}
3327  
3328  		/* allocate the required pConfigSessions */
3329  		size = sizeof (SUN_IMA_CONFIG_SESSIONS) + ((sessions - 1) *
3330  		    sizeof (IMA_ADDRESS_KEY));
3331  		pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size);
3332  		if (pConfigSessions == NULL) {
3333  			return (1);
3334  		}
3335  
3336  		/* setup pConfigSessions */
3337  		pConfigSessions->bound	= IMA_TRUE;
3338  		pConfigSessions->in	= sessions;
3339  		pConfigSessions->out	= 0;
3340  
3341  		/* Now fill in the binding information.  */
3342  		sessions = 0;
3343  		addressPos = optarg;
3344  		/*
3345  		 * Walk thru possible address strings
3346  		 * stop once all strings are processed.
3347  		 */
3348  		while (addressPos != NULL) {
3349  			/*
3350  			 * Check if there is another address after this
3351  			 * one. If so terminate the current address and
3352  			 * keep a pointer to the next one.
3353  			 */
3354  			commaPos = strchr(addressPos, ',');
3355  			if (commaPos != NULL) {
3356  				*commaPos++ = 0x00;
3357  			}
3358  
3359  			/*
3360  			 * Parse current address.  If invalid abort
3361  			 * processing of addresses and free memory.
3362  			 */
3363  			if (parseAddress(addressPos, 0, address,
3364  			    MAX_ADDRESS_LEN, &port, &isIpv6) != PARSE_ADDR_OK) {
3365  				free(pConfigSessions);
3366  				printLibError(IMA_ERROR_INVALID_PARAMETER);
3367  				return (1);
3368  			}
3369  
3370  			/* Convert address into binary form */
3371  			if (isIpv6 == B_FALSE) {
3372  				pConfigSessions->bindings[sessions].
3373  				    ipAddress.ipv4Address = IMA_TRUE;
3374  				rtn = inet_pton(AF_INET, address,
3375  				    pConfigSessions->bindings[sessions].
3376  				    ipAddress.ipAddress);
3377  			} else {
3378  				pConfigSessions->bindings[sessions].ipAddress.
3379  				    ipv4Address =
3380  				    IMA_FALSE;
3381  				rtn = inet_pton(AF_INET6, address,
3382  				    pConfigSessions->bindings[sessions].
3383  				    ipAddress.ipAddress);
3384  			}
3385  			if (rtn == 0) {
3386  				/* inet_pton found address invalid */
3387  				free(pConfigSessions);
3388  				printLibError(IMA_ERROR_INVALID_PARAMETER);
3389  				return (1);
3390  			}
3391  
3392  			/* update addressPos to next address */
3393  			sessions++;
3394  			addressPos = commaPos;
3395  		}
3396  	}
3397  
3398  	/* issue SUN_IMA request */
3399  	status = SUN_IMA_SetConfigSessions(targetOid,
3400  	    pConfigSessions);
3401  	if (!IMA_SUCCESS(status)) {
3402  		printLibError(status);
3403  		free(pConfigSessions);
3404  		return (1);
3405  	}
3406  
3407  	free(pConfigSessions);
3408  	return (0);
3409  }
3410  
3411  static int
getAuthMethodValue(char * method,IMA_AUTHMETHOD * value)3412  getAuthMethodValue(char *method, IMA_AUTHMETHOD *value)
3413  {
3414  	if (strcasecmp(method, "chap") == 0) {
3415  		*value = IMA_AUTHMETHOD_CHAP;
3416  		return (0);
3417  	}
3418  
3419  	if (strcasecmp(method, "none") == 0) {
3420  		*value =  IMA_AUTHMETHOD_NONE;
3421  		return (0);
3422  	}
3423  
3424  	return (1);
3425  }
3426  
3427  
3428  /*
3429   * Set the authentication method
3430   * Currently only supports CHAP and NONE
3431   */
3432  static int
modifyNodeAuthMethod(IMA_OID oid,char * optarg,int * funcRet)3433  modifyNodeAuthMethod(IMA_OID oid, char *optarg, int *funcRet)
3434  {
3435  	IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS];
3436  	IMA_UINT methodCount = 0;
3437  	IMA_STATUS status;
3438  	IMA_AUTHMETHOD value;
3439  	char *method;
3440  	char *commaPos;
3441  
3442  	assert(funcRet != NULL);
3443  
3444  	/*
3445  	 * optarg will be a , delimited set of auth methods, in order
3446  	 * of preference
3447  	 * if any values here are incorrect, return without setting
3448  	 * anything.
3449  	 */
3450  	method = optarg;
3451  
3452  	commaPos = strchr(optarg, ',');
3453  
3454  	while (commaPos && methodCount < MAX_AUTH_METHODS) {
3455  		*commaPos = '\0';
3456  		if (getAuthMethodValue(method, &value) != 0) {
3457  			(void) fprintf(stderr, "%s: a: %s\n",
3458  			    cmdName, gettext("invalid option argument"));
3459  			return (1);
3460  		}
3461  		methodList[methodCount++] = value;
3462  		commaPos++;
3463  		method = commaPos;
3464  		commaPos = strchr(method, ',');
3465  	}
3466  	/* Should not find more method specified - if found, error */
3467  	if (commaPos) {
3468  		(void) fprintf(stderr, "%s: -a: %s\n",
3469  		    cmdName, gettext("invalid option argument"));
3470  		return (1);
3471  	}
3472  	if (getAuthMethodValue(method, &value) != 0) {
3473  		(void) fprintf(stderr, "%s: -a: %s\n",
3474  		    cmdName, gettext("invalid option argument"));
3475  		return (1);
3476  	}
3477  	methodList[methodCount++] = value;
3478  
3479  	status = IMA_SetInitiatorAuthMethods(oid, methodCount, &methodList[0]);
3480  	if (!IMA_SUCCESS(status)) {
3481  		printLibError(status);
3482  		*funcRet = 1;
3483  	}
3484  	return (0);
3485  }
3486  
3487  static int
modifyTargetAuthMethod(IMA_OID oid,char * optarg,int * funcRet)3488  modifyTargetAuthMethod(IMA_OID oid, char *optarg, int *funcRet)
3489  {
3490  	IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS];
3491  	IMA_UINT methodCount = 0;
3492  	IMA_STATUS status;
3493  	IMA_AUTHMETHOD value;
3494  	char *method;
3495  	char *commaPos;
3496  
3497  	assert(funcRet != NULL);
3498  
3499  	/*
3500  	 * optarg will be a , delimited set of auth methods, in order
3501  	 * of preference
3502  	 * if any values here are incorrect, return without setting
3503  	 * anything.
3504  	 */
3505  	method = optarg;
3506  
3507  	commaPos = strchr(optarg, ',');
3508  
3509  	while (commaPos && methodCount < MAX_AUTH_METHODS) {
3510  		*commaPos = '\0';
3511  		if (getAuthMethodValue(method, &value) != 0) {
3512  			(void) fprintf(stderr, "%s: a: %s\n",
3513  			    cmdName, gettext("invalid option argument"));
3514  			return (1);
3515  		}
3516  		methodList[methodCount++] = value;
3517  		commaPos++;
3518  		method = commaPos;
3519  		commaPos = strchr(method, ',');
3520  	}
3521  	/* Should not find more method specified - if found, error */
3522  	if (commaPos) {
3523  		(void) fprintf(stderr, "%s: -a: %s\n",
3524  		    cmdName, gettext("invalid option argument"));
3525  		return (1);
3526  	}
3527  	if (getAuthMethodValue(method, &value) != 0) {
3528  		(void) fprintf(stderr, "%s: -a: %s\n",
3529  		    cmdName, gettext("invalid option argument"));
3530  		return (1);
3531  	}
3532  	methodList[methodCount++] = value;
3533  
3534  	status = SUN_IMA_SetTargetAuthMethods(oid, &methodCount,
3535  	    &methodList[0]);
3536  	if (!IMA_SUCCESS(status)) {
3537  		printLibError(status);
3538  		*funcRet = 1;
3539  	}
3540  	return (0);
3541  }
3542  
3543  /*
3544   * Modify the RADIUS configuration of the initiator node.
3545   *
3546   * Return 0 on success.
3547   */
3548  static int
modifyNodeRadiusConfig(IMA_OID oid,char * optarg,int * funcRet)3549  modifyNodeRadiusConfig(IMA_OID oid, char *optarg, int *funcRet)
3550  {
3551  	SUN_IMA_RADIUS_CONFIG config;
3552  	IMA_STATUS status;
3553  	boolean_t isIpv6 = B_FALSE;
3554  	uint16_t port;
3555  
3556  	assert(funcRet != NULL);
3557  
3558  	(void) memset(&config, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
3559  	if (parseAddress(optarg, DEFAULT_RADIUS_PORT,
3560  	    &config.hostnameIpAddress[0], SUN_IMA_IP_ADDRESS_PORT_LEN,
3561  	    &port, &isIpv6) !=
3562  	    PARSE_ADDR_OK) {
3563  		return (1);
3564  	}
3565  	config.port = (IMA_UINT16)port;
3566  	config.isIpv6 = (isIpv6 == B_TRUE) ? IMA_TRUE : IMA_FALSE;
3567  	/* Not setting shared secret here. */
3568  	config.sharedSecretValid = IMA_FALSE;
3569  
3570  	status = SUN_IMA_SetInitiatorRadiusConfig(oid, &config);
3571  	if (!IMA_SUCCESS(status)) {
3572  		printLibError(status);
3573  		*funcRet = 1;
3574  	}
3575  
3576  	return (0);
3577  }
3578  
3579  /*
3580   * Modify the RADIUS access flag of the initiator node.
3581   *
3582   * Return 0 on success.
3583   */
3584  static int
modifyNodeRadiusAccess(IMA_OID oid,char * optarg,int * funcRet)3585  modifyNodeRadiusAccess(IMA_OID oid, char *optarg, int *funcRet)
3586  {
3587  	IMA_BOOL radiusAccess;
3588  	IMA_OID initiatorOid;
3589  	IMA_STATUS status;
3590  	SUN_IMA_RADIUS_CONFIG radiusConfig;
3591  	int ret;
3592  
3593  	assert(funcRet != NULL);
3594  
3595  	/* Check if Radius Config is there */
3596  	ret = sunInitiatorFind(&initiatorOid);
3597  	if (ret != 0) {
3598  		(void) fprintf(stderr, "%s: %s\n",
3599  		    cmdName, gettext("no initiator found"));
3600  		return (1);
3601  	}
3602  	(void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
3603  	status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig);
3604  	if (!IMA_SUCCESS(status)) {
3605  		(void) fprintf(stderr, "%s: %s\n",
3606  		    cmdName, gettext("RADIUS server not configured yet"));
3607  		*funcRet = 1;
3608  		return (ret);
3609  	}
3610  
3611  	/* Check if Radius Shared is set */
3612  	if (radiusConfig.sharedSecretValid == IMA_FALSE) {
3613  		(void) fprintf(stderr, "%s: %s\n", cmdName,
3614  		    gettext("RADIUS server secret not configured yet"));
3615  		return (1);
3616  	}
3617  
3618  	if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) {
3619  		radiusAccess = IMA_TRUE;
3620  	} else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) {
3621  		radiusAccess = IMA_FALSE;
3622  	} else {
3623  		(void) fprintf(stderr, "%s: %s %s\n",
3624  		    cmdName,
3625  		    gettext("invalid option argument"),
3626  		    optarg);
3627  		return (1);
3628  	}
3629  	status = SUN_IMA_SetInitiatorRadiusAccess(oid, radiusAccess);
3630  	if (!IMA_SUCCESS(status)) {
3631  		printLibError(status);
3632  		*funcRet = 1;
3633  	}
3634  
3635  	return (ret);
3636  }
3637  
3638  /*
3639   * Modify the RADIUS shared secret.
3640   *
3641   * Returns:
3642   *  zero on success.
3643   *  > 0 on failure.
3644   */
3645  static int
modifyNodeRadiusSharedSecret(IMA_OID oid,int * funcRet)3646  modifyNodeRadiusSharedSecret(IMA_OID oid, int *funcRet)
3647  {
3648  	IMA_BYTE radiusSharedSecret[SUN_IMA_MAX_RADIUS_SECRET_LEN + 1];
3649  	IMA_OID initiatorOid;
3650  	IMA_STATUS status;
3651  	SUN_IMA_RADIUS_CONFIG radiusConfig;
3652  	int ret;
3653  	int secretLen = SUN_IMA_MAX_RADIUS_SECRET_LEN;
3654  
3655  	assert(funcRet != NULL);
3656  
3657  	ret = getSecret((char *)&radiusSharedSecret[0], &secretLen,
3658  	    0, SUN_IMA_MAX_RADIUS_SECRET_LEN);
3659  	if (ret != 0) {
3660  		return (1);
3661  	}
3662  
3663  	ret = sunInitiatorFind(&initiatorOid);
3664  	if (ret > 0) {
3665  		(void) fprintf(stderr, "%s: %s\n",
3666  		    cmdName, gettext("no initiator found"));
3667  	}
3668  	if (ret != 0) {
3669  		return (1);
3670  	}
3671  	/* First obtain existing RADIUS configuration (if any) */
3672  	(void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
3673  	status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig);
3674  	if (!IMA_SUCCESS(status)) {
3675  		(void) fprintf(stderr, "%s: %s\n",
3676  		    cmdName, gettext("RADIUS server not configured yet"));
3677  		return (1);
3678  	}
3679  
3680  	/* Modify the shared secret only */
3681  	radiusConfig.sharedSecretLength = secretLen;
3682  	(void) memcpy(&radiusConfig.sharedSecret,
3683  	    &radiusSharedSecret[0], secretLen);
3684  	radiusConfig.sharedSecretValid = IMA_TRUE;
3685  	status = SUN_IMA_SetInitiatorRadiusConfig(oid, &radiusConfig);
3686  	if (!IMA_SUCCESS(status)) {
3687  		printLibError(status);
3688  		*funcRet = 1;
3689  	}
3690  
3691  	return (0);
3692  }
3693  
3694  /*
3695   * Set initiator node attributes.
3696   */
3697  static int
modifyNode(cmdOptions_t * options,int * funcRet)3698  modifyNode(cmdOptions_t *options, int *funcRet)
3699  {
3700  	IMA_NODE_NAME	nodeName;
3701  	IMA_NODE_ALIAS	nodeAlias;
3702  	IMA_OID		oid;
3703  	IMA_STATUS	status;
3704  	cmdOptions_t	*optionList = options;
3705  	int		ret;
3706  	iSCSINameCheckStatusType nameCheckStatus;
3707  	IMA_OID sharedNodeOid;
3708  	int		i;
3709  	int		lowerCase;
3710  	IMA_BOOL	iscsiBoot = IMA_FALSE;
3711  	IMA_BOOL	mpxioEnabled = IMA_FALSE;
3712  	char		*mb_name = NULL;
3713  	int		prefixlen = 0;
3714  
3715  	assert(funcRet != NULL);
3716  
3717  	/* Get boot session's info */
3718  	(void) SUN_IMA_GetBootIscsi(&iscsiBoot);
3719  	if (iscsiBoot == IMA_TRUE) {
3720  		status = SUN_IMA_GetBootMpxio(&mpxioEnabled);
3721  		if (!IMA_SUCCESS(status)) {
3722  			(void) fprintf(stderr, "%s: %s\n",
3723  			    cmdName, gettext("unable to get MPxIO info"
3724  			    " of root disk"));
3725  			*funcRet = 1;
3726  			return (1);
3727  		}
3728  	}
3729  
3730  	/* Find Sun initiator */
3731  	ret = sunInitiatorFind(&oid);
3732  	if (ret != 0) {
3733  		(void) fprintf(stderr, "%s: %s\n",
3734  		    cmdName, gettext("no initiator found"));
3735  		return (ret);
3736  	}
3737  
3738  	for (; optionList->optval; optionList++) {
3739  		switch (optionList->optval) {
3740  			case 'N':
3741  				if (strlen(optionList->optarg) >=
3742  				    MAX_ISCSI_NAME_LEN) {
3743  					(void) fprintf(stderr, "%s: %s %d\n",
3744  					    cmdName,
3745  					    gettext("name too long, \
3746  					    maximum length is:"),
3747  					    MAX_ISCSI_NAME_LEN);
3748  				}
3749  
3750  				/* Take the first operand as node name. */
3751  				(void) memset(&nodeName, 0,
3752  				    sizeof (IMA_NODE_NAME));
3753  				if (mbstowcs(nodeName, optionList->optarg,
3754  				    IMA_NODE_NAME_LEN) == (size_t)-1) {
3755  					(void) fprintf(stderr, "%s: %s\n",
3756  					    cmdName,
3757  					    gettext("conversion error"));
3758  					return (1);
3759  				}
3760  
3761  				prefixlen = strlen(ISCSI_IQN_NAME_PREFIX);
3762  				mb_name = (char *)calloc(1, prefixlen + 1);
3763  				if (mb_name == NULL) {
3764  					return (1);
3765  				}
3766  
3767  				if (wcstombs(mb_name, nodeName,
3768  				    prefixlen) == (size_t)-1) {
3769  					(void) fprintf(stderr, "%s: %s\n",
3770  					    cmdName,
3771  					    gettext("conversion error"));
3772  					(void) IMA_FreeMemory(mb_name);
3773  					return (1);
3774  				}
3775  				if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX,
3776  				    prefixlen) == 0) {
3777  					/*
3778  					 * For iqn format, we should map
3779  					 * the upper-case characters to
3780  					 * their lower-case equivalents.
3781  					 */
3782  					for (i = 0; nodeName[i] != 0; i++) {
3783  						lowerCase =
3784  						    tolower(nodeName[i]);
3785  						nodeName[i] = lowerCase;
3786  					}
3787  				}
3788  				(void) IMA_FreeMemory(mb_name);
3789  
3790  				/* Perform string profile checks */
3791  				nameCheckStatus =
3792  				    iSCSINameStringProfileCheck(nodeName);
3793  				iSCSINameCheckStatusDisplay(nameCheckStatus);
3794  				if (nameCheckStatus != iSCSINameCheckOK) {
3795  					*funcRet = 1; /* DIY message fix */
3796  					return (1);
3797  				}
3798  
3799  				/*
3800  				 * IMA_GetSharedNodeOid(&sharedNodeOid);
3801  				 * if (!IMA_SUCCESS(status)) {
3802  				 *   printLibError(status);
3803  				 *   return (INF_ERROR);
3804  				 * }
3805  				 */
3806  				if (iscsiBoot == IMA_TRUE) {
3807  					(void) fprintf(stderr, "%s: %s\n",
3808  					    cmdName, gettext("iscsi boot, not"
3809  					    " allowed to change"
3810  					    " initiator's name"));
3811  					return (1);
3812  				}
3813  				oid.objectType = IMA_OBJECT_TYPE_NODE;
3814  				status = IMA_SetNodeName(oid, nodeName);
3815  				if (!IMA_SUCCESS(status)) {
3816  					printLibError(status);
3817  					*funcRet = 1;
3818  					return (ret);
3819  				}
3820  				break;
3821  
3822  			case 'A':
3823  				if (iscsiBoot == IMA_TRUE) {
3824  					(void) fprintf(stderr, "%s: %s\n",
3825  					    cmdName, gettext("iscsi boot, not"
3826  					    " allowed to change"
3827  					    " initiator's alias"));
3828  					return (1);
3829  				}
3830  				/* Take the first operand as node alias. */
3831  				if (strlen(optionList->optarg) >=
3832  				    MAX_ISCSI_NAME_LEN) {
3833  					(void) fprintf(stderr, "%s: %s %d\n",
3834  					    cmdName,
3835  					    gettext("alias too long, maximum  \
3836  					    length is:"),
3837  					    MAX_ISCSI_NAME_LEN);
3838  				}
3839  
3840  				(void) memset(&nodeAlias, 0,
3841  				    sizeof (IMA_NODE_ALIAS));
3842  				if (mbstowcs(nodeAlias, optionList->optarg,
3843  				    IMA_NODE_ALIAS_LEN) == (size_t)-1) {
3844  					(void) fprintf(stderr, "%s: %s\n",
3845  					    cmdName,
3846  					    gettext("conversion error"));
3847  					return (1);
3848  				}
3849  
3850  				status = IMA_GetSharedNodeOid(&sharedNodeOid);
3851  				if (!IMA_SUCCESS(status)) {
3852  					printLibError(status);
3853  					*funcRet = 1;
3854  					return (ret);
3855  				}
3856  
3857  				status = IMA_SetNodeAlias(sharedNodeOid,
3858  				    nodeAlias);
3859  				if (!IMA_SUCCESS(status)) {
3860  					printLibError(status);
3861  					*funcRet = 1;
3862  					return (ret);
3863  				}
3864  				break;
3865  
3866  			case 'a':
3867  				if (iscsiBoot == IMA_TRUE) {
3868  					(void) fprintf(stderr, "%s: %s\n",
3869  					    cmdName, gettext("iscsi boot, not"
3870  					    " allowed to change authentication"
3871  					    " method"));
3872  					return (1);
3873  				}
3874  				if (modifyNodeAuthMethod(oid, options->optarg,
3875  				    funcRet) != 0) {
3876  					return (1);
3877  				}
3878  				break;
3879  
3880  			case 'R':
3881  				if (modifyNodeRadiusAccess(oid, options->optarg,
3882  				    funcRet) != 0) {
3883  					return (1);
3884  				}
3885  				break;
3886  
3887  			case 'r':
3888  				if (modifyNodeRadiusConfig(oid, options->optarg,
3889  				    funcRet) != 0) {
3890  					return (1);
3891  				}
3892  				break;
3893  
3894  			case 'P':
3895  				if (modifyNodeRadiusSharedSecret(oid, funcRet)
3896  				    != 0) {
3897  					return (1);
3898  				}
3899  				break;
3900  
3901  			case 'C':
3902  				if (iscsiBoot == IMA_TRUE) {
3903  					(void) fprintf(stderr, "%s: %s\n",
3904  					    cmdName, gettext("iscsi boot, not"
3905  					    " allowed to change CHAP secret"));
3906  					return (1);
3907  				}
3908  				if (modifyNodeAuthParam(oid, AUTH_PASSWORD,
3909  				    NULL, funcRet) != 0) {
3910  					return (1);
3911  				}
3912  				break;
3913  
3914  			case 'c':
3915  				if (iscsiBoot == IMA_TRUE) {
3916  					if (mpxioEnabled == IMA_FALSE) {
3917  						(void) fprintf(stderr,
3918  						    "%s: %s\n", cmdName,
3919  						    gettext("iscsi"
3920  						    " boot and MPxIO"
3921  						    " is disabled, not allowed"
3922  						    " to change number of"
3923  						    " sessions to be"
3924  						    " configured"));
3925  						return (1);
3926  					}
3927  				}
3928  				if (modifyConfiguredSessions(oid,
3929  				    optionList->optarg) != 0) {
3930  					if (iscsiBoot == IMA_TRUE) {
3931  						(void) fprintf(stderr,
3932  						    "%s: %s\n", cmdName,
3933  						    gettext("iscsi boot,"
3934  						    " fail to set configured"
3935  						    " session"));
3936  					}
3937  					return (1);
3938  				}
3939  				break;
3940  
3941  
3942  			case 'H':
3943  				if (iscsiBoot == IMA_TRUE) {
3944  					(void) fprintf(stderr, "%s: %s\n",
3945  					    cmdName, gettext("iscsi boot, not"
3946  					    " allowed to change CHAP name"));
3947  					return (1);
3948  				}
3949  				if (modifyNodeAuthParam(oid, AUTH_NAME,
3950  				    optionList->optarg, funcRet) != 0) {
3951  					return (1);
3952  				}
3953  				break;
3954  
3955  
3956  			case 'd':
3957  				if (iscsiBoot == IMA_TRUE) {
3958  					if (mpxioEnabled == IMA_FALSE) {
3959  						(void) fprintf(stderr,
3960  						    "%s: %s\n", cmdName,
3961  						    gettext("iscsi"
3962  						    " boot and MPxIO"
3963  						    " is disabled, not"
3964  						    " allowed to"
3965  						    " change initiator's"
3966  						    " login params"));
3967  						return (1);
3968  					}
3969  				}
3970  				if (setLoginParameter(oid, DATA_DIGEST,
3971  				    optionList->optarg) != 0) {
3972  					return (1);
3973  				}
3974  				break;
3975  
3976  			case 'h':
3977  				if (iscsiBoot == IMA_TRUE) {
3978  					if (mpxioEnabled == IMA_FALSE) {
3979  						(void) fprintf(stderr,
3980  						    "%s: %s\n", cmdName,
3981  						    gettext("iscsi"
3982  						    " boot and MPxIO"
3983  						    " is disabled, not"
3984  						    " allowed to"
3985  						    " change initiator's"
3986  						    " login params"));
3987  						return (1);
3988  					}
3989  				}
3990  				if (setLoginParameter(oid, HEADER_DIGEST,
3991  				    optionList->optarg) != 0) {
3992  					return (1);
3993  				}
3994  				break;
3995  
3996  			case 'T':
3997  				if (setTunableParameters(oid,
3998  				    optionList->optarg) != 0) {
3999  					return (1);
4000  				}
4001  				break;
4002  			default:
4003  				(void) fprintf(stderr, "%s: %c: %s\n",
4004  				    cmdName, optionList->optval,
4005  				    gettext("unknown option"));
4006  				break;
4007  		}
4008  	}
4009  
4010  	return (ret);
4011  }
4012  
4013  /*
4014   * Modify target parameters
4015   */
4016  static int
modifyTargetParam(cmdOptions_t * options,char * targetName,int * funcRet)4017  modifyTargetParam(cmdOptions_t *options, char *targetName, int *funcRet)
4018  {
4019  	IMA_OID oid;
4020  	IMA_OID targetOid;
4021  	IMA_STATUS status;
4022  	IMA_OID_LIST *targetList;
4023  	SUN_IMA_TARGET_PROPERTIES targetProps;
4024  	wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1];
4025  	wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
4026  	int ret;
4027  	boolean_t found;
4028  	boolean_t targetAddressSpecified = B_TRUE;
4029  	boolean_t tpgtSpecified = B_FALSE;
4030  	boolean_t isIpv6 = B_FALSE;
4031  	int i;
4032  	iSCSINameCheckStatusType nameCheckStatus;
4033  	IMA_UINT16 port = 0;
4034  	IMA_UINT16 tpgt = 0;
4035  
4036  	IMA_NODE_NAME bootTargetName;
4037  	IMA_INITIATOR_AUTHPARMS bootTargetCHAP;
4038  	IMA_BOOL  iscsiBoot;
4039  	IMA_BOOL  mpxioEnabled;
4040  
4041  	cmdOptions_t *optionList = options;
4042  
4043  	assert(funcRet != NULL);
4044  
4045  	/* Find Sun initiator */
4046  	ret = sunInitiatorFind(&oid);
4047  	if (ret > 0) {
4048  		(void) fprintf(stderr, "%s: %s\n",
4049  		    cmdName, gettext("no initiator found"));
4050  	}
4051  
4052  	if (ret != 0) {
4053  		return (ret);
4054  	}
4055  
4056  	if (parseTarget(targetName,
4057  	    &wcInputObject[0],
4058  	    MAX_ISCSI_NAME_LEN + 1,
4059  	    &targetAddressSpecified,
4060  	    &targetAddress[0],
4061  	    SUN_IMA_IP_ADDRESS_PORT_LEN,
4062  	    &port,
4063  	    &tpgtSpecified,
4064  	    &tpgt,
4065  	    &isIpv6) != PARSE_TARGET_OK) {
4066  		return (1);
4067  	}
4068  
4069  	/* Perform string profile checks */
4070  	nameCheckStatus = iSCSINameStringProfileCheck(wcInputObject);
4071  	iSCSINameCheckStatusDisplay(nameCheckStatus);
4072  	if (nameCheckStatus != iSCSINameCheckOK) {
4073  		return (1);
4074  	}
4075  
4076  	status = IMA_GetTargetOidList(oid, &targetList);
4077  	if (!IMA_SUCCESS(status)) {
4078  		printLibError(status);
4079  		*funcRet = 1;
4080  		return (0);
4081  	}
4082  
4083  	(void) SUN_IMA_GetBootIscsi(&iscsiBoot);
4084  	if (iscsiBoot == IMA_TRUE) {
4085  		status = SUN_IMA_GetBootMpxio(&mpxioEnabled);
4086  		if (!IMA_SUCCESS(status)) {
4087  			(void) fprintf(stderr, "%s: %s\n",
4088  			    cmdName, gettext("unable to get MPxIO info"
4089  			    " of root disk"));
4090  			*funcRet = 1;
4091  			return (ret);
4092  		}
4093  		status = SUN_IMA_GetBootTargetName(bootTargetName);
4094  		if (!IMA_SUCCESS(status)) {
4095  			(void) fprintf(stderr, "%s: %s\n",
4096  			    cmdName, gettext("unable to get boot target's"
4097  			    " name"));
4098  			*funcRet = 1;
4099  			return (ret);
4100  		}
4101  		status = SUN_IMA_GetBootTargetAuthParams(&bootTargetCHAP);
4102  		if (!IMA_SUCCESS(status)) {
4103  			(void) fprintf(stderr, "%s: %s\n",
4104  			    cmdName, gettext("unable to get boot target's"
4105  			    " auth param"));
4106  			*funcRet = 1;
4107  			return (ret);
4108  		}
4109  	}
4110  
4111  	/* find target oid */
4112  	for (found = B_FALSE, i = 0; i < targetList->oidCount; i++) {
4113  		status = SUN_IMA_GetTargetProperties(targetList->oids[i],
4114  		    &targetProps);
4115  		if (!IMA_SUCCESS(status)) {
4116  			printLibError(status);
4117  			(void) IMA_FreeMemory(targetList);
4118  			*funcRet = 1;
4119  			return (ret);
4120  		}
4121  
4122  		/*
4123  		 * Compare the target name with the input name
4124  		 */
4125  		if ((targetNamesEqual(wcInputObject, targetProps.imaProps.name)
4126  		    == B_TRUE)) {
4127  			/*
4128  			 * For now, regardless of whether a target address
4129  			 * is specified, we return B_TRUE because
4130  			 * IMA_TARGET_PROPERTIES does not have a field for
4131  			 * specifying address.
4132  			 */
4133  			found = B_TRUE;
4134  			targetOid = targetList->oids[i];
4135  
4136  			if ((targetNamesEqual(bootTargetName, wcInputObject)
4137  			    == B_TRUE) && (iscsiBoot == IMA_TRUE)) {
4138  				/*
4139  				 * iscsi booting, need changed target param is
4140  				 * booting target, for auth param, not allow
4141  				 * to change, for others dependent on mpxio
4142  				 */
4143  
4144  				if ((optionList->optval == 'C') ||
4145  				    (optionList->optval == 'H') ||
4146  				    (optionList->optval == 'B') ||
4147  				    (optionList->optval == 'a')) {
4148  					/*
4149  					 * -C CHAP secret set
4150  					 * -H CHAP name set
4151  					 * -a authentication
4152  					 * -B bi-directional-authentication
4153  					 */
4154  					(void) fprintf(stderr, "%s: %s\n",
4155  					    cmdName, gettext("iscsi boot,"
4156  					    " not allowed to modify"
4157  					    " authentication parameters"
4158  					    "  of boot target"));
4159  					return (1);
4160  				}
4161  				if (mpxioEnabled == IMA_FALSE) {
4162  					(void) fprintf(stderr, "%s: %s\n",
4163  					    cmdName, gettext("iscsi boot and"
4164  					    " MPxIO is disabled, not allowed"
4165  					    " to modify boot target's"
4166  					    " parameters"));
4167  					return (1);
4168  				}
4169  
4170  			}
4171  
4172  			if (modifyIndividualTargetParam(optionList, targetOid,
4173  			    funcRet) != 0) {
4174  				return (ret);
4175  			}
4176  
4177  			/*
4178  			 * Even after finding a matched target, keep going
4179  			 * since there could be multiple target objects
4180  			 * associated with one target name in the system
4181  			 * because of different TPGTs.
4182  			 */
4183  		}
4184  	}
4185  
4186  	/* If the target OID cannot be found create one */
4187  	if (!found) {
4188  		status = SUN_IMA_CreateTargetOid(wcInputObject, &targetOid);
4189  		if (!IMA_SUCCESS(status)) {
4190  			printLibError(status);
4191  			(void) IMA_FreeMemory(targetList);
4192  			*funcRet = 1;
4193  			return (ret);
4194  		}
4195  		if (modifyIndividualTargetParam(optionList, targetOid,
4196  		    funcRet) != 0) {
4197  				return (ret);
4198  		}
4199  	}
4200  
4201  	(void) IMA_FreeMemory(targetList);
4202  	return (ret);
4203  }
4204  
4205  /*
4206   * Add one or more addresses
4207   */
4208  static int
addAddress(int addrType,int operandLen,char * operand[],int * funcRet)4209  addAddress(int addrType, int operandLen, char *operand[], int *funcRet)
4210  {
4211  	IMA_STATUS status;
4212  	IMA_OID oid, addressOid;
4213  	SUN_IMA_TARGET_ADDRESS address;
4214  	wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
4215  	int ret;
4216  	int i;
4217  
4218  	assert(funcRet != NULL);
4219  
4220  	/* Find Sun initiator */
4221  	ret = sunInitiatorFind(&oid);
4222  	if (ret > 0) {
4223  		(void) fprintf(stderr, "%s: %s\n",
4224  		    cmdName, gettext("no initiator found"));
4225  	}
4226  
4227  	if (ret != 0) {
4228  		return (ret);
4229  	}
4230  
4231  	/*
4232  	 * Format of discovery address operand:
4233  	 *
4234  	 * <IP address|hostname>:<port>
4235  	 */
4236  	for (i = 0; i < operandLen; i++) {
4237  		/* initialize */
4238  		(void) memset(&wcInputObject[0], 0, sizeof (wcInputObject));
4239  		(void) memset(&address, 0, sizeof (address));
4240  
4241  		if (mbstowcs(wcInputObject, operand[i],
4242  		    (MAX_ADDRESS_LEN + 1)) == (size_t)-1) {
4243  			(void) fprintf(stderr, "%s: %s\n",
4244  			    cmdName, gettext("conversion error"));
4245  			ret = 1;
4246  			continue;
4247  		}
4248  		if (getTargetAddress(addrType, operand[i], &address.imaStruct)
4249  		    != 0) {
4250  			ret = 1;
4251  			continue;
4252  		}
4253  		if (addrType == DISCOVERY_ADDRESS) {
4254  			status = IMA_AddDiscoveryAddress(oid,
4255  			    address.imaStruct, &addressOid);
4256  			if (!IMA_SUCCESS(status)) {
4257  				printLibError(status);
4258  				*funcRet = 1;
4259  				return (ret);
4260  			}
4261  		} else if (addrType == ISNS_SERVER_ADDRESS) {
4262  			status = SUN_IMA_AddISNSServerAddress(address);
4263  			if (!IMA_SUCCESS(status)) {
4264  				printLibError(status);
4265  				*funcRet = 1;
4266  				return (ret);
4267  			}
4268  		}
4269  	}
4270  	return (ret);
4271  }
4272  
4273  /*
4274   * Add one or more static configuration targets
4275   */
4276  static int
addStaticConfig(int operandLen,char * operand[],int * funcRet)4277  addStaticConfig(int operandLen, char *operand[], int *funcRet)
4278  {
4279  	int i;
4280  	boolean_t targetAddressSpecified = B_FALSE;
4281  	boolean_t tpgtSpecified = B_FALSE;
4282  	boolean_t isIpv6 = B_FALSE;
4283  	int ret;
4284  	int addrType;
4285  	IMA_STATUS status;
4286  	IMA_OID oid;
4287  	SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig;
4288  	IMA_UINT16 port = 0;
4289  	IMA_UINT16 tpgt = 0;
4290  	wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1];
4291  	wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
4292  	iSCSINameCheckStatusType nameCheckStatus;
4293  	char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
4294  
4295  	assert(funcRet != NULL);
4296  
4297  	/* Find Sun initiator */
4298  	ret = sunInitiatorFind(&oid);
4299  	if (ret > 0) {
4300  		(void) fprintf(stderr, "%s: %s\n",
4301  		    cmdName, gettext("no initiator found"));
4302  	}
4303  
4304  	if (ret != 0) {
4305  		return (ret);
4306  	}
4307  
4308  	/*
4309  	 * Format of static config operand:
4310  	 *  <target-name>,<IP address|hostname>[:port][,tpgt]
4311  	 */
4312  	for (i = 0; i < operandLen; i++) {
4313  		if (parseTarget(operand[i],
4314  		    &staticTargetName[0],
4315  		    MAX_ISCSI_NAME_LEN + 1,
4316  		    &targetAddressSpecified,
4317  		    &staticTargetAddress[0],
4318  		    SUN_IMA_IP_ADDRESS_PORT_LEN,
4319  		    &port,
4320  		    &tpgtSpecified,
4321  		    &tpgt,
4322  		    &isIpv6) != PARSE_TARGET_OK) {
4323  			ret = 1;
4324  			continue;
4325  		}
4326  
4327  		if (targetAddressSpecified != B_TRUE) {
4328  			(void) fprintf(stderr, "%s: %s\n",
4329  			    cmdName, gettext("missing target address"));
4330  			*funcRet = 1; /* DIY message fix */
4331  			return (1);
4332  		}
4333  		/* Perform string profile checks */
4334  		nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName);
4335  		iSCSINameCheckStatusDisplay(nameCheckStatus);
4336  		if (nameCheckStatus != iSCSINameCheckOK) {
4337  			*funcRet = 1; /* DIY message fix */
4338  			return (1);
4339  		}
4340  		(void) wcsncpy(staticConfig.targetName, staticTargetName,
4341  		    MAX_ISCSI_NAME_LEN + 1);
4342  
4343  		(void) wcstombs(sAddr, staticTargetAddress, sizeof (sAddr));
4344  
4345  		if (isIpv6 == B_TRUE) {
4346  			staticConfig.targetAddress.imaStruct.hostnameIpAddress.
4347  			    id.ipAddress.ipv4Address = B_FALSE;
4348  			addrType = AF_INET6;
4349  		} else {
4350  			staticConfig.targetAddress.imaStruct.hostnameIpAddress.
4351  			    id.ipAddress.ipv4Address = B_TRUE;
4352  			addrType = AF_INET;
4353  		}
4354  
4355  		if (inet_pton(addrType, sAddr, staticConfig.targetAddress.
4356  		    imaStruct.hostnameIpAddress.id.ipAddress.ipAddress) != 1) {
4357  			(void) fprintf(stderr, "%s: %s\n",
4358  			    cmdName, gettext("static config conversion error"));
4359  			ret = 1;
4360  			continue;
4361  		}
4362  
4363  		staticConfig.targetAddress.imaStruct.portNumber = port;
4364  		if (tpgtSpecified == B_TRUE) {
4365  			staticConfig.targetAddress.defaultTpgt = B_FALSE;
4366  			staticConfig.targetAddress.tpgt = tpgt;
4367  		} else {
4368  			staticConfig.targetAddress.defaultTpgt = B_TRUE;
4369  			staticConfig.targetAddress.tpgt = 0;
4370  		}
4371  
4372  		status = SUN_IMA_AddStaticTarget(oid, staticConfig, &oid);
4373  		if (!IMA_SUCCESS(status)) {
4374  			printLibError(status);
4375  			*funcRet = 1;
4376  			return (1);
4377  		}
4378  	}
4379  
4380  	if (ret != 0) {
4381  		*funcRet = 1;
4382  	}
4383  
4384  	return (ret);
4385  }
4386  
4387  /*
4388   * Remove one or more addresses
4389   */
4390  static int
removeAddress(int addrType,int operandLen,char * operand[],int * funcRet)4391  removeAddress(int addrType, int operandLen, char *operand[], int *funcRet)
4392  {
4393  	IMA_STATUS status;
4394  	IMA_OID initiatorOid;
4395  	SUN_IMA_TARGET_ADDRESS address;
4396  	wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
4397  	int ret;
4398  	int i;
4399  
4400  	assert(funcRet != NULL);
4401  
4402  	/* Find Sun initiator */
4403  	ret = sunInitiatorFind(&initiatorOid);
4404  	if (ret > 0) {
4405  		(void) fprintf(stderr, "%s: %s\n",
4406  		    cmdName, gettext("no initiator found"));
4407  	}
4408  
4409  	if (ret != 0) {
4410  		return (ret);
4411  	}
4412  
4413  	for (i = 0; i < operandLen; i++) {
4414  		/* initialize */
4415  		(void) memset(&wcInputObject[0], 0, sizeof (wcInputObject));
4416  		(void) memset(&address, 0, sizeof (address));
4417  
4418  		if (mbstowcs(wcInputObject, operand[i],
4419  		    MAX_ADDRESS_LEN + 1) == (size_t)-1) {
4420  			(void) fprintf(stderr, "%s: %s\n",
4421  			    cmdName, gettext("conversion error"));
4422  			ret = 1;
4423  			continue;
4424  		}
4425  
4426  		if (getTargetAddress(addrType, operand[i], &address.imaStruct)
4427  		    != 0) {
4428  			ret = 1;
4429  			continue;
4430  		}
4431  
4432  		if (addrType == DISCOVERY_ADDRESS) {
4433  			status = SUN_IMA_RemoveDiscoveryAddress(address);
4434  			if (!IMA_SUCCESS(status)) {
4435  				if (status == IMA_ERROR_OBJECT_NOT_FOUND) {
4436  					(void) fprintf(stderr, "%s: %s\n",
4437  					    operand[i], gettext("not found"));
4438  				} else {
4439  					printLibError(status);
4440  				}
4441  				*funcRet = 1;
4442  			}
4443  		} else {
4444  			status = SUN_IMA_RemoveISNSServerAddress(address);
4445  			if (!IMA_SUCCESS(status)) {
4446  				printLibError(status);
4447  				*funcRet = 1;
4448  			}
4449  		}
4450  	}
4451  	return (ret);
4452  }
4453  
4454  /*
4455   * Remove one or more static configuration targets
4456   */
4457  static int
removeStaticConfig(int operandLen,char * operand[],int * funcRet)4458  removeStaticConfig(int operandLen, char *operand[], int *funcRet)
4459  {
4460  	IMA_STATUS status;
4461  	IMA_OID initiatorOid;
4462  	IMA_OID_LIST *staticTargetList;
4463  	SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps;
4464  	wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1];
4465  	wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
4466  	int ret;
4467  	boolean_t atLeastFoundOne;
4468  	boolean_t matched;
4469  	boolean_t targetAddressSpecified = B_TRUE;
4470  	boolean_t tpgtSpecified = B_FALSE;
4471  	boolean_t isIpv6 = B_FALSE;
4472  	int i, j;
4473  	IMA_UINT16 port = 0;
4474  	IMA_UINT16 tpgt = 0;
4475  	iSCSINameCheckStatusType nameCheckStatus;
4476  	char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN];
4477  	wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
4478  
4479  	assert(funcRet != NULL);
4480  
4481  	/* Find Sun initiator */
4482  	ret = sunInitiatorFind(&initiatorOid);
4483  	if (ret > 0) {
4484  		(void) fprintf(stderr, "%s: %s\n",
4485  		    cmdName, gettext("no initiator found"));
4486  	}
4487  
4488  	if (ret != 0) {
4489  		return (ret);
4490  	}
4491  
4492  	status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid,
4493  	    &staticTargetList);
4494  	if (!IMA_SUCCESS(status)) {
4495  		printLibError(status);
4496  		*funcRet = 1;
4497  		return (ret);
4498  	}
4499  
4500  	for (i = 0; i < operandLen; i++) {
4501  		if (parseTarget(operand[i],
4502  		    &staticTargetName[0],
4503  		    MAX_ISCSI_NAME_LEN + 1,
4504  		    &targetAddressSpecified,
4505  		    &staticTargetAddress[0],
4506  		    SUN_IMA_IP_ADDRESS_PORT_LEN,
4507  		    &port,
4508  		    &tpgtSpecified,
4509  		    &tpgt,
4510  		    &isIpv6) != PARSE_TARGET_OK) {
4511  			ret = 1;
4512  			continue;
4513  		}
4514  
4515  		/* Perform string profile checks */
4516  		nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName);
4517  		iSCSINameCheckStatusDisplay(nameCheckStatus);
4518  		if (nameCheckStatus != iSCSINameCheckOK) {
4519  			return (1);
4520  		}
4521  
4522  		for (atLeastFoundOne = B_FALSE, j = 0;
4523  		    j < staticTargetList->oidCount;
4524  		    j++) {
4525  			IMA_UINT16 stpgt;
4526  
4527  			matched = B_FALSE;
4528  			status = SUN_IMA_GetStaticTargetProperties(
4529  			    staticTargetList->oids[j], &staticTargetProps);
4530  			if (!IMA_SUCCESS(status)) {
4531  				if (status == IMA_ERROR_OBJECT_NOT_FOUND) {
4532  					/*
4533  					 * When removing multiple static-config
4534  					 * entries we need to expect get
4535  					 * failures. These failures occur when
4536  					 * we are trying to get entry
4537  					 * information we have just removed.
4538  					 * Ignore the failure and continue.
4539  					 */
4540  					ret = 1;
4541  					continue;
4542  				} else {
4543  					printLibError(status);
4544  					(void) IMA_FreeMemory(staticTargetList);
4545  					*funcRet = 1;
4546  					return (ret);
4547  				}
4548  			}
4549  
4550  			stpgt =
4551  			    staticTargetProps.staticTarget.targetAddress.tpgt;
4552  
4553  			/*
4554  			 * Compare the static target name with the input if
4555  			 * one was input
4556  			 */
4557  			if ((targetNamesEqual(
4558  			    staticTargetProps.staticTarget.targetName,
4559  			    staticTargetName) == B_TRUE)) {
4560  				if (targetAddressSpecified == B_FALSE) {
4561  					matched = B_TRUE;
4562  				} else {
4563  
4564  					if (staticTargetProps.staticTarget.
4565  					    targetAddress.imaStruct.
4566  					    hostnameIpAddress.
4567  					    id.ipAddress.ipv4Address ==
4568  					    IMA_TRUE) {
4569  						(void) inet_ntop(AF_INET,
4570  						    staticTargetProps.
4571  						    staticTarget.targetAddress.
4572  						    imaStruct.hostnameIpAddress.
4573  						    id.ipAddress.ipAddress,
4574  						    tmpStr,
4575  						    sizeof (tmpStr));
4576  					} else {
4577  						(void) inet_ntop(AF_INET6,
4578  						    staticTargetProps.
4579  						    staticTarget.targetAddress.
4580  						    imaStruct.hostnameIpAddress.
4581  						    id.ipAddress.ipAddress,
4582  						    tmpStr,
4583  						    sizeof (tmpStr));
4584  					}
4585  
4586  					if (mbstowcs(tmpTargetAddress, tmpStr,
4587  					    SUN_IMA_IP_ADDRESS_PORT_LEN) ==
4588  					    (size_t)-1) {
4589  						(void) fprintf(stderr,
4590  						    "%s: %s\n",
4591  						    cmdName, gettext(
4592  						    "conversion error"));
4593  						ret = 1;
4594  						continue;
4595  					}
4596  
4597  					if ((wcsncmp(tmpTargetAddress,
4598  					    staticTargetAddress,
4599  					    SUN_IMA_IP_ADDRESS_PORT_LEN) ==
4600  					    0) && (staticTargetProps.
4601  					    staticTarget.targetAddress.
4602  					    imaStruct.portNumber == port)) {
4603  						if (tpgtSpecified == B_FALSE) {
4604  							matched = B_TRUE;
4605  						} else {
4606  							if (tpgt == stpgt) {
4607  								matched =
4608  								    B_TRUE;
4609  							}
4610  						}
4611  					}
4612  				}
4613  
4614  				if (matched) {
4615  					status =
4616  					    IMA_RemoveStaticDiscoveryTarget(
4617  					    staticTargetList->oids[j]);
4618  					if (!IMA_SUCCESS(status)) {
4619  						printLibError(status);
4620  						*funcRet = 1;
4621  						return (ret);
4622  					}
4623  					atLeastFoundOne = B_TRUE;
4624  				}
4625  			}
4626  		}
4627  		if (!atLeastFoundOne) {
4628  			(void) fprintf(stderr, gettext("%ws,%ws: %s\n"),
4629  			    staticTargetName, staticTargetAddress,
4630  			    gettext("not found"));
4631  		}
4632  	}
4633  	return (ret);
4634  }
4635  
4636  /*
4637   * Remove one or more target params.
4638   */
4639  static int
removeTargetParam(int operandLen,char * operand[],int * funcRet)4640  removeTargetParam(int operandLen, char *operand[], int *funcRet)
4641  {
4642  	char *commaPos;
4643  	IMA_STATUS status;
4644  	IMA_OID initiatorOid;
4645  	IMA_OID_LIST *targetList;
4646  	SUN_IMA_TARGET_PROPERTIES targetProps;
4647  	wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1];
4648  	int ret;
4649  	boolean_t found;
4650  	int i, j;
4651  	IMA_NODE_NAME bootTargetName;
4652  	IMA_BOOL	iscsiBoot = IMA_FALSE;
4653  	IMA_BOOL	mpxioEnabled = IMA_FALSE;
4654  
4655  	/* Get boot session's info */
4656  	(void) SUN_IMA_GetBootIscsi(&iscsiBoot);
4657  	if (iscsiBoot == IMA_TRUE) {
4658  		status = SUN_IMA_GetBootMpxio(&mpxioEnabled);
4659  		if (!IMA_SUCCESS(status)) {
4660  			(void) fprintf(stderr, "%s: %s\n",
4661  			    cmdName, gettext("unable to get MPxIO info of"
4662  			    " root disk"));
4663  			*funcRet = 1;
4664  			return (1);
4665  		}
4666  		status = SUN_IMA_GetBootTargetName(bootTargetName);
4667  		if (!IMA_SUCCESS(status)) {
4668  			(void) fprintf(stderr, "%s: %s\n",
4669  			    cmdName, gettext("unable to get boot"
4670  			    " target's name"));
4671  			*funcRet = 1;
4672  			return (1);
4673  		}
4674  	}
4675  
4676  	assert(funcRet != NULL);
4677  
4678  	/* Find Sun initiator */
4679  	ret = sunInitiatorFind(&initiatorOid);
4680  	if (ret > 0) {
4681  		(void) fprintf(stderr, "%s: %s\n",
4682  		    cmdName, gettext("no initiator found"));
4683  	}
4684  
4685  	if (ret != 0) {
4686  		return (ret);
4687  	}
4688  
4689  	status = IMA_GetTargetOidList(initiatorOid, &targetList);
4690  	if (!IMA_SUCCESS(status)) {
4691  		printLibError(status);
4692  		*funcRet = 1;
4693  		return (ret);
4694  	}
4695  
4696  	for (i = 0; i < operandLen; i++) {
4697  		/* initialize */
4698  		commaPos = strchr(operand[i], ',');
4699  		if (commaPos) {
4700  			/* Ignore IP address. */
4701  			*commaPos = '\0';
4702  		}
4703  		(void) memset(&wcInputObject[0], 0, sizeof (wcInputObject));
4704  		if (mbstowcs(wcInputObject, operand[i],
4705  		    MAX_ISCSI_NAME_LEN + 1) == (size_t)-1) {
4706  			(void) fprintf(stderr, "%s: %s\n", cmdName,
4707  			    gettext("conversion error"));
4708  			ret = 1;
4709  			continue;
4710  		}
4711  
4712  		for (found = B_FALSE, j = 0; j < targetList->oidCount;
4713  		    j++) {
4714  			status = SUN_IMA_GetTargetProperties(
4715  			    targetList->oids[j], &targetProps);
4716  			if (!IMA_SUCCESS(status)) {
4717  				printLibError(status);
4718  				(void) IMA_FreeMemory(targetList);
4719  				*funcRet = 1;
4720  				return (ret);
4721  			}
4722  
4723  			/*
4724  			 * Compare the target name with the input if
4725  			 * one was input
4726  			 */
4727  			if (targetNamesEqual(targetProps.imaProps.name,
4728  			    wcInputObject) == B_TRUE) {
4729  				found = B_TRUE;
4730  				if ((targetNamesEqual(bootTargetName,
4731  				    wcInputObject) == B_TRUE) &&
4732  				    (iscsiBoot == IMA_TRUE)) {
4733  					/*
4734  					 * iscsi booting, need changed target
4735  					 * param is booting target, booting
4736  					 * session mpxio disabled, not
4737  					 * allow to update
4738  					 */
4739  					if (mpxioEnabled == IMA_FALSE) {
4740  						(void) fprintf(stderr,
4741  						    "%s: %s\n", cmdName,
4742  						    gettext("iscsi boot"
4743  						    " with MPxIO disabled,"
4744  						    " not allowed to remove"
4745  						    " boot sess param"));
4746  						ret = 1;
4747  						continue;
4748  					}
4749  
4750  				}
4751  
4752  				status = SUN_IMA_RemoveTargetParam(
4753  				    targetList->oids[j]);
4754  				if (!IMA_SUCCESS(status)) {
4755  					printLibError(status);
4756  					(void) IMA_FreeMemory(targetList);
4757  					*funcRet = 1;
4758  					return (ret);
4759  				}
4760  			}
4761  		}
4762  		if (!found) {
4763  			/* Silently ignoring it? */
4764  			(void) fprintf(stderr, gettext("%ws: %s\n"),
4765  			    wcInputObject, gettext("not found"));
4766  		}
4767  	}
4768  
4769  	(void) IMA_FreeMemory(targetList);
4770  	return (ret);
4771  }
4772  
4773  /*ARGSUSED*/
4774  static int
addFunc(int operandLen,char * operand[],int object,cmdOptions_t * options,void * addArgs,int * funcRet)4775  addFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
4776      void *addArgs, int *funcRet)
4777  {
4778  	int ret;
4779  
4780  	assert(funcRet != NULL);
4781  
4782  	switch (object) {
4783  		case DISCOVERY_ADDRESS:
4784  		case ISNS_SERVER_ADDRESS:
4785  			ret = addAddress(object, operandLen, operand, funcRet);
4786  			break;
4787  		case STATIC_CONFIG:
4788  			ret = addStaticConfig(operandLen, operand, funcRet);
4789  			break;
4790  		default:
4791  			(void) fprintf(stderr, "%s: %s\n",
4792  			    cmdName, gettext("unknown object"));
4793  			ret = 1;
4794  			break;
4795  	}
4796  	return (ret);
4797  }
4798  
4799  /*ARGSUSED*/
4800  static int
listFunc(int operandLen,char * operand[],int object,cmdOptions_t * options,void * addArgs,int * funcRet)4801  listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
4802      void *addArgs, int *funcRet)
4803  {
4804  	int ret;
4805  
4806  	assert(funcRet != NULL);
4807  
4808  	switch (object) {
4809  	case DISCOVERY:
4810  		ret = listDiscovery(funcRet);
4811  		break;
4812  	case DISCOVERY_ADDRESS:
4813  		ret = listDiscoveryAddress(operandLen, operand, options,
4814  		    funcRet);
4815  		break;
4816  	case ISNS_SERVER_ADDRESS:
4817  		ret = listISNSServerAddress(operandLen, operand, options,
4818  		    funcRet);
4819  		break;
4820  	case NODE:
4821  		ret = listNode(funcRet);
4822  		break;
4823  	case STATIC_CONFIG:
4824  		ret = listStaticConfig(operandLen, operand, funcRet);
4825  		break;
4826  	case TARGET:
4827  		ret = listTarget(operandLen, operand, options, funcRet);
4828  		break;
4829  	case TARGET_PARAM:
4830  		ret = listTargetParam(operandLen, operand, options, funcRet);
4831  		break;
4832  	default:
4833  		(void) fprintf(stderr, "%s: %s\n",
4834  		    cmdName, gettext("unknown object"));
4835  		ret = 1;
4836  		break;
4837  	}
4838  	return (ret);
4839  }
4840  
4841  /*ARGSUSED*/
4842  static int
modifyFunc(int operandLen,char * operand[],int object,cmdOptions_t * options,void * addArgs,int * funcRet)4843  modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
4844      void *addArgs, int *funcRet)
4845  {
4846  	int ret, i;
4847  
4848  	assert(funcRet != NULL);
4849  
4850  	switch (object) {
4851  	case DISCOVERY:
4852  		ret = modifyDiscovery(options, funcRet);
4853  		break;
4854  	case NODE:
4855  		ret = modifyNode(options, funcRet);
4856  		break;
4857  	case TARGET_PARAM:
4858  		i = 0;
4859  		while (operand[i]) {
4860  			ret = modifyTargetParam(options, operand[i], funcRet);
4861  
4862  			if (ret) {
4863  				(void) fprintf(stderr, "%s: %s: %s\n",
4864  				    cmdName, gettext("modify failed"),
4865  				    operand[i]);
4866  				return (ret);
4867  			}
4868  			i++;
4869  		}
4870  
4871  		break;
4872  	default:
4873  		(void) fprintf(stderr, "%s: %s\n",
4874  		    cmdName, gettext("unknown object"));
4875  		ret = 1;
4876  		break;
4877  	}
4878  	return (ret);
4879  }
4880  
4881  /*ARGSUSED*/
4882  static int
removeFunc(int operandLen,char * operand[],int object,cmdOptions_t * options,void * addArgs,int * funcRet)4883  removeFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
4884      void *addArgs, int *funcRet)
4885  {
4886  	int ret;
4887  
4888  	switch (object) {
4889  		case DISCOVERY_ADDRESS:
4890  		case ISNS_SERVER_ADDRESS:
4891  			ret = removeAddress(object, operandLen, operand,
4892  			    funcRet);
4893  			break;
4894  		case STATIC_CONFIG:
4895  			ret = removeStaticConfig(operandLen, operand, funcRet);
4896  			break;
4897  		case TARGET_PARAM:
4898  			ret = removeTargetParam(operandLen, operand, funcRet);
4899  			break;
4900  		default:
4901  			(void) fprintf(stderr, "%s: %s\n",
4902  			    cmdName, gettext("unknown object"));
4903  			ret = 1;
4904  			break;
4905  	}
4906  	return (ret);
4907  }
4908  
4909  static void
iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status)4910  iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status)
4911  {
4912  	switch (status) {
4913  		case iSCSINameLenZero:
4914  			(void) fprintf(stderr, "%s: %s\n",
4915  			    cmdName, gettext("empty iSCSI name."));
4916  			break;
4917  		case iSCSINameLenExceededMax:
4918  			(void) fprintf(stderr, "%s: %s\n", cmdName,
4919  			    gettext("iSCSI name exceeded maximum length."));
4920  			break;
4921  		case iSCSINameUnknownType:
4922  			(void) fprintf(stderr, "%s: %s\n", cmdName,
4923  			    gettext("unknown iSCSI name type."));
4924  			break;
4925  		case iSCSINameInvalidCharacter:
4926  			(void) fprintf(stderr, "%s: %s\n",
4927  			    cmdName,
4928  			    gettext("iSCSI name invalid character used"));
4929  			break;
4930  		case iSCSINameIqnFormatError:
4931  			(void) fprintf(stderr, "%s: %s\n", cmdName,
4932  			    gettext("iqn formatting error."));
4933  			break;
4934  		case iSCSINameIqnDateFormatError:
4935  			(void) fprintf(stderr, "%s: %s\n",
4936  			    cmdName, gettext("invalid iqn date." \
4937  			    "  format is: YYYY-MM"));
4938  			break;
4939  		case iSCSINameIqnSubdomainFormatError:
4940  			(void) fprintf(stderr, "%s: %s\n",
4941  			    cmdName, gettext("missing subdomain after \":\""));
4942  			break;
4943  		case iSCSINameIqnInvalidYearError:
4944  			(void) fprintf(stderr, "%s: %s\n",
4945  			    cmdName, gettext("invalid year"));
4946  			break;
4947  		case iSCSINameIqnInvalidMonthError:
4948  			(void) fprintf(stderr, "%s: %s\n",
4949  			    cmdName, gettext("invalid month"));
4950  			break;
4951  		case iSCSINameIqnFQDNError:
4952  			(void) fprintf(stderr, "%s: %s\n",
4953  			    cmdName, gettext("missing reversed fully qualified"\
4954  			    " domain name"));
4955  			break;
4956  		case iSCSINameEUIFormatError:
4957  			(void) fprintf(stderr, "%s: %s\n", cmdName,
4958  			    gettext("eui formatting error."));
4959  			break;
4960  	}
4961  }
4962  
4963  /*
4964   * A convenient function to modify the target parameters of an individual
4965   * target.
4966   *
4967   * Return 0 if successful
4968   * Return 1 if failed
4969   */
4970  static int
modifyIndividualTargetParam(cmdOptions_t * optionList,IMA_OID targetOid,int * funcRet)4971  modifyIndividualTargetParam(cmdOptions_t *optionList, IMA_OID targetOid,
4972      int *funcRet)
4973  {
4974  	assert(funcRet != NULL);
4975  
4976  	for (; optionList->optval; optionList++) {
4977  		switch (optionList->optval) {
4978  			case 'a':
4979  				if (modifyTargetAuthMethod(targetOid,
4980  				    optionList->optarg, funcRet) != 0) {
4981  					return (1);
4982  				}
4983  				break;
4984  			case 'B':
4985  				if (modifyTargetBidirAuthFlag(targetOid,
4986  				    optionList->optarg, funcRet) != 0) {
4987  					return (1);
4988  				}
4989  				break;
4990  			case 'C':
4991  				if (modifyTargetAuthParam(targetOid,
4992  				    AUTH_PASSWORD, NULL, funcRet) != 0) {
4993  					return (1);
4994  				}
4995  				break;
4996  			case 'd':
4997  				if (setLoginParameter(targetOid, DATA_DIGEST,
4998  				    optionList->optarg) != 0) {
4999  					return (1);
5000  				}
5001  				break;
5002  			case 'h':
5003  				if (setLoginParameter(targetOid, HEADER_DIGEST,
5004  				    optionList->optarg) != 0) {
5005  					return (1);
5006  				}
5007  				break;
5008  			case 'p':
5009  				/* Login parameter */
5010  				if (setLoginParameters(targetOid,
5011  				    optionList->optarg) != 0) {
5012  					return (1);
5013  				}
5014  				break;
5015  			case 'c':
5016  				/* Modify configure sessions */
5017  				if (modifyConfiguredSessions(targetOid,
5018  				    optionList->optarg) != 0) {
5019  					return (1);
5020  				}
5021  				break;
5022  			case 'H':
5023  				if (modifyTargetAuthParam(targetOid, AUTH_NAME,
5024  				    optionList->optarg, funcRet) != 0) {
5025  					return (1);
5026  				}
5027  				break;
5028  			case 'T':
5029  				if (setTunableParameters(targetOid,
5030  				    optionList->optarg) != 0) {
5031  					return (1);
5032  				}
5033  				break;
5034  		}
5035  	}
5036  
5037  	return (0);
5038  }
5039  
5040  /*
5041   * This helper function could go into a utility module for general use.
5042   */
5043  static int
parseAddress(char * address_port_str,uint16_t defaultPort,char * address_str,size_t address_str_len,uint16_t * port,boolean_t * isIpv6)5044  parseAddress(char *address_port_str,
5045      uint16_t defaultPort,
5046      char *address_str,
5047      size_t address_str_len,
5048      uint16_t *port,
5049      boolean_t *isIpv6)
5050  {
5051  	char port_str[64];
5052  	int tmp_port;
5053  	char *errchr;
5054  
5055  	if (address_port_str[0] == '[') {
5056  		/* IPv6 address */
5057  		char *close_bracket_pos;
5058  		close_bracket_pos = strchr(address_port_str, ']');
5059  		if (!close_bracket_pos) {
5060  			syslog(LOG_USER|LOG_DEBUG,
5061  			    "IP address format error: %s\n", address_str);
5062  			return (PARSE_ADDR_MISSING_CLOSING_BRACKET);
5063  		}
5064  
5065  		*close_bracket_pos = '\0';
5066  		(void) strlcpy(address_str, &address_port_str[1],
5067  		    address_str_len);
5068  
5069  		/* Extract the port number */
5070  		close_bracket_pos++;
5071  		if (*close_bracket_pos == ':') {
5072  			close_bracket_pos++;
5073  			if (*close_bracket_pos != '\0') {
5074  				(void) strlcpy(port_str, close_bracket_pos, 64);
5075  				tmp_port = strtol(port_str, &errchr, 10);
5076  				if (tmp_port == 0 && errchr != NULL) {
5077  					(void) fprintf(stderr, "%s: %s:%s %s\n",
5078  					    cmdName, address_str,
5079  					    close_bracket_pos,
5080  					    gettext("port number invalid"));
5081  					return (PARSE_ADDR_PORT_OUT_OF_RANGE);
5082  				}
5083  				if ((tmp_port > 0) && (tmp_port > USHRT_MAX) ||
5084  				    (tmp_port < 0)) {
5085  					/* Port number out of range */
5086  					syslog(LOG_USER|LOG_DEBUG,
5087  					    "Specified port out of range: %d",
5088  					    tmp_port);
5089  					return (PARSE_ADDR_PORT_OUT_OF_RANGE);
5090  				} else {
5091  					*port = (uint16_t)tmp_port;
5092  				}
5093  			} else {
5094  				*port = defaultPort;
5095  			}
5096  		} else {
5097  			*port = defaultPort;
5098  		}
5099  
5100  		*isIpv6 = B_TRUE;
5101  	} else {
5102  		/* IPv4 address */
5103  		char *colon_pos;
5104  		colon_pos = strchr(address_port_str, ':');
5105  		if (!colon_pos) {
5106  			/* No port number specified. */
5107  			*port = defaultPort;
5108  			(void) strlcpy(address_str, address_port_str,
5109  			    address_str_len);
5110  		} else {
5111  			*colon_pos = '\0';
5112  			(void) strlcpy(address_str, address_port_str,
5113  			    address_str_len);
5114  
5115  			/* Extract the port number */
5116  			colon_pos++;
5117  			if (*colon_pos != '\0') {
5118  
5119  				(void) strlcpy(port_str, colon_pos, 64);
5120  				tmp_port = strtol(port_str, &errchr, 10);
5121  				if (tmp_port == 0 && errchr != NULL) {
5122  					(void) fprintf(stderr, "%s: %s:%s %s\n",
5123  					    cmdName, address_str, colon_pos,
5124  					    gettext("port number invalid"));
5125  					return (PARSE_ADDR_PORT_OUT_OF_RANGE);
5126  				}
5127  				if ((tmp_port > 0) && (tmp_port > USHRT_MAX) ||
5128  				    (tmp_port < 0)) {
5129  					/* Port number out of range */
5130  					syslog(LOG_USER|LOG_DEBUG,
5131  					    "Specified port out of range: %d",
5132  					    tmp_port);
5133  					return (PARSE_ADDR_PORT_OUT_OF_RANGE);
5134  				} else {
5135  					*port = (uint16_t)tmp_port;
5136  				}
5137  			} else {
5138  				*port = defaultPort;
5139  			}
5140  		}
5141  
5142  		*isIpv6 = B_FALSE;
5143  	}
5144  
5145  	return (PARSE_ADDR_OK);
5146  }
5147  
5148  /*
5149   * This helper function could go into a utility module for general use.
5150   */
5151  iSCSINameCheckStatusType
iSCSINameStringProfileCheck(wchar_t * name)5152  iSCSINameStringProfileCheck(wchar_t *name)
5153  {
5154  	char mb_name[MAX_ISCSI_NAME_LEN + 1];
5155  	size_t name_len;
5156  	char *tmp;
5157  
5158  	(void) wcstombs(mb_name, name, MAX_ISCSI_NAME_LEN + 1);
5159  
5160  	if ((name_len = strlen(mb_name)) == 0) {
5161  		return (iSCSINameLenZero);
5162  	} else if (name_len > MAX_ISCSI_NAME_LEN) {
5163  		return (iSCSINameLenExceededMax);
5164  	}
5165  
5166  	/*
5167  	 * check for invalid characters
5168  	 * According to RFC 3722 iSCSI name must be either a letter,
5169  	 * a digit or one of the following '-' '.' ':'
5170  	 */
5171  	for (tmp = mb_name; *tmp != '\0'; tmp++) {
5172  		if ((isalnum(*tmp) == 0) &&
5173  		    (*tmp != '-') &&
5174  		    (*tmp != '.') &&
5175  		    (*tmp != ':')) {
5176  			return (iSCSINameInvalidCharacter);
5177  		}
5178  	}
5179  
5180  	if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX,
5181  	    strlen(ISCSI_IQN_NAME_PREFIX)) == 0) {
5182  		/*
5183  		 * If name is of type iqn, check date string and naming
5184  		 * authority.
5185  		 */
5186  		char *strp = NULL;
5187  
5188  		/*
5189  		 * Don't allow the string to end with a colon.  If there is a
5190  		 * colon then there must be a subdomain provided.
5191  		 */
5192  		if (mb_name[strlen(mb_name) - 1] == ':') {
5193  			return (iSCSINameIqnSubdomainFormatError);
5194  		}
5195  
5196  		/* Date string */
5197  		strp = strtok(&mb_name[3], ".");
5198  		if (strp) {
5199  			char tmpYear[5], tmpMonth[3], *endPtr = NULL;
5200  			int year, month;
5201  
5202  			/* Date string should be in YYYY-MM format */
5203  			if (strlen(strp) != strlen("YYYY-MM") ||
5204  			    strp[4] != '-') {
5205  				return (iSCSINameIqnDateFormatError);
5206  			}
5207  
5208  			/*
5209  			 * Validate year.  Only validating that the
5210  			 * year can be converted to a number.  No
5211  			 * validation will be done on year's actual
5212  			 * value.
5213  			 */
5214  			(void) strncpy(tmpYear, strp, 4);
5215  			tmpYear[4] = '\0';
5216  
5217  			errno = 0;
5218  			year = strtol(tmpYear, &endPtr, 10);
5219  			if (errno != 0 || *endPtr != '\0' ||
5220  			    year < 0 || year > 9999) {
5221  				return (iSCSINameIqnInvalidYearError);
5222  			}
5223  
5224  			/*
5225  			 * Validate month is valid.
5226  			 */
5227  			(void) strncpy(tmpMonth, &strp[5], 2);
5228  			tmpMonth[2] = '\0';
5229  			errno = 0;
5230  			month = strtol(tmpMonth, &endPtr, 10);
5231  
5232  			if (errno != 0 || *endPtr != '\0' ||
5233  			    month < 1 || month > 12) {
5234  				return (iSCSINameIqnInvalidMonthError);
5235  			}
5236  
5237  			/*
5238  			 * A reversed FQDN needs to be provided.  We
5239  			 * will only check for a "." followed by more
5240  			 * than two or more characters.  The list of domains is
5241  			 * too large and changes too frequently to
5242  			 * add validation for.
5243  			 */
5244  			strp = strtok(NULL, ".");
5245  			if (!strp || strlen(strp) < 2) {
5246  				return (iSCSINameIqnFQDNError);
5247  			}
5248  
5249  			/* Name authority string */
5250  			strp = strtok(NULL, ":");
5251  			if (strp) {
5252  				return (iSCSINameCheckOK);
5253  			} else {
5254  				return (iSCSINameIqnFQDNError);
5255  			}
5256  		} else {
5257  			return (iSCSINameIqnFormatError);
5258  		}
5259  	} else if (strncmp(mb_name, ISCSI_EUI_NAME_PREFIX,
5260  	    strlen(ISCSI_EUI_NAME_PREFIX)) == 0) {
5261  		/* If name is of type EUI, change its length */
5262  
5263  		if (strlen(mb_name) != ISCSI_EUI_NAME_LEN) {
5264  			return (iSCSINameEUIFormatError);
5265  		}
5266  
5267  		for (tmp = mb_name + strlen(ISCSI_EUI_NAME_PREFIX) + 1;
5268  		    *tmp != '\0'; tmp++) {
5269  			if (isxdigit(*tmp)) {
5270  				continue;
5271  			}
5272  			return (iSCSINameEUIFormatError);
5273  		}
5274  
5275  		return (iSCSINameCheckOK);
5276  	} else {
5277  		return (iSCSINameUnknownType);
5278  	}
5279  }
5280  
5281  /*
5282   * This helper function could go into a utility module for general use.
5283   *
5284   * Returns:
5285   * B_TRUE is the numberStr is an unsigned natural number and within the
5286   * specified bound.
5287   * B_FALSE otherwise.
5288   */
5289  boolean_t
isNaturalNumber(char * numberStr,uint32_t upperBound)5290  isNaturalNumber(char *numberStr, uint32_t upperBound)
5291  {
5292  	int i;
5293  	int number_str_len;
5294  
5295  	if ((number_str_len = strlen(numberStr)) == 0) {
5296  		return (B_FALSE);
5297  	}
5298  
5299  	for (i = 0; i < number_str_len; i++) {
5300  		if (numberStr[i] < 060 || numberStr[i] > 071) {
5301  			return (B_FALSE);
5302  		}
5303  	}
5304  
5305  	if (atoi(numberStr) > upperBound) {
5306  		return (B_FALSE);
5307  	}
5308  
5309  	return (B_TRUE);
5310  }
5311  
5312  /*
5313   * This helper function could go into a utility module for general use.
5314   * It parses a target string in the format of:
5315   *
5316   *	<target_name>,[<ip_address>[:port][,tpgt]]
5317   *
5318   * and creates wchar strings for target name and target address. It
5319   * also populates port and tpgt if found.
5320   *
5321   * Returns:
5322   *	PARSE_TARGET_OK if parsing is successful.
5323   *	PARSE_TARGET_INVALID_TPGT if the specified tpgt is
5324   *	invalid.
5325   *	PARSE_TARGET_INVALID_ADDR if the address specified is
5326   *	invalid.
5327   */
5328  int
parseTarget(char * targetStr,wchar_t * targetNameStr,size_t targetNameStrLen,boolean_t * targetAddressSpecified,wchar_t * targetAddressStr,size_t targetAddressStrLen,uint16_t * port,boolean_t * tpgtSpecified,uint16_t * tpgt,boolean_t * isIpv6)5329  parseTarget(char *targetStr, wchar_t *targetNameStr, size_t targetNameStrLen,
5330      boolean_t *targetAddressSpecified, wchar_t *targetAddressStr,
5331      size_t targetAddressStrLen, uint16_t *port, boolean_t *tpgtSpecified,
5332      uint16_t *tpgt, boolean_t *isIpv6)
5333  {
5334  	char *commaPos;
5335  	char *commaPos2;
5336  	char targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
5337  	int i;
5338  	int lowerCase;
5339  
5340  	(void) memset(targetNameStr, 0,
5341  	    targetNameStrLen * sizeof (wchar_t));
5342  	(void) memset(targetAddressStr, 0,
5343  	    targetAddressStrLen * sizeof (wchar_t));
5344  
5345  	commaPos = strchr(targetStr, ',');
5346  	if (commaPos != NULL) {
5347  		*commaPos = '\0';
5348  		commaPos++;
5349  		*targetAddressSpecified = B_TRUE;
5350  
5351  		/*
5352  		 * Checking of tpgt makes sense only when
5353  		 * the target address/port are specified.
5354  		 */
5355  		commaPos2 = strchr(commaPos, ',');
5356  		if (commaPos2 != NULL) {
5357  			*commaPos2 = '\0';
5358  			commaPos2++;
5359  			if (isNaturalNumber(commaPos2, ISCSI_MAX_TPGT_VALUE) ==
5360  			    B_TRUE) {
5361  				*tpgt = atoi(commaPos2);
5362  				*tpgtSpecified = B_TRUE;
5363  			} else {
5364  				(void) fprintf(stderr, "%s: %s\n", cmdName,
5365  				    gettext("parse target invalid TPGT"));
5366  				return (PARSE_TARGET_INVALID_TPGT);
5367  			}
5368  		}
5369  
5370  		switch (parseAddress(commaPos, ISCSI_LISTEN_PORT,
5371  		    &targetAddress[0], MAX_ADDRESS_LEN + 1, port, isIpv6)) {
5372  		case PARSE_ADDR_PORT_OUT_OF_RANGE:
5373  			return (PARSE_TARGET_INVALID_ADDR);
5374  		case PARSE_ADDR_OK:
5375  			break;
5376  		default:
5377  			(void) fprintf(stderr, "%s: %s\n",
5378  			    cmdName, gettext("cannot parse target name"));
5379  			return (PARSE_TARGET_INVALID_ADDR);
5380  		}
5381  		(void) mbstowcs(targetAddressStr, targetAddress,
5382  		    targetAddressStrLen);
5383  		for (i = 0; targetAddressStr[i] != 0; i++) {
5384  			lowerCase = tolower(targetAddressStr[i]);
5385  			targetAddressStr[i] = lowerCase;
5386  		}
5387  	} else {
5388  		*targetAddressSpecified = B_FALSE;
5389  		*tpgtSpecified = B_FALSE;
5390  	}
5391  
5392  	(void) mbstowcs(targetNameStr, targetStr, targetNameStrLen);
5393  	for (i = 0; targetNameStr[i] != 0; i++) {
5394  		lowerCase = tolower(targetNameStr[i]);
5395  		targetNameStr[i] = lowerCase;
5396  	}
5397  
5398  	return (PARSE_TARGET_OK);
5399  }
5400  
5401  /*ARGSUSED*/
5402  static void
listCHAPName(IMA_OID oid)5403  listCHAPName(IMA_OID oid)
5404  {
5405  	IMA_INITIATOR_AUTHPARMS authParams;
5406  	IMA_STATUS status;
5407  	IMA_BYTE chapName [MAX_CHAP_NAME_LEN + 1];
5408  
5409  	/* Get Chap Name depending upon oid object type */
5410  	if (oid.objectType == IMA_OBJECT_TYPE_LHBA) {
5411  		status = IMA_GetInitiatorAuthParms(oid,
5412  		    IMA_AUTHMETHOD_CHAP, &authParams);
5413  	} else {
5414  		status = SUN_IMA_GetTargetAuthParms(oid,
5415  		    IMA_AUTHMETHOD_CHAP, &authParams);
5416  	}
5417  
5418  	(void) fprintf(stdout, "\n\t\t%s: ", gettext("CHAP Name"));
5419  
5420  	if (IMA_SUCCESS(status)) {
5421  		/*
5422  		 * Default chap name will be the node name.  The default will
5423  		 * be set by the driver.
5424  		 */
5425  		if (authParams.chapParms.nameLength != 0) {
5426  			(void) memset(chapName, 0, sizeof (chapName));
5427  			(void) memcpy(chapName, authParams.chapParms.name,
5428  			    authParams.chapParms.nameLength);
5429  			(void) fprintf(stdout, "%s", chapName);
5430  
5431  		} else {
5432  			(void) fprintf(stdout, "%s", "-");
5433  		}
5434  	} else {
5435  		(void) fprintf(stdout, "%s", "-");
5436  	}
5437  }
5438  
5439  static boolean_t
checkServiceStatus(void)5440  checkServiceStatus(void)
5441  {
5442  	IMA_STATUS	status	=	IMA_ERROR_UNKNOWN_ERROR;
5443  	IMA_BOOL	enabled =	0;
5444  
5445  	status = SUN_IMA_GetSvcStatus(&enabled);
5446  
5447  	if (status != IMA_STATUS_SUCCESS) {
5448  		(void) fprintf(stdout, "%s\n%s\n",
5449  		    gettext("Unable to query the service status of"
5450  		    " iSCSI initiator."),
5451  		    gettext("For more information, please refer to"
5452  		    " iscsi(4D)."));
5453  		return (B_FALSE);
5454  	}
5455  
5456  	if (enabled == 0) {
5457  		(void) fprintf(stdout, "%s\n%s\n",
5458  		    gettext("iSCSI Initiator Service is disabled,"
5459  		    " try 'svcadm enable network/iscsi/initiator' to"
5460  		    " enable the service."),
5461  		    gettext("For more information, please refer to"
5462  		    " iscsi(4D)."));
5463  		return (B_FALSE);
5464  	}
5465  
5466  	return (B_TRUE);
5467  }
5468  
5469  /*
5470   * Prints out see manual page.
5471   * Called out through atexit(3C) so is always last thing displayed.
5472   */
5473  void
seeMan(void)5474  seeMan(void)
5475  {
5476  	static int sent = 0;
5477  
5478  	if (sent)
5479  		return;
5480  
5481  	(void) fprintf(stdout, "%s %s(8)\n",
5482  	    gettext("For more information, please see"), cmdName);
5483  
5484  	sent = 1;
5485  }
5486  
5487  
5488  /*
5489   * main calls a parser that checks syntax of the input command against
5490   * various rules tables.
5491   *
5492   * The parser provides usage feedback based upon same tables by calling
5493   * two usage functions, usage and subUsage, handling command and subcommand
5494   * usage respectively.
5495   *
5496   * The parser handles all printing of usage syntactical errors
5497   *
5498   * When syntax is successfully validated, the parser calls the associated
5499   * function using the subcommands table functions.
5500   *
5501   * Syntax is as follows:
5502   *	command subcommand [options] resource-type [<object>]
5503   *
5504   * The return value from the function is placed in funcRet
5505   */
5506  int
main(int argc,char * argv[])5507  main(int argc, char *argv[])
5508  {
5509  	synTables_t synTables;
5510  	char versionString[VERSION_STRING_MAX_LEN];
5511  	int ret;
5512  	int funcRet = 0;
5513  	void *subcommandArgs = NULL;
5514  
5515  	if (geteuid() != 0) {
5516  		(void) fprintf(stderr, "%s\n", gettext("permission denied"));
5517  		return (1);
5518  	}
5519  
5520  	if (checkServiceStatus() == B_FALSE) {
5521  		return (1);
5522  	}
5523  
5524  	/* set global command name */
5525  	cmdName = getExecBasename(argv[0]);
5526  
5527  	(void) snprintf(versionString, sizeof (versionString), "%s.%s",
5528  	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
5529  	synTables.versionString = versionString;
5530  	synTables.longOptionTbl = &longOptions[0];
5531  	synTables.subcommandTbl = &subcommands[0];
5532  	synTables.objectTbl = &objects[0];
5533  	synTables.objectRulesTbl = &objectRules[0];
5534  	synTables.optionRulesTbl = &optionRules[0];
5535  
5536  	/* call the CLI parser */
5537  	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
5538  	if (ret == -1) {
5539  		perror(cmdName);
5540  		ret = 1;
5541  	}
5542  
5543  	if (funcRet != 0) {
5544  		(void) fprintf(stderr, "%s: %s\n",
5545  		    cmdName, gettext("Unable to complete operation"));
5546  		ret = 1;
5547  	}
5548  	return (ret);
5549  }
5550  
5551  static int
setTunableParameters(IMA_OID oid,char * optarg)5552  setTunableParameters(IMA_OID oid, char *optarg)
5553  {
5554  	char keyp[MAXOPTARGLEN];
5555  	char valp[MAXOPTARGLEN];
5556  	int key;
5557  	IMA_STATUS status;
5558  	IMA_UINT uintValue;
5559  	ISCSI_TUNABLE_PARAM	tunableObj;
5560  	char *nameValueString, *endptr;
5561  
5562  	if ((nameValueString = strdup(optarg)) == NULL) {
5563  		if (errno == ENOMEM) {
5564  			(void) fprintf(stderr, "%s: %s\n",
5565  			    cmdName, strerror(errno));
5566  		} else {
5567  			(void) fprintf(stderr, "%s: %s\n", cmdName,
5568  			    gettext("unknown error"));
5569  		}
5570  		return (1);
5571  	}
5572  
5573  	(void) memset(keyp, 0, sizeof (keyp));
5574  	(void) memset(valp, 0, sizeof (valp));
5575  	if (sscanf(nameValueString, gettext("%[^=]=%s"), keyp, valp) != 2) {
5576  		(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
5577  		    gettext("Unknown param"), nameValueString);
5578  		if (nameValueString) {
5579  			free(nameValueString);
5580  			nameValueString = NULL;
5581  		}
5582  		return (1);
5583  	}
5584  	if ((key = getTunableParam(keyp)) == -1) {
5585  		(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
5586  		    gettext("Unknown key"), keyp);
5587  		if (nameValueString) {
5588  			free(nameValueString);
5589  			nameValueString = NULL;
5590  		}
5591  		return (1);
5592  	}
5593  	switch (key) {
5594  	case RECV_LOGIN_RSP_TIMEOUT:
5595  	case CONN_LOGIN_MAX:
5596  	case POLLING_LOGIN_DELAY:
5597  		errno = 0;
5598  		uintValue = strtoul(valp, &endptr, 0);
5599  		if (*endptr != '\0' || errno != 0) {
5600  			(void) fprintf(stderr, "%s: %s - %s\n",
5601  			    cmdName,
5602  			    gettext("invalid option argument"),
5603  			    optarg);
5604  			if (nameValueString) {
5605  				free(nameValueString);
5606  				nameValueString = NULL;
5607  			}
5608  			return (1);
5609  		}
5610  		if (uintValue > 3600) {
5611  			(void) fprintf(stderr, "%s: %s\n",
5612  			    cmdName,
5613  gettext("value must be between 0 and 3600"));
5614  			if (nameValueString) {
5615  				free(nameValueString);
5616  				nameValueString = NULL;
5617  			}
5618  			return (1);
5619  		}
5620  
5621  		if (chkConnLoginMaxPollingLoginDelay(oid, key, uintValue) > 0) {
5622  			if (nameValueString) {
5623  				free(nameValueString);
5624  				nameValueString = NULL;
5625  			}
5626  			return (1);
5627  		}
5628  
5629  		if (key == RECV_LOGIN_RSP_TIMEOUT) {
5630  			tunableObj.tunable_objectType =
5631  			    ISCSI_RX_TIMEOUT_VALUE;
5632  		} else if (key == CONN_LOGIN_MAX) {
5633  			tunableObj.tunable_objectType =
5634  			    ISCSI_CONN_DEFAULT_LOGIN_MAX;
5635  		} else if (key == POLLING_LOGIN_DELAY) {
5636  			tunableObj.tunable_objectType =
5637  			    ISCSI_LOGIN_POLLING_DELAY;
5638  		}
5639  		tunableObj.tunable_objectValue = valp;
5640  		status = SUN_IMA_SetTunableProperties(oid, &tunableObj);
5641  		break;
5642  	default:
5643  		(void) fprintf(stderr, "%s: %s: %s\n", cmdName,
5644  		    gettext("Unsupported key"), keyp);
5645  		if (nameValueString) {
5646  			free(nameValueString);
5647  			nameValueString = NULL;
5648  		}
5649  		return (1);
5650  	}
5651  	if (!IMA_SUCCESS(status)) {
5652  		printLibError(status);
5653  		if (nameValueString) {
5654  			free(nameValueString);
5655  			nameValueString = NULL;
5656  		}
5657  		return (1);
5658  	}
5659  
5660  	if (nameValueString) {
5661  		free(nameValueString);
5662  		nameValueString = NULL;
5663  	}
5664  	return (0);
5665  }
5666  
5667  /*
5668   * Print tunable parameters information
5669   */
5670  static int
printTunableParameters(IMA_OID oid)5671  printTunableParameters(IMA_OID oid)
5672  {
5673  	ISCSI_TUNABLE_PARAM tunableObj;
5674  	char value[MAXOPTARGLEN] = "\0";
5675  	IMA_STATUS status;
5676  
5677  	tunableObj.tunable_objectValue = value;
5678  	(void) fprintf(stdout, "\t%s:\n",
5679  	    gettext("Tunable Parameters (Default/Configured)"));
5680  	tunableObj.tunable_objectType = ISCSI_RX_TIMEOUT_VALUE;
5681  	status = SUN_IMA_GetTunableProperties(oid, &tunableObj);
5682  	if (!IMA_SUCCESS(status)) {
5683  		printLibError(status);
5684  		return (1);
5685  	}
5686  	if (value[0] == '\0') {
5687  		value[0] = '-';
5688  		value[1] = '\0';
5689  	}
5690  	(void) fprintf(stdout, "\t\t%s: ",
5691  	    gettext("Session Login Response Time"));
5692  	(void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_RX_TIMEOUT_VALUE,
5693  	    tunableObj.tunable_objectValue);
5694  
5695  	value[0] = '\0';
5696  	tunableObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX;
5697  	status = SUN_IMA_GetTunableProperties(oid, &tunableObj);
5698  	if (!IMA_SUCCESS(status)) {
5699  		printLibError(status);
5700  		return (1);
5701  	}
5702  	if (value[0] == '\0') {
5703  		value[0] = '-';
5704  		value[1] = '\0';
5705  	}
5706  	(void) fprintf(stdout, "\t\t%s: ",
5707  	    gettext("Maximum Connection Retry Time"));
5708  	(void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX,
5709  	    tunableObj.tunable_objectValue);
5710  
5711  	value[0] = '\0';
5712  	tunableObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY;
5713  	status = SUN_IMA_GetTunableProperties(oid, &tunableObj);
5714  	if (!IMA_SUCCESS(status)) {
5715  		printLibError(status);
5716  		return (1);
5717  	}
5718  	if (value[0] == '\0') {
5719  		value[0] = '-';
5720  		value[1] = '\0';
5721  	}
5722  	(void) fprintf(stdout, "\t\t%s: ",
5723  	    gettext("Login Retry Time Interval"));
5724  	(void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_LOGIN_POLLING_DELAY,
5725  	    tunableObj.tunable_objectValue);
5726  	return (0);
5727  }
5728  
5729  /*
5730   * This is helper function to check conn_login_max and polling_login_delay.
5731   */
5732  static int
chkConnLoginMaxPollingLoginDelay(IMA_OID oid,int key,int uintValue)5733  chkConnLoginMaxPollingLoginDelay(IMA_OID oid, int key, int uintValue)
5734  {
5735  	char valuep[MAXOPTARGLEN];
5736  	IMA_STATUS	status;
5737  	IMA_UINT	getValue;
5738  	ISCSI_TUNABLE_PARAM	getObj;
5739  	char *endptr;
5740  
5741  	if (key == CONN_LOGIN_MAX) {
5742  		getObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY;
5743  	} else if (key == POLLING_LOGIN_DELAY) {
5744  		getObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX;
5745  	} else {
5746  		return (0);
5747  	}
5748  	valuep[0] = '\0';
5749  	getObj.tunable_objectValue = valuep;
5750  	status = SUN_IMA_GetTunableProperties(oid, &getObj);
5751  	if (!IMA_SUCCESS(status)) {
5752  		printLibError(status);
5753  		return (1);
5754  	}
5755  	if (valuep[0] == '\0') {
5756  		if (key == CONN_LOGIN_MAX) {
5757  			(void) strlcpy(valuep,
5758  			    ISCSI_DEFAULT_LOGIN_POLLING_DELAY,
5759  			    strlen(ISCSI_DEFAULT_LOGIN_POLLING_DELAY) +1);
5760  		} else {
5761  			(void) strlcpy(valuep,
5762  			    ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX,
5763  			    strlen(ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX) +1);
5764  		}
5765  	}
5766  
5767  	errno = 0;
5768  	getValue = strtoul(valuep, &endptr, 0);
5769  	if (*endptr != '\0' || errno != 0) {
5770  		(void) fprintf(stderr, "%s: %s - %s\n",
5771  		    cmdName,
5772  		    gettext("cannot convert tunable string"),
5773  		    valuep);
5774  		return (1);
5775  	}
5776  	if (key == CONN_LOGIN_MAX) {
5777  		if (uintValue < getValue) {
5778  			(void) fprintf(stderr, "%s: %s %ld\n",
5779  			    cmdName, gettext("value must larger than"),
5780  			    getValue);
5781  			return (1);
5782  		}
5783  	} else {
5784  		if (uintValue > getValue) {
5785  			(void) fprintf(stderr, "%s: %s %ld\n",
5786  			    cmdName, gettext("value must smaller than"),
5787  			    getValue);
5788  			return (1);
5789  		}
5790  	}
5791  	return (0);
5792  }
5793