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