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 <stdlib.h>
272a8164dfSZhong Wang #include <stdio.h>
282a8164dfSZhong Wang #include <wchar.h>
292a8164dfSZhong Wang #include <strings.h>
302a8164dfSZhong Wang #include <sys/types.h>
312a8164dfSZhong Wang #include <sys/stat.h>
322a8164dfSZhong Wang #include <fcntl.h>
332a8164dfSZhong Wang #include <unistd.h>
342a8164dfSZhong Wang #include <libintl.h>
352a8164dfSZhong Wang #include <errno.h>
362a8164dfSZhong Wang #include <string.h>
372a8164dfSZhong Wang #include <assert.h>
382a8164dfSZhong Wang #include <syslog.h>
392a8164dfSZhong Wang #include <libfcoe.h>
40d4401b99SKelly Hu #include <libdllink.h>
412a8164dfSZhong Wang #include <fcoeio.h>
42e6eb57e7SKevin Yu #include <libscf.h>
43e6eb57e7SKevin Yu #include <inttypes.h>
442a8164dfSZhong Wang 
452a8164dfSZhong Wang #define	FCOE_DEV_PATH	 "/devices/fcoe:admin"
462a8164dfSZhong Wang 
472a8164dfSZhong Wang #define	OPEN_FCOE 0
482a8164dfSZhong Wang #define	OPEN_EXCL_FCOE O_EXCL
492a8164dfSZhong Wang 
502a8164dfSZhong Wang /*
512a8164dfSZhong Wang  * Open for fcoe module
522a8164dfSZhong Wang  *
532a8164dfSZhong Wang  * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE)
542a8164dfSZhong Wang  * fd - pointer to integer. On success, contains the fcoe file descriptor
552a8164dfSZhong Wang  */
562a8164dfSZhong Wang static int
openFcoe(int flag,int * fd)572a8164dfSZhong Wang openFcoe(int flag, int *fd)
582a8164dfSZhong Wang {
592a8164dfSZhong Wang 	int ret = FCOE_STATUS_ERROR;
602a8164dfSZhong Wang 
612a8164dfSZhong Wang 	if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
622a8164dfSZhong Wang 		ret = FCOE_STATUS_OK;
632a8164dfSZhong Wang 	} else {
642a8164dfSZhong Wang 		if (errno == EPERM || errno == EACCES) {
652a8164dfSZhong Wang 			ret = FCOE_STATUS_ERROR_PERM;
662a8164dfSZhong Wang 		} else {
672a8164dfSZhong Wang 			ret = FCOE_STATUS_ERROR_OPEN_DEV;
682a8164dfSZhong Wang 		}
692a8164dfSZhong Wang 		syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)",
702a8164dfSZhong Wang 		    FCOE_DEV_PATH, errno);
712a8164dfSZhong Wang 	}
722a8164dfSZhong Wang 
732a8164dfSZhong Wang 	return (ret);
742a8164dfSZhong Wang }
752a8164dfSZhong Wang 
76e6eb57e7SKevin Yu static void
WWN2str(char * buf,FCOE_PORT_WWN * wwn)77*6cd9fed7SToomas Soome WWN2str(char *buf, FCOE_PORT_WWN *wwn)
78*6cd9fed7SToomas Soome {
79e6eb57e7SKevin Yu 	int j;
80e6eb57e7SKevin Yu 	unsigned char *pc = (unsigned char *)&(wwn->wwn[0]);
81e6eb57e7SKevin Yu 	buf[0] = '\0';
82e6eb57e7SKevin Yu 	for (j = 0; j < 16; j += 2) {
83e6eb57e7SKevin Yu 		(void) sprintf(&buf[j], "%02X", (int)*pc++);
84e6eb57e7SKevin Yu 	}
85e6eb57e7SKevin Yu }
86e6eb57e7SKevin Yu 
872a8164dfSZhong Wang static int
isWWNZero(FCOE_PORT_WWN portwwn)882a8164dfSZhong Wang isWWNZero(FCOE_PORT_WWN portwwn)
892a8164dfSZhong Wang {
902a8164dfSZhong Wang 	int i;
912a8164dfSZhong Wang 	int size = sizeof (FCOE_PORT_WWN);
922a8164dfSZhong Wang 
932a8164dfSZhong Wang 	for (i = 0; i < size; i++) {
942a8164dfSZhong Wang 		if (portwwn.wwn[i] != 0) {
952a8164dfSZhong Wang 			return (0);
962a8164dfSZhong Wang 		}
972a8164dfSZhong Wang 	}
982a8164dfSZhong Wang 	return (1);
992a8164dfSZhong Wang }
1002a8164dfSZhong Wang 
101e6eb57e7SKevin Yu /*
102e6eb57e7SKevin Yu  * Initialize scf fcoe service access
103e6eb57e7SKevin Yu  * handle - returned handle
104e6eb57e7SKevin Yu  * service - returned service handle
105e6eb57e7SKevin Yu  */
106e6eb57e7SKevin Yu static int
fcoe_cfg_scf_init(scf_handle_t ** handle,scf_service_t ** service,int is_target)107e6eb57e7SKevin Yu fcoe_cfg_scf_init(scf_handle_t **handle, scf_service_t **service, int is_target)
108e6eb57e7SKevin Yu {
109e6eb57e7SKevin Yu 	scf_scope_t	*scope = NULL;
110e6eb57e7SKevin Yu 	int		ret;
111e6eb57e7SKevin Yu 
112e6eb57e7SKevin Yu 	if ((*handle = scf_handle_create(SCF_VERSION)) == NULL) {
113e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf_handle_create failed - %s",
114e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
115e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
116e6eb57e7SKevin Yu 		goto err;
117e6eb57e7SKevin Yu 	}
118e6eb57e7SKevin Yu 
119e6eb57e7SKevin Yu 	if (scf_handle_bind(*handle) == -1) {
120e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf_handle_bind failed - %s",
121e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
122e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
123e6eb57e7SKevin Yu 		goto err;
124e6eb57e7SKevin Yu 	}
125e6eb57e7SKevin Yu 
126e6eb57e7SKevin Yu 	if ((*service = scf_service_create(*handle)) == NULL) {
127e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf_service_create failed - %s",
128e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
129e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
130e6eb57e7SKevin Yu 		goto err;
131e6eb57e7SKevin Yu 	}
132e6eb57e7SKevin Yu 
133e6eb57e7SKevin Yu 	if ((scope = scf_scope_create(*handle)) == NULL) {
134e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf_scope_create failed - %s",
135e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
136e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
137e6eb57e7SKevin Yu 		goto err;
138e6eb57e7SKevin Yu 	}
139e6eb57e7SKevin Yu 
140e6eb57e7SKevin Yu 	if (scf_handle_get_scope(*handle, SCF_SCOPE_LOCAL, scope) == -1) {
141e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf_handle_get_scope failed - %s",
142e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
143e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
144e6eb57e7SKevin Yu 		goto err;
145e6eb57e7SKevin Yu 	}
146e6eb57e7SKevin Yu 
147e6eb57e7SKevin Yu 	if (scf_scope_get_service(scope,
148e6eb57e7SKevin Yu 	    is_target ? FCOE_TARGET_SERVICE: FCOE_INITIATOR_SERVICE,
149e6eb57e7SKevin Yu 	    *service) == -1) {
150e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf_scope_get_service failed - %s",
151e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
152e6eb57e7SKevin Yu 		ret = FCOE_ERROR_SERVICE_NOT_FOUND;
153e6eb57e7SKevin Yu 		goto err;
154e6eb57e7SKevin Yu 	}
155e6eb57e7SKevin Yu 
156e6eb57e7SKevin Yu 	scf_scope_destroy(scope);
157e6eb57e7SKevin Yu 
158e6eb57e7SKevin Yu 	return (FCOE_SUCCESS);
159e6eb57e7SKevin Yu 
160e6eb57e7SKevin Yu err:
161e6eb57e7SKevin Yu 	if (*handle != NULL) {
162e6eb57e7SKevin Yu 		scf_handle_destroy(*handle);
163e6eb57e7SKevin Yu 	}
164e6eb57e7SKevin Yu 	if (*service != NULL) {
165e6eb57e7SKevin Yu 		scf_service_destroy(*service);
166e6eb57e7SKevin Yu 		*service = NULL;
167e6eb57e7SKevin Yu 	}
168e6eb57e7SKevin Yu 	if (scope != NULL) {
169e6eb57e7SKevin Yu 		scf_scope_destroy(scope);
170e6eb57e7SKevin Yu 	}
171e6eb57e7SKevin Yu 	return (ret);
172e6eb57e7SKevin Yu }
173e6eb57e7SKevin Yu 
174e6eb57e7SKevin Yu static int
fcoe_add_remove_scf_entry(char * mac_name,char * pwwn,char * nwwn,int is_target,int is_promiscuous,int addRemoveFlag)175e6eb57e7SKevin Yu fcoe_add_remove_scf_entry(char *mac_name,
176e6eb57e7SKevin Yu     char *pwwn, char *nwwn,
177e6eb57e7SKevin Yu     int is_target, int is_promiscuous, int addRemoveFlag)
178e6eb57e7SKevin Yu {
179e6eb57e7SKevin Yu 	scf_handle_t	*handle = NULL;
180e6eb57e7SKevin Yu 	scf_service_t	*svc = NULL;
181e6eb57e7SKevin Yu 	scf_propertygroup_t	*pg = NULL;
182e6eb57e7SKevin Yu 	scf_transaction_t	*tran = NULL;
183e6eb57e7SKevin Yu 	scf_transaction_entry_t	*entry = NULL;
184e6eb57e7SKevin Yu 	scf_property_t	*prop = NULL;
185e6eb57e7SKevin Yu 	scf_value_t	*valueLookup = NULL;
186e6eb57e7SKevin Yu 	scf_iter_t	*valueIter = NULL;
187e6eb57e7SKevin Yu 	scf_value_t	**valueSet = NULL;
188e6eb57e7SKevin Yu 	int	ret = FCOE_SUCCESS;
189e6eb57e7SKevin Yu 	boolean_t	createProp = B_FALSE;
190e6eb57e7SKevin Yu 	int	lastAlloc = 0;
191e6eb57e7SKevin Yu 	char	buf[FCOE_PORT_LIST_LENGTH] = {0};
192e6eb57e7SKevin Yu 	char	memberName[FCOE_PORT_LIST_LENGTH] = {0};
193e6eb57e7SKevin Yu 	boolean_t	found = B_FALSE;
194e6eb57e7SKevin Yu 	int	i = 0;
195e6eb57e7SKevin Yu 	int	valueArraySize = 0;
196e6eb57e7SKevin Yu 	int	commitRet;
197e6eb57e7SKevin Yu 	int portListAlloc = 100;
198e6eb57e7SKevin Yu 
199e6eb57e7SKevin Yu 	(void) snprintf(memberName, FCOE_PORT_LIST_LENGTH,
200e6eb57e7SKevin Yu 	    "%s:%s:%s:%d:%d", mac_name, pwwn, nwwn,
201e6eb57e7SKevin Yu 	    is_target, is_promiscuous);
202e6eb57e7SKevin Yu 
203e6eb57e7SKevin Yu 	ret = fcoe_cfg_scf_init(&handle, &svc, is_target);
204e6eb57e7SKevin Yu 	if (ret != FCOE_SUCCESS) {
205e6eb57e7SKevin Yu 		goto out;
206e6eb57e7SKevin Yu 	}
207e6eb57e7SKevin Yu 
208e6eb57e7SKevin Yu 	if (((pg = scf_pg_create(handle)) == NULL) ||
209e6eb57e7SKevin Yu 	    ((tran = scf_transaction_create(handle)) == NULL) ||
210e6eb57e7SKevin Yu 	    ((entry = scf_entry_create(handle)) == NULL) ||
211e6eb57e7SKevin Yu 	    ((prop = scf_property_create(handle)) == NULL) ||
212e6eb57e7SKevin Yu 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
213e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
214e6eb57e7SKevin Yu 		goto out;
215e6eb57e7SKevin Yu 	}
216e6eb57e7SKevin Yu 
217e6eb57e7SKevin Yu 	/* get property group or create it */
218e6eb57e7SKevin Yu 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
219e6eb57e7SKevin Yu 		if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
220e6eb57e7SKevin Yu 			if (scf_service_add_pg(svc, FCOE_PG_NAME,
221e6eb57e7SKevin Yu 			    SCF_GROUP_APPLICATION, 0, pg) == -1) {
222e6eb57e7SKevin Yu 				syslog(LOG_ERR, "add pg failed - %s",
223e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
224e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
225e6eb57e7SKevin Yu 			} else {
226e6eb57e7SKevin Yu 				createProp = B_TRUE;
227e6eb57e7SKevin Yu 			}
228e6eb57e7SKevin Yu 		} else {
229e6eb57e7SKevin Yu 			syslog(LOG_ERR, "get pg failed - %s",
230e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
231e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
232e6eb57e7SKevin Yu 		}
233e6eb57e7SKevin Yu 		if (ret != FCOE_SUCCESS) {
234e6eb57e7SKevin Yu 			goto out;
235e6eb57e7SKevin Yu 		}
236e6eb57e7SKevin Yu 	}
237e6eb57e7SKevin Yu 
238e6eb57e7SKevin Yu 	/* to make sure property exists */
239e6eb57e7SKevin Yu 	if (createProp == B_FALSE) {
240e6eb57e7SKevin Yu 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
241e6eb57e7SKevin Yu 			if ((scf_error() == SCF_ERROR_NOT_FOUND)) {
242e6eb57e7SKevin Yu 				createProp = B_TRUE;
243e6eb57e7SKevin Yu 			} else {
244e6eb57e7SKevin Yu 				syslog(LOG_ERR, "get property failed - %s",
245e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
246e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
247e6eb57e7SKevin Yu 				goto out;
248e6eb57e7SKevin Yu 			}
249e6eb57e7SKevin Yu 		}
250e6eb57e7SKevin Yu 	}
251e6eb57e7SKevin Yu 
252e6eb57e7SKevin Yu 	/* Begin the transaction */
253e6eb57e7SKevin Yu 	if (scf_transaction_start(tran, pg) == -1) {
254e6eb57e7SKevin Yu 		syslog(LOG_ERR, "start transaction failed - %s",
255e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
256e6eb57e7SKevin Yu 		ret = FCOE_ERROR;
257e6eb57e7SKevin Yu 		goto out;
258e6eb57e7SKevin Yu 	}
259e6eb57e7SKevin Yu 
260e6eb57e7SKevin Yu 	valueSet = (scf_value_t **)calloc(1, sizeof (*valueSet)
261e6eb57e7SKevin Yu 	    * (lastAlloc = portListAlloc));
262e6eb57e7SKevin Yu 	if (valueSet == NULL) {
263e6eb57e7SKevin Yu 		ret = FCOE_ERROR_NOMEM;
264e6eb57e7SKevin Yu 		goto out;
265e6eb57e7SKevin Yu 	}
266e6eb57e7SKevin Yu 
267e6eb57e7SKevin Yu 	if (createProp) {
268e6eb57e7SKevin Yu 		if (scf_transaction_property_new(tran, entry, FCOE_PORT_LIST,
269e6eb57e7SKevin Yu 		    SCF_TYPE_USTRING) == -1) {
270e6eb57e7SKevin Yu 			if (scf_error() == SCF_ERROR_EXISTS) {
271e6eb57e7SKevin Yu 				ret = FCOE_ERROR_EXISTS;
272e6eb57e7SKevin Yu 			} else {
273e6eb57e7SKevin Yu 				syslog(LOG_ERR,
274e6eb57e7SKevin Yu 				    "transaction property new failed - %s",
275e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
276e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
277e6eb57e7SKevin Yu 			}
278e6eb57e7SKevin Yu 			goto out;
279e6eb57e7SKevin Yu 		}
280e6eb57e7SKevin Yu 	} else {
281e6eb57e7SKevin Yu 		if (scf_transaction_property_change(tran, entry,
282e6eb57e7SKevin Yu 		    FCOE_PORT_LIST, SCF_TYPE_USTRING) == -1) {
283e6eb57e7SKevin Yu 			syslog(LOG_ERR,
284e6eb57e7SKevin Yu 			    "transaction property change failed - %s",
285e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
286e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
287e6eb57e7SKevin Yu 			goto out;
288e6eb57e7SKevin Yu 		}
289e6eb57e7SKevin Yu 
290e6eb57e7SKevin Yu 		if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
291e6eb57e7SKevin Yu 			syslog(LOG_ERR, "get property failed - %s",
292e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
293e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
294e6eb57e7SKevin Yu 			goto out;
295e6eb57e7SKevin Yu 		}
296e6eb57e7SKevin Yu 
297e6eb57e7SKevin Yu 		valueLookup = scf_value_create(handle);
298e6eb57e7SKevin Yu 		if (valueLookup == NULL) {
299e6eb57e7SKevin Yu 			syslog(LOG_ERR, "scf value alloc failed - %s",
300e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
301e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
302e6eb57e7SKevin Yu 			goto out;
303e6eb57e7SKevin Yu 		}
304e6eb57e7SKevin Yu 
305e6eb57e7SKevin Yu 		if (scf_iter_property_values(valueIter, prop) == -1) {
306e6eb57e7SKevin Yu 			syslog(LOG_ERR, "iter value failed - %s",
307e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
308e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
309e6eb57e7SKevin Yu 			goto out;
310e6eb57e7SKevin Yu 		}
311e6eb57e7SKevin Yu 
312e6eb57e7SKevin Yu 		while (scf_iter_next_value(valueIter, valueLookup) == 1) {
313e6eb57e7SKevin Yu 			char *macnameIter = NULL;
314e6eb57e7SKevin Yu 			char buftmp[FCOE_PORT_LIST_LENGTH] = {0};
315e6eb57e7SKevin Yu 
316e6eb57e7SKevin Yu 			bzero(buf, sizeof (buf));
317e6eb57e7SKevin Yu 			if (scf_value_get_ustring(valueLookup,
318e6eb57e7SKevin Yu 			    buf, MAXNAMELEN) == -1) {
319e6eb57e7SKevin Yu 				syslog(LOG_ERR, "iter value failed- %s",
320e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
321e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
322e6eb57e7SKevin Yu 				break;
323e6eb57e7SKevin Yu 			}
324e6eb57e7SKevin Yu 			(void) strcpy(buftmp, buf);
325e6eb57e7SKevin Yu 			macnameIter = strtok(buftmp, ":");
326e6eb57e7SKevin Yu 			if (strcmp(macnameIter, mac_name) == 0) {
327e6eb57e7SKevin Yu 				if (addRemoveFlag == FCOE_SCF_ADD) {
328e6eb57e7SKevin Yu 					ret = FCOE_ERROR_EXISTS;
329e6eb57e7SKevin Yu 					break;
330e6eb57e7SKevin Yu 				} else {
331e6eb57e7SKevin Yu 					found = B_TRUE;
332e6eb57e7SKevin Yu 					continue;
333e6eb57e7SKevin Yu 				}
334e6eb57e7SKevin Yu 			}
335e6eb57e7SKevin Yu 
336e6eb57e7SKevin Yu 			valueSet[i] = scf_value_create(handle);
337e6eb57e7SKevin Yu 			if (valueSet[i] == NULL) {
338e6eb57e7SKevin Yu 				syslog(LOG_ERR, "scf value alloc failed - %s",
339e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
340e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
341e6eb57e7SKevin Yu 				break;
342e6eb57e7SKevin Yu 			}
343e6eb57e7SKevin Yu 
344e6eb57e7SKevin Yu 			if (scf_value_set_ustring(valueSet[i], buf) == -1) {
345e6eb57e7SKevin Yu 				syslog(LOG_ERR, "set value failed 1- %s",
346e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
347e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
348e6eb57e7SKevin Yu 				break;
349e6eb57e7SKevin Yu 			}
350e6eb57e7SKevin Yu 
351e6eb57e7SKevin Yu 			if (scf_entry_add_value(entry, valueSet[i]) == -1) {
352e6eb57e7SKevin Yu 				syslog(LOG_ERR, "add value failed - %s",
353e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
354e6eb57e7SKevin Yu 				ret = FCOE_ERROR;
355e6eb57e7SKevin Yu 				break;
356e6eb57e7SKevin Yu 			}
357e6eb57e7SKevin Yu 
358e6eb57e7SKevin Yu 			i++;
359e6eb57e7SKevin Yu 
360e6eb57e7SKevin Yu 			if (i >= lastAlloc) {
361e6eb57e7SKevin Yu 				lastAlloc += portListAlloc;
362e6eb57e7SKevin Yu 				valueSet = realloc(valueSet,
363e6eb57e7SKevin Yu 				    sizeof (*valueSet) * lastAlloc);
364e6eb57e7SKevin Yu 				if (valueSet == NULL) {
365e6eb57e7SKevin Yu 					ret = FCOE_ERROR;
366e6eb57e7SKevin Yu 					break;
367e6eb57e7SKevin Yu 				}
368e6eb57e7SKevin Yu 			}
369e6eb57e7SKevin Yu 		}
370e6eb57e7SKevin Yu 	}
371e6eb57e7SKevin Yu 
372e6eb57e7SKevin Yu 	valueArraySize = i;
373e6eb57e7SKevin Yu 	if (!found && (addRemoveFlag == FCOE_SCF_REMOVE)) {
374e6eb57e7SKevin Yu 		ret = FCOE_ERROR_MEMBER_NOT_FOUND;
375e6eb57e7SKevin Yu 	}
376e6eb57e7SKevin Yu 	if (ret != FCOE_SUCCESS) {
377e6eb57e7SKevin Yu 		goto out;
378e6eb57e7SKevin Yu 	}
379e6eb57e7SKevin Yu 
380e6eb57e7SKevin Yu 	if (addRemoveFlag == FCOE_SCF_ADD) {
381e6eb57e7SKevin Yu 		/*
382e6eb57e7SKevin Yu 		 * Now create the new entry
383e6eb57e7SKevin Yu 		 */
384e6eb57e7SKevin Yu 		valueSet[i] = scf_value_create(handle);
385e6eb57e7SKevin Yu 		if (valueSet[i] == NULL) {
386e6eb57e7SKevin Yu 			syslog(LOG_ERR, "scf value alloc failed - %s",
387e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
388e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
389e6eb57e7SKevin Yu 			goto out;
390e6eb57e7SKevin Yu 		} else {
391e6eb57e7SKevin Yu 			valueArraySize++;
392e6eb57e7SKevin Yu 		}
393e6eb57e7SKevin Yu 
394e6eb57e7SKevin Yu 		/*
395e6eb57e7SKevin Yu 		 * Set the new member name
396e6eb57e7SKevin Yu 		 */
397e6eb57e7SKevin Yu 		if (scf_value_set_ustring(valueSet[i], memberName) == -1) {
398e6eb57e7SKevin Yu 			syslog(LOG_ERR, "set value failed 2- %s",
399e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
400e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
401e6eb57e7SKevin Yu 			goto out;
402e6eb57e7SKevin Yu 		}
403e6eb57e7SKevin Yu 
404e6eb57e7SKevin Yu 		/*
405e6eb57e7SKevin Yu 		 * Add the new member
406e6eb57e7SKevin Yu 		 */
407e6eb57e7SKevin Yu 		if (scf_entry_add_value(entry, valueSet[i]) == -1) {
408e6eb57e7SKevin Yu 			syslog(LOG_ERR, "add value failed - %s",
409e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
410e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
411e6eb57e7SKevin Yu 			goto out;
412e6eb57e7SKevin Yu 		}
413e6eb57e7SKevin Yu 	}
414e6eb57e7SKevin Yu 
415e6eb57e7SKevin Yu 	if ((commitRet = scf_transaction_commit(tran)) != 1) {
416e6eb57e7SKevin Yu 		syslog(LOG_ERR, "transaction commit failed - %s",
417e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
418e6eb57e7SKevin Yu 		if (commitRet == 0) {
419e6eb57e7SKevin Yu 			ret = FCOE_ERROR_BUSY;
420e6eb57e7SKevin Yu 		} else {
421e6eb57e7SKevin Yu 			ret = FCOE_ERROR;
422e6eb57e7SKevin Yu 		}
423e6eb57e7SKevin Yu 		goto out;
424e6eb57e7SKevin Yu 	}
425e6eb57e7SKevin Yu 
426e6eb57e7SKevin Yu out:
427e6eb57e7SKevin Yu 	/*
428e6eb57e7SKevin Yu 	 * Free resources
429e6eb57e7SKevin Yu 	 */
430e6eb57e7SKevin Yu 	if (handle != NULL) {
431e6eb57e7SKevin Yu 		scf_handle_destroy(handle);
432e6eb57e7SKevin Yu 	}
433e6eb57e7SKevin Yu 	if (svc != NULL) {
434e6eb57e7SKevin Yu 		scf_service_destroy(svc);
435e6eb57e7SKevin Yu 	}
436e6eb57e7SKevin Yu 	if (pg != NULL) {
437e6eb57e7SKevin Yu 		scf_pg_destroy(pg);
438e6eb57e7SKevin Yu 	}
439e6eb57e7SKevin Yu 	if (tran != NULL) {
440e6eb57e7SKevin Yu 		scf_transaction_destroy(tran);
441e6eb57e7SKevin Yu 	}
442e6eb57e7SKevin Yu 	if (entry != NULL) {
443e6eb57e7SKevin Yu 		scf_entry_destroy(entry);
444e6eb57e7SKevin Yu 	}
445e6eb57e7SKevin Yu 	if (prop != NULL) {
446e6eb57e7SKevin Yu 		scf_property_destroy(prop);
447e6eb57e7SKevin Yu 	}
448e6eb57e7SKevin Yu 	if (valueIter != NULL) {
449e6eb57e7SKevin Yu 		scf_iter_destroy(valueIter);
450e6eb57e7SKevin Yu 	}
451e6eb57e7SKevin Yu 	if (valueLookup != NULL) {
452e6eb57e7SKevin Yu 		scf_value_destroy(valueLookup);
453e6eb57e7SKevin Yu 	}
454e6eb57e7SKevin Yu 
455e6eb57e7SKevin Yu 	/*
456e6eb57e7SKevin Yu 	 * Free valueSet scf resources
457e6eb57e7SKevin Yu 	 */
458e6eb57e7SKevin Yu 	if (valueArraySize > 0) {
459e6eb57e7SKevin Yu 		for (i = 0; i < valueArraySize; i++) {
460e6eb57e7SKevin Yu 			scf_value_destroy(valueSet[i]);
461e6eb57e7SKevin Yu 		}
462e6eb57e7SKevin Yu 	}
463e6eb57e7SKevin Yu 	/*
464e6eb57e7SKevin Yu 	 * Now free the pointer array to the resources
465e6eb57e7SKevin Yu 	 */
466e6eb57e7SKevin Yu 	if (valueSet != NULL) {
467e6eb57e7SKevin Yu 		free(valueSet);
468e6eb57e7SKevin Yu 	}
469e6eb57e7SKevin Yu 
470e6eb57e7SKevin Yu 	return (ret);
471e6eb57e7SKevin Yu }
472e6eb57e7SKevin Yu 
4732a8164dfSZhong Wang FCOE_STATUS
FCOE_CreatePort(const FCOE_UINT8 * macLinkName,FCOE_UINT8 portType,FCOE_PORT_WWN pwwn,FCOE_PORT_WWN nwwn,FCOE_UINT8 promiscuous)4742a8164dfSZhong Wang FCOE_CreatePort(
4752a8164dfSZhong Wang 	const FCOE_UINT8		*macLinkName,
4762a8164dfSZhong Wang 	FCOE_UINT8		portType,
4772a8164dfSZhong Wang 	FCOE_PORT_WWN		pwwn,
4782a8164dfSZhong Wang 	FCOE_PORT_WWN		nwwn,
4792a8164dfSZhong Wang 	FCOE_UINT8		promiscuous)
4802a8164dfSZhong Wang {
481e6eb57e7SKevin Yu 	FCOE_STATUS		status;
482d4401b99SKelly Hu 	int			fcoe_fd;
483d4401b99SKelly Hu 	fcoeio_t		fcoeio;
4842a8164dfSZhong Wang 	fcoeio_create_port_param_t	param;
485d4401b99SKelly Hu 	dladm_handle_t		handle;
486d4401b99SKelly Hu 	datalink_id_t		linkid;
487d4401b99SKelly Hu 	datalink_class_t	class;
4882a8164dfSZhong Wang 
4892a8164dfSZhong Wang 	bzero(&param, sizeof (fcoeio_create_port_param_t));
4902a8164dfSZhong Wang 
4912a8164dfSZhong Wang 	if (macLinkName == NULL) {
4922a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
4932a8164dfSZhong Wang 	}
4942a8164dfSZhong Wang 
495d4401b99SKelly Hu 	if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
496d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_MAC_LEN);
497d4401b99SKelly Hu 	}
498d4401b99SKelly Hu 
499d4401b99SKelly Hu 	if (dladm_open(&handle) != DLADM_STATUS_OK) {
500d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR);
501d4401b99SKelly Hu 	}
502d4401b99SKelly Hu 
503d4401b99SKelly Hu 	if (dladm_name2info(handle, (const char *)macLinkName,
504d4401b99SKelly Hu 	    &linkid, NULL, &class, NULL) != DLADM_STATUS_OK) {
505d4401b99SKelly Hu 		dladm_close(handle);
506e6eb57e7SKevin Yu 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
507e6eb57e7SKevin Yu 		    "",
508e6eb57e7SKevin Yu 		    "",
509e6eb57e7SKevin Yu 		    portType,
510e6eb57e7SKevin Yu 		    0,
511e6eb57e7SKevin Yu 		    FCOE_SCF_REMOVE);
512d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_GET_LINKINFO);
513d4401b99SKelly Hu 	}
514d4401b99SKelly Hu 	dladm_close(handle);
515d4401b99SKelly Hu 
516d4401b99SKelly Hu 	if (class != DATALINK_CLASS_PHYS) {
517d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_CLASS_UNSUPPORT);
518d4401b99SKelly Hu 	}
519d4401b99SKelly Hu 
5202a8164dfSZhong Wang 	if (portType != FCOE_PORTTYPE_INITIATOR &&
5212a8164dfSZhong Wang 	    portType != FCOE_PORTTYPE_TARGET) {
5222a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
5232a8164dfSZhong Wang 	}
5242a8164dfSZhong Wang 
5252a8164dfSZhong Wang 	if (!isWWNZero(pwwn)) {
5262a8164dfSZhong Wang 		param.fcp_pwwn_provided = 1;
5272a8164dfSZhong Wang 		bcopy(pwwn.wwn, param.fcp_pwwn, 8);
5282a8164dfSZhong Wang 	}
5292a8164dfSZhong Wang 
5302a8164dfSZhong Wang 	if (!isWWNZero(nwwn)) {
5312a8164dfSZhong Wang 		param.fcp_nwwn_provided = 1;
5322a8164dfSZhong Wang 		bcopy(nwwn.wwn, param.fcp_nwwn, 8);
5332a8164dfSZhong Wang 	}
5342a8164dfSZhong Wang 
5352a8164dfSZhong Wang 	if (param.fcp_pwwn_provided == 1 &&
5362a8164dfSZhong Wang 	    param.fcp_nwwn_provided == 1 &&
5372a8164dfSZhong Wang 	    bcmp(&pwwn, &nwwn, 8) == 0) {
5382a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_WWN_SAME);
5392a8164dfSZhong Wang 	}
5402a8164dfSZhong Wang 
5412a8164dfSZhong Wang 	param.fcp_force_promisc = promiscuous;
542d4401b99SKelly Hu 	param.fcp_mac_linkid = linkid;
5432a8164dfSZhong Wang 	param.fcp_port_type = (fcoe_cli_type_t)portType;
5442a8164dfSZhong Wang 
5452a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
5462a8164dfSZhong Wang 		return (status);
5472a8164dfSZhong Wang 	}
5482a8164dfSZhong Wang 
5492a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
5502a8164dfSZhong Wang 	fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT;
5512a8164dfSZhong Wang 
5522a8164dfSZhong Wang 	fcoeio.fcoeio_ilen = sizeof (param);
5532a8164dfSZhong Wang 	fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
5542a8164dfSZhong Wang 	fcoeio.fcoeio_ibuf = (uintptr_t)&param;
5552a8164dfSZhong Wang 
5562a8164dfSZhong Wang 	if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
5572a8164dfSZhong Wang 		switch (fcoeio.fcoeio_status) {
5582a8164dfSZhong Wang 		case FCOEIOE_INVAL_ARG:
5592a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_INVAL_ARG;
5602a8164dfSZhong Wang 			break;
5612a8164dfSZhong Wang 
5622a8164dfSZhong Wang 		case FCOEIOE_BUSY:
5632a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_BUSY;
5642a8164dfSZhong Wang 			break;
5652a8164dfSZhong Wang 
5662a8164dfSZhong Wang 		case FCOEIOE_ALREADY:
5672a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_ALREADY;
5682a8164dfSZhong Wang 			break;
5692a8164dfSZhong Wang 
5702a8164dfSZhong Wang 		case FCOEIOE_PWWN_CONFLICTED:
5712a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_PWWN_CONFLICTED;
5722a8164dfSZhong Wang 			break;
5732a8164dfSZhong Wang 
5742a8164dfSZhong Wang 		case FCOEIOE_NWWN_CONFLICTED:
5752a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_NWWN_CONFLICTED;
5762a8164dfSZhong Wang 			break;
5772a8164dfSZhong Wang 
5782a8164dfSZhong Wang 		case FCOEIOE_CREATE_MAC:
5792a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_CREATE_MAC;
5802a8164dfSZhong Wang 			break;
5812a8164dfSZhong Wang 
5822a8164dfSZhong Wang 		case FCOEIOE_OPEN_MAC:
5832a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_OPEN_MAC;
5842a8164dfSZhong Wang 			break;
5852a8164dfSZhong Wang 
5862a8164dfSZhong Wang 		case FCOEIOE_CREATE_PORT:
5872a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_CREATE_PORT;
5882a8164dfSZhong Wang 			break;
5892a8164dfSZhong Wang 
5902a8164dfSZhong Wang 		case FCOEIOE_NEED_JUMBO_FRAME:
5912a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME;
5922a8164dfSZhong Wang 			break;
5932a8164dfSZhong Wang 
5942a8164dfSZhong Wang 		default:
5952a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR;
5962a8164dfSZhong Wang 		}
5972a8164dfSZhong Wang 	} else {
598e6eb57e7SKevin Yu 		char cpwwn[17], cnwwn[17];
599e6eb57e7SKevin Yu 
600e6eb57e7SKevin Yu 		WWN2str(cpwwn, &pwwn);
601e6eb57e7SKevin Yu 		WWN2str(cnwwn, &nwwn);
602e6eb57e7SKevin Yu 
603e6eb57e7SKevin Yu 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
604e6eb57e7SKevin Yu 		    cpwwn,
605e6eb57e7SKevin Yu 		    cnwwn,
606e6eb57e7SKevin Yu 		    portType,
607e6eb57e7SKevin Yu 		    promiscuous,
608e6eb57e7SKevin Yu 		    FCOE_SCF_ADD);
6092a8164dfSZhong Wang 		status = FCOE_STATUS_OK;
6102a8164dfSZhong Wang 	}
6112a8164dfSZhong Wang 	(void) close(fcoe_fd);
6122a8164dfSZhong Wang 	return (status);
6132a8164dfSZhong Wang }
6142a8164dfSZhong Wang 
6152a8164dfSZhong Wang FCOE_STATUS
FCOE_DeletePort(const FCOE_UINT8 * macLinkName)6162a8164dfSZhong Wang FCOE_DeletePort(const FCOE_UINT8 *macLinkName)
6172a8164dfSZhong Wang {
6182a8164dfSZhong Wang 	FCOE_STATUS status = FCOE_STATUS_OK;
6192a8164dfSZhong Wang 	int fcoe_fd;
6202a8164dfSZhong Wang 	fcoeio_t	fcoeio;
621d4401b99SKelly Hu 	dladm_handle_t		handle;
622d4401b99SKelly Hu 	datalink_id_t		linkid;
623d4401b99SKelly Hu 	fcoeio_delete_port_param_t fc_del_port;
624e6eb57e7SKevin Yu 	uint64_t	is_target = 0;
625e6eb57e7SKevin Yu 	int		io_ret = 0;
6262a8164dfSZhong Wang 
6272a8164dfSZhong Wang 	if (macLinkName == NULL) {
6282a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
6292a8164dfSZhong Wang 	}
6302a8164dfSZhong Wang 
631d4401b99SKelly Hu 	if (strlen((char *)macLinkName) > MAXLINKNAMELEN-1) {
6322a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_MAC_LEN);
6332a8164dfSZhong Wang 	}
634d4401b99SKelly Hu 	if (dladm_open(&handle) != DLADM_STATUS_OK) {
635d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR);
636d4401b99SKelly Hu 	}
637d4401b99SKelly Hu 
638d4401b99SKelly Hu 	if (dladm_name2info(handle, (const char *)macLinkName,
639d4401b99SKelly Hu 	    &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) {
640d4401b99SKelly Hu 		dladm_close(handle);
641d4401b99SKelly Hu 		return (FCOE_STATUS_ERROR_GET_LINKINFO);
642d4401b99SKelly Hu 	}
643d4401b99SKelly Hu 	dladm_close(handle);
6442a8164dfSZhong Wang 
6452a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
6462a8164dfSZhong Wang 		return (status);
6472a8164dfSZhong Wang 	}
6482a8164dfSZhong Wang 
649d4401b99SKelly Hu 	fc_del_port.fdp_mac_linkid = linkid;
650d4401b99SKelly Hu 
6512a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
6522a8164dfSZhong Wang 	fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT;
6532a8164dfSZhong Wang 
654d4401b99SKelly Hu 	/* only 4 bytes here, need to change */
655d4401b99SKelly Hu 	fcoeio.fcoeio_ilen = sizeof (fcoeio_delete_port_param_t);
656e6eb57e7SKevin Yu 	fcoeio.fcoeio_olen = sizeof (uint64_t);
657e6eb57e7SKevin Yu 	fcoeio.fcoeio_xfer = FCOEIO_XFER_RW;
658d4401b99SKelly Hu 	fcoeio.fcoeio_ibuf = (uintptr_t)&fc_del_port;
659e6eb57e7SKevin Yu 	fcoeio.fcoeio_obuf = (uintptr_t)&is_target;
6602a8164dfSZhong Wang 
661e6eb57e7SKevin Yu 	io_ret = ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio);
662e6eb57e7SKevin Yu 	if (io_ret != 0) {
6632a8164dfSZhong Wang 		switch (fcoeio.fcoeio_status) {
6642a8164dfSZhong Wang 		case FCOEIOE_INVAL_ARG:
6652a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_INVAL_ARG;
6662a8164dfSZhong Wang 			break;
6672a8164dfSZhong Wang 
6682a8164dfSZhong Wang 		case FCOEIOE_BUSY:
6692a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_BUSY;
6702a8164dfSZhong Wang 			break;
6712a8164dfSZhong Wang 
6722a8164dfSZhong Wang 		case FCOEIOE_ALREADY:
6732a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_ALREADY;
6742a8164dfSZhong Wang 			break;
6752a8164dfSZhong Wang 
6762a8164dfSZhong Wang 		case FCOEIOE_MAC_NOT_FOUND:
6772a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_MAC_NOT_FOUND;
6782a8164dfSZhong Wang 			break;
6792a8164dfSZhong Wang 
6802a8164dfSZhong Wang 		case FCOEIOE_OFFLINE_FAILURE:
6812a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_OFFLINE_DEV;
6822a8164dfSZhong Wang 			break;
6832a8164dfSZhong Wang 
6842a8164dfSZhong Wang 		default:
6852a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR;
6862a8164dfSZhong Wang 		}
6872a8164dfSZhong Wang 	} else {
688e6eb57e7SKevin Yu 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
689e6eb57e7SKevin Yu 		    "",
690e6eb57e7SKevin Yu 		    "",
691e6eb57e7SKevin Yu 		    is_target,
692e6eb57e7SKevin Yu 		    0,
693e6eb57e7SKevin Yu 		    FCOE_SCF_REMOVE);
6942a8164dfSZhong Wang 		status = FCOE_STATUS_OK;
6952a8164dfSZhong Wang 	}
696e6eb57e7SKevin Yu 
697e6eb57e7SKevin Yu 	if (io_ret == FCOEIOE_MAC_NOT_FOUND) {
698e6eb57e7SKevin Yu 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
699e6eb57e7SKevin Yu 		    "",
700e6eb57e7SKevin Yu 		    "",
701e6eb57e7SKevin Yu 		    0,
702e6eb57e7SKevin Yu 		    0,
703e6eb57e7SKevin Yu 		    FCOE_SCF_REMOVE);
704e6eb57e7SKevin Yu 		(void) fcoe_add_remove_scf_entry((char *)macLinkName,
705e6eb57e7SKevin Yu 		    "",
706e6eb57e7SKevin Yu 		    "",
707e6eb57e7SKevin Yu 		    1,
708e6eb57e7SKevin Yu 		    0,
709e6eb57e7SKevin Yu 		    FCOE_SCF_REMOVE);
710e6eb57e7SKevin Yu 	}
7112a8164dfSZhong Wang 	(void) close(fcoe_fd);
7122a8164dfSZhong Wang 	return (status);
7132a8164dfSZhong Wang }
7142a8164dfSZhong Wang 
7152a8164dfSZhong Wang FCOE_STATUS
FCOE_GetPortList(FCOE_UINT32 * port_num,FCOE_PORT_ATTRIBUTE ** portlist)7162a8164dfSZhong Wang FCOE_GetPortList(
7172a8164dfSZhong Wang 	FCOE_UINT32		*port_num,
7182a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	**portlist)
7192a8164dfSZhong Wang {
7202a8164dfSZhong Wang 	FCOE_STATUS	status = FCOE_STATUS_OK;
721d4401b99SKelly Hu 	int		fcoe_fd;
7222a8164dfSZhong Wang 	fcoeio_t	fcoeio;
723d4401b99SKelly Hu 	fcoe_port_list_t	*inportlist = NULL;
7242a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	*outportlist = NULL;
725d4401b99SKelly Hu 	int		i;
726d4401b99SKelly Hu 	int		size = 64; /* default first attempt */
727d4401b99SKelly Hu 	int		retry = 0;
728d4401b99SKelly Hu 	int		bufsize;
729d4401b99SKelly Hu 	dladm_handle_t	handle;
730d4401b99SKelly Hu 	char		mac_name[MAXLINKNAMELEN];
7312a8164dfSZhong Wang 
7322a8164dfSZhong Wang 	if (port_num == NULL || portlist == NULL) {
7332a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
7342a8164dfSZhong Wang 	}
7352a8164dfSZhong Wang 	*port_num = 0;
7362a8164dfSZhong Wang 
7372a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
7382a8164dfSZhong Wang 		return (status);
7392a8164dfSZhong Wang 	}
7402a8164dfSZhong Wang 
7412a8164dfSZhong Wang 	/* Get fcoe port list */
7422a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
7432a8164dfSZhong Wang 	retry = 0;
7442a8164dfSZhong Wang 
7452a8164dfSZhong Wang 	do {
7462a8164dfSZhong Wang 		bufsize = sizeof (fcoe_port_instance_t) * (size - 1) +
7472a8164dfSZhong Wang 		    sizeof (fcoe_port_list_t);
7482a8164dfSZhong Wang 		inportlist = (fcoe_port_list_t *)malloc(bufsize);
7492a8164dfSZhong Wang 		fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST;
7502a8164dfSZhong Wang 		fcoeio.fcoeio_olen = bufsize;
7512a8164dfSZhong Wang 		fcoeio.fcoeio_xfer = FCOEIO_XFER_READ;
7522a8164dfSZhong Wang 		fcoeio.fcoeio_obuf = (uintptr_t)inportlist;
7532a8164dfSZhong Wang 
7542a8164dfSZhong Wang 		if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
7552a8164dfSZhong Wang 			if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) {
7562a8164dfSZhong Wang 				size = inportlist->numPorts;
7572a8164dfSZhong Wang 			}
7582a8164dfSZhong Wang 			free(inportlist);
7592a8164dfSZhong Wang 			switch (fcoeio.fcoeio_status) {
7602a8164dfSZhong Wang 			case FCOEIOE_INVAL_ARG:
7612a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_INVAL_ARG;
7622a8164dfSZhong Wang 				(void) close(fcoe_fd);
7632a8164dfSZhong Wang 				return (status);
7642a8164dfSZhong Wang 
7652a8164dfSZhong Wang 			case FCOEIOE_BUSY:
7662a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_BUSY;
7672a8164dfSZhong Wang 				retry++;
7682a8164dfSZhong Wang 				break;
7692a8164dfSZhong Wang 
7702a8164dfSZhong Wang 			case FCOEIOE_MORE_DATA:
7712a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_MORE_DATA;
7722a8164dfSZhong Wang 				retry++;
773*6cd9fed7SToomas Soome 				break;
774*6cd9fed7SToomas Soome 
7752a8164dfSZhong Wang 			default:
7762a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR;
777e6eb57e7SKevin Yu 				(void) close(fcoe_fd);
778e6eb57e7SKevin Yu 				return (status);
7792a8164dfSZhong Wang 			}
7802a8164dfSZhong Wang 		} else {
7812a8164dfSZhong Wang 			status = FCOE_STATUS_OK;
7822a8164dfSZhong Wang 			break;
7832a8164dfSZhong Wang 		}
7842a8164dfSZhong Wang 	} while (retry <= 3 && status != FCOE_STATUS_OK);
7852a8164dfSZhong Wang 
786d4401b99SKelly Hu 	if (status == FCOE_STATUS_OK && inportlist->numPorts > 0) {
787d4401b99SKelly Hu 		if (dladm_open(&handle) != DLADM_STATUS_OK) {
788d4401b99SKelly Hu 			handle = NULL;
789d4401b99SKelly Hu 		}
790d4401b99SKelly Hu 
7912a8164dfSZhong Wang 		outportlist = (PFCOE_PORT_ATTRIBUTE)
7922a8164dfSZhong Wang 		    malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts);
7932a8164dfSZhong Wang 
7942a8164dfSZhong Wang 		for (i = 0; i < inportlist->numPorts; i++) {
7952a8164dfSZhong Wang 			fcoe_port_instance_t *pi = &inportlist->ports[i];
7962a8164dfSZhong Wang 			FCOE_PORT_ATTRIBUTE *po = &outportlist[i];
7972a8164dfSZhong Wang 			bcopy(pi->fpi_pwwn, &po->port_wwn, 8);
798d4401b99SKelly Hu 
799d4401b99SKelly Hu 			if (handle == NULL ||
800d4401b99SKelly Hu 			    dladm_datalink_id2info(handle, pi->fpi_mac_linkid,
801d4401b99SKelly Hu 			    NULL, NULL, NULL, mac_name, sizeof (mac_name))
802d4401b99SKelly Hu 			    != DLADM_STATUS_OK) {
803d4401b99SKelly Hu 				(void) strcpy((char *)po->mac_link_name,
804d4401b99SKelly Hu 				    "<unknown>");
805d4401b99SKelly Hu 			} else {
806d4401b99SKelly Hu 				(void) strcpy((char *)po->mac_link_name,
807d4401b99SKelly Hu 				    mac_name);
808d4401b99SKelly Hu 			}
8092a8164dfSZhong Wang 			bcopy(pi->fpi_mac_factory_addr,
8102a8164dfSZhong Wang 			    po->mac_factory_addr, 6);
8112a8164dfSZhong Wang 			bcopy(pi->fpi_mac_current_addr,
8122a8164dfSZhong Wang 			    po->mac_current_addr, 6);
8132a8164dfSZhong Wang 			po->port_type = (FCOE_UINT8)pi->fpi_port_type;
8142a8164dfSZhong Wang 			po->mtu_size = pi->fpi_mtu_size;
8152a8164dfSZhong Wang 			po->mac_promisc = pi->fpi_mac_promisc;
8162a8164dfSZhong Wang 		}
817d4401b99SKelly Hu 
818d4401b99SKelly Hu 		if (handle != NULL) {
819d4401b99SKelly Hu 			dladm_close(handle);
820d4401b99SKelly Hu 		}
8212a8164dfSZhong Wang 		*port_num = inportlist->numPorts;
8222a8164dfSZhong Wang 		*portlist = outportlist;
8232a8164dfSZhong Wang 		free(inportlist);
8242a8164dfSZhong Wang 	} else {
8252a8164dfSZhong Wang 		*port_num = 0;
8262a8164dfSZhong Wang 		*portlist = NULL;
8272a8164dfSZhong Wang 	}
8282a8164dfSZhong Wang 	(void) close(fcoe_fd);
8292a8164dfSZhong Wang 	return (status);
8302a8164dfSZhong Wang }
831e6eb57e7SKevin Yu 
FCOE_LoadConfig(FCOE_UINT8 portType,FCOE_SMF_PORT_LIST ** portlist)832e6eb57e7SKevin Yu FCOE_STATUS FCOE_LoadConfig(
833e6eb57e7SKevin Yu 	FCOE_UINT8		portType,
834e6eb57e7SKevin Yu     FCOE_SMF_PORT_LIST **portlist)
835e6eb57e7SKevin Yu {
836e6eb57e7SKevin Yu 	scf_handle_t	*handle = NULL;
837e6eb57e7SKevin Yu 	scf_service_t	*svc = NULL;
838e6eb57e7SKevin Yu 	scf_propertygroup_t	*pg = NULL;
839e6eb57e7SKevin Yu 	scf_transaction_t	*tran = NULL;
840e6eb57e7SKevin Yu 	scf_transaction_entry_t	*entry = NULL;
841e6eb57e7SKevin Yu 	scf_property_t		*prop = NULL;
842e6eb57e7SKevin Yu 	scf_value_t	*valueLookup = NULL;
843e6eb57e7SKevin Yu 	scf_iter_t	*valueIter = NULL;
844e6eb57e7SKevin Yu 	char		buf[FCOE_PORT_LIST_LENGTH] = {0};
845e6eb57e7SKevin Yu 	int		commitRet;
846e6eb57e7SKevin Yu 	FCOE_UINT32	portIndex;
847e6eb57e7SKevin Yu 	int		bufsize, retry;
848e6eb57e7SKevin Yu 	int		size = 10; /* default first attempt */
849e6eb57e7SKevin Yu 	int		pg_or_prop_not_found = 0;
850e6eb57e7SKevin Yu 
851e6eb57e7SKevin Yu 	commitRet = fcoe_cfg_scf_init(&handle, &svc, portType);
852e6eb57e7SKevin Yu 	if (commitRet != FCOE_SUCCESS) {
853e6eb57e7SKevin Yu 		goto out;
854e6eb57e7SKevin Yu 	}
855e6eb57e7SKevin Yu 
856e6eb57e7SKevin Yu 	if (((pg = scf_pg_create(handle)) == NULL) ||
857e6eb57e7SKevin Yu 	    ((tran = scf_transaction_create(handle)) == NULL) ||
858e6eb57e7SKevin Yu 	    ((entry = scf_entry_create(handle)) == NULL) ||
859e6eb57e7SKevin Yu 	    ((prop = scf_property_create(handle)) == NULL) ||
860e6eb57e7SKevin Yu 	    ((valueIter = scf_iter_create(handle)) == NULL)) {
861e6eb57e7SKevin Yu 		goto out;
862e6eb57e7SKevin Yu 	}
863e6eb57e7SKevin Yu 
864e6eb57e7SKevin Yu 	if (scf_service_get_pg(svc, FCOE_PG_NAME, pg) == -1) {
865e6eb57e7SKevin Yu 		pg_or_prop_not_found = 1;
866e6eb57e7SKevin Yu 		goto out;
867e6eb57e7SKevin Yu 	}
868e6eb57e7SKevin Yu 
869e6eb57e7SKevin Yu 	if (scf_pg_get_property(pg, FCOE_PORT_LIST, prop) == -1) {
870e6eb57e7SKevin Yu 		pg_or_prop_not_found = 1;
871e6eb57e7SKevin Yu 		goto out;
872e6eb57e7SKevin Yu 	}
873e6eb57e7SKevin Yu 
874e6eb57e7SKevin Yu 	valueLookup = scf_value_create(handle);
875e6eb57e7SKevin Yu 	if (valueLookup == NULL) {
876e6eb57e7SKevin Yu 		syslog(LOG_ERR, "scf value alloc failed - %s",
877e6eb57e7SKevin Yu 		    scf_strerror(scf_error()));
878e6eb57e7SKevin Yu 		goto out;
879e6eb57e7SKevin Yu 	}
880e6eb57e7SKevin Yu 
881e6eb57e7SKevin Yu 	portIndex = 0;
882e6eb57e7SKevin Yu 
883e6eb57e7SKevin Yu 	do {
884e6eb57e7SKevin Yu 		if (scf_iter_property_values(valueIter, prop) == -1) {
885e6eb57e7SKevin Yu 			syslog(LOG_ERR, "iter value failed - %s",
886e6eb57e7SKevin Yu 			    scf_strerror(scf_error()));
887e6eb57e7SKevin Yu 			goto out;
888e6eb57e7SKevin Yu 		}
889e6eb57e7SKevin Yu 
890e6eb57e7SKevin Yu 		retry = 0;
891e6eb57e7SKevin Yu 		bufsize = sizeof (FCOE_SMF_PORT_INSTANCE) * (size - 1) +
892e6eb57e7SKevin Yu 		    sizeof (FCOE_SMF_PORT_LIST);
893e6eb57e7SKevin Yu 		*portlist = (PFCOE_SMF_PORT_LIST)malloc(bufsize);
894e6eb57e7SKevin Yu 
895e6eb57e7SKevin Yu 		while (scf_iter_next_value(valueIter, valueLookup) == 1) {
896e6eb57e7SKevin Yu 			uint8_t *macLinkName = NULL;
897e6eb57e7SKevin Yu 			char *remainder = NULL;
898e6eb57e7SKevin Yu 			uint64_t	nodeWWN, portWWN;
899e6eb57e7SKevin Yu 			int is_target, is_promiscuous;
900e6eb57e7SKevin Yu 
901e6eb57e7SKevin Yu 			bzero(buf, sizeof (buf));
902e6eb57e7SKevin Yu 			if (scf_value_get_ustring(valueLookup, buf,
903e6eb57e7SKevin Yu 			    MAXNAMELEN) == -1) {
904e6eb57e7SKevin Yu 				syslog(LOG_ERR, "iter value failed - %s",
905e6eb57e7SKevin Yu 				    scf_strerror(scf_error()));
906e6eb57e7SKevin Yu 				break;
907e6eb57e7SKevin Yu 			}
908e6eb57e7SKevin Yu 			macLinkName = (uint8_t *)strtok(buf, ":");
909e6eb57e7SKevin Yu 			remainder = strtok(NULL, "#");
910e6eb57e7SKevin Yu 			(void) sscanf(remainder,
911e6eb57e7SKevin Yu 			    "%016" PRIx64 ":%016" PRIx64 ":%d:%d",
912e6eb57e7SKevin Yu 			    &portWWN, &nodeWWN, &is_target, &is_promiscuous);
913e6eb57e7SKevin Yu 
914e6eb57e7SKevin Yu 			if (portIndex >= size) {
915e6eb57e7SKevin Yu 				free(*portlist);
916e6eb57e7SKevin Yu 				retry = 1;
917e6eb57e7SKevin Yu 				size *= 2;
918e6eb57e7SKevin Yu 				break;
919e6eb57e7SKevin Yu 			} else {
920e6eb57e7SKevin Yu 				PFCOE_SMF_PORT_INSTANCE pi =
921e6eb57e7SKevin Yu 				    &(*portlist)->ports[portIndex++];
922e6eb57e7SKevin Yu 				(void) strcpy((char *)pi->mac_link_name,
923e6eb57e7SKevin Yu 				    (char *)macLinkName);
924e6eb57e7SKevin Yu 				pi->port_type = is_target ?
925e6eb57e7SKevin Yu 				    FCOE_PORTTYPE_TARGET:
926e6eb57e7SKevin Yu 				    FCOE_PORTTYPE_INITIATOR;
927e6eb57e7SKevin Yu 				portWWN = htonll(portWWN);
928e6eb57e7SKevin Yu 				nodeWWN = htonll(nodeWWN);
929e6eb57e7SKevin Yu 				(void) memcpy(&pi->port_pwwn, &portWWN,
930e6eb57e7SKevin Yu 				    sizeof (FCOE_PORT_WWN));
931e6eb57e7SKevin Yu 				(void) memcpy(&pi->port_nwwn, &nodeWWN,
932e6eb57e7SKevin Yu 				    sizeof (FCOE_PORT_WWN));
933e6eb57e7SKevin Yu 				pi->mac_promisc = is_promiscuous;
934e6eb57e7SKevin Yu 			}
935e6eb57e7SKevin Yu 		}
936e6eb57e7SKevin Yu 
937e6eb57e7SKevin Yu 		(*portlist)->port_num = portIndex;
938e6eb57e7SKevin Yu 	} while (retry == 1);
939e6eb57e7SKevin Yu 
940e6eb57e7SKevin Yu 	return (FCOE_STATUS_OK);
941e6eb57e7SKevin Yu out:
942e6eb57e7SKevin Yu 	/*
943e6eb57e7SKevin Yu 	 * Free resources
944e6eb57e7SKevin Yu 	 */
945e6eb57e7SKevin Yu 	if (handle != NULL) {
946e6eb57e7SKevin Yu 		scf_handle_destroy(handle);
947e6eb57e7SKevin Yu 	}
948e6eb57e7SKevin Yu 	if (svc != NULL) {
949e6eb57e7SKevin Yu 		scf_service_destroy(svc);
950e6eb57e7SKevin Yu 	}
951e6eb57e7SKevin Yu 	if (pg != NULL) {
952e6eb57e7SKevin Yu 		scf_pg_destroy(pg);
953e6eb57e7SKevin Yu 	}
954e6eb57e7SKevin Yu 	if (tran != NULL) {
955e6eb57e7SKevin Yu 		scf_transaction_destroy(tran);
956e6eb57e7SKevin Yu 	}
957e6eb57e7SKevin Yu 	if (entry != NULL) {
958e6eb57e7SKevin Yu 		scf_entry_destroy(entry);
959e6eb57e7SKevin Yu 	}
960e6eb57e7SKevin Yu 	if (prop != NULL) {
961e6eb57e7SKevin Yu 		scf_property_destroy(prop);
962e6eb57e7SKevin Yu 	}
963e6eb57e7SKevin Yu 	if (valueIter != NULL) {
964e6eb57e7SKevin Yu 		scf_iter_destroy(valueIter);
965e6eb57e7SKevin Yu 	}
966e6eb57e7SKevin Yu 	if (valueLookup != NULL) {
967e6eb57e7SKevin Yu 		scf_value_destroy(valueLookup);
968e6eb57e7SKevin Yu 	}
969e6eb57e7SKevin Yu 
970e6eb57e7SKevin Yu 	if (pg_or_prop_not_found == 1) {
971e6eb57e7SKevin Yu 		return (FCOE_STATUS_OK);
972e6eb57e7SKevin Yu 	} else {
973e6eb57e7SKevin Yu 		return (FCOE_STATUS_ERROR);
974e6eb57e7SKevin Yu 	}
975e6eb57e7SKevin Yu }
976