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(