xref: /titanic_53/usr/src/cmd/fcinfo/fcoeadm.c (revision d4401b99a36e5170ccaa7defc0d2ac65b23f08c6)
12a8164dfSZhong Wang /*
22a8164dfSZhong Wang  * CDDL HEADER START
32a8164dfSZhong Wang  *
42a8164dfSZhong Wang  * The contents of this file are subject to the terms of the
52a8164dfSZhong Wang  * Common Development and Distribution License (the "License").
62a8164dfSZhong Wang  * You may not use this file except in compliance with the License.
72a8164dfSZhong Wang  *
82a8164dfSZhong Wang  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92a8164dfSZhong Wang  * or http://www.opensolaris.org/os/licensing.
102a8164dfSZhong Wang  * See the License for the specific language governing permissions
112a8164dfSZhong Wang  * and limitations under the License.
122a8164dfSZhong Wang  *
132a8164dfSZhong Wang  * When distributing Covered Code, include this CDDL HEADER in each
142a8164dfSZhong Wang  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152a8164dfSZhong Wang  * If applicable, add the following below this CDDL HEADER, with the
162a8164dfSZhong Wang  * fields enclosed by brackets "[]" replaced with your own identifying
172a8164dfSZhong Wang  * information: Portions Copyright [yyyy] [name of copyright owner]
182a8164dfSZhong Wang  *
192a8164dfSZhong Wang  * CDDL HEADER END
202a8164dfSZhong Wang  */
212a8164dfSZhong Wang /*
222a8164dfSZhong Wang  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
232a8164dfSZhong Wang  * Use is subject to license terms.
242a8164dfSZhong Wang  */
252a8164dfSZhong Wang 
262a8164dfSZhong Wang #include "fcinfo.h"
272a8164dfSZhong Wang #include <libintl.h>
282a8164dfSZhong Wang #include <fcntl.h>
292a8164dfSZhong Wang #include <errno.h>
302a8164dfSZhong Wang #include <assert.h>
312a8164dfSZhong Wang #include <ctype.h>
322a8164dfSZhong Wang #include <sys/list.h>
332a8164dfSZhong Wang #include <stddef.h>
342a8164dfSZhong Wang #include <strings.h>
352a8164dfSZhong Wang #include <libfcoe.h>
362a8164dfSZhong Wang #include <libscf.h>
372a8164dfSZhong Wang #include <syslog.h>
382a8164dfSZhong Wang 
392a8164dfSZhong Wang static const char *FCOE_DRIVER_PATH	= "/devices/fcoe:admin";
402a8164dfSZhong Wang 
412a8164dfSZhong Wang static char *
422a8164dfSZhong Wang WWN2str(char *buf, FCOE_PORT_WWN *wwn) {
432a8164dfSZhong Wang 	int j;
442a8164dfSZhong Wang 	unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
452a8164dfSZhong Wang 	buf[0] = '\0';
462a8164dfSZhong Wang 	for (j = 0; j < 16; j += 2) {
472a8164dfSZhong Wang 		sprintf(&buf[j], "%02X", (int)*pc++);
482a8164dfSZhong Wang 	}
492a8164dfSZhong Wang 	return (buf);
502a8164dfSZhong Wang }
512a8164dfSZhong Wang 
522a8164dfSZhong Wang static int
532a8164dfSZhong Wang isValidWWN(char *wwn)
542a8164dfSZhong Wang {
552a8164dfSZhong Wang 	int index;
562a8164dfSZhong Wang 
572a8164dfSZhong Wang 	if (wwn == NULL) {
582a8164dfSZhong Wang 		return (0);
592a8164dfSZhong Wang 	}
602a8164dfSZhong Wang 
612a8164dfSZhong Wang 	if (strlen(wwn) != 16) {
622a8164dfSZhong Wang 		return (0);
632a8164dfSZhong Wang 	}
642a8164dfSZhong Wang 
652a8164dfSZhong Wang 	for (index = 0; index < 16; index++) {
662a8164dfSZhong Wang 		if (isxdigit(wwn[index])) {
672a8164dfSZhong Wang 			continue;
682a8164dfSZhong Wang 		}
692a8164dfSZhong Wang 		return (0);
702a8164dfSZhong Wang 	}
712a8164dfSZhong Wang 	return (1);
722a8164dfSZhong Wang }
732a8164dfSZhong Wang 
742a8164dfSZhong Wang static uint64_t wwnconvert(uchar_t *wwn)
752a8164dfSZhong Wang {
762a8164dfSZhong Wang 	uint64_t tmp;
772a8164dfSZhong Wang 	memcpy(&tmp, wwn, sizeof (uint64_t));
782a8164dfSZhong Wang 	return (ntohll(tmp));
792a8164dfSZhong Wang }
802a8164dfSZhong Wang 
812a8164dfSZhong Wang /*
822a8164dfSZhong Wang  * prints out all the HBA port information
832a8164dfSZhong Wang  */
842a8164dfSZhong Wang void
852a8164dfSZhong Wang printFCOEPortInfo(FCOE_PORT_ATTRIBUTE *attr)
862a8164dfSZhong Wang {
872a8164dfSZhong Wang 	int i;
882a8164dfSZhong Wang 	if (attr == NULL) {
892a8164dfSZhong Wang 		return;
902a8164dfSZhong Wang 	}
912a8164dfSZhong Wang 	fprintf(stdout, gettext("HBA Port WWN: %016llx\n"),
922a8164dfSZhong Wang 	    wwnconvert((unsigned char *)&attr->port_wwn));
932a8164dfSZhong Wang 
942a8164dfSZhong Wang 	fprintf(stdout, gettext("\tPort Type: %s\n"),
952a8164dfSZhong Wang 	    (attr->port_type == 0) ? "Initiator" : "Target");
962a8164dfSZhong Wang 
972a8164dfSZhong Wang 	fprintf(stdout, gettext("\tMAC Name: %s\n"), attr->mac_link_name);
982a8164dfSZhong Wang 
992a8164dfSZhong Wang 	fprintf(stdout, gettext("\tMTU Size: %d\n"), attr->mtu_size);
1002a8164dfSZhong Wang 
1012a8164dfSZhong Wang 	fprintf(stdout, gettext("\tMAC Factory Address: "));
1022a8164dfSZhong Wang 	for (i = 0; i < 6; i++) {
1032a8164dfSZhong Wang 		fprintf(stdout, gettext("%02x"), attr->mac_factory_addr[i]);
1042a8164dfSZhong Wang 	}
1052a8164dfSZhong Wang 	fprintf(stdout, gettext("\n\tMAC Current Address: "));
1062a8164dfSZhong Wang 	for (i = 0; i < 6; i++) {
1072a8164dfSZhong Wang 		fprintf(stdout, gettext("%02x"), attr->mac_current_addr[i]);
1082a8164dfSZhong Wang 	}
1092a8164dfSZhong Wang 	fprintf(stdout, gettext("\n\tPromiscuous Mode: %s\n"),
1102a8164dfSZhong Wang 	    attr->mac_promisc == 1 ? "On" : "Off");
1112a8164dfSZhong Wang }
1122a8164dfSZhong Wang 
1132a8164dfSZhong Wang /*
1142a8164dfSZhong Wang  * Initialize scf fcoe service access
1152a8164dfSZhong Wang  * handle - returned handle
1162a8164dfSZhong Wang  * service - returned service handle
1172a8164dfSZhong Wang  */
1182a8164dfSZhong Wang static int
1192a8164dfSZhong Wang fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service)
1202a8164dfSZhong Wang {
1212a8164dfSZhong Wang 	scf_scope_t	*scope = NULL;
1222a8164dfSZhong Wang 	int		ret;
1232a8164dfSZhong Wang 
1242a8164dfSZhong Wang 	if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
1252a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_handle_create failed - %s",
1262a8164dfSZhong Wang 		    scf_strerror(scf_error()));
1272a8164dfSZhong Wang 		ret = FCOE_ERROR;
1282a8164dfSZhong Wang 		goto err;
1292a8164dfSZhong Wang 	}
1302a8164dfSZhong Wang 
1312a8164dfSZhong Wang 	if (scf_handle_bind(*handle) == -1) {
1322a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_handle_bind failed - %s",
1332a8164dfSZhong Wang 		    scf_strerror(scf_error()));
1342a8164dfSZhong Wang 		ret = FCOE_ERROR;
1352a8164dfSZhong Wang 		goto err;
1362a8164dfSZhong Wang 	}
1372a8164dfSZhong Wang 
1382a8164dfSZhong Wang 	if ((*service = scf_service_create(*handle)) == NULL) {
1392a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_service_create failed - %s",
1402a8164dfSZhong Wang 		    scf_strerror(scf_error()));
1412a8164dfSZhong Wang 		ret = FCOE_ERROR;
1422a8164dfSZhong Wang 		goto err;
1432a8164dfSZhong Wang 	}
1442a8164dfSZhong Wang 
1452a8164dfSZhong Wang 	if ((scope = scf_scope_create(*handle)) == NULL) {
1462a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_scope_create failed - %s",
1472a8164dfSZhong Wang 		    scf_strerror(scf_error()));
1482a8164dfSZhong Wang 		ret = FCOE_ERROR;
1492a8164dfSZhong Wang 		goto err;
1502a8164dfSZhong Wang 	}
1512a8164dfSZhong Wang 
1522a8164dfSZhong Wang 	if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
1532a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
1542a8164dfSZhong Wang 		    scf_strerror(scf_error()));
1552a8164dfSZhong Wang 		ret = FCOE_ERROR;
1562a8164dfSZhong Wang 		goto err;
1572a8164dfSZhong Wang 	}
1582a8164dfSZhong Wang 
1592a8164dfSZhong Wang 	if (scf_scope_get_service(scope, FCOE_SERVICE, *service) == -1) {
1602a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_scope_get_service failed - %s",
1612a8164dfSZhong Wang 		    scf_strerror(scf_error()));
1622a8164dfSZhong Wang 		ret = FCOE_ERROR_SERVICE_NOT_FOUND;
1632a8164dfSZhong Wang 		goto err;
1642a8164dfSZhong Wang 	}
1652a8164dfSZhong Wang 
1662a8164dfSZhong Wang 	scf_scope_destroy(scope);
1672a8164dfSZhong Wang 
1682a8164dfSZhong Wang 	return (FCOE_SUCCESS);
1692a8164dfSZhong Wang 
1702a8164dfSZhong Wang err:
1712a8164dfSZhong Wang 	if (*handle != NULL) {
1722a8164dfSZhong Wang 		scf_handle_destroy(*handle);
1732a8164dfSZhong Wang 	}
1742a8164dfSZhong Wang 	if (*service != NULL) {
1752a8164dfSZhong Wang 		scf_service_destroy(*service);
1762a8164dfSZhong Wang 		*service = NULL;
1772a8164dfSZhong Wang 	}
1782a8164dfSZhong Wang 	if (scope != NULL) {
1792a8164dfSZhong Wang 		scf_scope_destroy(scope);
1802a8164dfSZhong Wang 	}
1812a8164dfSZhong Wang 	return (ret);
1822a8164dfSZhong Wang }
1832a8164dfSZhong Wang 
1842a8164dfSZhong Wang 
1852a8164dfSZhong Wang static int
1862a8164dfSZhong Wang fcoe_adm_add_remove_scf_entry(char *mac_name,
1872a8164dfSZhong Wang     char *pwwn, char *nwwn,
1882a8164dfSZhong Wang     int is_target, int is_promiscuous, int addRemoveFlag)
1892a8164dfSZhong Wang {
1902a8164dfSZhong Wang 	scf_handle_t	*handle = NULL;
1912a8164dfSZhong Wang 	scf_service_t	*svc = NULL;
1922a8164dfSZhong Wang 	scf_propertygroup_t	*pg = NULL;
1932a8164dfSZhong Wang 	scf_transaction_t	*tran = NULL;
1942a8164dfSZhong Wang 	scf_transaction_entry_t	*entry = NULL;
1952a8164dfSZhong Wang 	scf_property_t	*prop = NULL;
1962a8164dfSZhong Wang 	scf_value_t	*valueLookup = NULL;
1972a8164dfSZhong Wang 	scf_iter_t	*valueIter = NULL;
1982a8164dfSZhong Wang 	scf_value_t	**valueSet = NULL;
1992a8164dfSZhong Wang 	int	ret = FCOE_SUCCESS;
2002a8164dfSZhong Wang 	boolean_t	createProp = B_FALSE;
2012a8164dfSZhong Wang 	int	lastAlloc = 0;
2022a8164dfSZhong Wang 	char	buf[FCOE_PORT_LIST_LENGTH] = {0};
2032a8164dfSZhong Wang 	char	memberName[FCOE_PORT_LIST_LENGTH] = {0};
2042a8164dfSZhong Wang 	boolean_t	found = B_FALSE;
2052a8164dfSZhong Wang 	int	i = 0;
2062a8164dfSZhong Wang 	int	valueArraySize = 0;
2072a8164dfSZhong Wang 	int	commitRet;
2082a8164dfSZhong Wang 
2092a8164dfSZhong Wang 	sprintf(memberName, "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn,
2102a8164dfSZhong Wang 	    is_target, is_promiscuous);
2112a8164dfSZhong Wang 
2122a8164dfSZhong Wang 	ret = fcoe_cfg_scf_init(&handle, &svc);
2132a8164dfSZhong Wang 	if (ret != FCOE_SUCCESS) {
2142a8164dfSZhong Wang 		goto out;
2152a8164dfSZhong Wang 	}
2162a8164dfSZhong Wang 
2172a8164dfSZhong Wang 	if (((pg = scf_pg_create(handle)) == NULL) ||
2182a8164dfSZhong Wang 	    ((tran = scf_transaction_create(handle)) == NULL) ||
2192a8164dfSZhong Wang 	    ((entry = scf_entry_create(handle)) == NULL) ||
2202a8164dfSZhong Wang 	    ((prop = scf_property_create(handle)) == NULL) ||
2212a8164dfSZhong Wang 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
2222a8164dfSZhong Wang 		ret = FCOE_ERROR;
2232a8164dfSZhong Wang 		goto out;
2242a8164dfSZhong Wang 	}
2252a8164dfSZhong Wang 
2262a8164dfSZhong Wang 	/* get property group or create it */
2272a8164dfSZhong Wang 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
2282a8164dfSZhong Wang 		if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
2292a8164dfSZhong Wang 			if (scf_service_add_pg(svc, FCOE_PG_NAME,
2302a8164dfSZhong Wang 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
2312a8164dfSZhong Wang 				syslog(LOG_ERR, "add pg failed - %s",
2322a8164dfSZhong Wang 				    scf_strerror(scf_error()));
2332a8164dfSZhong Wang 				ret = FCOE_ERROR;
2342a8164dfSZhong Wang 			} else {
2352a8164dfSZhong Wang 				createProp = B_TRUE;
2362a8164dfSZhong Wang 			}
2372a8164dfSZhong Wang 		} else {
2382a8164dfSZhong Wang 			syslog(LOG_ERR, "get pg failed - %s",
2392a8164dfSZhong Wang 			    scf_strerror(scf_error()));
2402a8164dfSZhong Wang 			ret = FCOE_ERROR;
2412a8164dfSZhong Wang 		}
2422a8164dfSZhong Wang 		if (ret != FCOE_SUCCESS) {
2432a8164dfSZhong Wang 			goto out;
2442a8164dfSZhong Wang 		}
2452a8164dfSZhong Wang 	}
2462a8164dfSZhong Wang 
2472a8164dfSZhong Wang 	/* to make sure property exists */
2482a8164dfSZhong Wang 	if (createProp == B_FALSE) {
2492a8164dfSZhong Wang 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
2502a8164dfSZhong Wang 			if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
2512a8164dfSZhong Wang 				createProp = B_TRUE;
2522a8164dfSZhong Wang 			} else {
2532a8164dfSZhong Wang 				syslog(LOG_ERR, "get property failed - %s",
2542a8164dfSZhong Wang 				    scf_strerror(scf_error()));
2552a8164dfSZhong Wang 				ret = FCOE_ERROR;
2562a8164dfSZhong Wang 				goto out;
2572a8164dfSZhong Wang 			}
2582a8164dfSZhong Wang 		}
2592a8164dfSZhong Wang 	}
2602a8164dfSZhong Wang 
2612a8164dfSZhong Wang 	/* Begin the transaction */
2622a8164dfSZhong Wang 	if (scf_transaction_start(tran, pg) == -1) {
2632a8164dfSZhong Wang 		syslog(LOG_ERR, "start transaction failed - %s",
2642a8164dfSZhong Wang 		    scf_strerror(scf_error()));
2652a8164dfSZhong Wang 		ret = FCOE_ERROR;
2662a8164dfSZhong Wang 		goto out;
2672a8164dfSZhong Wang 	}
2682a8164dfSZhong Wang 
2692a8164dfSZhong Wang 	valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
2702a8164dfSZhong Wang 	    * (lastAlloc = PORT_LIST_ALLOC));
2712a8164dfSZhong Wang 	if (valueSet == NULL) {
2722a8164dfSZhong Wang 		ret = FCOE_ERROR_NOMEM;
2732a8164dfSZhong Wang 		goto out;
2742a8164dfSZhong Wang 	}
2752a8164dfSZhong Wang 
2762a8164dfSZhong Wang 	if (createProp) {
2772a8164dfSZhong Wang 		if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST,
2782a8164dfSZhong Wang 		    SCF_TYPE_USTRING) == -1) {
2792a8164dfSZhong Wang 			if (scf_error() == SCF_ERROR_EXISTS) {
2802a8164dfSZhong Wang 				ret = FCOE_ERROR_EXISTS;
2812a8164dfSZhong Wang 			} else {
2822a8164dfSZhong Wang 				syslog(LOG_ERR,
2832a8164dfSZhong Wang 				    "transaction property new failed - %s",
2842a8164dfSZhong Wang 				    scf_strerror(scf_error()));
2852a8164dfSZhong Wang 				ret = FCOE_ERROR;
2862a8164dfSZhong Wang 			}
2872a8164dfSZhong Wang 			goto out;
2882a8164dfSZhong Wang 		}
2892a8164dfSZhong Wang 	} else {
2902a8164dfSZhong Wang 		if (scf_transaction_property_change(tran, entry,
2912a8164dfSZhong Wang 		    FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) {
2922a8164dfSZhong Wang 			syslog(LOG_ERR,
2932a8164dfSZhong Wang 			    "transaction property change failed - %s",
2942a8164dfSZhong Wang 			    scf_strerror(scf_error()));
2952a8164dfSZhong Wang 			ret = FCOE_ERROR;
2962a8164dfSZhong Wang 			goto out;
2972a8164dfSZhong Wang 		}
2982a8164dfSZhong Wang 
2992a8164dfSZhong Wang 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
3002a8164dfSZhong Wang 			syslog(LOG_ERR, "get property failed - %s",
3012a8164dfSZhong Wang 			    scf_strerror(scf_error()));
3022a8164dfSZhong Wang 			ret = FCOE_ERROR;
3032a8164dfSZhong Wang 			goto out;
3042a8164dfSZhong Wang 		}
3052a8164dfSZhong Wang 
3062a8164dfSZhong Wang 		valueLookup = scf_value_create(handle);
3072a8164dfSZhong Wang 		if (valueLookup == NULL) {
3082a8164dfSZhong Wang 			syslog(LOG_ERR, "scf value alloc failed - %s",
3092a8164dfSZhong Wang 			    scf_strerror(scf_error()));
3102a8164dfSZhong Wang 			ret = FCOE_ERROR;
3112a8164dfSZhong Wang 			goto out;
3122a8164dfSZhong Wang 		}
3132a8164dfSZhong Wang 
3142a8164dfSZhong Wang 		if (scf_iter_property_values(valueIter, prop) == -1) {
3152a8164dfSZhong Wang 			syslog(LOG_ERR, "iter value failed - %s",
3162a8164dfSZhong Wang 			    scf_strerror(scf_error()));
3172a8164dfSZhong Wang 			ret = FCOE_ERROR;
3182a8164dfSZhong Wang 			goto out;
3192a8164dfSZhong Wang 		}
3202a8164dfSZhong Wang 
3212a8164dfSZhong Wang 		while (scf_iter_next_value(valueIter, valueLookup) == 1) {
3222a8164dfSZhong Wang 			char *macnameIter = NULL;
3232a8164dfSZhong Wang 			char buftmp[FCOE_PORT_LIST_LENGTH] = {0};
3242a8164dfSZhong Wang 
3252a8164dfSZhong Wang 			bzero(buf, sizeof (buf));
3262a8164dfSZhong Wang 			if (scf_value_get_ustring(valueLookup,
3272a8164dfSZhong Wang 			    buf, MAXNAMELEN) == -1) {
3282a8164dfSZhong Wang 				syslog(LOG_ERR, "iter value failed- %s",
3292a8164dfSZhong Wang 				    scf_strerror(scf_error()));
3302a8164dfSZhong Wang 				ret = FCOE_ERROR;
3312a8164dfSZhong Wang 				break;
3322a8164dfSZhong Wang 			}
3332a8164dfSZhong Wang 			strcpy(buftmp, buf);
3342a8164dfSZhong Wang 			macnameIter = strtok(buftmp, ":");
3352a8164dfSZhong Wang 			if (bcmp(macnameIter, mac_name,
3362a8164dfSZhong Wang 			    strlen(mac_name)) == 0) {
3372a8164dfSZhong Wang 				if (addRemoveFlag == FCOE_SCF_ADD) {
3382a8164dfSZhong Wang 					ret = FCOE_ERROR_EXISTS;
3392a8164dfSZhong Wang 					break;
3402a8164dfSZhong Wang 				} else {
3412a8164dfSZhong Wang 					found = B_TRUE;
3422a8164dfSZhong Wang 					continue;
3432a8164dfSZhong Wang 				}
3442a8164dfSZhong Wang 			}
3452a8164dfSZhong Wang 
3462a8164dfSZhong Wang 			valueSet[i] = scf_value_create(handle);
3472a8164dfSZhong Wang 			if (valueSet[i] == NULL) {
3482a8164dfSZhong Wang 				syslog(LOG_ERR, "scf value alloc failed - %s",
3492a8164dfSZhong Wang 				    scf_strerror(scf_error()));
3502a8164dfSZhong Wang 				ret = FCOE_ERROR;
3512a8164dfSZhong Wang 				break;
3522a8164dfSZhong Wang 			}
3532a8164dfSZhong Wang 
3542a8164dfSZhong Wang 			if (scf_value_set_ustring(valueSet[i], buf) == -1) {
3552a8164dfSZhong Wang 				syslog(LOG_ERR, "set value failed 1- %s",
3562a8164dfSZhong Wang 				    scf_strerror(scf_error()));
3572a8164dfSZhong Wang 				ret = FCOE_ERROR;
3582a8164dfSZhong Wang 				break;
3592a8164dfSZhong Wang 			}
3602a8164dfSZhong Wang 
3612a8164dfSZhong Wang 			if (scf_entry_add_value(entry, valueSet[i]) == -1) {
3622a8164dfSZhong Wang 				syslog(LOG_ERR, "add value failed - %s",
3632a8164dfSZhong Wang 				    scf_strerror(scf_error()));
3642a8164dfSZhong Wang 				ret = FCOE_ERROR;
3652a8164dfSZhong Wang 				break;
3662a8164dfSZhong Wang 			}
3672a8164dfSZhong Wang 
3682a8164dfSZhong Wang 			i++;
3692a8164dfSZhong Wang 
3702a8164dfSZhong Wang 			if (i >= lastAlloc) {
3712a8164dfSZhong Wang 				lastAlloc += PORT_LIST_ALLOC;
3722a8164dfSZhong Wang 				valueSet = realloc(valueSet,
3732a8164dfSZhong Wang 				    sizeof (*valueSet) * lastAlloc);
3742a8164dfSZhong Wang 				if (valueSet == NULL) {
3752a8164dfSZhong Wang 					ret = FCOE_ERROR;
3762a8164dfSZhong Wang 					break;
3772a8164dfSZhong Wang 				}
3782a8164dfSZhong Wang 			}
3792a8164dfSZhong Wang 		}
3802a8164dfSZhong Wang 	}
3812a8164dfSZhong Wang 
3822a8164dfSZhong Wang 	valueArraySize = i;
3832a8164dfSZhong Wang 	if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) {
3842a8164dfSZhong Wang 		ret = FCOE_ERROR_MEMBER_NOT_FOUND;
3852a8164dfSZhong Wang 	}
3862a8164dfSZhong Wang 	if (ret != FCOE_SUCCESS) {
3872a8164dfSZhong Wang 		goto out;
3882a8164dfSZhong Wang 	}
3892a8164dfSZhong Wang 
3902a8164dfSZhong Wang 	if (addRemoveFlag == FCOE_SCF_ADD) {
3912a8164dfSZhong Wang 		/*
3922a8164dfSZhong Wang 		 * Now create the new entry
3932a8164dfSZhong Wang 		 */
3942a8164dfSZhong Wang 		valueSet[i] = scf_value_create(handle);
3952a8164dfSZhong Wang 		if (valueSet[i] == NULL) {
3962a8164dfSZhong Wang 			syslog(LOG_ERR, "scf value alloc failed - %s",
3972a8164dfSZhong Wang 			    scf_strerror(scf_error()));
3982a8164dfSZhong Wang 			ret = FCOE_ERROR;
3992a8164dfSZhong Wang 			goto out;
4002a8164dfSZhong Wang 		} else {
4012a8164dfSZhong Wang 			valueArraySize++;
4022a8164dfSZhong Wang 		}
4032a8164dfSZhong Wang 
4042a8164dfSZhong Wang 		/*
4052a8164dfSZhong Wang 		 * Set the new member name
4062a8164dfSZhong Wang 		 */
4072a8164dfSZhong Wang 		if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
4082a8164dfSZhong Wang 			syslog(LOG_ERR, "set value failed 2- %s",
4092a8164dfSZhong Wang 			    scf_strerror(scf_error()));
4102a8164dfSZhong Wang 			ret = FCOE_ERROR;
4112a8164dfSZhong Wang 			goto out;
4122a8164dfSZhong Wang 		}
4132a8164dfSZhong Wang 
4142a8164dfSZhong Wang 		/*
4152a8164dfSZhong Wang 		 * Add the new member
4162a8164dfSZhong Wang 		 */
4172a8164dfSZhong Wang 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
4182a8164dfSZhong Wang 			syslog(LOG_ERR, "add value failed - %s",
4192a8164dfSZhong Wang 			    scf_strerror(scf_error()));
4202a8164dfSZhong Wang 			ret = FCOE_ERROR;
4212a8164dfSZhong Wang 			goto out;
4222a8164dfSZhong Wang 		}
4232a8164dfSZhong Wang 	}
4242a8164dfSZhong Wang 
4252a8164dfSZhong Wang 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
4262a8164dfSZhong Wang 		syslog(LOG_ERR, "transaction commit failed - %s",
4272a8164dfSZhong Wang 		    scf_strerror(scf_error()));
4282a8164dfSZhong Wang 		if (commitRet == 0) {
4292a8164dfSZhong Wang 			ret = FCOE_ERROR_BUSY;
4302a8164dfSZhong Wang 		} else {
4312a8164dfSZhong Wang 			ret = FCOE_ERROR;
4322a8164dfSZhong Wang 		}
4332a8164dfSZhong Wang 		goto out;
4342a8164dfSZhong Wang 	}
4352a8164dfSZhong Wang 
4362a8164dfSZhong Wang out:
4372a8164dfSZhong Wang 	/*
4382a8164dfSZhong Wang 	 * Free resources
4392a8164dfSZhong Wang 	 */
4402a8164dfSZhong Wang 	if (handle != NULL) {
4412a8164dfSZhong Wang 		scf_handle_destroy(handle);
4422a8164dfSZhong Wang 	}
4432a8164dfSZhong Wang 	if (svc != NULL) {
4442a8164dfSZhong Wang 		scf_service_destroy(svc);
4452a8164dfSZhong Wang 	}
4462a8164dfSZhong Wang 	if (pg != NULL) {
4472a8164dfSZhong Wang 		scf_pg_destroy(pg);
4482a8164dfSZhong Wang 	}
4492a8164dfSZhong Wang 	if (tran != NULL) {
4502a8164dfSZhong Wang 		scf_transaction_destroy(tran);
4512a8164dfSZhong Wang 	}
4522a8164dfSZhong Wang 	if (entry != NULL) {
4532a8164dfSZhong Wang 		scf_entry_destroy(entry);
4542a8164dfSZhong Wang 	}
4552a8164dfSZhong Wang 	if (prop != NULL) {
4562a8164dfSZhong Wang 		scf_property_destroy(prop);
4572a8164dfSZhong Wang 	}
4582a8164dfSZhong Wang 	if (valueIter != NULL) {
4592a8164dfSZhong Wang 		scf_iter_destroy(valueIter);
4602a8164dfSZhong Wang 	}
4612a8164dfSZhong Wang 	if (valueLookup != NULL) {
4622a8164dfSZhong Wang 		scf_value_destroy(valueLookup);
4632a8164dfSZhong Wang 	}
4642a8164dfSZhong Wang 
4652a8164dfSZhong Wang 	/*
4662a8164dfSZhong Wang 	 * Free valueSet scf resources
4672a8164dfSZhong Wang 	 */
4682a8164dfSZhong Wang 	if (valueArraySize > 0) {
4692a8164dfSZhong Wang 		for (i = 0; i < valueArraySize; i++) {
4702a8164dfSZhong Wang 			scf_value_destroy(valueSet[i]);
4712a8164dfSZhong Wang 		}
4722a8164dfSZhong Wang 	}
4732a8164dfSZhong Wang 	/*
4742a8164dfSZhong Wang 	 * Now free the pointer array to the resources
4752a8164dfSZhong Wang 	 */
4762a8164dfSZhong Wang 	if (valueSet != NULL) {
4772a8164dfSZhong Wang 		free(valueSet);
4782a8164dfSZhong Wang 	}
4792a8164dfSZhong Wang 
4802a8164dfSZhong Wang 	return (ret);
4812a8164dfSZhong Wang }
4822a8164dfSZhong Wang 
4832a8164dfSZhong Wang int
4842a8164dfSZhong Wang fcoe_adm_create_port(int objects, char *argv[],
4852a8164dfSZhong Wang     cmdOptions_t *options)
4862a8164dfSZhong Wang {
4872a8164dfSZhong Wang 	FCOE_STATUS status = FCOE_STATUS_OK;
4882a8164dfSZhong Wang 	uint64_t	nodeWWN, portWWN;
4892a8164dfSZhong Wang 	FCOE_PORT_WWN	pwwn, nwwn;
4902a8164dfSZhong Wang 	FCOE_UINT8	macLinkName[FCOE_MAX_MAC_NAME_LEN];
4912a8164dfSZhong Wang 	FCOE_UINT8	promiscuous = 0;
4922a8164dfSZhong Wang 	int		createini = 0, createtgt = 0;
4932a8164dfSZhong Wang 
4942a8164dfSZhong Wang 	/* check the mac name operand */
4952a8164dfSZhong Wang 	assert(objects == 1);
4962a8164dfSZhong Wang 
4972a8164dfSZhong Wang 	strcpy((char *)macLinkName, argv[0]);
4982a8164dfSZhong Wang 	bzero(&pwwn, 8);
4992a8164dfSZhong Wang 	bzero(&nwwn, 8);
5002a8164dfSZhong Wang 
5012a8164dfSZhong Wang 	for (; options->optval; options++) {
5022a8164dfSZhong Wang 		switch (options->optval) {
5032a8164dfSZhong Wang 		case 'i':
5042a8164dfSZhong Wang 			createini = 1;
5052a8164dfSZhong Wang 			break;
5062a8164dfSZhong Wang 
5072a8164dfSZhong Wang 		case 't':
5082a8164dfSZhong Wang 			createtgt = 1;
5092a8164dfSZhong Wang 			break;
5102a8164dfSZhong Wang 		case 'p':
5112a8164dfSZhong Wang 			if (!isValidWWN(options->optarg)) {
5122a8164dfSZhong Wang 				fprintf(stderr,
5132a8164dfSZhong Wang 				    gettext("Error: Invalid Port WWN\n"));
5142a8164dfSZhong Wang 				return (1);
5152a8164dfSZhong Wang 			}
5162a8164dfSZhong Wang 			sscanf(options->optarg, "%016llx", &portWWN);
5172a8164dfSZhong Wang 			portWWN = htonll(portWWN);
5182a8164dfSZhong Wang 			memcpy(&pwwn, &portWWN, sizeof (portWWN));
5192a8164dfSZhong Wang 			break;
5202a8164dfSZhong Wang 
5212a8164dfSZhong Wang 		case 'n':
5222a8164dfSZhong Wang 			if (!isValidWWN(options->optarg)) {
5232a8164dfSZhong Wang 				fprintf(stderr,
5242a8164dfSZhong Wang 				    gettext("Error: Invalid Node WWN\n"));
5252a8164dfSZhong Wang 				return (1);
5262a8164dfSZhong Wang 			}
5272a8164dfSZhong Wang 			sscanf(options->optarg, "%016llx", &nodeWWN);
5282a8164dfSZhong Wang 			nodeWWN = htonll(nodeWWN);
5292a8164dfSZhong Wang 			memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN));
5302a8164dfSZhong Wang 			break;
5312a8164dfSZhong Wang 		case 'f':
5322a8164dfSZhong Wang 			promiscuous = 1;
5332a8164dfSZhong Wang 			break;
5342a8164dfSZhong Wang 
5352a8164dfSZhong Wang 		default:
5362a8164dfSZhong Wang 			fprintf(stderr, gettext("Error: Illegal option: %c\n"),
5372a8164dfSZhong Wang 			    options->optval);
5382a8164dfSZhong Wang 			return (1);
5392a8164dfSZhong Wang 		}
5402a8164dfSZhong Wang 	}
5412a8164dfSZhong Wang 
5422a8164dfSZhong Wang 	if (createini == 1 && createtgt == 1) {
5432a8164dfSZhong Wang 		fprintf(stderr, "Error: Option -i and -t should "
5442a8164dfSZhong Wang 		    "not be both specified\n");
5452a8164dfSZhong Wang 		return (1);
5462a8164dfSZhong Wang 	}
5472a8164dfSZhong Wang 	status = FCOE_CreatePort(macLinkName,
5482a8164dfSZhong Wang 	    createtgt == 1 ? FCOE_PORTTYPE_TARGET :
5492a8164dfSZhong Wang 	    FCOE_PORTTYPE_INITIATOR, pwwn, nwwn, promiscuous);
5502a8164dfSZhong Wang 
5512a8164dfSZhong Wang 	if (status != FCOE_STATUS_OK) {
5522a8164dfSZhong Wang 		switch (status) {
5532a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_BUSY:
5542a8164dfSZhong Wang 			fprintf(stderr,
5552a8164dfSZhong Wang 			    gettext("Error: fcoe driver is busy\n"));
5562a8164dfSZhong Wang 			break;
5572a8164dfSZhong Wang 
5582a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_ALREADY:
5592a8164dfSZhong Wang 			fprintf(stderr,
5602a8164dfSZhong Wang 			    gettext("Error: Existing FCoE port "
5612a8164dfSZhong Wang 			    "found on the specified MAC link\n"));
5622a8164dfSZhong Wang 			break;
5632a8164dfSZhong Wang 
5642a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PERM:
5652a8164dfSZhong Wang 			fprintf(stderr,
5662a8164dfSZhong Wang 			    gettext("Error: Not enough permission to "
5672a8164dfSZhong Wang 			    "open fcoe device\n"));
5682a8164dfSZhong Wang 			break;
5692a8164dfSZhong Wang 
5702a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_DEV:
5712a8164dfSZhong Wang 			fprintf(stderr,
5722a8164dfSZhong Wang 			    gettext("Error: Failed to open fcoe device\n"));
5732a8164dfSZhong Wang 			break;
5742a8164dfSZhong Wang 
5752a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_WWN_SAME:
5762a8164dfSZhong Wang 			fprintf(stderr,
5772a8164dfSZhong Wang 			    gettext("Error: Port WWN is same as Node "
5782a8164dfSZhong Wang 			    "WWN\n"));
5792a8164dfSZhong Wang 			break;
5802a8164dfSZhong Wang 
5812a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MAC_LEN:
5822a8164dfSZhong Wang 			fprintf(stderr,
5832a8164dfSZhong Wang 			    gettext("Error: MAC name exceeds maximum "
5842a8164dfSZhong Wang 			    "length\n"));
5852a8164dfSZhong Wang 			break;
5862a8164dfSZhong Wang 
5872a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PWWN_CONFLICTED:
5882a8164dfSZhong Wang 			fprintf(stderr,
5892a8164dfSZhong Wang 			    gettext("Error: The specified Port WWN "
5902a8164dfSZhong Wang 			    "is already in use\n"));
5912a8164dfSZhong Wang 			break;
5922a8164dfSZhong Wang 
5932a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_NWWN_CONFLICTED:
5942a8164dfSZhong Wang 			fprintf(stderr,
5952a8164dfSZhong Wang 			    gettext("Error: The specified Node WWN "
5962a8164dfSZhong Wang 			    "is already in use\n"));
5972a8164dfSZhong Wang 			break;
5982a8164dfSZhong Wang 
5992a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_NEED_JUMBO_FRAME:
6002a8164dfSZhong Wang 			fprintf(stderr,
6012a8164dfSZhong Wang 			    gettext("Error: MTU size of the specified "
6022a8164dfSZhong Wang 			    "MAC link needs to be increased to 2500 "
6032a8164dfSZhong Wang 			    "or above\n"));
6042a8164dfSZhong Wang 			break;
6052a8164dfSZhong Wang 
6062a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_CREATE_MAC:
6072a8164dfSZhong Wang 			fprintf(stderr,
6082a8164dfSZhong Wang 			    gettext("Error: Out of memory\n"));
6092a8164dfSZhong Wang 			break;
6102a8164dfSZhong Wang 
6112a8164dfSZhong Wang 
6122a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_MAC:
6132a8164dfSZhong Wang 			fprintf(stderr,
6142a8164dfSZhong Wang 			    gettext("Error: Failed to open the "
6152a8164dfSZhong Wang 			    "specified MAC link\n"));
6162a8164dfSZhong Wang 			break;
6172a8164dfSZhong Wang 
6182a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_CREATE_PORT:
6192a8164dfSZhong Wang 			fprintf(stderr,
6202a8164dfSZhong Wang 			    gettext("Error: Failed to create FCoE "
6212a8164dfSZhong Wang 			    "port on the specified MAC link\n"));
6222a8164dfSZhong Wang 			break;
6232a8164dfSZhong Wang 
624*d4401b99SKelly Hu 		case  FCOE_STATUS_ERROR_CLASS_UNSUPPORT:
6252a8164dfSZhong Wang 			fprintf(stderr,
626*d4401b99SKelly Hu 			    gettext("Error: Link class other than physical "
627*d4401b99SKelly Hu 			    "link is not supported\n"));
628*d4401b99SKelly Hu 			break;
629*d4401b99SKelly Hu 
630*d4401b99SKelly Hu 		case FCOE_STATUS_ERROR_GET_LINKINFO:
631*d4401b99SKelly Hu 			fprintf(stderr,
632*d4401b99SKelly Hu 			    gettext("Error: Failed to get link infomation "
633*d4401b99SKelly Hu 			    "for %s\n"), macLinkName);
6342a8164dfSZhong Wang 			break;
6352a8164dfSZhong Wang 
6362a8164dfSZhong Wang 		case FCOE_STATUS_ERROR:
6372a8164dfSZhong Wang 		default:
6382a8164dfSZhong Wang 			fprintf(stderr,
6392a8164dfSZhong Wang 			    gettext("Error: Due to reason code %d\n"), status);
6402a8164dfSZhong Wang 		}
6412a8164dfSZhong Wang 		return (1);
6422a8164dfSZhong Wang 	} else {
6432a8164dfSZhong Wang 		char cpwwn[17], cnwwn[17];
6442a8164dfSZhong Wang 
6452a8164dfSZhong Wang 		WWN2str(cpwwn, &pwwn);
6462a8164dfSZhong Wang 		WWN2str(cnwwn, &nwwn);
6472a8164dfSZhong Wang 
6482a8164dfSZhong Wang 		fcoe_adm_add_remove_scf_entry((char *)macLinkName,
6492a8164dfSZhong Wang 		    cpwwn,
6502a8164dfSZhong Wang 		    cnwwn,
6512a8164dfSZhong Wang 		    createtgt,
6522a8164dfSZhong Wang 		    promiscuous,
6532a8164dfSZhong Wang 		    FCOE_SCF_ADD);
6542a8164dfSZhong Wang 		return (0);
6552a8164dfSZhong Wang 	}
6562a8164dfSZhong Wang }
6572a8164dfSZhong Wang 
6582a8164dfSZhong Wang int
6592a8164dfSZhong Wang fcoe_adm_delete_port(int objects, char *argv[])
6602a8164dfSZhong Wang {
6612a8164dfSZhong Wang 	FCOE_STATUS status;
6622a8164dfSZhong Wang 	FCOE_UINT8	*macLinkName;
6632a8164dfSZhong Wang 
6642a8164dfSZhong Wang 	/* check the mac name operand */
6652a8164dfSZhong Wang 	assert(objects == 1);
6662a8164dfSZhong Wang 
6672a8164dfSZhong Wang 	macLinkName = (FCOE_UINT8 *) argv[0];
6682a8164dfSZhong Wang 
6692a8164dfSZhong Wang 	status = FCOE_DeletePort(macLinkName);
6702a8164dfSZhong Wang 	if (status != FCOE_STATUS_OK) {
6712a8164dfSZhong Wang 		switch (status) {
6722a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_BUSY:
6732a8164dfSZhong Wang 			fprintf(stderr,
6742a8164dfSZhong Wang 			    gettext("Error: fcoe driver is busy\n"));
6752a8164dfSZhong Wang 			break;
6762a8164dfSZhong Wang 
6772a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_ALREADY:
6782a8164dfSZhong Wang 			fprintf(stderr,
6792a8164dfSZhong Wang 			    gettext("Error: FCoE port not found on the "
6802a8164dfSZhong Wang 			    "specified MAC link\n"));
6812a8164dfSZhong Wang 			break;
6822a8164dfSZhong Wang 
6832a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PERM:
6842a8164dfSZhong Wang 			fprintf(stderr,
6852a8164dfSZhong Wang 			    gettext("Error: Not enough permission to "
6862a8164dfSZhong Wang 			    "open fcoe device\n"));
6872a8164dfSZhong Wang 			break;
6882a8164dfSZhong Wang 
6892a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MAC_LEN:
6902a8164dfSZhong Wang 			fprintf(stderr,
6912a8164dfSZhong Wang 			    gettext("Failed: MAC name exceeds maximum "
6922a8164dfSZhong Wang 			    "length 32\n"));
6932a8164dfSZhong Wang 			break;
6942a8164dfSZhong Wang 
6952a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_DEV:
6962a8164dfSZhong Wang 			fprintf(stderr,
6972a8164dfSZhong Wang 			    gettext("Error: Failed to open fcoe device\n"));
6982a8164dfSZhong Wang 			break;
6992a8164dfSZhong Wang 
7002a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MAC_NOT_FOUND:
7012a8164dfSZhong Wang 			fprintf(stderr,
7022a8164dfSZhong Wang 			    gettext("Error: FCoE port not found on the "
7032a8164dfSZhong Wang 			    "specified MAC link\n"));
7042a8164dfSZhong Wang 			break;
7052a8164dfSZhong Wang 
7062a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OFFLINE_DEV:
7072a8164dfSZhong Wang 			fprintf(stderr,
7082a8164dfSZhong Wang 			    gettext("Error: Please use stmfadm to offline "
7092a8164dfSZhong Wang 			    "the FCoE target first\n"));
7102a8164dfSZhong Wang 			break;
7112a8164dfSZhong Wang 
712*d4401b99SKelly Hu 		case FCOE_STATUS_ERROR_GET_LINKINFO:
713*d4401b99SKelly Hu 			fprintf(stderr,
714*d4401b99SKelly Hu 			    gettext("Error: Failed to get link information "
715*d4401b99SKelly Hu 			    "for %s\n"), macLinkName);
716*d4401b99SKelly Hu 			break;
717*d4401b99SKelly Hu 
7182a8164dfSZhong Wang 		case FCOE_STATUS_ERROR:
7192a8164dfSZhong Wang 		default:
7202a8164dfSZhong Wang 			fprintf(stderr,
7212a8164dfSZhong Wang 			    gettext("Error: Due to reason code %d\n"), status);
7222a8164dfSZhong Wang 		}
7232a8164dfSZhong Wang 		return (1);
7242a8164dfSZhong Wang 	} else {
7252a8164dfSZhong Wang 		fcoe_adm_add_remove_scf_entry((char *)macLinkName,
7262a8164dfSZhong Wang 		    "",
7272a8164dfSZhong Wang 		    "",
7282a8164dfSZhong Wang 		    0,
7292a8164dfSZhong Wang 		    0,
7302a8164dfSZhong Wang 		    FCOE_SCF_REMOVE);
7312a8164dfSZhong Wang 		return (0);
7322a8164dfSZhong Wang 	}
7332a8164dfSZhong Wang }
7342a8164dfSZhong Wang 
7352a8164dfSZhong Wang int
7362a8164dfSZhong Wang fcoe_adm_list_ports(cmdOptions_t *options)
7372a8164dfSZhong Wang {
7382a8164dfSZhong Wang 	FCOE_STATUS	status;
7392a8164dfSZhong Wang 	int	showini = 0, showtgt = 0;
7402a8164dfSZhong Wang 	FCOE_UINT32	port_num;
7412a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	*portlist = NULL;
7422a8164dfSZhong Wang 	int i;
7432a8164dfSZhong Wang 	int ret;
7442a8164dfSZhong Wang 
7452a8164dfSZhong Wang 	for (; options->optval; options++) {
7462a8164dfSZhong Wang 		switch (options->optval) {
7472a8164dfSZhong Wang 		case 'i':
7482a8164dfSZhong Wang 			showini = 1;
7492a8164dfSZhong Wang 			break;
7502a8164dfSZhong Wang 
7512a8164dfSZhong Wang 		case 't':
7522a8164dfSZhong Wang 			showtgt = 1;
7532a8164dfSZhong Wang 			break;
7542a8164dfSZhong Wang 
7552a8164dfSZhong Wang 		default:
7562a8164dfSZhong Wang 			fprintf(stderr, gettext("Error: Illegal option: %c\n"),
7572a8164dfSZhong Wang 			    options->optval);
7582a8164dfSZhong Wang 			return (1);
7592a8164dfSZhong Wang 		}
7602a8164dfSZhong Wang 	}
7612a8164dfSZhong Wang 	if (showini == 0 && showtgt == 0) {
7622a8164dfSZhong Wang 		showini = 1;
7632a8164dfSZhong Wang 		showtgt = 1;
7642a8164dfSZhong Wang 	}
7652a8164dfSZhong Wang 
7662a8164dfSZhong Wang 	status = FCOE_GetPortList(&port_num, &portlist);
7672a8164dfSZhong Wang 
7682a8164dfSZhong Wang 	if (status != FCOE_STATUS_OK) {
7692a8164dfSZhong Wang 		switch (status) {
7702a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_BUSY:
7712a8164dfSZhong Wang 			fprintf(stderr,
7722a8164dfSZhong Wang 			    gettext("Error: fcoe driver is busy\n"));
7732a8164dfSZhong Wang 			break;
7742a8164dfSZhong Wang 
7752a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PERM:
7762a8164dfSZhong Wang 			fprintf(stderr,
7772a8164dfSZhong Wang 			    gettext("Error: Not enough permission to "
7782a8164dfSZhong Wang 			    "open fcoe device\n"));
7792a8164dfSZhong Wang 			break;
7802a8164dfSZhong Wang 
7812a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_DEV:
7822a8164dfSZhong Wang 			fprintf(stderr,
7832a8164dfSZhong Wang 			    gettext("Error: Failed to open fcoe device\n"));
7842a8164dfSZhong Wang 			break;
7852a8164dfSZhong Wang 
7862a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_INVAL_ARG:
7872a8164dfSZhong Wang 			fprintf(stderr,
7882a8164dfSZhong Wang 			    gettext("Error: Invalid argument\n"));
7892a8164dfSZhong Wang 			break;
7902a8164dfSZhong Wang 
7912a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MORE_DATA:
7922a8164dfSZhong Wang 			fprintf(stderr,
7932a8164dfSZhong Wang 			    gettext("Error: More data\n"));
7942a8164dfSZhong Wang 			break;
7952a8164dfSZhong Wang 
7962a8164dfSZhong Wang 		case FCOE_STATUS_ERROR:
7972a8164dfSZhong Wang 		default:
7982a8164dfSZhong Wang 			fprintf(stderr,
7992a8164dfSZhong Wang 			    gettext("Error: Due to reason code %d\n"), status);
8002a8164dfSZhong Wang 		}
8012a8164dfSZhong Wang 		ret = 1;
8022a8164dfSZhong Wang 	} else {
8032a8164dfSZhong Wang 		if (port_num == 0) {
8042a8164dfSZhong Wang 			fprintf(stdout, gettext("No FCoE Ports Found!\n"));
8052a8164dfSZhong Wang 		} else {
8062a8164dfSZhong Wang 			for (i = 0; i < port_num; i++) {
8072a8164dfSZhong Wang 				if ((portlist[i].port_type ==
8082a8164dfSZhong Wang 				    FCOE_PORTTYPE_INITIATOR &&
8092a8164dfSZhong Wang 				    showini == 1) || (showtgt == 1 &&
8102a8164dfSZhong Wang 				    portlist[i].port_type ==
8112a8164dfSZhong Wang 				    FCOE_PORTTYPE_TARGET)) {
8122a8164dfSZhong Wang 					printFCOEPortInfo(&portlist[i]);
8132a8164dfSZhong Wang 				}
8142a8164dfSZhong Wang 			}
8152a8164dfSZhong Wang 		}
8162a8164dfSZhong Wang 		ret = 0;
8172a8164dfSZhong Wang 	}
8182a8164dfSZhong Wang 
8192a8164dfSZhong Wang 	if (portlist != NULL) {
8202a8164dfSZhong Wang 		free(portlist);
8212a8164dfSZhong Wang 	}
8222a8164dfSZhong Wang 	return (ret);
8232a8164dfSZhong Wang 
8242a8164dfSZhong Wang }
8252a8164dfSZhong Wang 
8262a8164dfSZhong Wang int
8272a8164dfSZhong Wang fcoe_adm_create_portlist(cmdOptions_t *options)
8282a8164dfSZhong Wang {
8292a8164dfSZhong Wang 	scf_handle_t	*handle = NULL;
8302a8164dfSZhong Wang 	scf_service_t	*svc = NULL;
8312a8164dfSZhong Wang 	scf_propertygroup_t	*pg = NULL;
8322a8164dfSZhong Wang 	scf_transaction_t	*tran = NULL;
8332a8164dfSZhong Wang 	scf_transaction_entry_t	*entry = NULL;
8342a8164dfSZhong Wang 	scf_property_t		*prop = NULL;
8352a8164dfSZhong Wang 	scf_value_t	*valueLookup = NULL;
8362a8164dfSZhong Wang 	scf_iter_t	*valueIter = NULL;
8372a8164dfSZhong Wang 	char		buf[FCOE_PORT_LIST_LENGTH] = {0};
8382a8164dfSZhong Wang 	int		commitRet;
8392a8164dfSZhong Wang 	int		create_target = 0, create_initiator = 0;
8402a8164dfSZhong Wang 
8412a8164dfSZhong Wang 	/* Check what type of port list will be created */
8422a8164dfSZhong Wang 	for (; options->optval; options++) {
8432a8164dfSZhong Wang 		switch (options->optval) {
8442a8164dfSZhong Wang 		case 'i':
8452a8164dfSZhong Wang 			create_initiator = 1;
8462a8164dfSZhong Wang 			break;
8472a8164dfSZhong Wang 		case 't':
8482a8164dfSZhong Wang 			create_target = 1;
8492a8164dfSZhong Wang 			break;
8502a8164dfSZhong Wang 		default:
8512a8164dfSZhong Wang 			fprintf(stderr, gettext("Error: Illegal option: %c\n"),
8522a8164dfSZhong Wang 			    options->optval);
8532a8164dfSZhong Wang 			return (1);
8542a8164dfSZhong Wang 		}
8552a8164dfSZhong Wang 	}
8562a8164dfSZhong Wang 
8572a8164dfSZhong Wang 	if (create_initiator == 0 && create_target == 0) {
8582a8164dfSZhong Wang 		create_initiator = 1;
8592a8164dfSZhong Wang 		create_target = 1;
8602a8164dfSZhong Wang 	}
8612a8164dfSZhong Wang 
8622a8164dfSZhong Wang 	commitRet = fcoe_cfg_scf_init(&handle, &svc);
8632a8164dfSZhong Wang 	if (commitRet != FCOE_SUCCESS) {
8642a8164dfSZhong Wang 		goto out;
8652a8164dfSZhong Wang 	}
8662a8164dfSZhong Wang 
8672a8164dfSZhong Wang 	if (((pg = scf_pg_create(handle)) == NULL) ||
8682a8164dfSZhong Wang 	    ((tran = scf_transaction_create(handle)) == NULL) ||
8692a8164dfSZhong Wang 	    ((entry = scf_entry_create(handle)) == NULL) ||
8702a8164dfSZhong Wang 	    ((prop = scf_property_create(handle)) == NULL) ||
8712a8164dfSZhong Wang 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
8722a8164dfSZhong Wang 		goto out;
8732a8164dfSZhong Wang 	}
8742a8164dfSZhong Wang 
8752a8164dfSZhong Wang 	/* get property group or create it */
8762a8164dfSZhong Wang 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
8772a8164dfSZhong Wang 		goto out;
8782a8164dfSZhong Wang 	}
8792a8164dfSZhong Wang 
8802a8164dfSZhong Wang 	if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
8812a8164dfSZhong Wang 		syslog(LOG_ERR, "get property failed - %s",
8822a8164dfSZhong Wang 		    scf_strerror(scf_error()));
8832a8164dfSZhong Wang 		goto out;
8842a8164dfSZhong Wang 	}
8852a8164dfSZhong Wang 
8862a8164dfSZhong Wang 	valueLookup = scf_value_create(handle);
8872a8164dfSZhong Wang 	if (valueLookup == NULL) {
8882a8164dfSZhong Wang 		syslog(LOG_ERR, "scf value alloc failed - %s",
8892a8164dfSZhong Wang 		    scf_strerror(scf_error()));
8902a8164dfSZhong Wang 		goto out;
8912a8164dfSZhong Wang 	}
8922a8164dfSZhong Wang 
8932a8164dfSZhong Wang 	if (scf_iter_property_values(valueIter, prop) == -1) {
8942a8164dfSZhong Wang 		syslog(LOG_ERR, "iter value failed - %s",
8952a8164dfSZhong Wang 		    scf_strerror(scf_error()));
8962a8164dfSZhong Wang 		goto out;
8972a8164dfSZhong Wang 	}
8982a8164dfSZhong Wang 	while (scf_iter_next_value(valueIter, valueLookup) == 1) {
8992a8164dfSZhong Wang 		uint8_t *macLinkName = NULL;
9002a8164dfSZhong Wang 		char *remainder = NULL;
9012a8164dfSZhong Wang 		FCOE_PORT_WWN pwwn, nwwn;
9022a8164dfSZhong Wang 		uint64_t	nodeWWN, portWWN;
9032a8164dfSZhong Wang 		int is_target, is_promiscuous;
9042a8164dfSZhong Wang 
9052a8164dfSZhong Wang 		bzero(buf, sizeof (buf));
9062a8164dfSZhong Wang 		bzero(&pwwn, sizeof (pwwn));
9072a8164dfSZhong Wang 		bzero(&nwwn, sizeof (nwwn));
9082a8164dfSZhong Wang 		if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
9092a8164dfSZhong Wang 			syslog(LOG_ERR, "iter value failed - %s",
9102a8164dfSZhong Wang 			    scf_strerror(scf_error()));
9112a8164dfSZhong Wang 			break;
9122a8164dfSZhong Wang 		}
9132a8164dfSZhong Wang 		macLinkName = (uint8_t *)strtok(buf, ":");
9142a8164dfSZhong Wang 		remainder = strtok(NULL, "#");
9152a8164dfSZhong Wang 		sscanf(remainder, "%016llx:%016llx:%d:%d",
9162a8164dfSZhong Wang 		    &portWWN, &nodeWWN, &is_target, &is_promiscuous);
9172a8164dfSZhong Wang 		if ((!create_target && is_target) ||
9182a8164dfSZhong Wang 		    (!create_initiator && !is_target)) {
9192a8164dfSZhong Wang 			continue;
9202a8164dfSZhong Wang 		}
9212a8164dfSZhong Wang 
9222a8164dfSZhong Wang 		nodeWWN = htonll(nodeWWN);
9232a8164dfSZhong Wang 		memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN));
9242a8164dfSZhong Wang 		portWWN = htonll(portWWN);
9252a8164dfSZhong Wang 		memcpy(&pwwn, &portWWN, sizeof (portWWN));
9262a8164dfSZhong Wang 
9272a8164dfSZhong Wang 		FCOE_CreatePort(macLinkName,
9282a8164dfSZhong Wang 		    is_target ? FCOE_PORTTYPE_TARGET : FCOE_PORTTYPE_INITIATOR,
9292a8164dfSZhong Wang 		    pwwn, nwwn, is_promiscuous);
9302a8164dfSZhong Wang 	}
9312a8164dfSZhong Wang 
9322a8164dfSZhong Wang out:
9332a8164dfSZhong Wang 	/*
9342a8164dfSZhong Wang 	 * Free resources
9352a8164dfSZhong Wang 	 */
9362a8164dfSZhong Wang 	if (handle != NULL) {
9372a8164dfSZhong Wang 		scf_handle_destroy(handle);
9382a8164dfSZhong Wang 	}
9392a8164dfSZhong Wang 	if (svc != NULL) {
9402a8164dfSZhong Wang 		scf_service_destroy(svc);
9412a8164dfSZhong Wang 	}
9422a8164dfSZhong Wang 	if (pg != NULL) {
9432a8164dfSZhong Wang 		scf_pg_destroy(pg);
9442a8164dfSZhong Wang 	}
9452a8164dfSZhong Wang 	if (tran != NULL) {
9462a8164dfSZhong Wang 		scf_transaction_destroy(tran);
9472a8164dfSZhong Wang 	}
9482a8164dfSZhong Wang 	if (entry != NULL) {
9492a8164dfSZhong Wang 		scf_entry_destroy(entry);
9502a8164dfSZhong Wang 	}
9512a8164dfSZhong Wang 	if (prop != NULL) {
9522a8164dfSZhong Wang 		scf_property_destroy(prop);
9532a8164dfSZhong Wang 	}
9542a8164dfSZhong Wang 	if (valueIter != NULL) {
9552a8164dfSZhong Wang 		scf_iter_destroy(valueIter);
9562a8164dfSZhong Wang 	}
9572a8164dfSZhong Wang 	if (valueLookup != NULL) {
9582a8164dfSZhong Wang 		scf_value_destroy(valueLookup);
9592a8164dfSZhong Wang 	}
9602a8164dfSZhong Wang 
9612a8164dfSZhong Wang 	return (0);
9622a8164dfSZhong Wang }
963