summaryrefslogtreecommitdiff
path: root/usr/src/cmd/iscsiadm/iscsiadm_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/iscsiadm/iscsiadm_main.c')
-rw-r--r--usr/src/cmd/iscsiadm/iscsiadm_main.c5145
1 files changed, 5145 insertions, 0 deletions
diff --git a/usr/src/cmd/iscsiadm/iscsiadm_main.c b/usr/src/cmd/iscsiadm/iscsiadm_main.c
new file mode 100644
index 0000000000..99ac43e7a2
--- /dev/null
+++ b/usr/src/cmd/iscsiadm/iscsiadm_main.c
@@ -0,0 +1,5145 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <widec.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <limits.h>
+#include <string.h>
+#include <strings.h>
+#include <syslog.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <wctype.h>
+#include <assert.h>
+
+#include <ima.h>
+#include <sys/scsi/adapters/iscsi_protocol.h>
+#include <sys/scsi/adapters/iscsi_if.h>
+
+#include "cmdparse.h"
+#include "sun_ima.h"
+#include "iscsiadm.h"
+
+#define VERSION_STRING_MAX_LEN 10
+#define MAX_LONG_CHAR_LEN 19
+
+#define MAX_AUTH_METHODS 5
+/*
+ * Version number:
+ * MAJOR - This should only change when there is an incompatible change made
+ * to the interfaces or the output.
+ *
+ * MINOR - This should change whenever there is a new command or new feature
+ * with no incompatible change.
+ */
+#define VERSION_STRING_MAJOR "1"
+#define VERSION_STRING_MINOR "0"
+
+#define OPTIONSTRING1 "yes|no"
+#define OPTIONSTRING2 "initiator node name"
+#define OPTIONSTRING3 "initiator node alias"
+#define OPTIONSTRING4 "enable|disable"
+#define OPTIONSTRING5 "key=value,..."
+#define OPTIONSTRING6 "none|CRC32"
+#define OPTIONSTRING7 "CHAP name"
+#define OPTIONSTRING8 "<# sessions>|<IP Address>[,<IP Address>]*"
+#define OPTIONVAL1 "0 to 3600"
+#define OPTIONVAL2 "512 to 2**24 - 1"
+#define OPTIONVAL3 "1 to 65535"
+#define OPTIONVAL4 "<IP address>[:port]"
+
+#define MAX_ISCSI_NAME_LEN 223
+#define MAX_ADDRESS_LEN 255
+#define MIN_CHAP_SECRET_LEN 12
+#define MAX_CHAP_SECRET_LEN 16
+#define DEFAULT_ISCSI_PORT 3260
+#define ISNS_DEFAULT_SERVER_PORT 3205
+#define DEFAULT_RADIUS_PORT 1812
+#define MAX_CHAP_NAME_LEN 512
+
+/* For listNode */
+#define INF_ERROR 1
+#define INVALID_NODE_NAME 2
+
+#define IMABOOLPRINT(prop, option) \
+ if ((option) == PRINT_CONFIGURED_PARAMS) { \
+ (void) fprintf(stdout, "%s/%s\n", \
+ (prop).defaultValue == IMA_TRUE ? gettext("yes") : \
+ gettext("no"), \
+ (prop).currentValueValid == IMA_TRUE ? \
+ ((prop).currentValue == IMA_TRUE ? \
+ gettext("yes"): gettext("no")) : "-"); \
+ } else if ((option) == PRINT_NEGOTIATED_PARAMS) { \
+ (void) fprintf(stdout, "%s\n", \
+ (prop).currentValueValid == IMA_TRUE ? \
+ (((prop).currentValue == IMA_TRUE) ? gettext("yes") : \
+ gettext("no")) : "-"); \
+ }
+
+#define IMAMINMAXPRINT(prop, option) \
+ if ((option) == PRINT_CONFIGURED_PARAMS) { \
+ (void) fprintf(stdout, "%d/", (prop).defaultValue); \
+ if ((prop).currentValueValid == IMA_TRUE) { \
+ (void) fprintf(stdout, "%d\n", (prop).currentValue); \
+ } else if ((prop).currentValueValid == IMA_FALSE) { \
+ (void) fprintf(stdout, "%s\n", "-"); \
+ } \
+ } else if ((option) == PRINT_NEGOTIATED_PARAMS) { \
+ if ((prop).currentValueValid == IMA_TRUE) { \
+ (void) fprintf(stdout, "%d\n", (prop).currentValue); \
+ } else if ((prop).currentValueValid == IMA_FALSE) { \
+ (void) fprintf(stdout, "%s\n", "-"); \
+ } \
+ }
+
+/* forward declarations */
+#define PARSE_ADDR_OK 0
+#define PARSE_ADDR_MISSING_CLOSING_BRACKET 1
+#define PARSE_ADDR_PORT_OUT_OF_RANGE 2
+#define PARSE_TARGET_OK 0
+#define PARSE_TARGET_INVALID_TPGT 1
+#define PARSE_TARGET_INVALID_ADDR 2
+
+#define PRINT_CONFIGURED_PARAMS 1
+#define PRINT_NEGOTIATED_PARAMS 2
+
+typedef enum iSCSINameCheckStatus {
+ iSCSINameCheckOK,
+ iSCSINameLenZero,
+ iSCSINameLenExceededMax,
+ iSCSINameUnknownType,
+ iSCSINameInvalidCharacter,
+ iSCSINameIqnFormatError,
+ iSCSINameEUIFormatError,
+ iSCSINameIqnDateFormatError,
+ iSCSINameIqnSubdomainFormatError,
+ iSCSINameIqnInvalidYearError,
+ iSCSINameIqnInvalidMonthError,
+ iSCSINameIqnFQDNError
+} iSCSINameCheckStatusType;
+
+/* Utility functions */
+iSCSINameCheckStatusType iSCSINameStringProfileCheck(wchar_t *name);
+boolean_t isNaturalNumber(char *numberStr, uint32_t upperBound);
+static int parseAddress(char *address_port_str, uint16_t defaultPort,
+ char *address_str, size_t address_str_len,
+ uint16_t *port, boolean_t *isIpv6);
+int parseTarget(char *targetStr,
+ wchar_t *targetNameStr,
+ size_t targetNameStrLen,
+ boolean_t *targetAddressSpecified,
+ wchar_t *targetAddressStr,
+ size_t targetAddressStrLen,
+ uint16_t *port,
+ boolean_t *tpgtSpecified,
+ uint16_t *tpgt,
+ boolean_t *isIpv6);
+
+/* subcommand functions */
+static int addFunc(int, char **, int, cmdOptions_t *, void *, int *);
+static int listFunc(int, char **, int, cmdOptions_t *, void *, int *);
+static int modifyFunc(int, char **, int, cmdOptions_t *, void *, int *);
+static int removeFunc(int, char **, int, cmdOptions_t *, void *, int *);
+
+/* helper functions */
+static char *getExecBasename(char *);
+static int getNodeProps(IMA_NODE_PROPERTIES *);
+static int getSecret(char *, int *, int, int);
+static int getTargetAddress(int, char *, IMA_TARGET_ADDRESS *);
+static int printLoginParameters(char *, IMA_OID, int);
+static void printDiscoveryMethod(char *, IMA_UINT32);
+static void printTargetLuns(IMA_OID_LIST *);
+static void printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *);
+static void printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE *, int);
+static int setLoginParameter(IMA_OID, int, char *);
+static int setLoginParameters(IMA_OID, char *);
+static void printLibError(IMA_STATUS);
+/* LINTED E_STATIC_UNUSED */
+static int sunPluginChk(IMA_OID, boolean_t *);
+static int sunInitiatorFind(IMA_OID *);
+static int getAuthMethodValue(char *, IMA_AUTHMETHOD *);
+static int getLoginParam(char *);
+static void iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status);
+static int modifyIndividualTargetParam(cmdOptions_t *optionList,
+ IMA_OID targetOid, int *);
+static void listCHAPName(IMA_OID oid);
+static int printConfiguredSessions(IMA_OID);
+
+/* object functions per subcommand */
+static int addAddress(int, int, char *[], int *);
+static int addStaticConfig(int, char *[], int *);
+static int listDiscovery(int *);
+static int listDiscoveryAddress(int, char *[], cmdOptions_t *, int *);
+static int listISNSServerAddress(int, char *[], cmdOptions_t *, int *);
+static int listNode(int *);
+static int listStaticConfig(int, char *[], int *);
+static int listTarget(int, char *[], cmdOptions_t *, int *);
+static int listTargetParam(int, char *[], cmdOptions_t *, int *);
+static int modifyDiscovery(cmdOptions_t *, int *);
+static int modifyNodeAuthMethod(IMA_OID, char *, int *);
+static int modifyNodeAuthParam(IMA_OID oid, int, char *, int *);
+static int modifyNodeRadiusConfig(IMA_OID, char *, int *);
+static int modifyNodeRadiusAccess(IMA_OID, char *, int *);
+static int modifyNodeRadiusSharedSecret(IMA_OID, int *);
+static int modifyNode(cmdOptions_t *, int *);
+static int modifyTargetAuthMethod(IMA_OID, char *, int *);
+static int modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *);
+static int modifyTargetParam(cmdOptions_t *, char *, int *);
+static int removeAddress(int, int, char *[], int *);
+static int removeStaticConfig(int, char *[], int *);
+static int removeTargetParam(int, char *[], int *);
+static int modifyTargetBidirAuthFlag(IMA_OID, char *, int *);
+static int modifyConfiguredSessions(IMA_OID targetOid, char *optarg);
+
+/* LINTED E_STATIC_UNUSED */
+static IMA_STATUS getISCSINodeParameter(int paramType,
+ IMA_OID *oid,
+ void *pProps,
+ uint32_t paramIndex);
+/* LINTED E_STATIC_UNUSED */
+static IMA_STATUS setISCSINodeParameter(int paramType,
+ IMA_OID *oid,
+ void *pProps,
+ uint32_t paramIndex);
+/* LINTED E_STATIC_UNUSED */
+static IMA_STATUS getDigest(IMA_OID oid, int ioctlCmd,
+ SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm);
+
+IMA_STATUS getNegotiatedDigest(int digestType,
+ SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm,
+ SUN_IMA_CONN_PROPERTIES *connProps);
+
+/* globals */
+static char *cmdName;
+
+/*
+ * Available option letters:
+ *
+ * bcefgijklmnoquwxyz
+ *
+ * DEFGHIJKLMOQTUVWXYZ
+ */
+
+/*
+ * Add new options here
+ */
+optionTbl_t longOptions[] = {
+ {"static", required_arg, 's', OPTIONSTRING4},
+ {"sendtargets", required_arg, 't', OPTIONSTRING4},
+ {"iSNS", required_arg, 'i', OPTIONSTRING4},
+ {"headerdigest", required_arg, 'h', OPTIONSTRING6},
+ {"datadigest", required_arg, 'd', OPTIONSTRING6},
+ {"login-param", required_arg, 'p', OPTIONSTRING5},
+ {"authentication", required_arg, 'a', "CHAP|none"},
+ {"bi-directional-authentication", required_arg, 'B', OPTIONSTRING4},
+ {"CHAP-secret", no_arg, 'C', NULL},
+ {"CHAP-name", required_arg, 'H', OPTIONSTRING7},
+ {"node-name", required_arg, 'N', OPTIONSTRING2},
+ {"node-alias", required_arg, 'A', OPTIONSTRING3},
+ {"radius-server", required_arg, 'r', OPTIONVAL4},
+ {"radius-access", required_arg, 'R', OPTIONSTRING4},
+ {"radius-shared-secret", no_arg, 'P', NULL},
+ {"verbose", no_arg, 'v', NULL},
+ {"scsi-target", no_arg, 'S', NULL},
+ {"configured-sessions", required_arg, 'c', OPTIONSTRING8},
+ {NULL, 0, 0, 0}
+};
+
+parameterTbl_t loginParams[] = {
+ {"dataseqinorder", DATA_SEQ_IN_ORDER},
+ {"defaulttime2retain", DEFAULT_TIME_2_RETAIN},
+ {"defaulttime2wait", DEFAULT_TIME_2_WAIT},
+ {"firstburstlength", FIRST_BURST_LENGTH},
+ {"immediatedata", IMMEDIATE_DATA},
+ {"initialr2t", INITIAL_R2T},
+ {"maxburstlength", MAX_BURST_LENGTH},
+ {"datapduinorder", DATA_PDU_IN_ORDER},
+ {"maxoutstandingr2t", MAX_OUTSTANDING_R2T},
+ {"maxrecvdataseglen", MAX_RECV_DATA_SEG_LEN},
+ {"maxconnections", MAX_CONNECTIONS},
+ {"errorrecoverylevel", ERROR_RECOVERY_LEVEL},
+ {NULL, 0}
+};
+
+/*
+ * Add new subcommands here
+ */
+subcommand_t subcommands[] = {
+ {"add", ADD, addFunc},
+ {"list", LIST, listFunc},
+ {"modify", MODIFY, modifyFunc},
+ {"remove", REMOVE, removeFunc},
+ {NULL, 0, NULL}
+};
+
+/*
+ * Add objects here
+ */
+object_t objects[] = {
+ {"discovery", DISCOVERY},
+ {"discovery-address", DISCOVERY_ADDRESS},
+ {"isns-server", ISNS_SERVER_ADDRESS},
+ {"initiator-node", NODE},
+ {"static-config", STATIC_CONFIG},
+ {"target", TARGET},
+ {"target-param", TARGET_PARAM},
+ {NULL, 0}
+};
+
+/*
+ * Rules for subcommands and objects
+ */
+objectRules_t objectRules[] = {
+ {TARGET, 0, LIST, 0, ADD|REMOVE|MODIFY, LIST,
+ "target-name"},
+ {TARGET_PARAM, MODIFY|REMOVE, LIST, 0, ADD, MODIFY,
+ "target-name"},
+ {DISCOVERY, 0, 0, LIST|MODIFY, ADD|REMOVE, 0, NULL},
+ {NODE, 0, 0, MODIFY|LIST, ADD|REMOVE, 0, NULL},
+ {STATIC_CONFIG, ADD|REMOVE, LIST, 0, MODIFY, ADD|REMOVE|LIST,
+ "target-name,target-address[:port-number][,tpgt]"},
+ {DISCOVERY_ADDRESS, ADD|REMOVE, LIST, 0, MODIFY,
+ ADD|REMOVE|LIST, "IP-address[:port-number]"},
+ {ISNS_SERVER_ADDRESS, ADD|REMOVE, LIST, 0, MODIFY,
+ ADD|REMOVE|LIST, "IP-address[:port-number]"},
+ {0, 0, 0, 0, 0, NULL}
+};
+
+/*
+ * list of objects, subcommands, valid short options, required flag and
+ * exclusive option string
+ *
+ * If it's not here, there are no options for that object.
+ */
+optionRules_t optionRules[] = {
+ {DISCOVERY, MODIFY, "sti", B_TRUE, NULL},
+ {DISCOVERY_ADDRESS, LIST, "v", B_FALSE, NULL},
+ {ISNS_SERVER_ADDRESS, LIST, "v", B_FALSE, NULL},
+ {TARGET, LIST, "vS", B_FALSE, NULL},
+ {NODE, MODIFY, "NAhdCaRrPHc", B_TRUE, "CP"},
+ {TARGET_PARAM, MODIFY, "ahdBCpcH", B_TRUE, "C"},
+ {TARGET_PARAM, LIST, "v", B_FALSE, NULL},
+ {0, 0, 0, 0, 0}
+};
+
+
+static boolean_t
+targetNamesEqual(wchar_t *name1, wchar_t *name2)
+{
+ int i;
+ wchar_t wchar1, wchar2;
+
+ if (name1 == NULL || name2 == NULL) {
+ return (B_FALSE);
+ }
+
+ if (wcslen(name1) != wcslen(name2)) {
+ return (B_FALSE);
+ }
+
+ /*
+ * Convert names to lower case and compare
+ */
+ for (i = 0; i < wcslen(name1); i++) {
+ wchar1 = towctrans((wint_t)name1[i], wctrans("tolower"));
+ wchar2 = towctrans((wint_t)name2[i], wctrans("tolower"));
+
+ if (wchar1 != wchar2) {
+ return (B_FALSE);
+ }
+ }
+
+ return (B_TRUE);
+}
+
+static boolean_t
+ipAddressesEqual(IMA_TARGET_ADDRESS addr1, IMA_TARGET_ADDRESS addr2)
+{
+#define IPV4_ADDR_BYTES 4
+#define IPV6_ADDR_BYTES 16
+
+ int compSize;
+
+ if (addr1.hostnameIpAddress.id.ipAddress.ipv4Address !=
+ addr2.hostnameIpAddress.id.ipAddress.ipv4Address) {
+ return (B_FALSE);
+ }
+
+ compSize = IPV6_ADDR_BYTES;
+ if (addr1.hostnameIpAddress.id.ipAddress.ipv4Address) {
+ compSize = IPV4_ADDR_BYTES;
+ }
+
+ if (bcmp(addr1.hostnameIpAddress.id.ipAddress.ipAddress,
+ addr2.hostnameIpAddress.id.ipAddress.ipAddress, compSize) == 0) {
+ return (B_TRUE);
+ }
+
+ return (B_FALSE);
+}
+
+static int
+getLoginParam(char *arg)
+{
+ parameterTbl_t *paramp;
+ int len;
+
+ for (paramp = loginParams; paramp->name; paramp++) {
+ len = strlen(arg);
+ if (len == strlen(paramp->name) &&
+ strncasecmp(arg, paramp->name, len) == 0) {
+ return (paramp->val);
+ }
+ }
+ return (-1);
+}
+
+static void
+printLibError(IMA_STATUS status)
+{
+ char *errorString;
+ switch (status) {
+ case IMA_ERROR_NOT_SUPPORTED:
+ errorString =
+ gettext("Operation currently not supported");
+ break;
+ case IMA_ERROR_INSUFFICIENT_MEMORY:
+ errorString = gettext("Insufficient memory");
+ break;
+ case IMA_ERROR_UNEXPECTED_OS_ERROR:
+ errorString = gettext("unexpected OS error");
+ break;
+ case IMA_ERROR_UNKNOWN_ERROR:
+ errorString = gettext("Unknown error");
+ break;
+ case IMA_ERROR_LU_IN_USE:
+ errorString = gettext("Logical unit in use");
+ break;
+ case IMA_ERROR_INVALID_PARAMETER:
+ errorString = gettext("Invalid parameter specified");
+ break;
+ case IMA_ERROR_INVALID_OBJECT_TYPE:
+ errorString =
+ gettext("Internal library error: Invalid oid type specified");
+ break;
+ case IMA_ERROR_INCORRECT_OBJECT_TYPE:
+ errorString =
+ gettext("Internal library error: Incorrect oid type specified");
+ break;
+ case IMA_ERROR_OBJECT_NOT_FOUND:
+ errorString = gettext("Internal library error: Oid not found");
+ break;
+ case IMA_ERROR_NAME_TOO_LONG:
+ errorString = gettext("Name too long");
+ break;
+ default:
+ errorString = gettext("Unknown error");
+ }
+ (void) fprintf(stderr, "%s: %s\n", cmdName, errorString);
+}
+
+/*
+ * input:
+ * execFullName - exec name of program (argv[0])
+ *
+ * Returns:
+ * command name portion of execFullName
+ */
+static char *
+getExecBasename(char *execFullname)
+{
+ char *lastSlash, *execBasename;
+
+ /* guard against '/' at end of command invocation */
+ for (;;) {
+ lastSlash = strrchr(execFullname, '/');
+ if (lastSlash == NULL) {
+ execBasename = execFullname;
+ break;
+ } else {
+ execBasename = lastSlash + 1;
+ if (*execBasename == '\0') {
+ *lastSlash = '\0';
+ continue;
+ }
+ break;
+ }
+ }
+ return (execBasename);
+}
+
+
+/*
+ * input:
+ * nodeProps - pointer to caller allocated IMA_NODE_PROPERTIES
+ *
+ * returns:
+ * zero on success
+ * non-zero otherwise
+ */
+static int
+getNodeProps(IMA_NODE_PROPERTIES *nodeProps)
+{
+ IMA_OID sharedNodeOid;
+
+ IMA_STATUS status = IMA_GetSharedNodeOid(&sharedNodeOid);
+ if (!(IMA_SUCCESS(status))) {
+ printLibError(status);
+ return (INF_ERROR);
+ }
+
+ status = IMA_GetNodeProperties(sharedNodeOid, nodeProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return (INF_ERROR);
+ }
+
+ return (0);
+}
+
+/*
+ * sunInitiatorFind
+ * Purpose:
+ * Finds the Sun iSCSI initiator (LHBA). This CLI currently supports only
+ * one initiator.
+ *
+ * output:
+ * oid of initiator
+ *
+ * Returns:
+ * zero on success with initiator found
+ * > 0 on success with no initiator found
+ * < 0 on failure
+ */
+static int
+sunInitiatorFind(IMA_OID *oid)
+{
+ IMA_OID_LIST *lhbaList;
+
+ IMA_STATUS status = IMA_GetLhbaOidList(&lhbaList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return (-1);
+ }
+
+ *oid = lhbaList->oids[0];
+
+ return (0);
+}
+
+/*
+ * input:
+ * wcInput - wide character string containing discovery address
+ * output:
+ * address - IMA_TARGET_ADDRESS structure containing valid
+ * discovery address
+ * returns:
+ * zero on success
+ * non-zero on failure
+ */
+
+static int
+getTargetAddress(int addrType, char *ipStr, IMA_TARGET_ADDRESS *address)
+{
+ char cCol = ':';
+ char cBracketL = '['; /* Open Bracket '[' */
+ char cBracketR = ']'; /* Close Bracket ']' */
+ char *colPos;
+ char *startPos;
+ unsigned long inputPort;
+ int addressType = AF_INET;
+ char *tmpStrPtr, tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ int rval;
+
+ /* Check if this is a ipv6 address */
+ if (ipStr[0] == cBracketL) {
+ addressType = AF_INET6;
+ startPos = strchr(ipStr, cBracketR);
+ if (!startPos) {
+ (void) fprintf(stderr, "%s: %s: ']' %s\n",
+ cmdName, ipStr, gettext("missing"));
+ return (1);
+ }
+ (void) strlcpy(tmpStr, ipStr+1, startPos-ipStr);
+ address->hostnameIpAddress.id.ipAddress.ipv4Address = IMA_FALSE;
+ tmpStrPtr = tmpStr;
+ } else {
+ /* set start position to beginning of input object */
+ addressType = AF_INET;
+ startPos = ipStr;
+ address->hostnameIpAddress.id.ipAddress.ipv4Address = IMA_TRUE;
+ tmpStrPtr = ipStr;
+ }
+ /* wcschr for ':'. If not there, use default port */
+ colPos = strchr(startPos, cCol);
+
+ if (!colPos) {
+ if (addrType == DISCOVERY_ADDRESS) {
+ inputPort = DEFAULT_ISCSI_PORT;
+ } else if (addrType == ISNS_SERVER_ADDRESS) {
+ inputPort = ISNS_DEFAULT_SERVER_PORT;
+ } else {
+ *colPos = NULL;
+ }
+ } else {
+ *colPos = NULL;
+ }
+
+ rval = inet_pton(addressType, tmpStrPtr,
+ address->hostnameIpAddress.id.ipAddress.ipAddress);
+ /* inet_pton returns 1 on success */
+ if (rval != 1) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName, ipStr,
+ gettext("invalid IP address"));
+ return (1);
+ }
+
+
+ if (colPos) {
+ char *errchr;
+
+ colPos++;
+ if (*colPos == NULL) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, ipStr,
+ gettext("port number missing"));
+ return (1);
+ }
+
+ /*
+ * convert port string to unsigned value
+ * Note: Don't remove errno = 0 as you may get false failures.
+ */
+ errno = 0;
+ inputPort = strtol(colPos, &errchr, 10);
+ if (errno != 0 || inputPort == 0 && errchr != NULL) {
+ (void) fprintf(stderr, "%s: %s:%s %s\n",
+ cmdName, ipStr, colPos,
+ gettext("port number invalid"));
+ return (1);
+ }
+ /* make sure it's in the range */
+ if (inputPort > USHRT_MAX) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, ipStr,
+ gettext("port number out of range"));
+ return (1);
+ }
+ }
+ address->portNumber = inputPort;
+
+ return (0);
+}
+
+/*
+ * Print results of send targets command
+ */
+static void
+printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList)
+{
+ char outBuf[INET6_ADDRSTRLEN];
+ int inetSize;
+ int af;
+ int i;
+
+ for (i = 0; i < pList->keyCount; i++) {
+ if (pList->keys[i].address.ipAddress.ipv4Address == IMA_TRUE) {
+ af = AF_INET;
+ inetSize = INET_ADDRSTRLEN;
+ } else {
+ af = AF_INET6;
+ inetSize = INET6_ADDRSTRLEN;
+ }
+ (void) fprintf(stdout, gettext("\tTarget name: %ws\n"),
+ pList->keys[i].name);
+ (void) fprintf(stdout, "\t\t%s: %15s:%d", "Target address",
+ inet_ntop(af, &(pList->keys[i].address.ipAddress.ipAddress),
+ outBuf, inetSize), pList->keys[i].address.portNumber);
+ (void) fprintf(stdout, ", %d", pList->keys[i].tpgt);
+ (void) fprintf(stdout, "\n");
+ }
+}
+
+
+/*
+ * Print all login parameters
+ */
+static int
+printLoginParameters(char *prefix, IMA_OID oid, int printOption)
+{
+ IMA_STATUS status;
+ IMA_BOOL_VALUE propBool;
+ IMA_MIN_MAX_VALUE propMinMax;
+ char longString[MAX_LONG_CHAR_LEN + 1];
+ SUN_IMA_CONN_PROPERTIES *connProps = NULL;
+ IMA_OID_LIST *pConnList;
+
+ (void) memset(longString, 0, sizeof (longString));
+
+ switch (printOption) {
+ case PRINT_CONFIGURED_PARAMS:
+ (void) fprintf(stdout, "%s%s:\n",
+ prefix,
+ gettext("Login Parameters (Default/Configured)"));
+ break;
+ case PRINT_NEGOTIATED_PARAMS:
+ (void) fprintf(stdout, "%s%s:\n",
+ prefix,
+ gettext("Login Parameters (Negotiated)"));
+ status = SUN_IMA_GetConnOidList(
+ &oid,
+ &pConnList);
+
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return (1);
+ }
+
+ status = SUN_IMA_GetConnProperties(&pConnList->oids[0],
+ &connProps);
+ propBool.currentValueValid = connProps->valuesValid;
+ propMinMax.currentValueValid = connProps->valuesValid;
+ break;
+ default:
+ return (1);
+ }
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propBool.currentValue = connProps->dataSequenceInOrder;
+ } else {
+ status = IMA_GetDataSequenceInOrderProperties(oid, &propBool);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Data Sequence In Order"));
+ IMABOOLPRINT(propBool, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propBool.currentValue = connProps->dataPduInOrder;
+ } else {
+ status = IMA_GetDataPduInOrderProperties(oid, &propBool);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Data PDU In Order"));
+ IMABOOLPRINT(propBool, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->defaultTime2Retain;
+ } else {
+ status = IMA_GetDefaultTime2RetainProperties(oid, &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Default Time To Retain"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->defaultTime2Wait;
+ } else {
+ status = IMA_GetDefaultTime2WaitProperties(oid, &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Default Time To Wait"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->errorRecoveryLevel;
+ } else {
+ status = IMA_GetErrorRecoveryLevelProperties(oid, &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Error Recovery Level"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->firstBurstLength;
+ } else {
+ status = IMA_GetFirstBurstLengthProperties(oid,
+ &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ",
+ prefix, gettext("First Burst Length"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propBool.currentValue = connProps->immediateData;
+ } else {
+ status = IMA_GetImmediateDataProperties(oid, &propBool);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Immediate Data"));
+ IMABOOLPRINT(propBool, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propBool.currentValue = connProps->initialR2T;
+ } else {
+ status = IMA_GetInitialR2TProperties(oid, &propBool);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Initial Ready To Transfer (R2T)"));
+ IMABOOLPRINT(propBool, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->maxBurstLength;
+ } else {
+ status = IMA_GetMaxBurstLengthProperties(oid, &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Max Burst Length"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->maxOutstandingR2T;
+ } else {
+ status = IMA_GetMaxOutstandingR2TProperties(oid, &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Max Outstanding R2T"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->maxRecvDataSegmentLength;
+ } else {
+ status = IMA_GetMaxRecvDataSegmentLengthProperties(oid,
+ &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix,
+ gettext("Max Receive Data Segment Length"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+
+ if (printOption == PRINT_NEGOTIATED_PARAMS) {
+ propMinMax.currentValue = connProps->maxConnections;
+ } else {
+ status = IMA_GetMaxConnectionsProperties(oid, &propMinMax);
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(connProps);
+ return (1);
+ }
+ (void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Max Connections"));
+ IMAMINMAXPRINT(propMinMax, printOption);
+
+ (void) IMA_FreeMemory(connProps);
+ return (0);
+}
+
+/*
+ * Print discovery information.
+ */
+static void
+printDiscoveryMethod(char *prefix, IMA_UINT32 discoveryMethodFlags)
+{
+ (void) fprintf(stdout, "%s%s: ", prefix, gettext("Discovery Method"));
+ if (discoveryMethodFlags == IMA_TARGET_DISCOVERY_METHOD_UNKNOWN) {
+ (void) fprintf(stdout, "%s\n", gettext("NA"));
+ } else {
+ if (!((discoveryMethodFlags &
+ IMA_TARGET_DISCOVERY_METHOD_STATIC) ^
+ IMA_TARGET_DISCOVERY_METHOD_STATIC)) {
+ (void) fprintf(stdout, "%s ", gettext("Static"));
+ }
+ if (!((discoveryMethodFlags &
+ IMA_TARGET_DISCOVERY_METHOD_SENDTARGETS) ^
+ IMA_TARGET_DISCOVERY_METHOD_SENDTARGETS)) {
+ (void) fprintf(stdout, "%s ", gettext("SendTargets"));
+ }
+ if (!((discoveryMethodFlags &
+ IMA_TARGET_DISCOVERY_METHOD_ISNS) ^
+ IMA_TARGET_DISCOVERY_METHOD_ISNS)) {
+ (void) fprintf(stdout, "%s ", gettext("iSNS"));
+ }
+ (void) fprintf(stdout, "\n");
+ }
+}
+
+/*
+ * printConnectionList - Prints the conection list provided
+ */
+static void
+printConnectionList(char *prefix, IMA_OID_LIST *pConnList)
+{
+ IMA_STATUS imaStatus;
+ int i;
+ SUN_IMA_CONN_PROPERTIES *connProps;
+ union {
+ char ipv4[INET_ADDRSTRLEN+1];
+ char ipv6[INET6_ADDRSTRLEN+1];
+ } tmp;
+
+ for (i = 0; i < pConnList->oidCount; i++) {
+ imaStatus = SUN_IMA_GetConnProperties(&pConnList->oids[i],
+ &connProps);
+
+ if (imaStatus != IMA_STATUS_SUCCESS) {
+ continue;
+ }
+
+ (void) fprintf(stdout, "%sCID: %d\n", prefix,
+ connProps->connectionID);
+
+ (void) memset(&tmp, 0, sizeof (tmp));
+ if (connProps->local.ipAddress.ipv4Address == IMA_TRUE) {
+ if (inet_ntop(AF_INET,
+ &connProps->local.ipAddress.ipAddress[0],
+ &tmp.ipv4[0],
+ INET_ADDRSTRLEN)) {
+ (void) fprintf(stdout,
+ "%s %s: %s:%u\n",
+ prefix,
+ gettext("IP address (Local)"),
+ &tmp.ipv4[0],
+ ntohs(connProps->local.portNumber));
+ }
+ } else {
+ if (inet_ntop(AF_INET6,
+ &connProps->local.ipAddress.ipAddress[0],
+ &tmp.ipv6[0],
+ INET6_ADDRSTRLEN)) {
+ (void) fprintf(stdout,
+ "%s %s: [%s]:%u\n",
+ prefix,
+ gettext("IP address (Local)"),
+ &tmp.ipv6[0],
+ ntohs(connProps->local.portNumber));
+ }
+ }
+ if (connProps->peer.ipAddress.ipv4Address == IMA_TRUE) {
+ if (inet_ntop(AF_INET,
+ &connProps->peer.ipAddress.ipAddress[0],
+ &tmp.ipv4[0],
+ INET_ADDRSTRLEN)) {
+ (void) fprintf(stdout,
+ "%s %s: %s:%u\n",
+ prefix,
+ gettext("IP address (Peer)"),
+ &tmp.ipv4[0],
+ ntohs(connProps->peer.portNumber));
+ }
+ } else {
+ if (inet_ntop(AF_INET6,
+ &connProps->peer.ipAddress.ipAddress[0],
+ &tmp.ipv6[0],
+ INET6_ADDRSTRLEN)) {
+ (void) fprintf(stdout,
+ "%s %s: [%s]:%u\n",
+ prefix,
+ gettext("IP address (Peer)"),
+ &tmp.ipv6[0],
+ ntohs(connProps->peer.portNumber));
+ }
+ }
+
+ (void) IMA_FreeMemory(connProps);
+ }
+}
+
+/*
+ * Set login parameters on a target or initiator
+ */
+static int
+setLoginParameter(IMA_OID oid, int optval, char *optarg)
+{
+ IMA_STATUS status = IMA_STATUS_SUCCESS;
+ IMA_UINT uintValue;
+ IMA_BOOL boolValue;
+ SUN_IMA_DIGEST_ALGORITHM digestAlgList[1];
+ IMA_MIN_MAX_VALUE propMinMax;
+ char *endptr;
+
+ /*
+ * for clarity, there are two switch statements
+ * The first loads the variable and the second
+ * calls the appropriate API
+ */
+ switch (optval) {
+ case DATA_SEQ_IN_ORDER:
+ case IMMEDIATE_DATA:
+ case INITIAL_R2T:
+ case DATA_PDU_IN_ORDER:
+ /* implement 'default'? */
+ if (strcasecmp(optarg, "yes") == 0) {
+ boolValue = IMA_TRUE;
+ } else if (strcasecmp(optarg, "no") == 0) {
+ boolValue = IMA_FALSE;
+ } else {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ break;
+ case DEFAULT_TIME_2_RETAIN:
+ case DEFAULT_TIME_2_WAIT:
+ errno = 0;
+ uintValue = strtoul(optarg, &endptr, 0);
+ if (*endptr != '\0' || errno != 0) {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ if (uintValue > 3600) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+gettext("value must be between 0 and 3600"));
+ return (1);
+ }
+ break;
+ case FIRST_BURST_LENGTH:
+ case MAX_BURST_LENGTH:
+ case MAX_RECV_DATA_SEG_LEN:
+ errno = 0;
+ /* implement 'default'? */
+ uintValue = strtoul(optarg, &endptr, 0);
+ if (*endptr != '\0' || errno != 0) {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ if (uintValue < 512 || uintValue > 16777215) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+gettext("value must be between 512 and 16777215"));
+ return (1);
+ }
+ break;
+ case MAX_OUTSTANDING_R2T:
+ errno = 0;
+ uintValue = strtoul(optarg, &endptr, 0);
+ if (*endptr != '\0' || errno != 0) {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ if (uintValue < 1 || uintValue > 65535) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+gettext("value must be between 1 and 65535"));
+ return (1);
+ }
+ break;
+ case HEADER_DIGEST:
+ case DATA_DIGEST:
+ if (strcasecmp(optarg, "none") == 0) {
+ digestAlgList[0] = SUN_IMA_DIGEST_NONE;
+ } else if (strcasecmp(optarg, "CRC32") == 0) {
+ digestAlgList[0] = SUN_IMA_DIGEST_CRC32;
+ } else {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ break;
+ case MAX_CONNECTIONS:
+ errno = 0;
+ uintValue = strtoul(optarg, &endptr, 0);
+ if (*endptr != '\0' || errno != 0) {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ if (uintValue < 1 || uintValue > 256) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+gettext("value must be between 1 and 256"));
+ return (1);
+ }
+ break;
+ case ERROR_RECOVERY_LEVEL:
+ errno = 0;
+ uintValue = strtoul(optarg, &endptr, 0);
+ if (*endptr != '\0' || errno != 0) {
+ (void) fprintf(stderr, "%s: %s - %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ if (uintValue > 2) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+gettext("value must be between 0 and 2"));
+ return (1);
+ }
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optval, gettext("unknown option"));
+ return (1);
+ }
+
+ switch (optval) {
+ case DATA_PDU_IN_ORDER:
+ status = IMA_SetDataPduInOrder(oid, boolValue);
+ break;
+ case DATA_SEQ_IN_ORDER:
+ status = IMA_SetDataSequenceInOrder(oid, boolValue);
+ break;
+ case DEFAULT_TIME_2_RETAIN:
+ status = IMA_SetDefaultTime2Retain(oid, uintValue);
+ break;
+ case DEFAULT_TIME_2_WAIT:
+ status = IMA_SetDefaultTime2Wait(oid, uintValue);
+ break;
+ case FIRST_BURST_LENGTH:
+ status = IMA_SetFirstBurstLength(oid, uintValue);
+
+ /*
+ * If this call fails check to see if it's because
+ * the requested value is > than maxBurstLength
+ */
+ if (!IMA_SUCCESS(status)) {
+ status = IMA_GetMaxBurstLengthProperties(oid,
+ &propMinMax);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return (1);
+ }
+ if (uintValue > propMinMax.currentValue) {
+ (void) fprintf(stderr,
+ "%s: %s\n", cmdName,
+ gettext("firstBurstLength must " \
+ "be less than or equal to than " \
+ "maxBurstLength"));
+ }
+ return (1);
+ }
+
+ break;
+ case IMMEDIATE_DATA:
+ status = IMA_SetImmediateData(oid, boolValue);
+ break;
+ case INITIAL_R2T:
+ status = IMA_SetInitialR2T(oid, boolValue);
+ break;
+ case MAX_BURST_LENGTH:
+ status = IMA_SetMaxBurstLength(oid, uintValue);
+ /*
+ * If this call fails check to see if it's because
+ * the requested value is < than firstBurstLength
+ */
+ if (!IMA_SUCCESS(status)) {
+ status = IMA_GetFirstBurstLengthProperties(oid,
+ &propMinMax);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return (1);
+ }
+ if (uintValue < propMinMax.currentValue) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("maxBurstLength must be " \
+ "greater than or equal to " \
+ "firstBurstLength"));
+ }
+ return (1);
+ }
+ break;
+
+ case MAX_OUTSTANDING_R2T:
+ status = IMA_SetMaxOutstandingR2T(oid, uintValue);
+ break;
+ case MAX_RECV_DATA_SEG_LEN:
+ status = IMA_SetMaxRecvDataSegmentLength(oid,
+ uintValue);
+ break;
+ case HEADER_DIGEST:
+ status = SUN_IMA_SetHeaderDigest(oid, 1,
+ &digestAlgList[0]);
+ break;
+ case DATA_DIGEST:
+ status = SUN_IMA_SetDataDigest(oid, 1,
+ &digestAlgList[0]);
+ break;
+ case MAX_CONNECTIONS:
+ status = IMA_SetMaxConnections(oid, uintValue);
+ break;
+ case ERROR_RECOVERY_LEVEL:
+ status = IMA_SetErrorRecoveryLevel(oid, uintValue);
+ break;
+ }
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return (1);
+ }
+ return (0);
+}
+
+static void
+printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE *digestAlgorithms,
+ int printOption)
+{
+ int i;
+
+ if (printOption == PRINT_CONFIGURED_PARAMS) {
+ for (i = 0; i < digestAlgorithms->defaultAlgorithmCount; i++) {
+ if (i > 0) {
+ (void) fprintf(stdout, "|");
+ }
+ switch (digestAlgorithms->defaultAlgorithms[i]) {
+ case SUN_IMA_DIGEST_NONE:
+ (void) fprintf(stdout,
+ gettext("NONE"));
+ break;
+ case SUN_IMA_DIGEST_CRC32:
+ (void) fprintf(stdout,
+ gettext("CRC32"));
+ break;
+ default:
+ (void) fprintf(stdout,
+ gettext("Unknown"));
+ break;
+ }
+ }
+ (void) fprintf(stdout, "/");
+ if (digestAlgorithms->currentValid == IMA_TRUE) {
+ for (i = 0;
+ i < digestAlgorithms->currentAlgorithmCount; i++) {
+ if (i > 0) {
+ (void) fprintf(stdout, "|");
+ }
+ switch (digestAlgorithms->
+ currentAlgorithms[i]) {
+ case SUN_IMA_DIGEST_NONE:
+ (void) fprintf(stdout,
+ gettext("NONE"));
+ break;
+ case SUN_IMA_DIGEST_CRC32:
+ (void) fprintf(stdout,
+ gettext("CRC32"));
+ break;
+ default:
+ (void) fprintf(stdout,
+ gettext("Unknown"));
+ break;
+ }
+ }
+ } else {
+ (void) fprintf(stdout, "-");
+ }
+ (void) fprintf(stdout, "\n");
+ } else if (printOption == PRINT_NEGOTIATED_PARAMS) {
+
+ if (digestAlgorithms->negotiatedValid == IMA_TRUE) {
+ for (i = 0;
+ i < digestAlgorithms->negotiatedAlgorithmCount;
+ i++) {
+ if (i > 0) {
+ (void) fprintf(stdout, "|");
+ }
+ switch (digestAlgorithms->
+ negotiatedAlgorithms[i]) {
+ case SUN_IMA_DIGEST_NONE:
+ (void) fprintf(stdout,
+ gettext("NONE"));
+ break;
+ case SUN_IMA_DIGEST_CRC32:
+ (void) fprintf(stdout,
+ gettext("CRC32"));
+ break;
+ default:
+ (void) fprintf(stdout,
+ gettext("Unknown"));
+ break;
+ }
+ }
+ } else {
+ (void) fprintf(stdout, "-");
+ }
+ (void) fprintf(stdout, "\n");
+ }
+}
+
+static int
+setLoginParameters(IMA_OID oid, char *optarg)
+{
+ char keyp[MAXOPTARGLEN];
+ char valp[MAXOPTARGLEN];
+ int key;
+ char *nameValueString, *indexp, *delim = NULL;
+
+ if ((nameValueString = strdup(optarg)) == NULL) {
+ if (errno == ENOMEM) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, strerror(errno));
+ } else {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown error"));
+ }
+ return (1);
+ }
+
+ indexp = nameValueString;
+
+ /*
+ * Retrieve all login params from option argument
+ * Syntax <key=value,...>
+ */
+ while (indexp) {
+ if (delim = strchr(indexp, ',')) {
+ delim[0] = '\0';
+ }
+ (void) memset(keyp, 0, sizeof (keyp));
+ (void) memset(valp, 0, sizeof (valp));
+ if (sscanf(indexp, gettext("%[^=]=%s"), keyp, valp) != 2) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ gettext("Unknown param"), indexp);
+ return (1);
+ }
+ if ((key = getLoginParam(keyp)) == -1) {
+ (void) fprintf(stderr, "%s: %s: %s\n", cmdName,
+ gettext("Unknown key"), keyp);
+ return (1);
+ }
+ if (setLoginParameter(oid, key, valp) != 0) {
+ return (1);
+ }
+ if (delim) {
+ indexp = delim + 1;
+ } else {
+ indexp = NULL;
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Print logical unit information for a specific target
+ */
+static void
+printTargetLuns(IMA_OID_LIST * lunList)
+{
+ int j;
+ IMA_STATUS status;
+ SUN_IMA_LU_PROPERTIES lunProps;
+
+ for (j = 0; j < lunList->oidCount; j++) {
+ status = SUN_IMA_GetLuProperties(lunList->oids[j],
+ &lunProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ return;
+ }
+
+ if (lunProps.imaProps.osDeviceNameValid == IMA_TRUE) {
+ (void) fprintf(stdout, "\tLUN: %lld\n",
+ lunProps.imaProps.targetLun);
+ (void) fprintf(stdout, "\t Vendor: %s\n",
+ lunProps.vendorId);
+ (void) fprintf(stdout, "\t Product: %s\n",
+ lunProps.productId);
+ (void) fprintf(stdout,
+ gettext("\t OS Device Name: %ws\n"),
+ lunProps.imaProps.osDeviceName);
+ }
+ }
+}
+
+/*
+ * Retrieve CHAP secret from input
+ */
+static int
+getSecret(char *secret, int *secretLen, int minSecretLen, int maxSecretLen)
+{
+ char *chapSecret;
+
+ /* get password */
+ chapSecret = getpassphrase(gettext("Enter secret:"));
+
+ if (strlen(chapSecret) > maxSecretLen) {
+ (void) fprintf(stderr, "%s: %s %d\n", cmdName,
+ gettext("secret too long, maximum length is"),
+ maxSecretLen);
+ *secret = NULL;
+ return (1);
+ }
+
+ if (strlen(chapSecret) < minSecretLen) {
+ (void) fprintf(stderr, "%s: %s %d\n", cmdName,
+ gettext("secret too short, minimum length is"),
+ minSecretLen);
+ *secret = NULL;
+ return (1);
+ }
+
+ (void) strcpy(secret, chapSecret);
+
+ chapSecret = getpassphrase(gettext("Re-enter secret:"));
+ if (strcmp(secret, chapSecret) != 0) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("secrets do not match, secret not changed"));
+ *secret = NULL;
+ return (1);
+ }
+ *secretLen = strlen(chapSecret);
+ return (0);
+}
+
+/*
+ * Lists the discovery attributes
+ */
+static int
+listDiscovery(int *funcRet)
+{
+ IMA_OID initiatorOid;
+ IMA_DISCOVERY_PROPERTIES discProps;
+ int ret;
+ IMA_STATUS status;
+
+ assert(funcRet != NULL);
+
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ /* Get discovery attributes from IMA */
+ status = IMA_GetDiscoveryProperties(initiatorOid, &discProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+
+ (void) fprintf(stdout, "%s:\n", "Discovery");
+ (void) fprintf(stdout, "\tStatic: %s\n",
+ discProps.staticDiscoveryEnabled == IMA_TRUE ? \
+ gettext("enabled") : gettext("disabled"));
+ (void) fprintf(stdout, "\tSend Targets: %s\n",
+ discProps.sendTargetsDiscoveryEnabled == IMA_TRUE ? \
+ gettext("enabled") : gettext("disabled"));
+ (void) fprintf(stdout, "\tiSNS: %s\n",
+ discProps.iSnsDiscoveryEnabled == IMA_TRUE ? \
+ gettext("enabled") : gettext("disabled"));
+
+ return (0);
+}
+
+/*
+ * Print all initiator node attributes
+ */
+static int
+listNode(int *funcRet)
+{
+ IMA_OID initiatorOid;
+ IMA_NODE_PROPERTIES nodeProps;
+ IMA_STATUS status;
+ int ret;
+ IMA_UINT maxEntries = MAX_AUTH_METHODS;
+ IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS];
+ SUN_IMA_RADIUS_CONFIG radiusConfig;
+ SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms;
+ IMA_BOOL radiusAccess;
+
+ int i;
+
+ assert(funcRet != NULL);
+
+ ret = getNodeProps(&nodeProps);
+ if (ret != 0) {
+ return (ret);
+ }
+
+ if (nodeProps.nameValid == IMA_FALSE) {
+ return (INVALID_NODE_NAME);
+ }
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+ /* Begin output */
+ (void) fprintf(stdout, gettext("%s: %ws\n"),
+ gettext("Initiator node name"),
+ nodeProps.name);
+ (void) fprintf(stdout, gettext("Initiator node alias: "));
+ if (nodeProps.aliasValid == IMA_TRUE) {
+ (void) fprintf(stdout, gettext("%ws\n"), nodeProps.alias);
+ } else {
+ (void) fprintf(stdout, "%s\n", "-");
+ }
+ (void) fprintf(stdout, "\t%s:\n",
+ gettext("Login Parameters (Default/Configured)"));
+
+ /* Get Digest configuration */
+ status = SUN_IMA_GetHeaderDigest(initiatorOid, &digestAlgorithms);
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t\t%s: ", gettext("Header Digest"));
+ printDigestAlgorithm(&digestAlgorithms,
+ PRINT_CONFIGURED_PARAMS);
+ } else {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ status = SUN_IMA_GetDataDigest(initiatorOid, &digestAlgorithms);
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t\t%s: ", gettext("Data Digest"));
+ printDigestAlgorithm(&digestAlgorithms,
+ PRINT_CONFIGURED_PARAMS);
+ } else {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /* Get authentication type for this lhba */
+ status = IMA_GetInUseInitiatorAuthMethods(initiatorOid, &maxEntries,
+ &methodList[0]);
+ (void) fprintf(stdout, "\t%s: ", gettext("Authentication Type"));
+ if (!IMA_SUCCESS(status)) {
+ /* No authentication method set - default is NONE */
+ (void) fprintf(stdout, gettext("NONE"));
+ } else {
+ for (i = 0; i < maxEntries; i++) {
+ if (i > 0) {
+ (void) fprintf(stdout, "|");
+ }
+ switch (methodList[i]) {
+ case IMA_AUTHMETHOD_NONE:
+ (void) fprintf(stdout, gettext("NONE"));
+ break;
+ case IMA_AUTHMETHOD_CHAP:
+ (void) fprintf(stdout, gettext("CHAP"));
+ listCHAPName(initiatorOid);
+ break;
+ default:
+ (void) fprintf(stdout,
+ gettext("unknown type"));
+ break;
+ }
+ }
+ }
+ (void) fprintf(stdout, "\n");
+
+
+ /* Get RADIUS configuration */
+ status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig);
+ (void) fprintf(stdout, "\t%s: ", gettext("RADIUS Server"));
+ if (IMA_SUCCESS(status)) {
+ if (strlen(radiusConfig.hostnameIpAddress) > 0) {
+ (void) fprintf(stdout, "%s:%d",
+ radiusConfig.hostnameIpAddress,
+ radiusConfig.port);
+ } else {
+ (void) fprintf(stdout, "%s", gettext("NONE"));
+ }
+ } else {
+ (void) fprintf(stdout, "%s", gettext("NONE"));
+ }
+ (void) fprintf(stdout, "\n");
+
+ status = SUN_IMA_GetInitiatorRadiusAccess(initiatorOid,
+ &radiusAccess);
+ (void) fprintf(stdout, "\t%s: ", gettext("RADIUS Access"));
+ if (IMA_SUCCESS(status)) {
+ if (radiusAccess == IMA_TRUE) {
+ (void) fprintf(stdout, "%s", gettext("enabled"));
+ } else {
+ (void) fprintf(stdout, "%s", gettext("disabled"));
+ }
+ } else if (status == IMA_ERROR_OBJECT_NOT_FOUND) {
+ (void) fprintf(stdout, "%s", gettext("disabled"));
+ } else {
+ (void) fprintf(stdout, "%s", gettext("unknown"));
+ }
+ (void) fprintf(stdout, "\n");
+
+ /* print configured session information. */
+ ret = printConfiguredSessions(initiatorOid);
+
+ return (ret);
+}
+
+/*
+ * Print discovery addresses
+ */
+static int
+listDiscoveryAddress(int objectLen, char *objects[], cmdOptions_t *options,
+ int *funcRet)
+{
+ IMA_OID initiatorOid;
+ SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList;
+ IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps;
+ IMA_TARGET_ADDRESS address;
+ SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList;
+ IMA_STATUS status;
+ wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
+ int ret;
+ boolean_t object = B_FALSE;
+ int outerLoop;
+ boolean_t found;
+ boolean_t verbose = B_FALSE;
+ int i, j;
+ cmdOptions_t *optionList = options;
+ char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optionList->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ /*
+ * If there are multiple objects, execute outer 'for' loop that
+ * many times for each target detail, otherwise, execute it only
+ * once with summaries only
+ */
+ if (objectLen > 0) {
+ object = B_TRUE;
+ outerLoop = objectLen;
+ } else {
+ object = B_FALSE;
+ outerLoop = 1;
+ }
+
+ status = SUN_IMA_GetDiscoveryAddressPropertiesList(
+ &discoveryAddressPropertiesList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ if (object) {
+ /* initialize */
+ (void) memset(&wcInputObject[0], 0,
+ sizeof (wcInputObject));
+ (void) memset(&address, 0, sizeof (address));
+ if (mbstowcs(wcInputObject, objects[i],
+ (MAX_ADDRESS_LEN + 1)) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ /*
+ * if one or more objects were input,
+ * get the values
+ */
+ if (getTargetAddress(DISCOVERY_ADDRESS,
+ objects[i], &address) != 0) {
+ ret = 1;
+ continue;
+ }
+ }
+ for (found = B_FALSE, j = 0;
+ j < discoveryAddressPropertiesList->discAddrCount;
+ j++) {
+ discAddrProps =
+ discoveryAddressPropertiesList->props[j];
+
+ /*
+ * Compare the discovery address with the input if
+ * one was input
+ */
+ if (object &&
+ ipAddressesEqual(discAddrProps.discoveryAddress,
+ address) && (discAddrProps.discoveryAddress.
+ portNumber == address.portNumber)) {
+ found = B_TRUE;
+ }
+
+ if (!object || found) {
+ /* Print summary - always */
+ if (discAddrProps.discoveryAddress.
+ hostnameIpAddress.id.ipAddress.
+ ipv4Address) {
+ (void) inet_ntop(AF_INET, discAddrProps.
+ discoveryAddress.hostnameIpAddress.
+ id.ipAddress.ipAddress, sAddr,
+ sizeof (sAddr));
+ (void) fprintf(stdout,
+ "Discovery Address: %s:%u\n",
+ sAddr, discAddrProps.
+ discoveryAddress.portNumber);
+ } else {
+ (void) inet_ntop(AF_INET6,
+ discAddrProps.
+ discoveryAddress.hostnameIpAddress.
+ id.ipAddress.ipAddress, sAddr,
+ sizeof (sAddr));
+ (void) fprintf(stdout,
+ "DiscoveryAddress: [%s]:%u\n",
+ sAddr, discAddrProps.
+ discoveryAddress.portNumber);
+ }
+ }
+
+ if ((!object || found) && verbose) {
+ IMA_NODE_PROPERTIES nodeProps;
+
+ if (getNodeProps(&nodeProps) != 0) {
+ break;
+ }
+
+ /*
+ * Issue sendTargets only when an addr is
+ * specified.
+ */
+ status = SUN_IMA_SendTargets(nodeProps.name,
+ discAddrProps.discoveryAddress, &pList);
+ if (!IMA_SUCCESS(status)) {
+ (void) fprintf(stderr, "%s\n",
+ gettext("\tUnable to get "\
+ "targets."));
+ *funcRet = 1;
+ continue;
+ }
+ printSendTargets(pList);
+ }
+
+ if (found) {
+ /* we found the discovery address - break */
+ break;
+ }
+ }
+ /*
+ * There was an object entered but we didn't
+ * find it.
+ */
+ if (object && !found) {
+ (void) fprintf(stdout, "%s: %s\n",
+ objects[i], gettext("not found"));
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Print ISNS Server addresses
+ */
+static int
+listISNSServerAddress(int objectLen, char *objects[], cmdOptions_t *options,
+ int *funcRet)
+{
+ IMA_OID initiatorOid;
+ SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList;
+ IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps;
+ IMA_TARGET_ADDRESS address;
+ SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList;
+ IMA_STATUS status;
+ wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
+ int ret;
+ boolean_t object = B_FALSE;
+ int outerLoop;
+ boolean_t found;
+ boolean_t showTarget = B_FALSE;
+ int i, j;
+ cmdOptions_t *optionList = options;
+ char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'v':
+ showTarget = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optionList->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ /*
+ * If there are multiple objects, execute outer 'for' loop that
+ * many times for each target detail, otherwise, execute it only
+ * once with summaries only
+ */
+ if (objectLen > 0) {
+ object = B_TRUE;
+ outerLoop = objectLen;
+ } else {
+ object = B_FALSE;
+ outerLoop = 1;
+ }
+
+ status = SUN_IMA_GetISNSServerAddressPropertiesList(
+ &discoveryAddressPropertiesList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ if (object) {
+ /* initialize */
+ (void) memset(&wcInputObject[0], 0,
+ sizeof (wcInputObject));
+ (void) memset(&address, 0, sizeof (address));
+ if (mbstowcs(wcInputObject, objects[i],
+ (MAX_ADDRESS_LEN + 1)) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ /*
+ * if one or more objects were input,
+ * get the values
+ */
+ if (getTargetAddress(ISNS_SERVER_ADDRESS,
+ objects[i], &address) != 0) {
+ ret = 1;
+ continue;
+ }
+ }
+ for (found = B_FALSE, j = 0;
+ j < discoveryAddressPropertiesList->discAddrCount;
+ j++) {
+ discAddrProps =
+ discoveryAddressPropertiesList->props[j];
+
+ /*
+ * Compare the discovery address with the input if
+ * one was input
+ */
+ if (object &&
+ ipAddressesEqual(discAddrProps.discoveryAddress,
+ address) &&
+ (discAddrProps.discoveryAddress.portNumber ==
+ address.portNumber)) {
+ found = B_TRUE;
+ }
+
+ if (!object || found) {
+ /* Print summary - always */
+ if (discAddrProps.discoveryAddress.
+ hostnameIpAddress.id.ipAddress.
+ ipv4Address) {
+ (void) inet_ntop(AF_INET, discAddrProps.
+ discoveryAddress.hostnameIpAddress.
+ id.ipAddress.ipAddress, sAddr,
+ sizeof (sAddr));
+ } else {
+ (void) inet_ntop(AF_INET6,
+ discAddrProps.
+ discoveryAddress.hostnameIpAddress.
+ id.ipAddress.ipAddress, sAddr,
+ sizeof (sAddr));
+ }
+ (void) fprintf(stdout,
+ "iSNS Server IP Address: %s:%u\n",
+ sAddr,
+ discAddrProps.discoveryAddress.portNumber);
+ }
+
+ if ((!object || found) && showTarget) {
+ IMA_NODE_PROPERTIES nodeProps;
+
+ if (getNodeProps(&nodeProps) != 0) {
+ break;
+ }
+
+ /*
+ * Issue sendTargets only when an addr is
+ * specified.
+ */
+ status = SUN_IMA_RetrieveISNSServerTargets(
+ discAddrProps.discoveryAddress,
+ &pList);
+ if (!IMA_SUCCESS(status)) {
+ /*
+ * Check if the discovery mode is
+ * disabled.
+ */
+ if (status ==
+ IMA_ERROR_OBJECT_NOT_FOUND) {
+ (void) fprintf(stderr, "%s\n",
+ gettext("\tiSNS "\
+ "discovery "\
+ "mode "\
+ "disabled. "\
+ "No targets "\
+ "to report."));
+
+ } else {
+ (void) fprintf(stderr, "%s\n",
+ gettext("\tUnable "\
+ "to get "\
+ "targets."));
+ }
+ continue;
+ }
+ printSendTargets(pList);
+ }
+
+ if (found) {
+ /* we found the discovery address - break */
+ break;
+ }
+ }
+ /*
+ * There was an object entered but we didn't
+ * find it.
+ */
+ if (object && !found) {
+ (void) fprintf(stdout, "%s: %s\n",
+ objects[i], gettext("not found"));
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Print static configuration targets
+ */
+static int
+listStaticConfig(int operandLen, char *operand[], int *funcRet)
+{
+ IMA_STATUS status;
+ IMA_OID initiatorOid;
+ IMA_OID_LIST *staticTargetList;
+ SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps;
+ wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1];
+ wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ wchar_t wcCol;
+ char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ int ret;
+ boolean_t object = B_FALSE;
+ int outerLoop;
+ boolean_t found; /* B_TRUE if a target name is found */
+ boolean_t matched; /* B_TRUE if a specific target is found */
+ boolean_t targetAddressSpecified = B_FALSE;
+ boolean_t tpgtSpecified = B_FALSE;
+ boolean_t isIpv6;
+ int i, j;
+ IMA_UINT16 port = 0;
+ IMA_UINT16 tpgt = 0;
+ char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ /*
+ * If there are multiple objects, execute outer 'for' loop that
+ * many times for each static config detail, otherwise, execute it only
+ * once with summaries only
+ */
+ if (operandLen > 0) {
+ object = B_TRUE;
+ outerLoop = operandLen;
+ } else {
+ object = B_FALSE;
+ outerLoop = 1;
+ }
+
+ /* convert ':' to wide char for wchar string search */
+ if (mbtowc(&wcCol, ":", sizeof (wcCol)) == -1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("conversion error"));
+ return (1);
+ }
+
+ status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid,
+ &staticTargetList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ if (object) {
+ if (parseTarget(operand[i],
+ &staticTargetName[0],
+ MAX_ISCSI_NAME_LEN + 1,
+ &targetAddressSpecified,
+ &staticTargetAddress[0],
+ SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port,
+ &tpgtSpecified,
+ &tpgt,
+ &isIpv6) != PARSE_TARGET_OK) {
+ ret = 1;
+ continue;
+ }
+ }
+
+ for (found = B_FALSE, j = 0; j < staticTargetList->oidCount;
+ j++) {
+ boolean_t isIpv6 = B_FALSE;
+ IMA_UINT16 stpgt;
+ IMA_BOOL defaultTpgt;
+
+ matched = B_FALSE;
+ (void) memset(&staticTargetProps, 0,
+ sizeof (staticTargetProps));
+
+ status = SUN_IMA_GetStaticTargetProperties(
+ staticTargetList->oids[j], &staticTargetProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(staticTargetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ stpgt = staticTargetProps.staticTarget.targetAddress.
+ tpgt;
+
+ defaultTpgt = staticTargetProps.staticTarget.
+ targetAddress.defaultTpgt;
+
+ isIpv6 = !staticTargetProps.staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.id.ipAddress.
+ ipv4Address;
+
+ /*
+ * Compare the static target name with the input if
+ * one was input
+ */
+
+ if (object &&
+ (targetNamesEqual(
+ staticTargetProps.staticTarget.targetName,
+ staticTargetName) == B_TRUE)) {
+ /* targetName found - found = B_TRUE */
+ found = B_TRUE;
+ if (targetAddressSpecified == B_FALSE) {
+ matched = B_TRUE;
+ } else {
+
+ if (staticTargetProps.staticTarget.
+ targetAddress.imaStruct.
+ hostnameIpAddress.id.ipAddress.
+ ipv4Address == IMA_TRUE) {
+ (void) inet_ntop(AF_INET,
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.id.
+ ipAddress.ipAddress, tmpStr,
+ sizeof (tmpStr));
+ } else {
+ (void) inet_ntop(AF_INET6,
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.id.
+ ipAddress.ipAddress, tmpStr,
+ sizeof (tmpStr));
+ }
+
+ if (mbstowcs(tmpTargetAddress, tmpStr,
+ SUN_IMA_IP_ADDRESS_PORT_LEN) ==
+ (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ if (wcsncmp(tmpTargetAddress,
+ staticTargetAddress,
+ SUN_IMA_IP_ADDRESS_PORT_LEN)
+ == 0 &&
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.portNumber == port) {
+ /*
+ * Since an object is
+ * specified, it should also
+ * have a tpgt specified. If
+ * not, that means the object
+ * specified is associated with
+ * the default tpgt. In
+ * either case, a tpgt
+ * comparison should be done
+ * before claiming that a
+ * match is found.
+ */
+ if ((tpgt == stpgt &&
+ tpgtSpecified == B_TRUE &&
+ defaultTpgt == IMA_FALSE) ||
+ (tpgt == stpgt &&
+ tpgtSpecified == B_FALSE &&
+ defaultTpgt == IMA_TRUE)) {
+ matched = B_TRUE;
+ }
+ }
+
+ }
+ }
+
+ if (!object || matched) {
+ /* print summary - always */
+ (void) fprintf(stdout, gettext("%s: %ws,"),
+ "Static Configuration Target",
+ staticTargetProps.staticTarget.targetName);
+
+ if (isIpv6 == B_FALSE) {
+ (void) inet_ntop(AF_INET,
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.id.
+ ipAddress.ipAddress, sAddr,
+ sizeof (sAddr));
+ (void) fprintf(stdout, "%s:%d",
+ sAddr,
+ staticTargetProps.staticTarget.
+ targetAddress.imaStruct.portNumber);
+ } else {
+ (void) inet_ntop(AF_INET6,
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.id.
+ ipAddress.ipAddress, sAddr,
+ sizeof (sAddr));
+ (void) fprintf(stdout, "[%s]:%d",
+ sAddr,
+ staticTargetProps.staticTarget.
+ targetAddress.imaStruct.portNumber);
+ }
+
+ if (staticTargetProps.staticTarget.
+ targetAddress.
+ defaultTpgt == IMA_FALSE) {
+ (void) fprintf(stdout, ",%d\n",
+ staticTargetProps.
+ staticTarget.targetAddress.tpgt);
+ } else {
+ (void) fprintf(stdout, "\n");
+ }
+ }
+
+ }
+ /*
+ * No details to display, but if there were:
+ * if (object && found)...
+ *
+ */
+
+ /*
+ * There was an object entered but we didn't
+ * find it.
+ */
+ if (object && !found) {
+ (void) fprintf(stdout, "%s: %s\n",
+ operand[i], gettext("not found"));
+ ret = 1; /* DIY test fix */
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Print targets
+ */
+/*ARGSUSED*/
+static int
+listTarget(int objectLen, char *objects[], cmdOptions_t *options, int *funcRet)
+{
+ IMA_OID initiatorOid;
+ IMA_OID_LIST *targetList;
+ IMA_OID_LIST *lunList;
+ SUN_IMA_TARGET_PROPERTIES targetProps;
+ IMA_STATUS status;
+ IMA_OID_LIST *pConnList;
+ SUN_IMA_CONN_PROPERTIES *connProps;
+
+ int ret;
+ wchar_t targetName[MAX_ISCSI_NAME_LEN + 1];
+ wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ int outerLoop;
+ boolean_t found;
+ boolean_t operandEntered = B_FALSE;
+ boolean_t verbose = B_FALSE;
+ boolean_t scsi_target = B_FALSE;
+ boolean_t targetAddressSpecified = B_FALSE;
+ boolean_t isIpv6 = B_FALSE;
+ int i, j;
+ cmdOptions_t *optionList = options;
+ boolean_t tpgtSpecified = B_FALSE;
+ IMA_UINT16 port = 0;
+ uint16_t tpgt;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'S':
+ scsi_target = B_TRUE;
+ break;
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optionList->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ /*
+ * If there are multiple objects, execute outer 'for' loop that
+ * many times for each target detail, otherwise, execute it only
+ * once with summaries only
+ */
+ if (objectLen > 0) {
+ operandEntered = B_TRUE;
+ outerLoop = objectLen;
+ } else {
+ operandEntered = B_FALSE;
+ outerLoop = 1;
+ }
+
+ status = SUN_IMA_GetSessionOidList(initiatorOid, &targetList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+
+ tpgtSpecified = B_FALSE;
+ if (operandEntered) {
+ if (parseTarget(objects[i],
+ &targetName[0],
+ MAX_ISCSI_NAME_LEN + 1,
+ &targetAddressSpecified,
+ &targetAddress[0],
+ SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port,
+ &tpgtSpecified,
+ &tpgt,
+ &isIpv6) != PARSE_TARGET_OK) {
+ ret = 1;
+ continue;
+ }
+ }
+ for (found = B_FALSE, j = 0; j < targetList->oidCount; j++) {
+ status = SUN_IMA_GetTargetProperties(
+ targetList->oids[j],
+ &targetProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /*
+ * Compare the target name with the input if
+ * one was input, if they match, print the target's info
+ *
+ * if no target name was input, continue printing this
+ * target
+ */
+ if (operandEntered) {
+ if (targetNamesEqual(targetProps.imaProps.name,
+ targetName) == B_TRUE) {
+ if (tpgtSpecified == B_TRUE) {
+ if (targetProps.
+ defaultTpgtConf ==
+ IMA_FALSE &&
+ targetProps.
+ tpgtConf == tpgt) {
+ found = B_TRUE;
+ } else {
+ /*
+ * tpgt does not match,
+ * move on to next
+ * target
+ */
+ continue;
+ }
+ } else {
+ found = B_TRUE;
+ }
+ } else {
+ /*
+ * target name does not match, move on
+ * to next target
+ */
+ continue;
+ }
+ }
+
+ /* print summary - always */
+ (void) fprintf(stdout, gettext("%s: %ws\n"),
+ gettext("Target"), targetProps.imaProps.name);
+
+ /* Alias */
+ (void) fprintf(stdout, "\t%s: ", gettext("Alias"));
+ if (wslen(targetProps.imaProps.alias) > (size_t)0) {
+ (void) fprintf(stdout, gettext("%ws\n"),
+ targetProps.imaProps.alias);
+ } else {
+ (void) fprintf(stdout, "%s\n", "-");
+ }
+
+ if (targetProps.defaultTpgtNego != IMA_TRUE) {
+ (void) fprintf(stdout, "%s%s: %d\n",
+ "\t", gettext("TPGT"),
+ targetProps.tpgtNego);
+ } else if (targetProps.defaultTpgtConf != IMA_TRUE) {
+ (void) fprintf(stdout, "%s%s: %d\n",
+ "\t", gettext("TPGT"),
+ targetProps.tpgtConf);
+ }
+
+ (void) fprintf(stdout,
+ "%s%s: %02x%02x%02x%02x%02x%02x\n",
+ "\t", gettext("ISID"),
+ targetProps.isid[0], targetProps.isid[1],
+ targetProps.isid[2], targetProps.isid[3],
+ targetProps.isid[4], targetProps.isid[5]);
+
+ pConnList = NULL;
+ status = SUN_IMA_GetConnOidList(
+ &targetList->oids[j],
+ &pConnList);
+
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ (void) fprintf(stdout, "%s%s: %lu\n",
+ "\t",
+ gettext("Connections"),
+ pConnList->oidCount);
+
+ if (verbose) {
+ SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms;
+
+ printConnectionList("\t\t", pConnList);
+ printDiscoveryMethod(
+ "\t\t ",
+ targetProps.imaProps.discoveryMethodFlags);
+ (void) printLoginParameters(
+ "\t\t ",
+ targetList->oids[j],
+ PRINT_NEGOTIATED_PARAMS);
+
+ /* Get Digest configuration */
+ status = SUN_IMA_GetConnProperties(
+ &pConnList->oids[0], &connProps);
+
+ (void) getNegotiatedDigest(
+ ISCSI_LOGIN_PARAM_HEADER_DIGEST,
+ &digestAlgorithms, connProps);
+
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t\t \t%s: ",
+ gettext("Header Digest"));
+ printDigestAlgorithm(
+ &digestAlgorithms,
+ PRINT_NEGOTIATED_PARAMS);
+ } else {
+ (void) IMA_FreeMemory(pConnList);
+ (void) IMA_FreeMemory(targetList);
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ (void) getNegotiatedDigest(
+ ISCSI_LOGIN_PARAM_DATA_DIGEST,
+ &digestAlgorithms, connProps);
+
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t\t \t%s: ",
+ gettext("Data Digest"));
+ printDigestAlgorithm(
+ &digestAlgorithms,
+ PRINT_NEGOTIATED_PARAMS);
+ } else {
+ (void) IMA_FreeMemory(pConnList);
+ (void) IMA_FreeMemory(targetList);
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ (void) fprintf(stdout, "\n");
+ }
+
+ if (scsi_target) {
+ status = IMA_GetLuOidList(
+ targetList->oids[j],
+ &lunList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+ if (lunList->oidCount != 0) {
+ printTargetLuns(lunList);
+ }
+ (void) fprintf(stdout, "\n");
+ (void) IMA_FreeMemory(lunList);
+ }
+ }
+ /*
+ * did we find the object
+ */
+
+ if (operandEntered && !found) {
+ (void) fprintf(stdout, "%s: %s\n",
+ objects[i], gettext("not found"));
+ }
+ }
+
+ (void) IMA_FreeMemory(targetList);
+ return (ret);
+}
+
+
+/*
+ * Print configured session information
+ */
+static int
+printConfiguredSessions(IMA_OID oid)
+{
+ IMA_STATUS status;
+ const char *rtn;
+ SUN_IMA_CONFIG_SESSIONS *pConfigSessions;
+ char address[MAX_ADDRESS_LEN];
+ int out;
+
+ /* Get configured session information */
+ status = SUN_IMA_GetConfigSessions(oid, &pConfigSessions);
+
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t%s: ",
+ gettext("Configured Sessions"));
+ if (pConfigSessions->bound == IMA_FALSE) {
+ /* default binding */
+ (void) fprintf(stdout, "%lu\n", pConfigSessions->out);
+ } else {
+ /* hardcoded binding */
+ for (out = 0;
+ out < pConfigSessions->out; out++) {
+ if (pConfigSessions->bindings[out].
+ ipAddress.ipv4Address == IMA_TRUE) {
+ rtn = inet_ntop(AF_INET,
+ pConfigSessions->bindings[out].
+ ipAddress.ipAddress, address,
+ MAX_ADDRESS_LEN);
+ } else {
+ rtn = inet_ntop(AF_INET6,
+ pConfigSessions->bindings[out].
+ ipAddress.ipAddress, address,
+ MAX_ADDRESS_LEN);
+ }
+ if (rtn != NULL) {
+ (void) printf("%s ", address);
+ }
+ }
+ (void) fprintf(stdout, "\n");
+ }
+ } else {
+ free(pConfigSessions);
+ printLibError(status);
+ return (1);
+ }
+
+ free(pConfigSessions);
+ return (0);
+}
+
+/*
+ * Print target parameters
+ */
+static int
+listTargetParam(int operandLen, char *operand[], cmdOptions_t *options,
+ int *funcRet)
+{
+ IMA_STATUS status;
+ IMA_OID initiatorOid;
+ IMA_OID_LIST *targetList;
+ IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS];
+ SUN_IMA_TARGET_PROPERTIES targetProps;
+ IMA_UINT maxEntries = MAX_AUTH_METHODS;
+ IMA_BOOL bidirAuth;
+ int ret;
+ wchar_t targetName[MAX_ISCSI_NAME_LEN + 1];
+ wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ boolean_t operandEntered = B_FALSE;
+ boolean_t targetAddressSpecified = B_FALSE;
+ boolean_t printObject = B_FALSE;
+ boolean_t tpgtSpecified = B_FALSE;
+ boolean_t isIpv6 = B_FALSE;
+ int outerLoop;
+ boolean_t found;
+ int i, j;
+ SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms;
+ boolean_t verbose = B_FALSE;
+ cmdOptions_t *optionList = options;
+ IMA_UINT16 port = 0;
+ IMA_UINT16 tpgt = 0;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'v':
+ verbose = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optionList->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ /*
+ * If there are multiple operands, execute outer 'for' loop that
+ * many times to find each target parameter operand entered, otherwise,
+ * execute it only once for all target parameters returned.
+ */
+ if (operandLen > 0) {
+ operandEntered = B_TRUE;
+ outerLoop = operandLen;
+ } else {
+ operandEntered = B_FALSE;
+ outerLoop = 1;
+ }
+
+ /*
+ * Ideally there should be an interface available for obtaining
+ * the list of target-param objects. Since the driver currently
+ * creates a target OID and the associated session structure when
+ * a target-param object is created, we can leverage the target
+ * OID list and use it to manage the target-param objects. When
+ * we stop creating a session for target-param object in the
+ * driver, we will switch to using a different interface to
+ * obtain target-param objects.
+ */
+ status = IMA_GetTargetOidList(initiatorOid, &targetList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < outerLoop; i++) {
+ if (operandEntered) {
+ if (parseTarget(operand[i],
+ &targetName[0],
+ MAX_ISCSI_NAME_LEN + 1,
+ &targetAddressSpecified,
+ &targetAddress[0],
+ SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port,
+ &tpgtSpecified,
+ &tpgt,
+ &isIpv6) != PARSE_TARGET_OK) {
+ ret = 1;
+ continue;
+ }
+ }
+ for (j = 0; j < targetList->oidCount; j++) {
+ found = B_FALSE;
+ printObject = B_FALSE;
+ status = SUN_IMA_GetTargetProperties(
+ targetList->oids[j],
+ &targetProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /*
+ * Compare the target name with the input if
+ * one was input
+ */
+ if (operandEntered &&
+ (targetNamesEqual(targetProps.imaProps.name,
+ targetName) == B_TRUE)) {
+ /*
+ * For now, regardless of whether a target
+ * address is specified, we return B_TRUE
+ * because IMA_TARGET_PROPERTIES does not
+ * have a field for specifying address.
+ */
+ found = B_TRUE;
+ }
+
+ /*
+ * if no operand was entered OR
+ * an operand was entered and it was
+ * found, we want to print
+ */
+ if (!operandEntered || found) {
+ printObject = B_TRUE;
+ }
+
+ if (printObject) {
+ (void) fprintf(stdout, gettext("%s: %ws\n"),
+ gettext("Target"),
+ targetProps.imaProps.name);
+
+ (void) fprintf(stdout,
+ "\t%s: ", gettext("Alias"));
+ if (wslen(targetProps.imaProps.alias) >
+ (size_t)0) {
+ (void) fprintf(stdout,
+ gettext("%ws\n"),
+ targetProps.imaProps.alias);
+ } else {
+ (void) fprintf(stdout, "%s\n", "-");
+ }
+ }
+
+ if (printObject && verbose) {
+ /* Get bidirectional authentication flag */
+ (void) fprintf(stdout, "\t%s: ",
+ gettext("Bi-directional Authentication"));
+ status = SUN_IMA_GetTargetBidirAuthFlag(
+ targetList->oids[j],
+ &bidirAuth);
+ if (IMA_SUCCESS(status)) {
+ if (bidirAuth == IMA_TRUE) {
+ (void) fprintf(stdout,
+ gettext("enabled"));
+ } else {
+ (void) fprintf(stdout,
+ gettext("disabled"));
+ }
+ } else {
+ (void) fprintf(stdout,
+ gettext("disabled"));
+ }
+ (void) fprintf(stdout, "\n");
+
+ /* Get authentication type for this target */
+ status = SUN_IMA_GetTargetAuthMethods(
+ initiatorOid,
+ targetList->oids[j],
+ &maxEntries,
+ &methodList[0]);
+ (void) fprintf(stdout, "\t%s: ",
+ gettext("Authentication Type"));
+ if (!IMA_SUCCESS(status)) {
+ /*
+ * No authentication method define
+ * NONE by default.
+ */
+ (void) fprintf(stdout, gettext("NONE"));
+ } else {
+ for (i = 0; i < maxEntries; i++) {
+ if (i > 0) {
+ (void) fprintf(stdout,
+ "|");
+ }
+ switch (methodList[i]) {
+ case IMA_AUTHMETHOD_NONE:
+ (void) fprintf(stdout,
+ gettext("NONE"));
+ break;
+
+ case IMA_AUTHMETHOD_CHAP:
+ (void) fprintf(stdout,
+ gettext("CHAP"));
+ listCHAPName(
+ targetList->
+ oids[j]);
+ break;
+
+ default:
+ (void) fprintf(stdout,
+ gettext(
+ "unknown "
+ "type"));
+ break;
+ }
+ }
+ }
+ (void) fprintf(stdout, "\n");
+ if (printLoginParameters("\t",
+ targetList->oids[j],
+ PRINT_CONFIGURED_PARAMS)
+ != 0) {
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /* Get Digest configuration */
+ status = SUN_IMA_GetHeaderDigest(
+ targetList->oids[j],
+ &digestAlgorithms);
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t\t%s: ",
+ gettext("Header Digest"));
+ printDigestAlgorithm(&digestAlgorithms,
+ PRINT_CONFIGURED_PARAMS);
+ } else {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ status = SUN_IMA_GetDataDigest(
+ targetList->oids[j],
+ &digestAlgorithms);
+ if (IMA_SUCCESS(status)) {
+ (void) fprintf(stdout, "\t\t%s: ",
+ gettext("Data Digest"));
+ printDigestAlgorithm(&digestAlgorithms,
+ PRINT_CONFIGURED_PARAMS);
+ } else {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /* print configured session information */
+ if (printConfiguredSessions(
+ targetList->oids[j]) != 0) {
+ *funcRet = 1;
+ return (ret);
+ }
+
+ (void) fprintf(stdout, "\n");
+ }
+
+ if (found) {
+ break;
+ }
+ }
+ if (operandEntered && !found) {
+ *funcRet = 1; /* DIY message fix */
+ (void) fprintf(stdout, "%s: %s\n",
+ operand[i], gettext("not found"));
+ }
+ }
+
+ (void) IMA_FreeMemory(targetList);
+ return (ret);
+}
+
+/*
+ * Modify discovery attributes
+ */
+static int
+modifyDiscovery(cmdOptions_t *options, int *funcRet)
+{
+ IMA_OID oid;
+ IMA_STATUS status;
+ IMA_BOOL setDiscovery;
+ IMA_HOST_ID hostId;
+
+ int ret;
+ cmdOptions_t *optionList = options;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&oid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (; optionList->optval; optionList++) {
+ /* check optarg and set bool accordingly */
+ if (strcasecmp(optionList->optarg, ISCSIADM_ARG_ENABLE) == 0) {
+ setDiscovery = IMA_TRUE;
+ } else if (strcasecmp(optionList->optarg, ISCSIADM_ARG_DISABLE)
+ == 0) {
+ setDiscovery = IMA_FALSE;
+ } else {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+
+ switch (optionList->optval) {
+ case 's':
+ /* Set static discovery */
+ status = IMA_SetStaticDiscovery(oid,
+ setDiscovery);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ break;
+ case 't':
+ /* Set send targets discovery */
+ status = IMA_SetSendTargetsDiscovery(oid,
+ setDiscovery);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ break;
+ case 'i':
+ /* Set iSNS discovery */
+ (void) memset(&hostId, 0, sizeof (hostId));
+ status = IMA_SetIsnsDiscovery(oid, setDiscovery,
+ IMA_ISNS_DISCOVERY_METHOD_STATIC, &hostId);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optionList->optval,
+ gettext("unknown option"));
+ return (1);
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * Set the initiator node's authentication method
+ */
+static int
+modifyNodeAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet)
+{
+ IMA_INITIATOR_AUTHPARMS authParams;
+ IMA_STATUS status;
+ int ret;
+ int secretLen = MAX_CHAP_SECRET_LEN;
+
+ IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1];
+
+ assert(funcRet != NULL);
+
+ /*
+ * Start with existing parameters and modify with the desired change
+ * before passing along. We ignore any failures as they probably
+ * are caused by non-existence of auth params for the given node.
+ */
+ status = IMA_GetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP,
+ &authParams);
+
+ switch (param) {
+ case AUTH_NAME:
+ if (chapName == NULL) {
+ (void) fprintf(stderr, "CHAP name cannot be NULL.\n");
+ return (1);
+ }
+ (void) memset(&authParams.chapParms.name, 0,
+ sizeof (authParams.chapParms.name));
+ (void) memcpy(&authParams.chapParms.name,
+ &chapName[0], strlen(chapName));
+ authParams.chapParms.nameLength = strlen(chapName);
+ break;
+
+ case AUTH_PASSWORD :
+ ret = getSecret((char *)&chapSecret[0], &secretLen,
+ MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN);
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ (void) memset(&authParams.chapParms.challengeSecret, 0,
+ sizeof (authParams.chapParms.challengeSecret));
+ (void) memcpy(&authParams.chapParms.challengeSecret,
+ &chapSecret[0], secretLen);
+ authParams.chapParms.challengeSecretLength = secretLen;
+ break;
+
+ default:
+ (void) fprintf(stderr, "Invalid auth parameter %d\n", param);
+ return (1);
+ }
+
+ status = IMA_SetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP,
+ &authParams);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+ return (ret);
+}
+
+/*
+ * Set the target's authentication method
+ */
+static int
+modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet)
+{
+ IMA_INITIATOR_AUTHPARMS authParams;
+ IMA_STATUS status;
+ int ret;
+ int secretLen = MAX_CHAP_SECRET_LEN;
+
+ IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1];
+
+ assert(funcRet != NULL);
+
+ /*
+ * Start with existing parameters and modify with the desired change
+ * before passing along. We ignore any get failures as they probably
+ * are caused by non-existence of auth params for the given target.
+ */
+ status = SUN_IMA_GetTargetAuthParms(oid, IMA_AUTHMETHOD_CHAP,
+ &authParams);
+
+ switch (param) {
+ case AUTH_NAME:
+ if (chapName == NULL) {
+ (void) fprintf(stderr, "CHAP name cannot be NULL.\n");
+ return (1);
+ }
+ (void) memset(&authParams.chapParms.name, 0,
+ sizeof (authParams.chapParms.name));
+ (void) memcpy(&authParams.chapParms.name,
+ &chapName[0], strlen(chapName));
+ authParams.chapParms.nameLength = strlen(chapName);
+ break;
+
+ case AUTH_PASSWORD :
+ ret = getSecret((char *)&chapSecret[0], &secretLen,
+ 1, MAX_CHAP_SECRET_LEN);
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ (void) memset(&authParams.chapParms.challengeSecret, 0,
+ sizeof (authParams.chapParms.challengeSecret));
+ (void) memcpy(&authParams.chapParms.challengeSecret,
+ &chapSecret[0], secretLen);
+ authParams.chapParms.challengeSecretLength = secretLen;
+ break;
+
+ default:
+ (void) fprintf(stderr, "Invalid auth parameter %d\n", param);
+ return (1);
+ }
+
+ status = SUN_IMA_SetTargetAuthParams(oid, IMA_AUTHMETHOD_CHAP,
+ &authParams);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+ return (0);
+}
+
+static int
+modifyTargetBidirAuthFlag(IMA_OID targetOid, char *optarg, int *funcRet)
+{
+ IMA_BOOL boolValue;
+ IMA_STATUS status;
+
+ assert(funcRet != NULL);
+
+ if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) {
+ boolValue = IMA_TRUE;
+ } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) {
+ boolValue = IMA_FALSE;
+ } else {
+ (void) fprintf(stderr, "%s: %s %s\n",
+ cmdName, gettext("invalid option argument"), optarg);
+ return (1);
+ }
+
+ status = SUN_IMA_SetTargetBidirAuthFlag(targetOid, &boolValue);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+ return (0);
+}
+
+static int
+modifyConfiguredSessions(IMA_OID targetOid, char *optarg)
+{
+ SUN_IMA_CONFIG_SESSIONS *pConfigSessions;
+ IMA_STATUS status;
+ int sessions;
+ int size;
+ char tmp[1024];
+ boolean_t isIpv6 = B_FALSE;
+ uint16_t port;
+ char address[MAX_ADDRESS_LEN];
+ char *commaPos;
+ char *addressPos;
+ int rtn;
+
+ /*
+ * Strip the first int value from the string. If we sprintf
+ * this back to a string and it matches the original string
+ * then this command is using default binding. If not a
+ * match we have hard coded binding or a usage error.
+ */
+ sessions = atoi(optarg);
+ (void) sprintf(tmp, "%d", sessions);
+ if (strcmp(optarg, tmp) == 0) {
+ /* default binding */
+
+ /* allocate the required pConfigSessions */
+ size = sizeof (SUN_IMA_CONFIG_SESSIONS);
+ pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size);
+ if (pConfigSessions == NULL) {
+ return (1);
+ }
+
+ /* setup pConfigSessions */
+ pConfigSessions->bound = IMA_FALSE;
+ pConfigSessions->in = sessions;
+ pConfigSessions->out = 0;
+ } else {
+ /* hardcoded binding */
+
+ /*
+ * First we need to determine how many bindings
+ * are available. This can be done by scanning
+ * for the number of ',' + 1.
+ */
+ sessions = 1;
+ commaPos = strchr(optarg, ',');
+ while (commaPos != NULL) {
+ sessions++;
+ commaPos = strchr(++commaPos, ',');
+ }
+
+ /* allocate the required pConfigSessions */
+ size = sizeof (SUN_IMA_CONFIG_SESSIONS) + ((sessions - 1) *
+ sizeof (IMA_ADDRESS_KEY));
+ pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size);
+ if (pConfigSessions == NULL) {
+ return (1);
+ }
+
+ /* setup pConfigSessions */
+ pConfigSessions->bound = IMA_TRUE;
+ pConfigSessions->in = sessions;
+ pConfigSessions->out = 0;
+
+ /* Now fill in the binding information. */
+ sessions = 0;
+ addressPos = optarg;
+ /*
+ * Walk thru possible address strings
+ * stop once all strings are processed.
+ */
+ while (addressPos != NULL) {
+ /*
+ * Check if there is another address after this
+ * one. If so terminate the current address and
+ * keep a pointer to the next one.
+ */
+ commaPos = strchr(addressPos, ',');
+ if (commaPos != NULL) {
+ *commaPos++ = 0x00;
+ }
+
+ /*
+ * Parse current address. If invalid abort
+ * processing of addresses and free memory.
+ */
+ if (parseAddress(addressPos, 0, address,
+ MAX_ADDRESS_LEN, &port, &isIpv6) != PARSE_ADDR_OK) {
+ free(pConfigSessions);
+ printLibError(IMA_ERROR_INVALID_PARAMETER);
+ return (1);
+ }
+
+ /* Convert address into binary form */
+ if (isIpv6 == B_FALSE) {
+ pConfigSessions->bindings[sessions].
+ ipAddress.ipv4Address = IMA_TRUE;
+ rtn = inet_pton(AF_INET, address,
+ pConfigSessions->bindings[sessions].
+ ipAddress.ipAddress);
+ } else {
+ pConfigSessions->bindings[sessions].ipAddress.
+ ipv4Address =
+ IMA_FALSE;
+ rtn = inet_pton(AF_INET6, address,
+ pConfigSessions->bindings[sessions].
+ ipAddress.ipAddress);
+ }
+ if (rtn == 0) {
+ /* inet_pton found address invalid */
+ free(pConfigSessions);
+ printLibError(IMA_ERROR_INVALID_PARAMETER);
+ return (1);
+ }
+
+ /* update addressPos to next address */
+ sessions++;
+ addressPos = commaPos;
+ }
+ }
+
+ /* issue SUN_IMA request */
+ status = SUN_IMA_SetConfigSessions(targetOid,
+ pConfigSessions);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ free(pConfigSessions);
+ return (1);
+ }
+
+ free(pConfigSessions);
+ return (0);
+}
+
+static int
+getAuthMethodValue(char *method, IMA_AUTHMETHOD *value)
+{
+ if (strcasecmp(method, "chap") == 0) {
+ *value = IMA_AUTHMETHOD_CHAP;
+ return (0);
+ }
+
+ if (strcasecmp(method, "none") == 0) {
+ *value = IMA_AUTHMETHOD_NONE;
+ return (0);
+ }
+
+ return (1);
+}
+
+
+/*
+ * Set the authentication method
+ * Currently only supports CHAP and NONE
+ */
+static int
+modifyNodeAuthMethod(IMA_OID oid, char *optarg, int *funcRet)
+{
+ IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS];
+ IMA_UINT methodCount = 0;
+ IMA_STATUS status;
+ IMA_AUTHMETHOD value;
+ char *method;
+ char *commaPos;
+
+ assert(funcRet != NULL);
+
+ /*
+ * optarg will be a , delimited set of auth methods, in order
+ * of preference
+ * if any values here are incorrect, return without setting
+ * anything.
+ */
+ method = optarg;
+
+ commaPos = strchr(optarg, ',');
+
+ while (commaPos && methodCount < MAX_AUTH_METHODS) {
+ *commaPos = NULL;
+ if (getAuthMethodValue(method, &value) != 0) {
+ (void) fprintf(stderr, "%s: a: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+ methodList[methodCount++] = value;
+ commaPos++;
+ method = commaPos;
+ commaPos = strchr(method, ',');
+ }
+ /* Should not find more method specified - if found, error */
+ if (commaPos) {
+ (void) fprintf(stderr, "%s: -a: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+ if (getAuthMethodValue(method, &value) != 0) {
+ (void) fprintf(stderr, "%s: -a: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+ methodList[methodCount++] = value;
+
+ status = IMA_SetInitiatorAuthMethods(oid, methodCount, &methodList[0]);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+ return (0);
+}
+
+static int
+modifyTargetAuthMethod(IMA_OID oid, char *optarg, int *funcRet)
+{
+ IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS];
+ IMA_UINT methodCount = 0;
+ IMA_STATUS status;
+ IMA_AUTHMETHOD value;
+ char *method;
+ char *commaPos;
+
+ assert(funcRet != NULL);
+
+ /*
+ * optarg will be a , delimited set of auth methods, in order
+ * of preference
+ * if any values here are incorrect, return without setting
+ * anything.
+ */
+ method = optarg;
+
+ commaPos = strchr(optarg, ',');
+
+ while (commaPos && methodCount < MAX_AUTH_METHODS) {
+ *commaPos = NULL;
+ if (getAuthMethodValue(method, &value) != 0) {
+ (void) fprintf(stderr, "%s: a: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+ methodList[methodCount++] = value;
+ commaPos++;
+ method = commaPos;
+ commaPos = strchr(method, ',');
+ }
+ /* Should not find more method specified - if found, error */
+ if (commaPos) {
+ (void) fprintf(stderr, "%s: -a: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+ if (getAuthMethodValue(method, &value) != 0) {
+ (void) fprintf(stderr, "%s: -a: %s\n",
+ cmdName, gettext("invalid option argument"));
+ return (1);
+ }
+ methodList[methodCount++] = value;
+
+ status = SUN_IMA_SetTargetAuthMethods(oid, &methodCount,
+ &methodList[0]);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+ return (0);
+}
+
+/*
+ * Modify the RADIUS configuration of the initiator node.
+ *
+ * Return 0 on success.
+ */
+static int
+modifyNodeRadiusConfig(IMA_OID oid, char *optarg, int *funcRet)
+{
+ SUN_IMA_RADIUS_CONFIG config;
+ IMA_STATUS status;
+ boolean_t isIpv6 = B_FALSE;
+ uint16_t port;
+
+ assert(funcRet != NULL);
+
+ (void) memset(&config, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
+ if (parseAddress(optarg, DEFAULT_RADIUS_PORT,
+ &config.hostnameIpAddress[0], SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port, &isIpv6) !=
+ PARSE_ADDR_OK) {
+ return (1);
+ }
+ config.port = (IMA_UINT16)port;
+ config.isIpv6 = (isIpv6 == B_TRUE) ? IMA_TRUE : IMA_FALSE;
+ /* Not setting shared secret here. */
+ config.sharedSecretValid = IMA_FALSE;
+
+ status = SUN_IMA_SetInitiatorRadiusConfig(oid, &config);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+
+ return (0);
+}
+
+/*
+ * Modify the RADIUS access flag of the initiator node.
+ *
+ * Return 0 on success.
+ */
+static int
+modifyNodeRadiusAccess(IMA_OID oid, char *optarg, int *funcRet)
+{
+ IMA_BOOL radiusAccess;
+ IMA_OID initiatorOid;
+ IMA_STATUS status;
+ SUN_IMA_RADIUS_CONFIG radiusConfig;
+ int ret;
+
+ assert(funcRet != NULL);
+
+ /* Check if Radius Config is there */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret != 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ return (1);
+ }
+ (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
+ status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig);
+ if (!IMA_SUCCESS(status)) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("RADIUS server not configured yet"));
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /* Check if Radius Shared is set */
+ if (radiusConfig.sharedSecretValid == IMA_FALSE) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("RADIUS server secret not configured yet"));
+ return (1);
+ }
+
+ if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) {
+ radiusAccess = IMA_TRUE;
+ } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) {
+ radiusAccess = IMA_FALSE;
+ } else {
+ (void) fprintf(stderr, "%s: %s %s\n",
+ cmdName,
+ gettext("invalid option argument"),
+ optarg);
+ return (1);
+ }
+ status = SUN_IMA_SetInitiatorRadiusAccess(oid, radiusAccess);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+
+ return (ret);
+}
+
+/*
+ * Modify the RADIUS shared secret.
+ *
+ * Returns:
+ * zero on success.
+ * > 0 on failure.
+ */
+static int
+modifyNodeRadiusSharedSecret(IMA_OID oid, int *funcRet)
+{
+ IMA_BYTE radiusSharedSecret[SUN_IMA_MAX_RADIUS_SECRET_LEN + 1];
+ IMA_OID initiatorOid;
+ IMA_STATUS status;
+ SUN_IMA_RADIUS_CONFIG radiusConfig;
+ int ret;
+ int secretLen = SUN_IMA_MAX_RADIUS_SECRET_LEN;
+
+ assert(funcRet != NULL);
+
+ ret = getSecret((char *)&radiusSharedSecret[0], &secretLen,
+ 0, SUN_IMA_MAX_RADIUS_SECRET_LEN);
+ if (ret != 0) {
+ return (1);
+ }
+
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+ if (ret != 0) {
+ return (1);
+ }
+ /* First obtain existing RADIUS configuration (if any) */
+ (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
+ status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig);
+ if (!IMA_SUCCESS(status)) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("RADIUS server not configured yet"));
+ return (1);
+ }
+
+ /* Modify the shared secret only */
+ radiusConfig.sharedSecretLength = secretLen;
+ (void) memcpy(&radiusConfig.sharedSecret,
+ &radiusSharedSecret[0], secretLen);
+ radiusConfig.sharedSecretValid = IMA_TRUE;
+ status = SUN_IMA_SetInitiatorRadiusConfig(oid, &radiusConfig);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+
+ return (0);
+}
+
+/*
+ * Set initiator node attributes.
+ */
+static int
+modifyNode(cmdOptions_t *options, int *funcRet)
+{
+ IMA_NODE_NAME nodeName;
+ IMA_NODE_ALIAS nodeAlias;
+ IMA_OID oid;
+ IMA_STATUS status;
+ cmdOptions_t *optionList = options;
+ int ret;
+ iSCSINameCheckStatusType nameCheckStatus;
+ IMA_OID sharedNodeOid;
+ int i;
+ int lowerCase;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&oid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'N':
+ if (strlen(optionList->optarg) >=
+ MAX_ISCSI_NAME_LEN) {
+ (void) fprintf(stderr, "%s: %s %d\n",
+ cmdName,
+ gettext("name too long, \
+ maximum length is:"),
+ MAX_ISCSI_NAME_LEN);
+ }
+
+ /* Take the first operand as node name. */
+ (void) memset(&nodeName, 0,
+ sizeof (IMA_NODE_NAME));
+ if (mbstowcs(nodeName, optionList->optarg,
+ IMA_NODE_NAME_LEN) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("conversion error"));
+ return (1);
+ }
+
+ for (i = 0; nodeName[i] != 0; i++) {
+ lowerCase = tolower(nodeName[i]);
+ nodeName[i] = lowerCase;
+ }
+ /* Perform string profile checks */
+ nameCheckStatus =
+ iSCSINameStringProfileCheck(nodeName);
+ iSCSINameCheckStatusDisplay(nameCheckStatus);
+ if (nameCheckStatus != iSCSINameCheckOK) {
+ *funcRet = 1; /* DIY message fix */
+ return (1);
+ }
+
+ /*
+ * IMA_GetSharedNodeOid(&sharedNodeOid);
+ * if (!IMA_SUCCESS(status)) {
+ * printLibError(status);
+ * return (INF_ERROR);
+ * }
+ */
+ oid.objectType = IMA_OBJECT_TYPE_NODE;
+ status = IMA_SetNodeName(oid, nodeName);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ break;
+
+ case 'A':
+ /* Take the first operand as node alias. */
+ if (strlen(optionList->optarg) >=
+ MAX_ISCSI_NAME_LEN) {
+ (void) fprintf(stderr, "%s: %s %d\n",
+ cmdName,
+ gettext("alias too long, maximum \
+ length is:"),
+ MAX_ISCSI_NAME_LEN);
+ }
+
+ (void) memset(&nodeAlias, 0,
+ sizeof (IMA_NODE_ALIAS));
+ if (mbstowcs(nodeAlias, optionList->optarg,
+ IMA_NODE_ALIAS_LEN) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("conversion error"));
+ return (1);
+ }
+
+ status = IMA_GetSharedNodeOid(&sharedNodeOid);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ status = IMA_SetNodeAlias(sharedNodeOid,
+ nodeAlias);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ break;
+
+ case 'a':
+ if (modifyNodeAuthMethod(oid, options->optarg,
+ funcRet) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'R':
+ if (modifyNodeRadiusAccess(oid, options->optarg,
+ funcRet) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'r':
+ if (modifyNodeRadiusConfig(oid, options->optarg,
+ funcRet) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'P':
+ if (modifyNodeRadiusSharedSecret(oid, funcRet)
+ != 0) {
+ return (1);
+ }
+ break;
+
+ case 'C':
+ if (modifyNodeAuthParam(oid, AUTH_PASSWORD,
+ NULL, funcRet) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'c':
+ if (modifyConfiguredSessions(oid,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'H':
+ if (modifyNodeAuthParam(oid, AUTH_NAME,
+ optionList->optarg, funcRet) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'd':
+ if (setLoginParameter(oid, DATA_DIGEST,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+
+ case 'h':
+ if (setLoginParameter(oid, HEADER_DIGEST,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+
+ default:
+ (void) fprintf(stderr, "%s: %c: %s\n",
+ cmdName, optionList->optval,
+ gettext("unknown option"));
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * Modify target parameters
+ */
+static int
+modifyTargetParam(cmdOptions_t *options, char *targetName, int *funcRet)
+{
+ IMA_OID oid;
+ IMA_OID targetOid;
+ IMA_STATUS status;
+ IMA_OID_LIST *targetList;
+ SUN_IMA_TARGET_PROPERTIES targetProps;
+ wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1];
+ wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ int ret;
+ boolean_t found;
+ boolean_t targetAddressSpecified = B_TRUE;
+ boolean_t tpgtSpecified = B_FALSE;
+ boolean_t isIpv6 = B_FALSE;
+ int i;
+ iSCSINameCheckStatusType nameCheckStatus;
+ IMA_UINT16 port = 0;
+ IMA_UINT16 tpgt = 0;
+
+ cmdOptions_t *optionList = options;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&oid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ if (parseTarget(targetName,
+ &wcInputObject[0],
+ MAX_ISCSI_NAME_LEN + 1,
+ &targetAddressSpecified,
+ &targetAddress[0],
+ SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port,
+ &tpgtSpecified,
+ &tpgt,
+ &isIpv6) != PARSE_TARGET_OK) {
+ return (1);
+ }
+
+ /* Perform string profile checks */
+ nameCheckStatus = iSCSINameStringProfileCheck(wcInputObject);
+ iSCSINameCheckStatusDisplay(nameCheckStatus);
+ if (nameCheckStatus != iSCSINameCheckOK) {
+ return (1);
+ }
+
+ status = IMA_GetTargetOidList(oid, &targetList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (0);
+ }
+
+ /* find target oid */
+ for (found = B_FALSE, i = 0; i < targetList->oidCount; i++) {
+ status = SUN_IMA_GetTargetProperties(targetList->oids[i],
+ &targetProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /*
+ * Compare the target name with the input name
+ */
+ if ((targetNamesEqual(wcInputObject, targetProps.imaProps.name)
+ == B_TRUE)) {
+ /*
+ * For now, regardless of whether a target address
+ * is specified, we return B_TRUE because
+ * IMA_TARGET_PROPERTIES does not have a field for
+ * specifying address.
+ */
+ found = B_TRUE;
+ targetOid = targetList->oids[i];
+ if (modifyIndividualTargetParam(optionList, targetOid,
+ funcRet) != 0) {
+ return (ret);
+ }
+
+ /*
+ * Even after finding a matched target, keep going
+ * since there could be multiple target objects
+ * associated with one target name in the system
+ * because of different TPGTs.
+ */
+ }
+ }
+
+ /* If the target OID cannot be found create one */
+ if (!found) {
+ status = SUN_IMA_CreateTargetOid(wcInputObject, &targetOid);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+ if (modifyIndividualTargetParam(optionList, targetOid,
+ funcRet) != 0) {
+ return (ret);
+ }
+ }
+
+ (void) IMA_FreeMemory(targetList);
+ return (ret);
+}
+
+/*
+ * Add one or more addresses
+ */
+static int
+addAddress(int addrType, int operandLen, char *operand[], int *funcRet)
+{
+ IMA_STATUS status;
+ IMA_OID oid, addressOid;
+ SUN_IMA_TARGET_ADDRESS address;
+ wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
+ int ret;
+ int i;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&oid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ /*
+ * Format of discovery address operand:
+ *
+ * <IP address|hostname>:<port>
+ */
+ for (i = 0; i < operandLen; i++) {
+ /* initialize */
+ (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject));
+ (void) memset(&address, 0, sizeof (address));
+
+ if (mbstowcs(wcInputObject, operand[i],
+ (MAX_ADDRESS_LEN + 1)) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("conversion error"));
+ ret = 1;
+ continue;
+ }
+ if (getTargetAddress(addrType, operand[i], &address.imaStruct)
+ != 0) {
+ ret = 1;
+ continue;
+ }
+ if (addrType == DISCOVERY_ADDRESS) {
+ status = IMA_AddDiscoveryAddress(oid,
+ address.imaStruct, &addressOid);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ } else if (addrType == ISNS_SERVER_ADDRESS) {
+ status = SUN_IMA_AddISNSServerAddress(address);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Add one or more static configuration targets
+ */
+static int
+addStaticConfig(int operandLen, char *operand[], int *funcRet)
+{
+ int i;
+ boolean_t targetAddressSpecified = B_FALSE;
+ boolean_t tpgtSpecified = B_FALSE;
+ boolean_t isIpv6 = B_FALSE;
+ int ret;
+ int addrType;
+ IMA_STATUS status;
+ IMA_OID oid;
+ SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig;
+ IMA_UINT16 port = 0;
+ IMA_UINT16 tpgt = 0;
+ wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1];
+ wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ iSCSINameCheckStatusType nameCheckStatus;
+ char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&oid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ /*
+ * Format of static config operand:
+ * <target-name>,<IP address|hostname>[:port][,tpgt]
+ */
+ for (i = 0; i < operandLen; i++) {
+ if (parseTarget(operand[i],
+ &staticTargetName[0],
+ MAX_ISCSI_NAME_LEN + 1,
+ &targetAddressSpecified,
+ &staticTargetAddress[0],
+ SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port,
+ &tpgtSpecified,
+ &tpgt,
+ &isIpv6) != PARSE_TARGET_OK) {
+ ret = 1;
+ continue;
+ }
+
+ if (targetAddressSpecified != B_TRUE) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("missing target address"));
+ *funcRet = 1; /* DIY message fix */
+ return (1);
+ }
+ /* Perform string profile checks */
+ nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName);
+ iSCSINameCheckStatusDisplay(nameCheckStatus);
+ if (nameCheckStatus != iSCSINameCheckOK) {
+ *funcRet = 1; /* DIY message fix */
+ return (1);
+ }
+ (void) wcsncpy(staticConfig.targetName, staticTargetName,
+ MAX_ISCSI_NAME_LEN + 1);
+
+ (void) wcstombs(sAddr, staticTargetAddress, sizeof (sAddr));
+
+ if (isIpv6 == B_TRUE) {
+ staticConfig.targetAddress.imaStruct.hostnameIpAddress.
+ id.ipAddress.ipv4Address = B_FALSE;
+ addrType = AF_INET6;
+ } else {
+ staticConfig.targetAddress.imaStruct.hostnameIpAddress.
+ id.ipAddress.ipv4Address = B_TRUE;
+ addrType = AF_INET;
+ }
+
+ if (inet_pton(addrType, sAddr, staticConfig.targetAddress.
+ imaStruct.hostnameIpAddress.id.ipAddress.ipAddress) != 1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("static config conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ staticConfig.targetAddress.imaStruct.portNumber = port;
+ if (tpgtSpecified == B_TRUE) {
+ staticConfig.targetAddress.defaultTpgt = B_FALSE;
+ staticConfig.targetAddress.tpgt = tpgt;
+ } else {
+ staticConfig.targetAddress.defaultTpgt = B_TRUE;
+ staticConfig.targetAddress.tpgt = 0;
+ }
+
+ status = SUN_IMA_AddStaticTarget(oid, staticConfig, &oid);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (1);
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Remove one or more addresses
+ */
+static int
+removeAddress(int addrType, int operandLen, char *operand[], int *funcRet)
+{
+ IMA_STATUS status;
+ IMA_OID initiatorOid;
+ SUN_IMA_TARGET_ADDRESS address;
+ wchar_t wcInputObject[MAX_ADDRESS_LEN + 1];
+ int ret;
+ int i;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ /* initialize */
+ (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject));
+ (void) memset(&address, 0, sizeof (address));
+
+ if (mbstowcs(wcInputObject, operand[i],
+ MAX_ADDRESS_LEN + 1) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ if (getTargetAddress(addrType, operand[i], &address.imaStruct)
+ != 0) {
+ ret = 1;
+ continue;
+ }
+
+ if (addrType == DISCOVERY_ADDRESS) {
+ status = SUN_IMA_RemoveDiscoveryAddress(address);
+ if (!IMA_SUCCESS(status)) {
+ if (status == IMA_ERROR_OBJECT_NOT_FOUND) {
+ (void) fprintf(stderr, "%s: %s\n",
+ operand[i], gettext("not found"));
+ } else {
+ printLibError(status);
+ }
+ *funcRet = 1;
+ }
+ } else {
+ status = SUN_IMA_RemoveISNSServerAddress(address);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ }
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Remove one or more static configuration targets
+ */
+static int
+removeStaticConfig(int operandLen, char *operand[], int *funcRet)
+{
+ IMA_STATUS status;
+ IMA_OID initiatorOid;
+ IMA_OID_LIST *staticTargetList;
+ SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps;
+ wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1];
+ wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ int ret;
+ boolean_t atLeastFoundOne;
+ boolean_t matched;
+ boolean_t targetAddressSpecified = B_TRUE;
+ boolean_t tpgtSpecified = B_FALSE;
+ boolean_t isIpv6 = B_FALSE;
+ int i, j;
+ IMA_UINT16 port = 0;
+ IMA_UINT16 tpgt = 0;
+ iSCSINameCheckStatusType nameCheckStatus;
+ char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid,
+ &staticTargetList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ if (parseTarget(operand[i],
+ &staticTargetName[0],
+ MAX_ISCSI_NAME_LEN + 1,
+ &targetAddressSpecified,
+ &staticTargetAddress[0],
+ SUN_IMA_IP_ADDRESS_PORT_LEN,
+ &port,
+ &tpgtSpecified,
+ &tpgt,
+ &isIpv6) != PARSE_TARGET_OK) {
+ ret = 1;
+ continue;
+ }
+
+ /* Perform string profile checks */
+ nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName);
+ iSCSINameCheckStatusDisplay(nameCheckStatus);
+ if (nameCheckStatus != iSCSINameCheckOK) {
+ return (1);
+ }
+
+ for (atLeastFoundOne = B_FALSE, j = 0;
+ j < staticTargetList->oidCount;
+ j++) {
+ IMA_UINT16 stpgt;
+
+ matched = B_FALSE;
+ status = SUN_IMA_GetStaticTargetProperties(
+ staticTargetList->oids[j], &staticTargetProps);
+ if (!IMA_SUCCESS(status)) {
+ if (status == IMA_ERROR_OBJECT_NOT_FOUND) {
+ /*
+ * When removing multiple static-config
+ * entries we need to expect get
+ * failures. These failures occur when
+ * we are trying to get entry
+ * information we have just removed.
+ * Ignore the failure and continue.
+ */
+ ret = 1;
+ continue;
+ } else {
+ printLibError(status);
+ (void) IMA_FreeMemory(staticTargetList);
+ *funcRet = 1;
+ return (ret);
+ }
+ }
+
+ stpgt =
+ staticTargetProps.staticTarget.targetAddress.tpgt;
+
+ /*
+ * Compare the static target name with the input if
+ * one was input
+ */
+ if ((targetNamesEqual(
+ staticTargetProps.staticTarget.targetName,
+ staticTargetName) == B_TRUE)) {
+ if (targetAddressSpecified == B_FALSE) {
+ matched = B_TRUE;
+ } else {
+
+ if (staticTargetProps.staticTarget.
+ targetAddress.imaStruct.
+ hostnameIpAddress.
+ id.ipAddress.ipv4Address ==
+ IMA_TRUE) {
+ (void) inet_ntop(AF_INET,
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.
+ id.ipAddress.ipAddress,
+ tmpStr,
+ sizeof (tmpStr));
+ } else {
+ (void) inet_ntop(AF_INET6,
+ staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.hostnameIpAddress.
+ id.ipAddress.ipAddress,
+ tmpStr,
+ sizeof (tmpStr));
+ }
+
+ if (mbstowcs(tmpTargetAddress, tmpStr,
+ SUN_IMA_IP_ADDRESS_PORT_LEN) ==
+ (size_t)-1) {
+ (void) fprintf(stderr,
+ "%s: %s\n",
+ cmdName, gettext(
+ "conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ if ((wcsncmp(tmpTargetAddress,
+ staticTargetAddress,
+ SUN_IMA_IP_ADDRESS_PORT_LEN) ==
+ 0) && (staticTargetProps.
+ staticTarget.targetAddress.
+ imaStruct.portNumber == port)) {
+ if (tpgtSpecified == B_FALSE) {
+ matched = B_TRUE;
+ } else {
+ if (tpgt == stpgt) {
+ matched =
+ B_TRUE;
+ }
+ }
+ }
+ }
+
+ if (matched) {
+ status =
+ IMA_RemoveStaticDiscoveryTarget(
+ staticTargetList->oids[j]);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+ atLeastFoundOne = B_TRUE;
+ }
+ }
+ }
+ if (!atLeastFoundOne) {
+ (void) fprintf(stderr, gettext("%ws,%ws: %s\n"),
+ staticTargetName, staticTargetAddress,
+ gettext("not found"));
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Remove one or more target params.
+ */
+static int
+removeTargetParam(int operandLen, char *operand[], int *funcRet)
+{
+ char *commaPos;
+ IMA_STATUS status;
+ IMA_OID initiatorOid;
+ IMA_OID_LIST *targetList;
+ SUN_IMA_TARGET_PROPERTIES targetProps;
+ wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1];
+ int ret;
+ boolean_t found;
+ int i, j;
+
+ assert(funcRet != NULL);
+
+ /* Find Sun initiator */
+ ret = sunInitiatorFind(&initiatorOid);
+ if (ret > 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("no initiator found"));
+ }
+
+ if (ret != 0) {
+ return (ret);
+ }
+
+ status = IMA_GetTargetOidList(initiatorOid, &targetList);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ for (i = 0; i < operandLen; i++) {
+ /* initialize */
+ commaPos = strchr(operand[i], ',');
+ if (commaPos) {
+ /* Ignore IP address. */
+ *commaPos = NULL;
+ }
+ (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject));
+ if (mbstowcs(wcInputObject, operand[i],
+ MAX_ISCSI_NAME_LEN + 1) == (size_t)-1) {
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("conversion error"));
+ ret = 1;
+ continue;
+ }
+
+ for (found = B_FALSE, j = 0; j < targetList->oidCount;
+ j++) {
+ status = SUN_IMA_GetTargetProperties(
+ targetList->oids[j], &targetProps);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+
+ /*
+ * Compare the target name with the input if
+ * one was input
+ */
+ if (targetNamesEqual(targetProps.imaProps.name,
+ wcInputObject) == B_TRUE) {
+ found = B_TRUE;
+ status = SUN_IMA_RemoveTargetParam(
+ targetList->oids[j]);
+ if (!IMA_SUCCESS(status)) {
+ printLibError(status);
+ (void) IMA_FreeMemory(targetList);
+ *funcRet = 1;
+ return (ret);
+ }
+ }
+ }
+ if (!found) {
+ /* Silently ignoring it? */
+ (void) fprintf(stderr, gettext("%ws: %s\n"),
+ wcInputObject, gettext("not found"));
+ }
+ }
+
+ (void) IMA_FreeMemory(targetList);
+ return (ret);
+}
+
+/*ARGSUSED*/
+static int
+addFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
+ void *addArgs, int *funcRet)
+{
+ int ret;
+
+ assert(funcRet != NULL);
+
+ switch (object) {
+ case DISCOVERY_ADDRESS:
+ case ISNS_SERVER_ADDRESS:
+ ret = addAddress(object, operandLen, operand, funcRet);
+ break;
+ case STATIC_CONFIG:
+ ret = addStaticConfig(operandLen, operand, funcRet);
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("unknown object"));
+ ret = 1;
+ break;
+ }
+ return (ret);
+}
+
+/*ARGSUSED*/
+static int
+listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
+ void *addArgs, int *funcRet)
+{
+ int ret;
+
+ assert(funcRet != NULL);
+
+ switch (object) {
+ case DISCOVERY:
+ ret = listDiscovery(funcRet);
+ break;
+ case DISCOVERY_ADDRESS:
+ ret = listDiscoveryAddress(operandLen, operand, options,
+ funcRet);
+ break;
+ case ISNS_SERVER_ADDRESS:
+ ret = listISNSServerAddress(operandLen, operand, options,
+ funcRet);
+ break;
+ case NODE:
+ ret = listNode(funcRet);
+ break;
+ case STATIC_CONFIG:
+ ret = listStaticConfig(operandLen, operand, funcRet);
+ break;
+ case TARGET:
+ ret = listTarget(operandLen, operand, options, funcRet);
+ break;
+ case TARGET_PARAM:
+ ret = listTargetParam(operandLen, operand, options, funcRet);
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("unknown object"));
+ ret = 1;
+ break;
+ }
+ return (ret);
+}
+
+/*ARGSUSED*/
+static int
+modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
+ void *addArgs, int *funcRet)
+{
+ int ret, i;
+
+ assert(funcRet != NULL);
+
+ switch (object) {
+ case DISCOVERY:
+ ret = modifyDiscovery(options, funcRet);
+ break;
+ case NODE:
+ ret = modifyNode(options, funcRet);
+ break;
+ case TARGET_PARAM:
+ i = 0;
+ while (operand[i]) {
+ ret = modifyTargetParam(options, operand[i], funcRet);
+
+ if (ret) {
+ (void) fprintf(stderr, "%s: %s: %s\n",
+ cmdName, gettext("modify failed"),
+ operand[i]);
+ return (ret);
+ }
+ i++;
+ }
+
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("unknown object"));
+ ret = 1;
+ break;
+ }
+ return (ret);
+}
+
+/*ARGSUSED*/
+static int
+removeFunc(int operandLen, char *operand[], int object, cmdOptions_t *options,
+ void *addArgs, int *funcRet)
+{
+ int ret;
+
+ switch (object) {
+ case DISCOVERY_ADDRESS:
+ case ISNS_SERVER_ADDRESS:
+ ret = removeAddress(object, operandLen, operand,
+ funcRet);
+ break;
+ case STATIC_CONFIG:
+ ret = removeStaticConfig(operandLen, operand, funcRet);
+ break;
+ case TARGET_PARAM:
+ ret = removeTargetParam(operandLen, operand, funcRet);
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("unknown object"));
+ ret = 1;
+ break;
+ }
+ return (ret);
+}
+
+static void
+iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status)
+{
+ switch (status) {
+ case iSCSINameLenZero:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("empty iSCSI name."));
+ break;
+ case iSCSINameLenExceededMax:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("iSCSI name exceeded maximum length."));
+ break;
+ case iSCSINameUnknownType:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("unknown iSCSI name type."));
+ break;
+ case iSCSINameInvalidCharacter:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName,
+ gettext("iSCSI name invalid character used"));
+ break;
+ case iSCSINameIqnFormatError:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("iqn formatting error."));
+ break;
+ case iSCSINameIqnDateFormatError:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("invalid iqn date." \
+ " format is: YYYY-MM"));
+ break;
+ case iSCSINameIqnSubdomainFormatError:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("missing subdomain after \":\""));
+ break;
+ case iSCSINameIqnInvalidYearError:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("invalid year"));
+ break;
+ case iSCSINameIqnInvalidMonthError:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("invalid month"));
+ break;
+ case iSCSINameIqnFQDNError:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("missing reversed fully qualified"\
+ " domain name"));
+ break;
+ case iSCSINameEUIFormatError:
+ (void) fprintf(stderr, "%s: %s\n", cmdName,
+ gettext("eui formatting error."));
+ break;
+ }
+}
+
+/*
+ * A convenient function to modify the target parameters of an individual
+ * target.
+ *
+ * Return 0 if successful
+ * Return 1 if failed
+ */
+static int
+modifyIndividualTargetParam(cmdOptions_t *optionList, IMA_OID targetOid,
+ int *funcRet)
+{
+ assert(funcRet != NULL);
+
+ for (; optionList->optval; optionList++) {
+ switch (optionList->optval) {
+ case 'a':
+ if (modifyTargetAuthMethod(targetOid,
+ optionList->optarg, funcRet) != 0) {
+ return (1);
+ }
+ break;
+ case 'B':
+ if (modifyTargetBidirAuthFlag(targetOid,
+ optionList->optarg, funcRet) != 0) {
+ return (1);
+ }
+ break;
+ case 'C':
+ if (modifyTargetAuthParam(targetOid,
+ AUTH_PASSWORD, NULL, funcRet) != 0) {
+ return (1);
+ }
+ break;
+ case 'd':
+ if (setLoginParameter(targetOid, DATA_DIGEST,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+ case 'h':
+ if (setLoginParameter(targetOid, HEADER_DIGEST,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+ case 'p':
+ /* Login parameter */
+ if (setLoginParameters(targetOid,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+ case 'c':
+ /* Modify configure sessions */
+ if (modifyConfiguredSessions(targetOid,
+ optionList->optarg) != 0) {
+ return (1);
+ }
+ break;
+ case 'H':
+ if (modifyTargetAuthParam(targetOid, AUTH_NAME,
+ optionList->optarg, funcRet) != 0) {
+ return (1);
+ }
+ break;
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * This helper function could go into a utility module for general use.
+ */
+static int
+parseAddress(char *address_port_str,
+ uint16_t defaultPort,
+ char *address_str,
+ size_t address_str_len,
+ uint16_t *port,
+ boolean_t *isIpv6)
+{
+ char port_str[64];
+ int tmp_port;
+ char *errchr;
+
+ if (address_port_str[0] == '[') {
+ /* IPv6 address */
+ char *close_bracket_pos;
+ close_bracket_pos = strchr(address_port_str, ']');
+ if (!close_bracket_pos) {
+ syslog(LOG_USER|LOG_DEBUG,
+ "IP address format error: %s\n", address_str);
+ return (PARSE_ADDR_MISSING_CLOSING_BRACKET);
+ }
+
+ *close_bracket_pos = NULL;
+ (void) strlcpy(address_str, &address_port_str[1],
+ address_str_len);
+
+ /* Extract the port number */
+ close_bracket_pos++;
+ if (*close_bracket_pos == ':') {
+ close_bracket_pos++;
+ if (*close_bracket_pos != NULL) {
+ (void) strlcpy(port_str, close_bracket_pos, 64);
+ tmp_port = strtol(port_str, &errchr, 10);
+ if (tmp_port == 0 && errchr != NULL) {
+ (void) fprintf(stderr, "%s: %s:%s %s\n",
+ cmdName, address_str,
+ close_bracket_pos,
+ gettext("port number invalid"));
+ return (PARSE_ADDR_PORT_OUT_OF_RANGE);
+ }
+ if ((tmp_port > 0) && (tmp_port > USHRT_MAX) ||
+ (tmp_port < 0)) {
+ /* Port number out of range */
+ syslog(LOG_USER|LOG_DEBUG,
+ "Specified port out of range: %d",
+ tmp_port);
+ return (PARSE_ADDR_PORT_OUT_OF_RANGE);
+ } else {
+ *port = (uint16_t)tmp_port;
+ }
+ } else {
+ *port = defaultPort;
+ }
+ } else {
+ *port = defaultPort;
+ }
+
+ *isIpv6 = B_TRUE;
+ } else {
+ /* IPv4 address */
+ char *colon_pos;
+ colon_pos = strchr(address_port_str, ':');
+ if (!colon_pos) {
+ /* No port number specified. */
+ *port = defaultPort;
+ (void) strlcpy(address_str, address_port_str,
+ address_str_len);
+ } else {
+ *colon_pos = (char)NULL;
+ (void) strlcpy(address_str, address_port_str,
+ address_str_len);
+
+ /* Extract the port number */
+ colon_pos++;
+ if (*colon_pos != NULL) {
+
+ (void) strlcpy(port_str, colon_pos, 64);
+ tmp_port = strtol(port_str, &errchr, 10);
+ if (tmp_port == 0 && errchr != NULL) {
+ (void) fprintf(stderr, "%s: %s:%s %s\n",
+ cmdName, address_str, colon_pos,
+ gettext("port number invalid"));
+ return (PARSE_ADDR_PORT_OUT_OF_RANGE);
+ }
+ if ((tmp_port > 0) && (tmp_port > USHRT_MAX) ||
+ (tmp_port < 0)) {
+ /* Port number out of range */
+ syslog(LOG_USER|LOG_DEBUG,
+ "Specified port out of range: %d",
+ tmp_port);
+ return (PARSE_ADDR_PORT_OUT_OF_RANGE);
+ } else {
+ *port = (uint16_t)tmp_port;
+ }
+ } else {
+ *port = defaultPort;
+ }
+ }
+
+ *isIpv6 = B_FALSE;
+ }
+
+ return (PARSE_ADDR_OK);
+}
+
+/*
+ * This helper function could go into a utility module for general use.
+ */
+iSCSINameCheckStatusType
+iSCSINameStringProfileCheck(wchar_t *name)
+{
+ char mb_name[MAX_ISCSI_NAME_LEN + 1];
+ size_t name_len;
+ char *tmp;
+
+ (void) wcstombs(mb_name, name, MAX_ISCSI_NAME_LEN + 1);
+
+ if ((name_len = strlen(mb_name)) == 0) {
+ return (iSCSINameLenZero);
+ } else if (name_len > MAX_ISCSI_NAME_LEN) {
+ return (iSCSINameLenExceededMax);
+ }
+
+ /*
+ * check for invalid characters
+ * According to RFC 3722 iSCSI name must be either a letter,
+ * a digit or one of the following '-' '.' ':'
+ */
+ for (tmp = mb_name; *tmp != NULL; tmp++) {
+ if ((isalnum(*tmp) == 0) &&
+ (*tmp != '-') &&
+ (*tmp != '.') &&
+ (*tmp != ':')) {
+ return (iSCSINameInvalidCharacter);
+ }
+ }
+
+ if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX,
+ strlen(ISCSI_IQN_NAME_PREFIX)) == 0) {
+ /*
+ * If name is of type iqn, check date string and naming
+ * authority.
+ */
+ char *strp = NULL;
+
+ /*
+ * Don't allow the string to end with a colon. If there is a
+ * colon then there must be a subdomain provided.
+ */
+ if (mb_name[strlen(mb_name) - 1] == ':') {
+ return (iSCSINameIqnSubdomainFormatError);
+ }
+
+ /* Date string */
+ strp = strtok(&mb_name[3], ".");
+ if (strp) {
+ char tmpYear[5], tmpMonth[3], *endPtr = NULL;
+ int year, month;
+
+ /* Date string should be in YYYY-MM format */
+ if (strlen(strp) != strlen("YYYY-MM") ||
+ strp[4] != '-') {
+ return (iSCSINameIqnDateFormatError);
+ }
+
+ /*
+ * Validate year. Only validating that the
+ * year can be converted to a number. No
+ * validation will be done on year's actual
+ * value.
+ */
+ (void) strncpy(tmpYear, strp, 4);
+ tmpYear[4] = '\0';
+
+ errno = 0;
+ year = strtol(tmpYear, &endPtr, 10);
+ if (errno != 0 || *endPtr != '\0' ||
+ year < 0 || year > 9999) {
+ return (iSCSINameIqnInvalidYearError);
+ }
+
+ /*
+ * Validate month is valid.
+ */
+ (void) strncpy(tmpMonth, &strp[5], 2);
+ tmpMonth[2] = '\0';
+ errno = 0;
+ month = strtol(tmpMonth, &endPtr, 10);
+
+ if (errno != 0 || *endPtr != '\0' ||
+ month < 1 || month > 12) {
+ return (iSCSINameIqnInvalidMonthError);
+ }
+
+ /*
+ * A reversed FQDN needs to be provided. We
+ * will only check for a "." followed by more
+ * than two or more characters. The list of domains is
+ * too large and changes too frequently to
+ * add validation for.
+ */
+ strp = strtok(NULL, ".");
+ if (!strp || strlen(strp) < 2) {
+ return (iSCSINameIqnFQDNError);
+ }
+
+ /* Name authority string */
+ strp = strtok(NULL, ":");
+ if (strp) {
+ return (iSCSINameCheckOK);
+ } else {
+ return (iSCSINameIqnFQDNError);
+ }
+ } else {
+ return (iSCSINameIqnFormatError);
+ }
+ } else if (strncmp(mb_name, ISCSI_EUI_NAME_PREFIX,
+ strlen(ISCSI_EUI_NAME_PREFIX)) == 0) {
+ /* If name is of type EUI, change its length */
+
+ if (strlen(mb_name) != ISCSI_EUI_NAME_LEN) {
+ return (iSCSINameEUIFormatError);
+ }
+
+ for (tmp = mb_name + strlen(ISCSI_EUI_NAME_PREFIX) + 1;
+ *tmp != '\0'; tmp++) {
+ if (isxdigit(*tmp)) {
+ continue;
+ }
+ return (iSCSINameEUIFormatError);
+ }
+
+ return (iSCSINameCheckOK);
+ } else {
+ return (iSCSINameUnknownType);
+ }
+}
+
+/*
+ * This helper function could go into a utility module for general use.
+ *
+ * Returns:
+ * B_TRUE is the numberStr is an unsigned natural number and within the
+ * specified bound.
+ * B_FALSE otherwise.
+ */
+boolean_t
+isNaturalNumber(char *numberStr, uint32_t upperBound)
+{
+ int i;
+ int number_str_len;
+
+ if ((number_str_len = strlen(numberStr)) == 0) {
+ return (B_FALSE);
+ }
+
+ for (i = 0; i < number_str_len; i++) {
+ if (numberStr[i] < 060 || numberStr[i] > 071) {
+ return (B_FALSE);
+ }
+ }
+
+ if (atoi(numberStr) > upperBound) {
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+/*
+ * This helper function could go into a utility module for general use.
+ * It parses a target string in the format of:
+ *
+ * <target_name>,[<ip_address>[:port][,tpgt]]
+ *
+ * and creates wchar strings for target name and target address. It
+ * also populates port and tpgt if found.
+ *
+ * Returns:
+ * PARSE_TARGET_OK if parsing is successful.
+ * PARSE_TARGET_INVALID_TPGT if the specified tpgt is
+ * invalid.
+ * PARSE_TARGET_INVALID_ADDR if the address specified is
+ * invalid.
+ */
+int
+parseTarget(char *targetStr,
+ wchar_t *targetNameStr,
+ size_t targetNameStrLen,
+ boolean_t *targetAddressSpecified,
+ wchar_t *targetAddressStr,
+ size_t targetAddressStrLen,
+ uint16_t *port,
+ boolean_t *tpgtSpecified,
+ uint16_t *tpgt,
+ boolean_t *isIpv6)
+{
+ char *commaPos;
+ char *commaPos2;
+ char targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN];
+ int i;
+ int lowerCase;
+
+ (void) memset(targetNameStr, 0,
+ targetNameStrLen * sizeof (wchar_t));
+ (void) memset(targetAddressStr, 0,
+ targetAddressStrLen * sizeof (wchar_t));
+
+ commaPos = strchr(targetStr, ',');
+ if (commaPos != NULL) {
+ *commaPos = NULL;
+ commaPos++;
+ *targetAddressSpecified = B_TRUE;
+
+ /*
+ * Checking of tpgt makes sense only when
+ * the target address/port are specified.
+ */
+ commaPos2 = strchr(commaPos, ',');
+ if (commaPos2 != NULL) {
+ *commaPos2 = NULL;
+ commaPos2++;
+ if (isNaturalNumber(commaPos2, ISCSI_MAX_TPGT_VALUE) ==
+ B_TRUE) {
+ *tpgt = atoi(commaPos2);
+ *tpgtSpecified = B_TRUE;
+ } else {
+ return (PARSE_TARGET_INVALID_TPGT);
+ }
+ }
+
+ switch (parseAddress(commaPos, ISCSI_LISTEN_PORT,
+ &targetAddress[0], MAX_ADDRESS_LEN + 1, port, isIpv6)) {
+ case PARSE_ADDR_PORT_OUT_OF_RANGE:
+ return (PARSE_TARGET_INVALID_ADDR);
+ case PARSE_ADDR_OK:
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("cannot parse target name"));
+ return (PARSE_TARGET_INVALID_ADDR);
+ }
+ (void) mbstowcs(targetAddressStr, targetAddress,
+ targetAddressStrLen);
+ for (i = 0; targetAddressStr[i] != 0; i++) {
+ lowerCase = tolower(targetAddressStr[i]);
+ targetAddressStr[i] = lowerCase;
+ }
+ } else {
+ *targetAddressSpecified = B_FALSE;
+ *tpgtSpecified = B_FALSE;
+ }
+
+ (void) mbstowcs(targetNameStr, targetStr, targetNameStrLen);
+ for (i = 0; targetNameStr[i] != 0; i++) {
+ lowerCase = tolower(targetNameStr[i]);
+ targetNameStr[i] = lowerCase;
+ }
+
+ return (PARSE_TARGET_OK);
+}
+
+/*ARGSUSED*/
+static void
+listCHAPName(IMA_OID oid)
+{
+ IMA_INITIATOR_AUTHPARMS authParams;
+ IMA_STATUS status;
+ IMA_BYTE chapName [MAX_CHAP_NAME_LEN + 1];
+
+ /* Get Chap Name depending upon oid object type */
+ if (oid.objectType == IMA_OBJECT_TYPE_LHBA) {
+ status = IMA_GetInitiatorAuthParms(oid,
+ IMA_AUTHMETHOD_CHAP, &authParams);
+ } else {
+ status = SUN_IMA_GetTargetAuthParms(oid,
+ IMA_AUTHMETHOD_CHAP, &authParams);
+ }
+
+ (void) fprintf(stdout, "\n\t\t%s: ", gettext("CHAP Name"));
+
+ if (IMA_SUCCESS(status)) {
+ /*
+ * Default chap name will be the node name. The default will
+ * be set by the driver.
+ */
+ if (authParams.chapParms.nameLength != 0) {
+ (void) memset(chapName, 0, sizeof (chapName));
+ (void) memcpy(chapName, authParams.chapParms.name,
+ authParams.chapParms.nameLength);
+ (void) fprintf(stdout, "%s", chapName);
+
+ } else {
+ (void) fprintf(stdout, "%s", "-");
+ }
+ } else {
+ (void) fprintf(stdout, "%s", "-");
+ }
+}
+
+/*
+ * Prints out see manual page.
+ * Called out through atexit(3C) so is always last thing displayed.
+ */
+void
+seeMan(void)
+{
+ static int sent = 0;
+
+ if (sent)
+ return;
+
+ (void) fprintf(stdout, "%s %s(1M)\n",
+ gettext("For more information, please see"), cmdName);
+
+ sent = 1;
+}
+
+
+/*
+ * main calls a parser that checks syntax of the input command against
+ * various rules tables.
+ *
+ * The parser provides usage feedback based upon same tables by calling
+ * two usage functions, usage and subUsage, handling command and subcommand
+ * usage respectively.
+ *
+ * The parser handles all printing of usage syntactical errors
+ *
+ * When syntax is successfully validated, the parser calls the associated
+ * function using the subcommands table functions.
+ *
+ * Syntax is as follows:
+ * command subcommand [options] resource-type [<object>]
+ *
+ * The return value from the function is placed in funcRet
+ */
+int
+main(int argc, char *argv[])
+{
+ synTables_t synTables;
+ char versionString[VERSION_STRING_MAX_LEN];
+ int ret;
+ int funcRet = 0;
+ void *subcommandArgs = NULL;
+
+ if (geteuid() != 0) {
+ (void) fprintf(stderr, "%s\n", gettext("permission denied"));
+ return (1);
+ }
+
+ /* set global command name */
+ cmdName = getExecBasename(argv[0]);
+
+ (void) snprintf(versionString, sizeof (versionString), "%s.%s",
+ VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
+ synTables.versionString = versionString;
+ synTables.longOptionTbl = &longOptions[0];
+ synTables.subcommandTbl = &subcommands[0];
+ synTables.objectTbl = &objects[0];
+ synTables.objectRulesTbl = &objectRules[0];
+ synTables.optionRulesTbl = &optionRules[0];
+
+ /* call the CLI parser */
+ ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
+ if (ret == -1) {
+ perror(cmdName);
+ ret = 1;
+ }
+
+ if (funcRet != 0) {
+ (void) fprintf(stderr, "%s: %s\n",
+ cmdName, gettext("Unable to complete operation"));
+ ret = 1;
+ }
+ return (ret);
+}