xref: /titanic_44/usr/src/cmd/fcinfo/fcoeadm.c (revision 2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41)
1*2a8164dfSZhong Wang /*
2*2a8164dfSZhong Wang  * CDDL HEADER START
3*2a8164dfSZhong Wang  *
4*2a8164dfSZhong Wang  * The contents of this file are subject to the terms of the
5*2a8164dfSZhong Wang  * Common Development and Distribution License (the "License").
6*2a8164dfSZhong Wang  * You may not use this file except in compliance with the License.
7*2a8164dfSZhong Wang  *
8*2a8164dfSZhong Wang  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2a8164dfSZhong Wang  * or http://www.opensolaris.org/os/licensing.
10*2a8164dfSZhong Wang  * See the License for the specific language governing permissions
11*2a8164dfSZhong Wang  * and limitations under the License.
12*2a8164dfSZhong Wang  *
13*2a8164dfSZhong Wang  * When distributing Covered Code, include this CDDL HEADER in each
14*2a8164dfSZhong Wang  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2a8164dfSZhong Wang  * If applicable, add the following below this CDDL HEADER, with the
16*2a8164dfSZhong Wang  * fields enclosed by brackets "[]" replaced with your own identifying
17*2a8164dfSZhong Wang  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2a8164dfSZhong Wang  *
19*2a8164dfSZhong Wang  * CDDL HEADER END
20*2a8164dfSZhong Wang  */
21*2a8164dfSZhong Wang /*
22*2a8164dfSZhong Wang  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*2a8164dfSZhong Wang  * Use is subject to license terms.
24*2a8164dfSZhong Wang  */
25*2a8164dfSZhong Wang 
26*2a8164dfSZhong Wang #include "fcinfo.h"
27*2a8164dfSZhong Wang #include <libintl.h>
28*2a8164dfSZhong Wang #include <fcntl.h>
29*2a8164dfSZhong Wang #include <errno.h>
30*2a8164dfSZhong Wang #include <assert.h>
31*2a8164dfSZhong Wang #include <ctype.h>
32*2a8164dfSZhong Wang #include <sys/list.h>
33*2a8164dfSZhong Wang #include <stddef.h>
34*2a8164dfSZhong Wang #include <strings.h>
35*2a8164dfSZhong Wang #include <libfcoe.h>
36*2a8164dfSZhong Wang #include <libscf.h>
37*2a8164dfSZhong Wang #include <syslog.h>
38*2a8164dfSZhong Wang 
39*2a8164dfSZhong Wang static const char *FCOE_DRIVER_PATH	= "/devices/fcoe:admin";
40*2a8164dfSZhong Wang 
41*2a8164dfSZhong Wang static char *
42*2a8164dfSZhong Wang WWN2str(char *buf, FCOE_PORT_WWN *wwn) {
43*2a8164dfSZhong Wang 	int j;
44*2a8164dfSZhong Wang 	unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
45*2a8164dfSZhong Wang 	buf[0] = '\0';
46*2a8164dfSZhong Wang 	for (j = 0; j < 16; j += 2) {
47*2a8164dfSZhong Wang 		sprintf(&buf[j], "%02X", (int)*pc++);
48*2a8164dfSZhong Wang 	}
49*2a8164dfSZhong Wang 	return (buf);
50*2a8164dfSZhong Wang }
51*2a8164dfSZhong Wang 
52*2a8164dfSZhong Wang static int
53*2a8164dfSZhong Wang isValidWWN(char *wwn)
54*2a8164dfSZhong Wang {
55*2a8164dfSZhong Wang 	int index;
56*2a8164dfSZhong Wang 
57*2a8164dfSZhong Wang 	if (wwn == NULL) {
58*2a8164dfSZhong Wang 		return (0);
59*2a8164dfSZhong Wang 	}
60*2a8164dfSZhong Wang 
61*2a8164dfSZhong Wang 	if (strlen(wwn) != 16) {
62*2a8164dfSZhong Wang 		return (0);
63*2a8164dfSZhong Wang 	}
64*2a8164dfSZhong Wang 
65*2a8164dfSZhong Wang 	for (index = 0; index < 16; index++) {
66*2a8164dfSZhong Wang 		if (isxdigit(wwn[index])) {
67*2a8164dfSZhong Wang 			continue;
68*2a8164dfSZhong Wang 		}
69*2a8164dfSZhong Wang 		return (0);
70*2a8164dfSZhong Wang 	}
71*2a8164dfSZhong Wang 	return (1);
72*2a8164dfSZhong Wang }
73*2a8164dfSZhong Wang 
74*2a8164dfSZhong Wang static uint64_t wwnconvert(uchar_t *wwn)
75*2a8164dfSZhong Wang {
76*2a8164dfSZhong Wang 	uint64_t tmp;
77*2a8164dfSZhong Wang 	memcpy(&tmp, wwn, sizeof (uint64_t));
78*2a8164dfSZhong Wang 	return (ntohll(tmp));
79*2a8164dfSZhong Wang }
80*2a8164dfSZhong Wang 
81*2a8164dfSZhong Wang /*
82*2a8164dfSZhong Wang  * prints out all the HBA port information
83*2a8164dfSZhong Wang  */
84*2a8164dfSZhong Wang void
85*2a8164dfSZhong Wang printFCOEPortInfo(FCOE_PORT_ATTRIBUTE *attr)
86*2a8164dfSZhong Wang {
87*2a8164dfSZhong Wang 	int i;
88*2a8164dfSZhong Wang 	if (attr == NULL) {
89*2a8164dfSZhong Wang 		return;
90*2a8164dfSZhong Wang 	}
91*2a8164dfSZhong Wang 	fprintf(stdout, gettext("HBA Port WWN: %016llx\n"),
92*2a8164dfSZhong Wang 	    wwnconvert((unsigned char *)&attr->port_wwn));
93*2a8164dfSZhong Wang 
94*2a8164dfSZhong Wang 	fprintf(stdout, gettext("\tPort Type: %s\n"),
95*2a8164dfSZhong Wang 	    (attr->port_type == 0) ? "Initiator" : "Target");
96*2a8164dfSZhong Wang 
97*2a8164dfSZhong Wang 	fprintf(stdout, gettext("\tMAC Name: %s\n"), attr->mac_link_name);
98*2a8164dfSZhong Wang 
99*2a8164dfSZhong Wang 	fprintf(stdout, gettext("\tMTU Size: %d\n"), attr->mtu_size);
100*2a8164dfSZhong Wang 
101*2a8164dfSZhong Wang 	fprintf(stdout, gettext("\tMAC Factory Address: "));
102*2a8164dfSZhong Wang 	for (i = 0; i < 6; i++) {
103*2a8164dfSZhong Wang 		fprintf(stdout, gettext("%02x"), attr->mac_factory_addr[i]);
104*2a8164dfSZhong Wang 	}
105*2a8164dfSZhong Wang 	fprintf(stdout, gettext("\n\tMAC Current Address: "));
106*2a8164dfSZhong Wang 	for (i = 0; i < 6; i++) {
107*2a8164dfSZhong Wang 		fprintf(stdout, gettext("%02x"), attr->mac_current_addr[i]);
108*2a8164dfSZhong Wang 	}
109*2a8164dfSZhong Wang 	fprintf(stdout, gettext("\n\tPromiscuous Mode: %s\n"),
110*2a8164dfSZhong Wang 	    attr->mac_promisc == 1 ? "On" : "Off");
111*2a8164dfSZhong Wang }
112*2a8164dfSZhong Wang 
113*2a8164dfSZhong Wang /*
114*2a8164dfSZhong Wang  * Initialize scf fcoe service access
115*2a8164dfSZhong Wang  * handle - returned handle
116*2a8164dfSZhong Wang  * service - returned service handle
117*2a8164dfSZhong Wang  */
118*2a8164dfSZhong Wang static int
119*2a8164dfSZhong Wang fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service)
120*2a8164dfSZhong Wang {
121*2a8164dfSZhong Wang 	scf_scope_t	*scope = NULL;
122*2a8164dfSZhong Wang 	int		ret;
123*2a8164dfSZhong Wang 
124*2a8164dfSZhong Wang 	if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
125*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_handle_create failed - %s",
126*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
127*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
128*2a8164dfSZhong Wang 		goto err;
129*2a8164dfSZhong Wang 	}
130*2a8164dfSZhong Wang 
131*2a8164dfSZhong Wang 	if (scf_handle_bind(*handle) == -1) {
132*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_handle_bind failed - %s",
133*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
134*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
135*2a8164dfSZhong Wang 		goto err;
136*2a8164dfSZhong Wang 	}
137*2a8164dfSZhong Wang 
138*2a8164dfSZhong Wang 	if ((*service = scf_service_create(*handle)) == NULL) {
139*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_service_create failed - %s",
140*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
141*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
142*2a8164dfSZhong Wang 		goto err;
143*2a8164dfSZhong Wang 	}
144*2a8164dfSZhong Wang 
145*2a8164dfSZhong Wang 	if ((scope = scf_scope_create(*handle)) == NULL) {
146*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_scope_create failed - %s",
147*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
148*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
149*2a8164dfSZhong Wang 		goto err;
150*2a8164dfSZhong Wang 	}
151*2a8164dfSZhong Wang 
152*2a8164dfSZhong Wang 	if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
153*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
154*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
155*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
156*2a8164dfSZhong Wang 		goto err;
157*2a8164dfSZhong Wang 	}
158*2a8164dfSZhong Wang 
159*2a8164dfSZhong Wang 	if (scf_scope_get_service(scope, FCOE_SERVICE, *service) == -1) {
160*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf_scope_get_service failed - %s",
161*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
162*2a8164dfSZhong Wang 		ret = FCOE_ERROR_SERVICE_NOT_FOUND;
163*2a8164dfSZhong Wang 		goto err;
164*2a8164dfSZhong Wang 	}
165*2a8164dfSZhong Wang 
166*2a8164dfSZhong Wang 	scf_scope_destroy(scope);
167*2a8164dfSZhong Wang 
168*2a8164dfSZhong Wang 	return (FCOE_SUCCESS);
169*2a8164dfSZhong Wang 
170*2a8164dfSZhong Wang err:
171*2a8164dfSZhong Wang 	if (*handle != NULL) {
172*2a8164dfSZhong Wang 		scf_handle_destroy(*handle);
173*2a8164dfSZhong Wang 	}
174*2a8164dfSZhong Wang 	if (*service != NULL) {
175*2a8164dfSZhong Wang 		scf_service_destroy(*service);
176*2a8164dfSZhong Wang 		*service = NULL;
177*2a8164dfSZhong Wang 	}
178*2a8164dfSZhong Wang 	if (scope != NULL) {
179*2a8164dfSZhong Wang 		scf_scope_destroy(scope);
180*2a8164dfSZhong Wang 	}
181*2a8164dfSZhong Wang 	return (ret);
182*2a8164dfSZhong Wang }
183*2a8164dfSZhong Wang 
184*2a8164dfSZhong Wang 
185*2a8164dfSZhong Wang static int
186*2a8164dfSZhong Wang fcoe_adm_add_remove_scf_entry(char *mac_name,
187*2a8164dfSZhong Wang     char *pwwn, char *nwwn,
188*2a8164dfSZhong Wang     int is_target, int is_promiscuous, int addRemoveFlag)
189*2a8164dfSZhong Wang {
190*2a8164dfSZhong Wang 	scf_handle_t	*handle = NULL;
191*2a8164dfSZhong Wang 	scf_service_t	*svc = NULL;
192*2a8164dfSZhong Wang 	scf_propertygroup_t	*pg = NULL;
193*2a8164dfSZhong Wang 	scf_transaction_t	*tran = NULL;
194*2a8164dfSZhong Wang 	scf_transaction_entry_t	*entry = NULL;
195*2a8164dfSZhong Wang 	scf_property_t	*prop = NULL;
196*2a8164dfSZhong Wang 	scf_value_t	*valueLookup = NULL;
197*2a8164dfSZhong Wang 	scf_iter_t	*valueIter = NULL;
198*2a8164dfSZhong Wang 	scf_value_t	**valueSet = NULL;
199*2a8164dfSZhong Wang 	int	ret = FCOE_SUCCESS;
200*2a8164dfSZhong Wang 	boolean_t	createProp = B_FALSE;
201*2a8164dfSZhong Wang 	int	lastAlloc = 0;
202*2a8164dfSZhong Wang 	char	buf[FCOE_PORT_LIST_LENGTH] = {0};
203*2a8164dfSZhong Wang 	char	memberName[FCOE_PORT_LIST_LENGTH] = {0};
204*2a8164dfSZhong Wang 	boolean_t	found = B_FALSE;
205*2a8164dfSZhong Wang 	int	i = 0;
206*2a8164dfSZhong Wang 	int	valueArraySize = 0;
207*2a8164dfSZhong Wang 	int	commitRet;
208*2a8164dfSZhong Wang 
209*2a8164dfSZhong Wang 	sprintf(memberName, "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn,
210*2a8164dfSZhong Wang 	    is_target, is_promiscuous);
211*2a8164dfSZhong Wang 
212*2a8164dfSZhong Wang 	ret = fcoe_cfg_scf_init(&handle, &svc);
213*2a8164dfSZhong Wang 	if (ret != FCOE_SUCCESS) {
214*2a8164dfSZhong Wang 		goto out;
215*2a8164dfSZhong Wang 	}
216*2a8164dfSZhong Wang 
217*2a8164dfSZhong Wang 	if (((pg = scf_pg_create(handle)) == NULL) ||
218*2a8164dfSZhong Wang 	    ((tran = scf_transaction_create(handle)) == NULL) ||
219*2a8164dfSZhong Wang 	    ((entry = scf_entry_create(handle)) == NULL) ||
220*2a8164dfSZhong Wang 	    ((prop = scf_property_create(handle)) == NULL) ||
221*2a8164dfSZhong Wang 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
222*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
223*2a8164dfSZhong Wang 		goto out;
224*2a8164dfSZhong Wang 	}
225*2a8164dfSZhong Wang 
226*2a8164dfSZhong Wang 	/* get property group or create it */
227*2a8164dfSZhong Wang 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
228*2a8164dfSZhong Wang 		if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
229*2a8164dfSZhong Wang 			if (scf_service_add_pg(svc, FCOE_PG_NAME,
230*2a8164dfSZhong Wang 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
231*2a8164dfSZhong Wang 				syslog(LOG_ERR, "add pg failed - %s",
232*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
233*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
234*2a8164dfSZhong Wang 			} else {
235*2a8164dfSZhong Wang 				createProp = B_TRUE;
236*2a8164dfSZhong Wang 			}
237*2a8164dfSZhong Wang 		} else {
238*2a8164dfSZhong Wang 			syslog(LOG_ERR, "get pg failed - %s",
239*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
240*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
241*2a8164dfSZhong Wang 		}
242*2a8164dfSZhong Wang 		if (ret != FCOE_SUCCESS) {
243*2a8164dfSZhong Wang 			goto out;
244*2a8164dfSZhong Wang 		}
245*2a8164dfSZhong Wang 	}
246*2a8164dfSZhong Wang 
247*2a8164dfSZhong Wang 	/* to make sure property exists */
248*2a8164dfSZhong Wang 	if (createProp == B_FALSE) {
249*2a8164dfSZhong Wang 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
250*2a8164dfSZhong Wang 			if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
251*2a8164dfSZhong Wang 				createProp = B_TRUE;
252*2a8164dfSZhong Wang 			} else {
253*2a8164dfSZhong Wang 				syslog(LOG_ERR, "get property failed - %s",
254*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
255*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
256*2a8164dfSZhong Wang 				goto out;
257*2a8164dfSZhong Wang 			}
258*2a8164dfSZhong Wang 		}
259*2a8164dfSZhong Wang 	}
260*2a8164dfSZhong Wang 
261*2a8164dfSZhong Wang 	/* Begin the transaction */
262*2a8164dfSZhong Wang 	if (scf_transaction_start(tran, pg) == -1) {
263*2a8164dfSZhong Wang 		syslog(LOG_ERR, "start transaction failed - %s",
264*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
265*2a8164dfSZhong Wang 		ret = FCOE_ERROR;
266*2a8164dfSZhong Wang 		goto out;
267*2a8164dfSZhong Wang 	}
268*2a8164dfSZhong Wang 
269*2a8164dfSZhong Wang 	valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
270*2a8164dfSZhong Wang 	    * (lastAlloc = PORT_LIST_ALLOC));
271*2a8164dfSZhong Wang 	if (valueSet == NULL) {
272*2a8164dfSZhong Wang 		ret = FCOE_ERROR_NOMEM;
273*2a8164dfSZhong Wang 		goto out;
274*2a8164dfSZhong Wang 	}
275*2a8164dfSZhong Wang 
276*2a8164dfSZhong Wang 	if (createProp) {
277*2a8164dfSZhong Wang 		if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST,
278*2a8164dfSZhong Wang 		    SCF_TYPE_USTRING) == -1) {
279*2a8164dfSZhong Wang 			if (scf_error() == SCF_ERROR_EXISTS) {
280*2a8164dfSZhong Wang 				ret = FCOE_ERROR_EXISTS;
281*2a8164dfSZhong Wang 			} else {
282*2a8164dfSZhong Wang 				syslog(LOG_ERR,
283*2a8164dfSZhong Wang 				    "transaction property new failed - %s",
284*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
285*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
286*2a8164dfSZhong Wang 			}
287*2a8164dfSZhong Wang 			goto out;
288*2a8164dfSZhong Wang 		}
289*2a8164dfSZhong Wang 	} else {
290*2a8164dfSZhong Wang 		if (scf_transaction_property_change(tran, entry,
291*2a8164dfSZhong Wang 		    FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) {
292*2a8164dfSZhong Wang 			syslog(LOG_ERR,
293*2a8164dfSZhong Wang 			    "transaction property change failed - %s",
294*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
295*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
296*2a8164dfSZhong Wang 			goto out;
297*2a8164dfSZhong Wang 		}
298*2a8164dfSZhong Wang 
299*2a8164dfSZhong Wang 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
300*2a8164dfSZhong Wang 			syslog(LOG_ERR, "get property failed - %s",
301*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
302*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
303*2a8164dfSZhong Wang 			goto out;
304*2a8164dfSZhong Wang 		}
305*2a8164dfSZhong Wang 
306*2a8164dfSZhong Wang 		valueLookup = scf_value_create(handle);
307*2a8164dfSZhong Wang 		if (valueLookup == NULL) {
308*2a8164dfSZhong Wang 			syslog(LOG_ERR, "scf value alloc failed - %s",
309*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
310*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
311*2a8164dfSZhong Wang 			goto out;
312*2a8164dfSZhong Wang 		}
313*2a8164dfSZhong Wang 
314*2a8164dfSZhong Wang 		if (scf_iter_property_values(valueIter, prop) == -1) {
315*2a8164dfSZhong Wang 			syslog(LOG_ERR, "iter value failed - %s",
316*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
317*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
318*2a8164dfSZhong Wang 			goto out;
319*2a8164dfSZhong Wang 		}
320*2a8164dfSZhong Wang 
321*2a8164dfSZhong Wang 		while (scf_iter_next_value(valueIter, valueLookup) == 1) {
322*2a8164dfSZhong Wang 			char *macnameIter = NULL;
323*2a8164dfSZhong Wang 			char buftmp[FCOE_PORT_LIST_LENGTH] = {0};
324*2a8164dfSZhong Wang 
325*2a8164dfSZhong Wang 			bzero(buf, sizeof (buf));
326*2a8164dfSZhong Wang 			if (scf_value_get_ustring(valueLookup,
327*2a8164dfSZhong Wang 			    buf, MAXNAMELEN) == -1) {
328*2a8164dfSZhong Wang 				syslog(LOG_ERR, "iter value failed- %s",
329*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
330*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
331*2a8164dfSZhong Wang 				break;
332*2a8164dfSZhong Wang 			}
333*2a8164dfSZhong Wang 			strcpy(buftmp, buf);
334*2a8164dfSZhong Wang 			macnameIter = strtok(buftmp, ":");
335*2a8164dfSZhong Wang 			if (bcmp(macnameIter, mac_name,
336*2a8164dfSZhong Wang 			    strlen(mac_name)) == 0) {
337*2a8164dfSZhong Wang 				if (addRemoveFlag == FCOE_SCF_ADD) {
338*2a8164dfSZhong Wang 					ret = FCOE_ERROR_EXISTS;
339*2a8164dfSZhong Wang 					break;
340*2a8164dfSZhong Wang 				} else {
341*2a8164dfSZhong Wang 					found = B_TRUE;
342*2a8164dfSZhong Wang 					continue;
343*2a8164dfSZhong Wang 				}
344*2a8164dfSZhong Wang 			}
345*2a8164dfSZhong Wang 
346*2a8164dfSZhong Wang 			valueSet[i] = scf_value_create(handle);
347*2a8164dfSZhong Wang 			if (valueSet[i] == NULL) {
348*2a8164dfSZhong Wang 				syslog(LOG_ERR, "scf value alloc failed - %s",
349*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
350*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
351*2a8164dfSZhong Wang 				break;
352*2a8164dfSZhong Wang 			}
353*2a8164dfSZhong Wang 
354*2a8164dfSZhong Wang 			if (scf_value_set_ustring(valueSet[i], buf) == -1) {
355*2a8164dfSZhong Wang 				syslog(LOG_ERR, "set value failed 1- %s",
356*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
357*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
358*2a8164dfSZhong Wang 				break;
359*2a8164dfSZhong Wang 			}
360*2a8164dfSZhong Wang 
361*2a8164dfSZhong Wang 			if (scf_entry_add_value(entry, valueSet[i]) == -1) {
362*2a8164dfSZhong Wang 				syslog(LOG_ERR, "add value failed - %s",
363*2a8164dfSZhong Wang 				    scf_strerror(scf_error()));
364*2a8164dfSZhong Wang 				ret = FCOE_ERROR;
365*2a8164dfSZhong Wang 				break;
366*2a8164dfSZhong Wang 			}
367*2a8164dfSZhong Wang 
368*2a8164dfSZhong Wang 			i++;
369*2a8164dfSZhong Wang 
370*2a8164dfSZhong Wang 			if (i >= lastAlloc) {
371*2a8164dfSZhong Wang 				lastAlloc += PORT_LIST_ALLOC;
372*2a8164dfSZhong Wang 				valueSet = realloc(valueSet,
373*2a8164dfSZhong Wang 				    sizeof (*valueSet) * lastAlloc);
374*2a8164dfSZhong Wang 				if (valueSet == NULL) {
375*2a8164dfSZhong Wang 					ret = FCOE_ERROR;
376*2a8164dfSZhong Wang 					break;
377*2a8164dfSZhong Wang 				}
378*2a8164dfSZhong Wang 			}
379*2a8164dfSZhong Wang 		}
380*2a8164dfSZhong Wang 	}
381*2a8164dfSZhong Wang 
382*2a8164dfSZhong Wang 	valueArraySize = i;
383*2a8164dfSZhong Wang 	if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) {
384*2a8164dfSZhong Wang 		ret = FCOE_ERROR_MEMBER_NOT_FOUND;
385*2a8164dfSZhong Wang 	}
386*2a8164dfSZhong Wang 	if (ret != FCOE_SUCCESS) {
387*2a8164dfSZhong Wang 		goto out;
388*2a8164dfSZhong Wang 	}
389*2a8164dfSZhong Wang 
390*2a8164dfSZhong Wang 	if (addRemoveFlag == FCOE_SCF_ADD) {
391*2a8164dfSZhong Wang 		/*
392*2a8164dfSZhong Wang 		 * Now create the new entry
393*2a8164dfSZhong Wang 		 */
394*2a8164dfSZhong Wang 		valueSet[i] = scf_value_create(handle);
395*2a8164dfSZhong Wang 		if (valueSet[i] == NULL) {
396*2a8164dfSZhong Wang 			syslog(LOG_ERR, "scf value alloc failed - %s",
397*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
398*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
399*2a8164dfSZhong Wang 			goto out;
400*2a8164dfSZhong Wang 		} else {
401*2a8164dfSZhong Wang 			valueArraySize++;
402*2a8164dfSZhong Wang 		}
403*2a8164dfSZhong Wang 
404*2a8164dfSZhong Wang 		/*
405*2a8164dfSZhong Wang 		 * Set the new member name
406*2a8164dfSZhong Wang 		 */
407*2a8164dfSZhong Wang 		if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
408*2a8164dfSZhong Wang 			syslog(LOG_ERR, "set value failed 2- %s",
409*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
410*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
411*2a8164dfSZhong Wang 			goto out;
412*2a8164dfSZhong Wang 		}
413*2a8164dfSZhong Wang 
414*2a8164dfSZhong Wang 		/*
415*2a8164dfSZhong Wang 		 * Add the new member
416*2a8164dfSZhong Wang 		 */
417*2a8164dfSZhong Wang 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
418*2a8164dfSZhong Wang 			syslog(LOG_ERR, "add value failed - %s",
419*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
420*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
421*2a8164dfSZhong Wang 			goto out;
422*2a8164dfSZhong Wang 		}
423*2a8164dfSZhong Wang 	}
424*2a8164dfSZhong Wang 
425*2a8164dfSZhong Wang 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
426*2a8164dfSZhong Wang 		syslog(LOG_ERR, "transaction commit failed - %s",
427*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
428*2a8164dfSZhong Wang 		if (commitRet == 0) {
429*2a8164dfSZhong Wang 			ret = FCOE_ERROR_BUSY;
430*2a8164dfSZhong Wang 		} else {
431*2a8164dfSZhong Wang 			ret = FCOE_ERROR;
432*2a8164dfSZhong Wang 		}
433*2a8164dfSZhong Wang 		goto out;
434*2a8164dfSZhong Wang 	}
435*2a8164dfSZhong Wang 
436*2a8164dfSZhong Wang out:
437*2a8164dfSZhong Wang 	/*
438*2a8164dfSZhong Wang 	 * Free resources
439*2a8164dfSZhong Wang 	 */
440*2a8164dfSZhong Wang 	if (handle != NULL) {
441*2a8164dfSZhong Wang 		scf_handle_destroy(handle);
442*2a8164dfSZhong Wang 	}
443*2a8164dfSZhong Wang 	if (svc != NULL) {
444*2a8164dfSZhong Wang 		scf_service_destroy(svc);
445*2a8164dfSZhong Wang 	}
446*2a8164dfSZhong Wang 	if (pg != NULL) {
447*2a8164dfSZhong Wang 		scf_pg_destroy(pg);
448*2a8164dfSZhong Wang 	}
449*2a8164dfSZhong Wang 	if (tran != NULL) {
450*2a8164dfSZhong Wang 		scf_transaction_destroy(tran);
451*2a8164dfSZhong Wang 	}
452*2a8164dfSZhong Wang 	if (entry != NULL) {
453*2a8164dfSZhong Wang 		scf_entry_destroy(entry);
454*2a8164dfSZhong Wang 	}
455*2a8164dfSZhong Wang 	if (prop != NULL) {
456*2a8164dfSZhong Wang 		scf_property_destroy(prop);
457*2a8164dfSZhong Wang 	}
458*2a8164dfSZhong Wang 	if (valueIter != NULL) {
459*2a8164dfSZhong Wang 		scf_iter_destroy(valueIter);
460*2a8164dfSZhong Wang 	}
461*2a8164dfSZhong Wang 	if (valueLookup != NULL) {
462*2a8164dfSZhong Wang 		scf_value_destroy(valueLookup);
463*2a8164dfSZhong Wang 	}
464*2a8164dfSZhong Wang 
465*2a8164dfSZhong Wang 	/*
466*2a8164dfSZhong Wang 	 * Free valueSet scf resources
467*2a8164dfSZhong Wang 	 */
468*2a8164dfSZhong Wang 	if (valueArraySize > 0) {
469*2a8164dfSZhong Wang 		for (i = 0; i < valueArraySize; i++) {
470*2a8164dfSZhong Wang 			scf_value_destroy(valueSet[i]);
471*2a8164dfSZhong Wang 		}
472*2a8164dfSZhong Wang 	}
473*2a8164dfSZhong Wang 	/*
474*2a8164dfSZhong Wang 	 * Now free the pointer array to the resources
475*2a8164dfSZhong Wang 	 */
476*2a8164dfSZhong Wang 	if (valueSet != NULL) {
477*2a8164dfSZhong Wang 		free(valueSet);
478*2a8164dfSZhong Wang 	}
479*2a8164dfSZhong Wang 
480*2a8164dfSZhong Wang 	return (ret);
481*2a8164dfSZhong Wang }
482*2a8164dfSZhong Wang 
483*2a8164dfSZhong Wang int
484*2a8164dfSZhong Wang fcoe_adm_create_port(int objects, char *argv[],
485*2a8164dfSZhong Wang     cmdOptions_t *options)
486*2a8164dfSZhong Wang {
487*2a8164dfSZhong Wang 	FCOE_STATUS status = FCOE_STATUS_OK;
488*2a8164dfSZhong Wang 	uint64_t	nodeWWN, portWWN;
489*2a8164dfSZhong Wang 	FCOE_PORT_WWN	pwwn, nwwn;
490*2a8164dfSZhong Wang 	FCOE_UINT8	macLinkName[FCOE_MAX_MAC_NAME_LEN];
491*2a8164dfSZhong Wang 	FCOE_UINT8	promiscuous = 0;
492*2a8164dfSZhong Wang 	int		createini = 0, createtgt = 0;
493*2a8164dfSZhong Wang 
494*2a8164dfSZhong Wang 	/* check the mac name operand */
495*2a8164dfSZhong Wang 	assert(objects == 1);
496*2a8164dfSZhong Wang 
497*2a8164dfSZhong Wang 	strcpy((char *)macLinkName, argv[0]);
498*2a8164dfSZhong Wang 	bzero(&pwwn, 8);
499*2a8164dfSZhong Wang 	bzero(&nwwn, 8);
500*2a8164dfSZhong Wang 
501*2a8164dfSZhong Wang 	for (; options->optval; options++) {
502*2a8164dfSZhong Wang 		switch (options->optval) {
503*2a8164dfSZhong Wang 		case 'i':
504*2a8164dfSZhong Wang 			createini = 1;
505*2a8164dfSZhong Wang 			break;
506*2a8164dfSZhong Wang 
507*2a8164dfSZhong Wang 		case 't':
508*2a8164dfSZhong Wang 			createtgt = 1;
509*2a8164dfSZhong Wang 			break;
510*2a8164dfSZhong Wang 		case 'p':
511*2a8164dfSZhong Wang 			if (!isValidWWN(options->optarg)) {
512*2a8164dfSZhong Wang 				fprintf(stderr,
513*2a8164dfSZhong Wang 				    gettext("Error: Invalid Port WWN\n"));
514*2a8164dfSZhong Wang 				return (1);
515*2a8164dfSZhong Wang 			}
516*2a8164dfSZhong Wang 			sscanf(options->optarg, "%016llx", &portWWN);
517*2a8164dfSZhong Wang 			portWWN = htonll(portWWN);
518*2a8164dfSZhong Wang 			memcpy(&pwwn, &portWWN, sizeof (portWWN));
519*2a8164dfSZhong Wang 			break;
520*2a8164dfSZhong Wang 
521*2a8164dfSZhong Wang 		case 'n':
522*2a8164dfSZhong Wang 			if (!isValidWWN(options->optarg)) {
523*2a8164dfSZhong Wang 				fprintf(stderr,
524*2a8164dfSZhong Wang 				    gettext("Error: Invalid Node WWN\n"));
525*2a8164dfSZhong Wang 				return (1);
526*2a8164dfSZhong Wang 			}
527*2a8164dfSZhong Wang 			sscanf(options->optarg, "%016llx", &nodeWWN);
528*2a8164dfSZhong Wang 			nodeWWN = htonll(nodeWWN);
529*2a8164dfSZhong Wang 			memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN));
530*2a8164dfSZhong Wang 			break;
531*2a8164dfSZhong Wang 		case 'f':
532*2a8164dfSZhong Wang 			promiscuous = 1;
533*2a8164dfSZhong Wang 			break;
534*2a8164dfSZhong Wang 
535*2a8164dfSZhong Wang 		default:
536*2a8164dfSZhong Wang 			fprintf(stderr, gettext("Error: Illegal option: %c\n"),
537*2a8164dfSZhong Wang 			    options->optval);
538*2a8164dfSZhong Wang 			return (1);
539*2a8164dfSZhong Wang 		}
540*2a8164dfSZhong Wang 	}
541*2a8164dfSZhong Wang 
542*2a8164dfSZhong Wang 	if (createini == 1 && createtgt == 1) {
543*2a8164dfSZhong Wang 		fprintf(stderr, "Error: Option -i and -t should "
544*2a8164dfSZhong Wang 		    "not be both specified\n");
545*2a8164dfSZhong Wang 		return (1);
546*2a8164dfSZhong Wang 	}
547*2a8164dfSZhong Wang 	status = FCOE_CreatePort(macLinkName,
548*2a8164dfSZhong Wang 	    createtgt == 1 ? FCOE_PORTTYPE_TARGET :
549*2a8164dfSZhong Wang 	    FCOE_PORTTYPE_INITIATOR, pwwn, nwwn, promiscuous);
550*2a8164dfSZhong Wang 
551*2a8164dfSZhong Wang 	if (status != FCOE_STATUS_OK) {
552*2a8164dfSZhong Wang 		switch (status) {
553*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_BUSY:
554*2a8164dfSZhong Wang 			fprintf(stderr,
555*2a8164dfSZhong Wang 			    gettext("Error: fcoe driver is busy\n"));
556*2a8164dfSZhong Wang 			break;
557*2a8164dfSZhong Wang 
558*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_ALREADY:
559*2a8164dfSZhong Wang 			fprintf(stderr,
560*2a8164dfSZhong Wang 			    gettext("Error: Existing FCoE port "
561*2a8164dfSZhong Wang 			    "found on the specified MAC link\n"));
562*2a8164dfSZhong Wang 			break;
563*2a8164dfSZhong Wang 
564*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PERM:
565*2a8164dfSZhong Wang 			fprintf(stderr,
566*2a8164dfSZhong Wang 			    gettext("Error: Not enough permission to "
567*2a8164dfSZhong Wang 			    "open fcoe device\n"));
568*2a8164dfSZhong Wang 			break;
569*2a8164dfSZhong Wang 
570*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_DEV:
571*2a8164dfSZhong Wang 			fprintf(stderr,
572*2a8164dfSZhong Wang 			    gettext("Error: Failed to open fcoe device\n"));
573*2a8164dfSZhong Wang 			break;
574*2a8164dfSZhong Wang 
575*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_WWN_SAME:
576*2a8164dfSZhong Wang 			fprintf(stderr,
577*2a8164dfSZhong Wang 			    gettext("Error: Port WWN is same as Node "
578*2a8164dfSZhong Wang 			    "WWN\n"));
579*2a8164dfSZhong Wang 			break;
580*2a8164dfSZhong Wang 
581*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MAC_LEN:
582*2a8164dfSZhong Wang 			fprintf(stderr,
583*2a8164dfSZhong Wang 			    gettext("Error: MAC name exceeds maximum "
584*2a8164dfSZhong Wang 			    "length\n"));
585*2a8164dfSZhong Wang 			break;
586*2a8164dfSZhong Wang 
587*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PWWN_CONFLICTED:
588*2a8164dfSZhong Wang 			fprintf(stderr,
589*2a8164dfSZhong Wang 			    gettext("Error: The specified Port WWN "
590*2a8164dfSZhong Wang 			    "is already in use\n"));
591*2a8164dfSZhong Wang 			break;
592*2a8164dfSZhong Wang 
593*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_NWWN_CONFLICTED:
594*2a8164dfSZhong Wang 			fprintf(stderr,
595*2a8164dfSZhong Wang 			    gettext("Error: The specified Node WWN "
596*2a8164dfSZhong Wang 			    "is already in use\n"));
597*2a8164dfSZhong Wang 			break;
598*2a8164dfSZhong Wang 
599*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_NEED_JUMBO_FRAME:
600*2a8164dfSZhong Wang 			fprintf(stderr,
601*2a8164dfSZhong Wang 			    gettext("Error: MTU size of the specified "
602*2a8164dfSZhong Wang 			    "MAC link needs to be increased to 2500 "
603*2a8164dfSZhong Wang 			    "or above\n"));
604*2a8164dfSZhong Wang 			break;
605*2a8164dfSZhong Wang 
606*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_CREATE_MAC:
607*2a8164dfSZhong Wang 			fprintf(stderr,
608*2a8164dfSZhong Wang 			    gettext("Error: Out of memory\n"));
609*2a8164dfSZhong Wang 			break;
610*2a8164dfSZhong Wang 
611*2a8164dfSZhong Wang 
612*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_MAC:
613*2a8164dfSZhong Wang 			fprintf(stderr,
614*2a8164dfSZhong Wang 			    gettext("Error: Failed to open the "
615*2a8164dfSZhong Wang 			    "specified MAC link\n"));
616*2a8164dfSZhong Wang 			break;
617*2a8164dfSZhong Wang 
618*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_CREATE_PORT:
619*2a8164dfSZhong Wang 			fprintf(stderr,
620*2a8164dfSZhong Wang 			    gettext("Error: Failed to create FCoE "
621*2a8164dfSZhong Wang 			    "port on the specified MAC link\n"));
622*2a8164dfSZhong Wang 			break;
623*2a8164dfSZhong Wang 
624*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_VNIC_UNSUPPORT:
625*2a8164dfSZhong Wang 			fprintf(stderr,
626*2a8164dfSZhong Wang 			    gettext("Error: VNIC is not supported\n"));
627*2a8164dfSZhong Wang 			break;
628*2a8164dfSZhong Wang 
629*2a8164dfSZhong Wang 		case FCOE_STATUS_ERROR:
630*2a8164dfSZhong Wang 		default:
631*2a8164dfSZhong Wang 			fprintf(stderr,
632*2a8164dfSZhong Wang 			    gettext("Error: Due to reason code %d\n"), status);
633*2a8164dfSZhong Wang 		}
634*2a8164dfSZhong Wang 		return (1);
635*2a8164dfSZhong Wang 	} else {
636*2a8164dfSZhong Wang 		char cpwwn[17], cnwwn[17];
637*2a8164dfSZhong Wang 
638*2a8164dfSZhong Wang 		WWN2str(cpwwn, &pwwn);
639*2a8164dfSZhong Wang 		WWN2str(cnwwn, &nwwn);
640*2a8164dfSZhong Wang 
641*2a8164dfSZhong Wang 		fcoe_adm_add_remove_scf_entry((char *)macLinkName,
642*2a8164dfSZhong Wang 		    cpwwn,
643*2a8164dfSZhong Wang 		    cnwwn,
644*2a8164dfSZhong Wang 		    createtgt,
645*2a8164dfSZhong Wang 		    promiscuous,
646*2a8164dfSZhong Wang 		    FCOE_SCF_ADD);
647*2a8164dfSZhong Wang 		return (0);
648*2a8164dfSZhong Wang 	}
649*2a8164dfSZhong Wang }
650*2a8164dfSZhong Wang 
651*2a8164dfSZhong Wang int
652*2a8164dfSZhong Wang fcoe_adm_delete_port(int objects, char *argv[])
653*2a8164dfSZhong Wang {
654*2a8164dfSZhong Wang 	FCOE_STATUS status;
655*2a8164dfSZhong Wang 	FCOE_UINT8	*macLinkName;
656*2a8164dfSZhong Wang 
657*2a8164dfSZhong Wang 	/* check the mac name operand */
658*2a8164dfSZhong Wang 	assert(objects == 1);
659*2a8164dfSZhong Wang 
660*2a8164dfSZhong Wang 	macLinkName = (FCOE_UINT8 *) argv[0];
661*2a8164dfSZhong Wang 
662*2a8164dfSZhong Wang 	status = FCOE_DeletePort(macLinkName);
663*2a8164dfSZhong Wang 	if (status != FCOE_STATUS_OK) {
664*2a8164dfSZhong Wang 		switch (status) {
665*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_BUSY:
666*2a8164dfSZhong Wang 			fprintf(stderr,
667*2a8164dfSZhong Wang 			    gettext("Error: fcoe driver is busy\n"));
668*2a8164dfSZhong Wang 			break;
669*2a8164dfSZhong Wang 
670*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_ALREADY:
671*2a8164dfSZhong Wang 			fprintf(stderr,
672*2a8164dfSZhong Wang 			    gettext("Error: FCoE port not found on the "
673*2a8164dfSZhong Wang 			    "specified MAC link\n"));
674*2a8164dfSZhong Wang 			break;
675*2a8164dfSZhong Wang 
676*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PERM:
677*2a8164dfSZhong Wang 			fprintf(stderr,
678*2a8164dfSZhong Wang 			    gettext("Error: Not enough permission to "
679*2a8164dfSZhong Wang 			    "open fcoe device\n"));
680*2a8164dfSZhong Wang 			break;
681*2a8164dfSZhong Wang 
682*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MAC_LEN:
683*2a8164dfSZhong Wang 			fprintf(stderr,
684*2a8164dfSZhong Wang 			    gettext("Failed: MAC name exceeds maximum "
685*2a8164dfSZhong Wang 			    "length 32\n"));
686*2a8164dfSZhong Wang 			break;
687*2a8164dfSZhong Wang 
688*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_DEV:
689*2a8164dfSZhong Wang 			fprintf(stderr,
690*2a8164dfSZhong Wang 			    gettext("Error: Failed to open fcoe device\n"));
691*2a8164dfSZhong Wang 			break;
692*2a8164dfSZhong Wang 
693*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MAC_NOT_FOUND:
694*2a8164dfSZhong Wang 			fprintf(stderr,
695*2a8164dfSZhong Wang 			    gettext("Error: FCoE port not found on the "
696*2a8164dfSZhong Wang 			    "specified MAC link\n"));
697*2a8164dfSZhong Wang 			break;
698*2a8164dfSZhong Wang 
699*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OFFLINE_DEV:
700*2a8164dfSZhong Wang 			fprintf(stderr,
701*2a8164dfSZhong Wang 			    gettext("Error: Please use stmfadm to offline "
702*2a8164dfSZhong Wang 			    "the FCoE target first\n"));
703*2a8164dfSZhong Wang 			break;
704*2a8164dfSZhong Wang 
705*2a8164dfSZhong Wang 		case FCOE_STATUS_ERROR:
706*2a8164dfSZhong Wang 		default:
707*2a8164dfSZhong Wang 			fprintf(stderr,
708*2a8164dfSZhong Wang 			    gettext("Error: Due to reason code %d\n"), status);
709*2a8164dfSZhong Wang 		}
710*2a8164dfSZhong Wang 		return (1);
711*2a8164dfSZhong Wang 	} else {
712*2a8164dfSZhong Wang 		fcoe_adm_add_remove_scf_entry((char *)macLinkName,
713*2a8164dfSZhong Wang 		    "",
714*2a8164dfSZhong Wang 		    "",
715*2a8164dfSZhong Wang 		    0,
716*2a8164dfSZhong Wang 		    0,
717*2a8164dfSZhong Wang 		    FCOE_SCF_REMOVE);
718*2a8164dfSZhong Wang 		return (0);
719*2a8164dfSZhong Wang 	}
720*2a8164dfSZhong Wang }
721*2a8164dfSZhong Wang 
722*2a8164dfSZhong Wang int
723*2a8164dfSZhong Wang fcoe_adm_list_ports(cmdOptions_t *options)
724*2a8164dfSZhong Wang {
725*2a8164dfSZhong Wang 	FCOE_STATUS	status;
726*2a8164dfSZhong Wang 	int	showini = 0, showtgt = 0;
727*2a8164dfSZhong Wang 	FCOE_UINT32	port_num;
728*2a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	*portlist = NULL;
729*2a8164dfSZhong Wang 	int i;
730*2a8164dfSZhong Wang 	int ret;
731*2a8164dfSZhong Wang 
732*2a8164dfSZhong Wang 	for (; options->optval; options++) {
733*2a8164dfSZhong Wang 		switch (options->optval) {
734*2a8164dfSZhong Wang 		case 'i':
735*2a8164dfSZhong Wang 			showini = 1;
736*2a8164dfSZhong Wang 			break;
737*2a8164dfSZhong Wang 
738*2a8164dfSZhong Wang 		case 't':
739*2a8164dfSZhong Wang 			showtgt = 1;
740*2a8164dfSZhong Wang 			break;
741*2a8164dfSZhong Wang 
742*2a8164dfSZhong Wang 		default:
743*2a8164dfSZhong Wang 			fprintf(stderr, gettext("Error: Illegal option: %c\n"),
744*2a8164dfSZhong Wang 			    options->optval);
745*2a8164dfSZhong Wang 			return (1);
746*2a8164dfSZhong Wang 		}
747*2a8164dfSZhong Wang 	}
748*2a8164dfSZhong Wang 	if (showini == 0 && showtgt == 0) {
749*2a8164dfSZhong Wang 		showini = 1;
750*2a8164dfSZhong Wang 		showtgt = 1;
751*2a8164dfSZhong Wang 	}
752*2a8164dfSZhong Wang 
753*2a8164dfSZhong Wang 	status = FCOE_GetPortList(&port_num, &portlist);
754*2a8164dfSZhong Wang 
755*2a8164dfSZhong Wang 	if (status != FCOE_STATUS_OK) {
756*2a8164dfSZhong Wang 		switch (status) {
757*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_BUSY:
758*2a8164dfSZhong Wang 			fprintf(stderr,
759*2a8164dfSZhong Wang 			    gettext("Error: fcoe driver is busy\n"));
760*2a8164dfSZhong Wang 			break;
761*2a8164dfSZhong Wang 
762*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_PERM:
763*2a8164dfSZhong Wang 			fprintf(stderr,
764*2a8164dfSZhong Wang 			    gettext("Error: Not enough permission to "
765*2a8164dfSZhong Wang 			    "open fcoe device\n"));
766*2a8164dfSZhong Wang 			break;
767*2a8164dfSZhong Wang 
768*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_OPEN_DEV:
769*2a8164dfSZhong Wang 			fprintf(stderr,
770*2a8164dfSZhong Wang 			    gettext("Error: Failed to open fcoe device\n"));
771*2a8164dfSZhong Wang 			break;
772*2a8164dfSZhong Wang 
773*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_INVAL_ARG:
774*2a8164dfSZhong Wang 			fprintf(stderr,
775*2a8164dfSZhong Wang 			    gettext("Error: Invalid argument\n"));
776*2a8164dfSZhong Wang 			break;
777*2a8164dfSZhong Wang 
778*2a8164dfSZhong Wang 		case  FCOE_STATUS_ERROR_MORE_DATA:
779*2a8164dfSZhong Wang 			fprintf(stderr,
780*2a8164dfSZhong Wang 			    gettext("Error: More data\n"));
781*2a8164dfSZhong Wang 			break;
782*2a8164dfSZhong Wang 
783*2a8164dfSZhong Wang 		case FCOE_STATUS_ERROR:
784*2a8164dfSZhong Wang 		default:
785*2a8164dfSZhong Wang 			fprintf(stderr,
786*2a8164dfSZhong Wang 			    gettext("Error: Due to reason code %d\n"), status);
787*2a8164dfSZhong Wang 		}
788*2a8164dfSZhong Wang 		ret = 1;
789*2a8164dfSZhong Wang 	} else {
790*2a8164dfSZhong Wang 		if (port_num == 0) {
791*2a8164dfSZhong Wang 			fprintf(stdout, gettext("No FCoE Ports Found!\n"));
792*2a8164dfSZhong Wang 		} else {
793*2a8164dfSZhong Wang 			for (i = 0; i < port_num; i++) {
794*2a8164dfSZhong Wang 				if ((portlist[i].port_type ==
795*2a8164dfSZhong Wang 				    FCOE_PORTTYPE_INITIATOR &&
796*2a8164dfSZhong Wang 				    showini == 1) || (showtgt == 1 &&
797*2a8164dfSZhong Wang 				    portlist[i].port_type ==
798*2a8164dfSZhong Wang 				    FCOE_PORTTYPE_TARGET)) {
799*2a8164dfSZhong Wang 					printFCOEPortInfo(&portlist[i]);
800*2a8164dfSZhong Wang 				}
801*2a8164dfSZhong Wang 			}
802*2a8164dfSZhong Wang 		}
803*2a8164dfSZhong Wang 		ret = 0;
804*2a8164dfSZhong Wang 	}
805*2a8164dfSZhong Wang 
806*2a8164dfSZhong Wang 	if (portlist != NULL) {
807*2a8164dfSZhong Wang 		free(portlist);
808*2a8164dfSZhong Wang 	}
809*2a8164dfSZhong Wang 	return (ret);
810*2a8164dfSZhong Wang 
811*2a8164dfSZhong Wang }
812*2a8164dfSZhong Wang 
813*2a8164dfSZhong Wang int
814*2a8164dfSZhong Wang fcoe_adm_create_portlist(cmdOptions_t *options)
815*2a8164dfSZhong Wang {
816*2a8164dfSZhong Wang 	scf_handle_t	*handle = NULL;
817*2a8164dfSZhong Wang 	scf_service_t	*svc = NULL;
818*2a8164dfSZhong Wang 	scf_propertygroup_t	*pg = NULL;
819*2a8164dfSZhong Wang 	scf_transaction_t	*tran = NULL;
820*2a8164dfSZhong Wang 	scf_transaction_entry_t	*entry = NULL;
821*2a8164dfSZhong Wang 	scf_property_t		*prop = NULL;
822*2a8164dfSZhong Wang 	scf_value_t	*valueLookup = NULL;
823*2a8164dfSZhong Wang 	scf_iter_t	*valueIter = NULL;
824*2a8164dfSZhong Wang 	char		buf[FCOE_PORT_LIST_LENGTH] = {0};
825*2a8164dfSZhong Wang 	int		commitRet;
826*2a8164dfSZhong Wang 	int		create_target = 0, create_initiator = 0;
827*2a8164dfSZhong Wang 
828*2a8164dfSZhong Wang 	/* Check what type of port list will be created */
829*2a8164dfSZhong Wang 	for (; options->optval; options++) {
830*2a8164dfSZhong Wang 		switch (options->optval) {
831*2a8164dfSZhong Wang 		case 'i':
832*2a8164dfSZhong Wang 			create_initiator = 1;
833*2a8164dfSZhong Wang 			break;
834*2a8164dfSZhong Wang 		case 't':
835*2a8164dfSZhong Wang 			create_target = 1;
836*2a8164dfSZhong Wang 			break;
837*2a8164dfSZhong Wang 		default:
838*2a8164dfSZhong Wang 			fprintf(stderr, gettext("Error: Illegal option: %c\n"),
839*2a8164dfSZhong Wang 			    options->optval);
840*2a8164dfSZhong Wang 			return (1);
841*2a8164dfSZhong Wang 		}
842*2a8164dfSZhong Wang 	}
843*2a8164dfSZhong Wang 
844*2a8164dfSZhong Wang 	if (create_initiator == 0 && create_target == 0) {
845*2a8164dfSZhong Wang 		create_initiator = 1;
846*2a8164dfSZhong Wang 		create_target = 1;
847*2a8164dfSZhong Wang 	}
848*2a8164dfSZhong Wang 
849*2a8164dfSZhong Wang 	commitRet = fcoe_cfg_scf_init(&handle, &svc);
850*2a8164dfSZhong Wang 	if (commitRet != FCOE_SUCCESS) {
851*2a8164dfSZhong Wang 		goto out;
852*2a8164dfSZhong Wang 	}
853*2a8164dfSZhong Wang 
854*2a8164dfSZhong Wang 	if (((pg = scf_pg_create(handle)) == NULL) ||
855*2a8164dfSZhong Wang 	    ((tran = scf_transaction_create(handle)) == NULL) ||
856*2a8164dfSZhong Wang 	    ((entry = scf_entry_create(handle)) == NULL) ||
857*2a8164dfSZhong Wang 	    ((prop = scf_property_create(handle)) == NULL) ||
858*2a8164dfSZhong Wang 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
859*2a8164dfSZhong Wang 		goto out;
860*2a8164dfSZhong Wang 	}
861*2a8164dfSZhong Wang 
862*2a8164dfSZhong Wang 	/* get property group or create it */
863*2a8164dfSZhong Wang 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
864*2a8164dfSZhong Wang 		goto out;
865*2a8164dfSZhong Wang 	}
866*2a8164dfSZhong Wang 
867*2a8164dfSZhong Wang 	if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
868*2a8164dfSZhong Wang 		syslog(LOG_ERR, "get property failed - %s",
869*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
870*2a8164dfSZhong Wang 		goto out;
871*2a8164dfSZhong Wang 	}
872*2a8164dfSZhong Wang 
873*2a8164dfSZhong Wang 	valueLookup = scf_value_create(handle);
874*2a8164dfSZhong Wang 	if (valueLookup == NULL) {
875*2a8164dfSZhong Wang 		syslog(LOG_ERR, "scf value alloc failed - %s",
876*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
877*2a8164dfSZhong Wang 		goto out;
878*2a8164dfSZhong Wang 	}
879*2a8164dfSZhong Wang 
880*2a8164dfSZhong Wang 	if (scf_iter_property_values(valueIter, prop) == -1) {
881*2a8164dfSZhong Wang 		syslog(LOG_ERR, "iter value failed - %s",
882*2a8164dfSZhong Wang 		    scf_strerror(scf_error()));
883*2a8164dfSZhong Wang 		goto out;
884*2a8164dfSZhong Wang 	}
885*2a8164dfSZhong Wang 	while (scf_iter_next_value(valueIter, valueLookup) == 1) {
886*2a8164dfSZhong Wang 		uint8_t *macLinkName = NULL;
887*2a8164dfSZhong Wang 		char *remainder = NULL;
888*2a8164dfSZhong Wang 		FCOE_PORT_WWN pwwn, nwwn;
889*2a8164dfSZhong Wang 		uint64_t	nodeWWN, portWWN;
890*2a8164dfSZhong Wang 		int is_target, is_promiscuous;
891*2a8164dfSZhong Wang 
892*2a8164dfSZhong Wang 		bzero(buf, sizeof (buf));
893*2a8164dfSZhong Wang 		bzero(&pwwn, sizeof (pwwn));
894*2a8164dfSZhong Wang 		bzero(&nwwn, sizeof (nwwn));
895*2a8164dfSZhong Wang 		if (scf_value_get_ustring(valueLookup, buf, MAXNAMELEN) == -1) {
896*2a8164dfSZhong Wang 			syslog(LOG_ERR, "iter value failed - %s",
897*2a8164dfSZhong Wang 			    scf_strerror(scf_error()));
898*2a8164dfSZhong Wang 			break;
899*2a8164dfSZhong Wang 		}
900*2a8164dfSZhong Wang 		macLinkName = (uint8_t *)strtok(buf, ":");
901*2a8164dfSZhong Wang 		remainder = strtok(NULL, "#");
902*2a8164dfSZhong Wang 		sscanf(remainder, "%016llx:%016llx:%d:%d",
903*2a8164dfSZhong Wang 		    &portWWN, &nodeWWN, &is_target, &is_promiscuous);
904*2a8164dfSZhong Wang 		if ((!create_target && is_target) ||
905*2a8164dfSZhong Wang 		    (!create_initiator && !is_target)) {
906*2a8164dfSZhong Wang 			continue;
907*2a8164dfSZhong Wang 		}
908*2a8164dfSZhong Wang 
909*2a8164dfSZhong Wang 		nodeWWN = htonll(nodeWWN);
910*2a8164dfSZhong Wang 		memcpy(&nwwn, &nodeWWN, sizeof (nodeWWN));
911*2a8164dfSZhong Wang 		portWWN = htonll(portWWN);
912*2a8164dfSZhong Wang 		memcpy(&pwwn, &portWWN, sizeof (portWWN));
913*2a8164dfSZhong Wang 
914*2a8164dfSZhong Wang 		FCOE_CreatePort(macLinkName,
915*2a8164dfSZhong Wang 		    is_target ? FCOE_PORTTYPE_TARGET : FCOE_PORTTYPE_INITIATOR,
916*2a8164dfSZhong Wang 		    pwwn, nwwn, is_promiscuous);
917*2a8164dfSZhong Wang 	}
918*2a8164dfSZhong Wang 
919*2a8164dfSZhong Wang out:
920*2a8164dfSZhong Wang 	/*
921*2a8164dfSZhong Wang 	 * Free resources
922*2a8164dfSZhong Wang 	 */
923*2a8164dfSZhong Wang 	if (handle != NULL) {
924*2a8164dfSZhong Wang 		scf_handle_destroy(handle);
925*2a8164dfSZhong Wang 	}
926*2a8164dfSZhong Wang 	if (svc != NULL) {
927*2a8164dfSZhong Wang 		scf_service_destroy(svc);
928*2a8164dfSZhong Wang 	}
929*2a8164dfSZhong Wang 	if (pg != NULL) {
930*2a8164dfSZhong Wang 		scf_pg_destroy(pg);
931*2a8164dfSZhong Wang 	}
932*2a8164dfSZhong Wang 	if (tran != NULL) {
933*2a8164dfSZhong Wang 		scf_transaction_destroy(tran);
934*2a8164dfSZhong Wang 	}
935*2a8164dfSZhong Wang 	if (entry != NULL) {
936*2a8164dfSZhong Wang 		scf_entry_destroy(entry);
937*2a8164dfSZhong Wang 	}
938*2a8164dfSZhong Wang 	if (prop != NULL) {
939*2a8164dfSZhong Wang 		scf_property_destroy(prop);
940*2a8164dfSZhong Wang 	}
941*2a8164dfSZhong Wang 	if (valueIter != NULL) {
942*2a8164dfSZhong Wang 		scf_iter_destroy(valueIter);
943*2a8164dfSZhong Wang 	}
944*2a8164dfSZhong Wang 	if (valueLookup != NULL) {
945*2a8164dfSZhong Wang 		scf_value_destroy(valueLookup);
946*2a8164dfSZhong Wang 	}
947*2a8164dfSZhong Wang 
948*2a8164dfSZhong Wang 	return (0);
949*2a8164dfSZhong Wang }
950