xref: /illumos-gate/usr/src/lib/libstmf/common/stmf.c (revision 33efde4275d24731ef87927237b0ffb0630b6b2d)
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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2012 Milan Jurik. All rights reserved.
24  */
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <wchar.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <libintl.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <libnvpair.h>
39 #include <pthread.h>
40 #include <syslog.h>
41 #include <libstmf.h>
42 #include <netinet/in.h>
43 #include <inttypes.h>
44 #include <store.h>
45 #include <locale.h>
46 #include <math.h>
47 #include <libstmf_impl.h>
48 #include <sys/stmf_ioctl.h>
49 #include <sys/stmf_sbd_ioctl.h>
50 #include <sys/pppt_ioctl.h>
51 #include <macros.h>
52 
53 #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
54 #define	SBD_PATH    "/devices/pseudo/stmf_sbd@0:admin"
55 #define	PPPT_PATH    "/devices/pseudo/pppt@0:pppt"
56 
57 #define	EUI "eui."
58 #define	WWN "wwn."
59 #define	IQN "iqn."
60 #define	LU_ASCII_GUID_SIZE 32
61 #define	LU_GUID_SIZE 16
62 #define	OUI_ASCII_SIZE 6
63 #define	HOST_ID_ASCII_SIZE 8
64 #define	OUI_SIZE 3
65 #define	HOST_ID_SIZE 4
66 #define	IDENT_LENGTH_BYTE 3
67 
68 /* various initial allocation values */
69 #define	ALLOC_LU		8192
70 #define	ALLOC_TARGET_PORT	2048
71 #define	ALLOC_PROVIDER		64
72 #define	ALLOC_GROUP		2048
73 #define	ALLOC_SESSION		2048
74 #define	ALLOC_VE		256
75 #define	ALLOC_PP_DATA_SIZE	128*1024
76 #define	ALLOC_GRP_MEMBER	256
77 
78 #define	MAX_ISCSI_NAME	223
79 #define	MAX_SERIAL_SIZE 252 + 1
80 #define	MAX_LU_ALIAS_SIZE 256
81 #define	MAX_SBD_PROPS	MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
82 
83 #define	OPEN_STMF 0
84 #define	OPEN_EXCL_STMF O_EXCL
85 
86 #define	OPEN_SBD 0
87 #define	OPEN_EXCL_SBD O_EXCL
88 
89 #define	OPEN_PPPT 0
90 #define	OPEN_EXCL_PPPT O_EXCL
91 
92 #define	LOGICAL_UNIT_TYPE 0
93 #define	TARGET_TYPE 1
94 #define	STMF_SERVICE_TYPE 2
95 
96 #define	HOST_GROUP   1
97 #define	TARGET_GROUP 2
98 
99 /* set default persistence here */
100 #define	STMF_DEFAULT_PERSIST	STMF_PERSIST_SMF
101 
102 #define	MAX_PROVIDER_RETRY 30
103 
104 static int openStmf(int, int *fd);
105 static int openSbd(int, int *fd);
106 static int openPppt(int, int *fd);
107 static int groupIoctl(int fd, int cmd, stmfGroupName *);
108 static int loadStore(int fd);
109 static int initializeConfig();
110 static int groupMemberIoctl(int fd, int cmd, stmfGroupName *, stmfDevid *);
111 static int guidCompare(const void *, const void *);
112 static int addViewEntryIoctl(int fd, stmfGuid *, stmfViewEntry *);
113 static int loadHostGroups(int fd, stmfGroupList *);
114 static int loadTargetGroups(int fd, stmfGroupList *);
115 static int getStmfState(stmf_state_desc_t *);
116 static int setStmfState(int fd, stmf_state_desc_t *, int);
117 static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
118 static int createDiskResource(luResourceImpl *);
119 static int createDiskLu(diskResource *, stmfGuid *);
120 static int deleteDiskLu(stmfGuid *luGuid);
121 static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
122 static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
123 static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
124 static int removeGuidFromDiskStore(stmfGuid *);
125 static int addGuidToDiskStore(stmfGuid *, char *);
126 static int persistDiskGuid(stmfGuid *, char *, boolean_t);
127 static int setDiskProp(luResourceImpl *, uint32_t, const char *);
128 static int getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen);
129 static int checkHexUpper(char *);
130 static int strToShift(const char *);
131 static int niceStrToNum(const char *, uint64_t *);
132 static void diskError(uint32_t, int *);
133 static int importDiskLu(char *fname, stmfGuid *);
134 static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
135 static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
136 static int validateModifyDiskProp(uint32_t);
137 static uint8_t iGetPersistMethod();
138 static int groupListIoctl(stmfGroupList **, int);
139 static int iLoadGroupFromPs(stmfGroupList **, int);
140 static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
141 static int getProviderData(char *, nvlist_t **, int, uint64_t *);
142 static int setDiskStandby(stmfGuid *luGuid);
143 static int setDiskGlobalProp(uint32_t, const char *);
144 static int viewEntryCompare(const void *, const void *);
145 static void deleteNonActiveLus();
146 static int loadStmfProp(int fd);
147 
148 static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
149 static int iPersistType = 0;
150 /* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
151 static boolean_t iLibSetPersist = B_FALSE;
152 
153 /*
154  * Open for stmf module
155  *
156  * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
157  * fd - pointer to integer. On success, contains the stmf file descriptor
158  */
159 static int
openStmf(int flag,int * fd)160 openStmf(int flag, int *fd)
161 {
162 	int ret = STMF_STATUS_ERROR;
163 
164 	if ((*fd = open(STMF_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
165 		ret = STMF_STATUS_SUCCESS;
166 	} else {
167 		if (errno == EBUSY) {
168 			ret = STMF_ERROR_BUSY;
169 		} else if (errno == EACCES) {
170 			ret = STMF_ERROR_PERM;
171 		} else {
172 			ret = STMF_STATUS_ERROR;
173 		}
174 		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
175 		    STMF_PATH, errno);
176 	}
177 
178 	return (ret);
179 }
180 
181 /*
182  * Open for sbd module
183  *
184  * flag - open flag (OPEN_SBD, OPEN_EXCL_SBD)
185  * fd - pointer to integer. On success, contains the stmf file descriptor
186  */
187 static int
openSbd(int flag,int * fd)188 openSbd(int flag, int *fd)
189 {
190 	int ret = STMF_STATUS_ERROR;
191 
192 	if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
193 		ret = STMF_STATUS_SUCCESS;
194 	} else {
195 		if (errno == EBUSY) {
196 			ret = STMF_ERROR_BUSY;
197 		} else if (errno == EACCES) {
198 			ret = STMF_ERROR_PERM;
199 		} else {
200 			ret = STMF_STATUS_ERROR;
201 		}
202 		syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
203 		    SBD_PATH, errno);
204 	}
205 
206 	return (ret);
207 }
208 
209 /*
210  * Open for pppt module
211  *
212  * flag - open flag (OPEN_PPPT, OPEN_EXCL_PPPT)
213  * fd - pointer to integer. On success, contains the stmf file descriptor
214  */
215 static int
openPppt(int flag,int * fd)216 openPppt(int flag, int *fd)
217 {
218 	int ret = STMF_STATUS_ERROR;
219 
220 	if ((*fd = open(PPPT_PATH, O_RDONLY | flag)) != -1) {
221 		ret = STMF_STATUS_SUCCESS;
222 	} else {
223 		if (errno == EBUSY) {
224 			ret = STMF_ERROR_BUSY;
225 		} else if (errno == EACCES) {
226 			ret = STMF_ERROR_PERM;
227 		} else {
228 			ret = STMF_STATUS_ERROR;
229 		}
230 		syslog(LOG_DEBUG, "openPppt:open failure:%s:errno(%d)",
231 		    PPPT_PATH, errno);
232 	}
233 
234 	return (ret);
235 }
236 
237 /*
238  * initializeConfig
239  *
240  * This routine should be called before any ioctl requiring initialization
241  * which is basically everything except stmfGetState(), setStmfState() and
242  * stmfLoadConfig().
243  */
244 static int
initializeConfig()245 initializeConfig()
246 {
247 	int ret;
248 	stmfState state;
249 
250 
251 	ret = stmfGetState(&state);
252 	if (ret != STMF_STATUS_SUCCESS) {
253 		return (ret);
254 	}
255 
256 	/* if we've already initialized or in the process, return success */
257 	if (state.configState == STMF_CONFIG_STATE_INIT_DONE ||
258 	    state.configState == STMF_CONFIG_STATE_INIT) {
259 		return (STMF_STATUS_SUCCESS);
260 	}
261 
262 	ret = stmfLoadConfig();
263 	if (ret != STMF_STATUS_SUCCESS) {
264 		syslog(LOG_DEBUG,
265 		    "initializeConfig:stmfLoadConfig:error(%d)", ret);
266 		return (ret);
267 	}
268 
269 	ret = stmfGetState(&state);
270 	if (ret != STMF_STATUS_SUCCESS) {
271 		syslog(LOG_DEBUG,
272 		    "initializeConfig:stmfGetState:error(%d)", ret);
273 		return (ret);
274 	}
275 
276 	if (state.configState != STMF_CONFIG_STATE_INIT_DONE) {
277 		syslog(LOG_DEBUG, "initializeConfig:state.configState(%d)",
278 		    state.configState);
279 		ret = STMF_STATUS_ERROR;
280 	}
281 
282 	return (ret);
283 }
284 
285 
286 /*
287  * groupIoctl
288  *
289  * Purpose: issue ioctl for create/delete on group
290  *
291  * cmd - valid STMF ioctl group cmd
292  * groupName - groupName to create or delete
293  */
294 static int
groupIoctl(int fd,int cmd,stmfGroupName * groupName)295 groupIoctl(int fd, int cmd, stmfGroupName *groupName)
296 {
297 	int ret = STMF_STATUS_SUCCESS;
298 	int ioctlRet;
299 	stmf_iocdata_t stmfIoctl;
300 	stmf_group_name_t iGroupName;
301 
302 	bzero(&iGroupName, sizeof (iGroupName));
303 
304 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
305 
306 	iGroupName.name_size = strlen((char *)groupName);
307 
308 	bzero(&stmfIoctl, sizeof (stmfIoctl));
309 	/*
310 	 * Issue ioctl to create the host group
311 	 */
312 	stmfIoctl.stmf_version = STMF_VERSION_1;
313 	stmfIoctl.stmf_ibuf_size = sizeof (iGroupName);
314 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
315 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
316 	if (ioctlRet != 0) {
317 		switch (errno) {
318 			case EPERM:
319 			case EACCES:
320 				ret = STMF_ERROR_PERM;
321 				break;
322 			default:
323 				switch (stmfIoctl.stmf_error) {
324 					case STMF_IOCERR_TG_EXISTS:
325 					case STMF_IOCERR_HG_EXISTS:
326 						ret = STMF_ERROR_EXISTS;
327 						break;
328 					case STMF_IOCERR_TG_IN_USE:
329 					case STMF_IOCERR_HG_IN_USE:
330 						ret = STMF_ERROR_GROUP_IN_USE;
331 						break;
332 					case STMF_IOCERR_INVALID_HG:
333 					case STMF_IOCERR_INVALID_TG:
334 						ret = STMF_ERROR_NOT_FOUND;
335 						break;
336 					default:
337 						syslog(LOG_DEBUG,
338 						    "groupIoctl:error(%d)",
339 						    stmfIoctl.stmf_error);
340 						ret = STMF_STATUS_ERROR;
341 						break;
342 				}
343 				break;
344 		}
345 	}
346 	return (ret);
347 }
348 
349 /*
350  * groupMemberIoctl
351  *
352  * Purpose: issue ioctl for add/remove member on group
353  *
354  * cmd - valid STMF ioctl group member cmd
355  * groupName - groupName to add to or remove from
356  * devid - group member to add or remove
357  */
358 static int
groupMemberIoctl(int fd,int cmd,stmfGroupName * groupName,stmfDevid * devid)359 groupMemberIoctl(int fd, int cmd, stmfGroupName *groupName, stmfDevid *devid)
360 {
361 	int ret = STMF_STATUS_SUCCESS;
362 	int ioctlRet;
363 	stmf_iocdata_t stmfIoctl;
364 	stmf_group_op_data_t stmfGroupData;
365 
366 	bzero(&stmfGroupData, sizeof (stmfGroupData));
367 
368 	bcopy(groupName, &stmfGroupData.group.name, strlen((char *)groupName));
369 
370 	stmfGroupData.group.name_size = strlen((char *)groupName);
371 	stmfGroupData.ident[IDENT_LENGTH_BYTE] = devid->identLength;
372 	bcopy(&(devid->ident), &stmfGroupData.ident[IDENT_LENGTH_BYTE + 1],
373 	    devid->identLength);
374 
375 	bzero(&stmfIoctl, sizeof (stmfIoctl));
376 	/*
377 	 * Issue ioctl to add to the host group
378 	 */
379 	stmfIoctl.stmf_version = STMF_VERSION_1;
380 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGroupData);
381 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&stmfGroupData;
382 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
383 	if (ioctlRet != 0) {
384 		switch (errno) {
385 			case EBUSY:
386 				switch (stmfIoctl.stmf_error) {
387 					case STMF_IOCERR_TG_NEED_TG_OFFLINE:
388 						ret = STMF_ERROR_TG_ONLINE;
389 						break;
390 					default:
391 						ret = STMF_ERROR_BUSY;
392 						break;
393 				}
394 				break;
395 			case EPERM:
396 			case EACCES:
397 				ret = STMF_ERROR_PERM;
398 				break;
399 			default:
400 				switch (stmfIoctl.stmf_error) {
401 					case STMF_IOCERR_TG_ENTRY_EXISTS:
402 					case STMF_IOCERR_HG_ENTRY_EXISTS:
403 						ret = STMF_ERROR_EXISTS;
404 						break;
405 					case STMF_IOCERR_INVALID_TG_ENTRY:
406 					case STMF_IOCERR_INVALID_HG_ENTRY:
407 						ret =
408 						    STMF_ERROR_MEMBER_NOT_FOUND;
409 						break;
410 					case STMF_IOCERR_INVALID_TG:
411 					case STMF_IOCERR_INVALID_HG:
412 						ret =
413 						    STMF_ERROR_GROUP_NOT_FOUND;
414 						break;
415 					default:
416 						syslog(LOG_DEBUG,
417 						    "groupMemberIoctl:error"
418 						    "(%d)",
419 						    stmfIoctl.stmf_error);
420 						ret = STMF_STATUS_ERROR;
421 						break;
422 				}
423 				break;
424 		}
425 	}
426 	return (ret);
427 }
428 
429 /*
430  * qsort function
431  * sort on veIndex
432  */
433 static int
viewEntryCompare(const void * p1,const void * p2)434 viewEntryCompare(const void *p1, const void *p2)
435 {
436 
437 	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
438 	if (v1->veIndex > v2->veIndex)
439 		return (1);
440 	if (v1->veIndex < v2->veIndex)
441 		return (-1);
442 	return (0);
443 }
444 
445 /*
446  * guidCompare
447  *
448  * qsort function
449  * sort on guid
450  */
451 static int
guidCompare(const void * p1,const void * p2)452 guidCompare(const void *p1, const void *p2)
453 {
454 
455 	stmfGuid *g1 = (stmfGuid *)p1, *g2 = (stmfGuid *)p2;
456 	int i;
457 
458 	for (i = 0; i < sizeof (stmfGuid); i++) {
459 		if (g1->guid[i] > g2->guid[i])
460 			return (1);
461 		if (g1->guid[i] < g2->guid[i])
462 			return (-1);
463 	}
464 
465 	return (0);
466 }
467 
468 /*
469  * stmfAddToHostGroup
470  *
471  * Purpose: Adds an initiator to an existing host group
472  *
473  * hostGroupName - name of an existing host group
474  * hostName - name of initiator to add
475  */
476 int
stmfAddToHostGroup(stmfGroupName * hostGroupName,stmfDevid * hostName)477 stmfAddToHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
478 {
479 	int ret;
480 	int fd;
481 
482 	if (hostGroupName == NULL ||
483 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
484 	    == sizeof (stmfGroupName)) || hostName == NULL) {
485 		return (STMF_ERROR_INVALID_ARG);
486 	}
487 
488 	/* call init */
489 	ret = initializeConfig();
490 	if (ret != STMF_STATUS_SUCCESS) {
491 		return (ret);
492 	}
493 
494 	/*
495 	 * Open control node for stmf
496 	 */
497 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
498 		return (ret);
499 
500 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY, hostGroupName,
501 	    hostName)) != STMF_STATUS_SUCCESS) {
502 		goto done;
503 	}
504 
505 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
506 		goto done;
507 	}
508 
509 	ret = psAddHostGroupMember((char *)hostGroupName,
510 	    (char *)hostName->ident);
511 	switch (ret) {
512 		case STMF_PS_SUCCESS:
513 			ret = STMF_STATUS_SUCCESS;
514 			break;
515 		case STMF_PS_ERROR_EXISTS:
516 			ret = STMF_ERROR_EXISTS;
517 			break;
518 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
519 			ret = STMF_ERROR_GROUP_NOT_FOUND;
520 			break;
521 		case STMF_PS_ERROR_BUSY:
522 			ret = STMF_ERROR_BUSY;
523 			break;
524 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
525 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
526 			break;
527 		case STMF_PS_ERROR_VERSION_MISMATCH:
528 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
529 			break;
530 		default:
531 			syslog(LOG_DEBUG,
532 			    "stmfAddToHostGroup:psAddHostGroupMember:error(%d)",
533 			    ret);
534 			ret = STMF_STATUS_ERROR;
535 			break;
536 	}
537 
538 done:
539 	(void) close(fd);
540 	return (ret);
541 }
542 
543 /*
544  * stmfAddToTargetGroup
545  *
546  * Purpose: Adds a local port to an existing target group
547  *
548  * targetGroupName - name of an existing target group
549  * targetName - name of target to add
550  */
551 int
stmfAddToTargetGroup(stmfGroupName * targetGroupName,stmfDevid * targetName)552 stmfAddToTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
553 {
554 	int ret;
555 	int fd;
556 
557 	if (targetGroupName == NULL ||
558 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
559 	    == sizeof (stmfGroupName)) || targetName == NULL) {
560 		return (STMF_ERROR_INVALID_ARG);
561 	}
562 
563 	/* call init */
564 	ret = initializeConfig();
565 	if (ret != STMF_STATUS_SUCCESS) {
566 		return (ret);
567 	}
568 
569 	/*
570 	 * Open control node for stmf
571 	 */
572 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
573 		return (ret);
574 
575 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
576 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
577 		goto done;
578 	}
579 
580 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
581 		goto done;
582 	}
583 
584 	ret = psAddTargetGroupMember((char *)targetGroupName,
585 	    (char *)targetName->ident);
586 	switch (ret) {
587 		case STMF_PS_SUCCESS:
588 			ret = STMF_STATUS_SUCCESS;
589 			break;
590 		case STMF_PS_ERROR_EXISTS:
591 			ret = STMF_ERROR_EXISTS;
592 			break;
593 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
594 			ret = STMF_ERROR_GROUP_NOT_FOUND;
595 			break;
596 		case STMF_PS_ERROR_BUSY:
597 			ret = STMF_ERROR_BUSY;
598 			break;
599 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
600 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
601 			break;
602 		case STMF_PS_ERROR_VERSION_MISMATCH:
603 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
604 			break;
605 		default:
606 			syslog(LOG_DEBUG,
607 			    "stmfAddToTargetGroup:psAddTargetGroupMember:"
608 			    "error(%d)", ret);
609 			ret = STMF_STATUS_ERROR;
610 			break;
611 	}
612 
613 done:
614 	(void) close(fd);
615 	return (ret);
616 }
617 
618 /*
619  * addViewEntryIoctl
620  *
621  * Purpose: Issues ioctl to add a view entry
622  *
623  * lu - Logical Unit identifier to which the view entry is added
624  * viewEntry - view entry to add
625  * init - When set to B_TRUE, we are in the init state, i.e. don't call open
626  */
627 static int
addViewEntryIoctl(int fd,stmfGuid * lu,stmfViewEntry * viewEntry)628 addViewEntryIoctl(int fd, stmfGuid *lu, stmfViewEntry *viewEntry)
629 {
630 	int ret = STMF_STATUS_SUCCESS;
631 	int ioctlRet;
632 	stmf_iocdata_t stmfIoctl;
633 	stmf_view_op_entry_t ioctlViewEntry;
634 
635 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
636 	/*
637 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
638 	 * false on input
639 	 */
640 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
641 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
642 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
643 
644 	if (viewEntry->allHosts == B_FALSE) {
645 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
646 		    sizeof (stmfGroupName));
647 		ioctlViewEntry.ve_host_group.name_size =
648 		    strlen((char *)viewEntry->hostGroup);
649 	}
650 	if (viewEntry->allTargets == B_FALSE) {
651 		bcopy(viewEntry->targetGroup,
652 		    &ioctlViewEntry.ve_target_group.name,
653 		    sizeof (stmfGroupName));
654 		ioctlViewEntry.ve_target_group.name_size =
655 		    strlen((char *)viewEntry->targetGroup);
656 	}
657 	if (viewEntry->luNbrValid) {
658 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
659 		    sizeof (ioctlViewEntry.ve_lu_nbr));
660 	}
661 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
662 
663 	bzero(&stmfIoctl, sizeof (stmfIoctl));
664 	/*
665 	 * Issue ioctl to add to the view entry
666 	 */
667 	stmfIoctl.stmf_version = STMF_VERSION_1;
668 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
669 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
670 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
671 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
672 	ioctlRet = ioctl(fd, STMF_IOCTL_ADD_VIEW_ENTRY, &stmfIoctl);
673 	if (ioctlRet != 0) {
674 		switch (errno) {
675 			case EBUSY:
676 				ret = STMF_ERROR_BUSY;
677 				break;
678 			case EPERM:
679 				ret = STMF_ERROR_PERM;
680 				break;
681 			case EACCES:
682 				switch (stmfIoctl.stmf_error) {
683 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
684 						ret = STMF_ERROR_CONFIG_NONE;
685 						break;
686 					default:
687 						ret = STMF_ERROR_PERM;
688 						break;
689 				}
690 				break;
691 			default:
692 				switch (stmfIoctl.stmf_error) {
693 					case STMF_IOCERR_LU_NUMBER_IN_USE:
694 						ret = STMF_ERROR_LUN_IN_USE;
695 						break;
696 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
697 						ret = STMF_ERROR_VE_CONFLICT;
698 						break;
699 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
700 						ret = STMF_ERROR_CONFIG_NONE;
701 						break;
702 					case STMF_IOCERR_INVALID_HG:
703 						ret = STMF_ERROR_INVALID_HG;
704 						break;
705 					case STMF_IOCERR_INVALID_TG:
706 						ret = STMF_ERROR_INVALID_TG;
707 						break;
708 					default:
709 						syslog(LOG_DEBUG,
710 						    "addViewEntryIoctl"
711 						    ":error(%d)",
712 						    stmfIoctl.stmf_error);
713 						ret = STMF_STATUS_ERROR;
714 						break;
715 				}
716 				break;
717 		}
718 		goto done;
719 	}
720 
721 	/* copy lu nbr back to caller's view entry on success */
722 	viewEntry->veIndex = ioctlViewEntry.ve_ndx;
723 	if (ioctlViewEntry.ve_lu_number_valid) {
724 		bcopy(&ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
725 		    sizeof (ioctlViewEntry.ve_lu_nbr));
726 	}
727 	viewEntry->luNbrValid = B_TRUE;
728 
729 done:
730 	return (ret);
731 }
732 
733 /*
734  * stmfAddViewEntry
735  *
736  * Purpose: Adds a view entry to a logical unit
737  *
738  * lu - guid of the logical unit to which the view entry is added
739  * viewEntry - view entry structure to add
740  */
741 int
stmfAddViewEntry(stmfGuid * lu,stmfViewEntry * viewEntry)742 stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry)
743 {
744 	int ret;
745 	int fd;
746 	stmfViewEntry iViewEntry;
747 
748 	if (lu == NULL || viewEntry == NULL) {
749 		return (STMF_ERROR_INVALID_ARG);
750 	}
751 
752 	/* initialize and set internal view entry */
753 	bzero(&iViewEntry, sizeof (iViewEntry));
754 
755 	if (!viewEntry->allHosts) {
756 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
757 		    sizeof (iViewEntry.hostGroup));
758 	} else {
759 		iViewEntry.allHosts = B_TRUE;
760 	}
761 
762 	if (!viewEntry->allTargets) {
763 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
764 		    sizeof (iViewEntry.targetGroup));
765 	} else {
766 		iViewEntry.allTargets = B_TRUE;
767 	}
768 
769 	if (viewEntry->luNbrValid) {
770 		iViewEntry.luNbrValid = B_TRUE;
771 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
772 		    sizeof (iViewEntry.luNbr));
773 	}
774 
775 	/*
776 	 * set users return view entry index valid flag to false
777 	 * in case of failure
778 	 */
779 	viewEntry->veIndexValid = B_FALSE;
780 
781 	/* Check to ensure service exists */
782 	if (psCheckService() != STMF_STATUS_SUCCESS) {
783 		return (STMF_ERROR_SERVICE_NOT_FOUND);
784 	}
785 
786 	/* call init */
787 	ret = initializeConfig();
788 	if (ret != STMF_STATUS_SUCCESS) {
789 		return (ret);
790 	}
791 
792 	/*
793 	 * Open control node for stmf
794 	 */
795 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
796 		return (ret);
797 
798 	/*
799 	 * First add the view entry to the driver
800 	 */
801 	ret = addViewEntryIoctl(fd, lu, &iViewEntry);
802 	if (ret != STMF_STATUS_SUCCESS) {
803 		goto done;
804 	}
805 
806 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
807 		goto done;
808 	}
809 
810 	/*
811 	 * If the add to driver was successful, add it to the persistent
812 	 * store.
813 	 */
814 	ret = psAddViewEntry(lu, &iViewEntry);
815 	switch (ret) {
816 		case STMF_PS_SUCCESS:
817 			ret = STMF_STATUS_SUCCESS;
818 			break;
819 		case STMF_PS_ERROR_NOT_FOUND:
820 			ret = STMF_ERROR_NOT_FOUND;
821 			break;
822 		case STMF_PS_ERROR_BUSY:
823 			ret = STMF_ERROR_BUSY;
824 			break;
825 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
826 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
827 			break;
828 		case STMF_PS_ERROR_VERSION_MISMATCH:
829 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
830 			break;
831 		default:
832 			syslog(LOG_DEBUG,
833 			    "stmfAddViewEntry:psAddViewEntry:error(%d)", ret);
834 			ret = STMF_STATUS_ERROR;
835 			break;
836 	}
837 
838 done:
839 	(void) close(fd);
840 
841 	if (ret == STMF_STATUS_SUCCESS) {
842 		/* set caller's view entry on success */
843 		viewEntry->veIndexValid = iViewEntry.veIndexValid;
844 		viewEntry->veIndex = iViewEntry.veIndex;
845 		viewEntry->luNbrValid = B_TRUE;
846 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
847 		    sizeof (iViewEntry.luNbr));
848 	}
849 	return (ret);
850 }
851 
852 /*
853  * stmfClearProviderData
854  *
855  * Purpose: delete all provider data for specified provider
856  *
857  * providerName - name of provider for which data should be deleted
858  */
859 int
stmfClearProviderData(char * providerName,int providerType)860 stmfClearProviderData(char *providerName, int providerType)
861 {
862 	int ret;
863 	int fd;
864 	int ioctlRet;
865 	int savedErrno;
866 	stmf_iocdata_t stmfIoctl;
867 	stmf_ppioctl_data_t ppi;
868 
869 	/* call init */
870 	ret = initializeConfig();
871 	if (ret != STMF_STATUS_SUCCESS) {
872 		return (ret);
873 	}
874 
875 	if (providerName == NULL) {
876 		return (STMF_ERROR_INVALID_ARG);
877 	}
878 
879 	if (providerType != STMF_LU_PROVIDER_TYPE &&
880 	    providerType != STMF_PORT_PROVIDER_TYPE) {
881 		return (STMF_ERROR_INVALID_ARG);
882 	}
883 
884 	/*
885 	 * Open control node for stmf
886 	 */
887 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
888 		return (ret);
889 
890 	bzero(&ppi, sizeof (ppi));
891 
892 	(void) strncpy(ppi.ppi_name, providerName, sizeof (ppi.ppi_name));
893 
894 	switch (providerType) {
895 		case STMF_LU_PROVIDER_TYPE:
896 			ppi.ppi_lu_provider = 1;
897 			break;
898 		case STMF_PORT_PROVIDER_TYPE:
899 			ppi.ppi_port_provider = 1;
900 			break;
901 		default:
902 			ret = STMF_ERROR_INVALID_ARG;
903 			goto done;
904 	}
905 
906 	bzero(&stmfIoctl, sizeof (stmfIoctl));
907 
908 	stmfIoctl.stmf_version = STMF_VERSION_1;
909 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
910 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
911 
912 	ioctlRet = ioctl(fd, STMF_IOCTL_CLEAR_PP_DATA, &stmfIoctl);
913 	if (ioctlRet != 0) {
914 		savedErrno = errno;
915 		switch (savedErrno) {
916 			case EBUSY:
917 				ret = STMF_ERROR_BUSY;
918 				break;
919 			case EPERM:
920 			case EACCES:
921 				ret = STMF_ERROR_PERM;
922 				break;
923 			default:
924 				syslog(LOG_DEBUG,
925 				    "stmfClearProviderData:ioctl error(%d)",
926 				    ioctlRet);
927 				ret = STMF_STATUS_ERROR;
928 				break;
929 		}
930 		if (savedErrno != ENOENT) {
931 			goto done;
932 		}
933 	}
934 
935 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
936 		goto done;
937 	}
938 
939 	ret = psClearProviderData(providerName, providerType);
940 	switch (ret) {
941 		case STMF_PS_SUCCESS:
942 			ret = STMF_STATUS_SUCCESS;
943 			break;
944 		case STMF_PS_ERROR_NOT_FOUND:
945 			ret = STMF_ERROR_NOT_FOUND;
946 			break;
947 		case STMF_PS_ERROR_BUSY:
948 			ret = STMF_ERROR_BUSY;
949 			break;
950 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
951 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
952 			break;
953 		case STMF_PS_ERROR_VERSION_MISMATCH:
954 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
955 			break;
956 		default:
957 			syslog(LOG_DEBUG,
958 			    "stmfClearProviderData:psClearProviderData"
959 			    ":error(%d)", ret);
960 			ret = STMF_STATUS_ERROR;
961 			break;
962 	}
963 
964 done:
965 	(void) close(fd);
966 	return (ret);
967 }
968 
969 /*
970  * stmfCreateHostGroup
971  *
972  * Purpose: Create a new initiator group
973  *
974  * hostGroupName - name of host group to create
975  */
976 int
stmfCreateHostGroup(stmfGroupName * hostGroupName)977 stmfCreateHostGroup(stmfGroupName *hostGroupName)
978 {
979 	int ret;
980 	int fd;
981 
982 	if (hostGroupName == NULL ||
983 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
984 	    == sizeof (stmfGroupName))) {
985 		return (STMF_ERROR_INVALID_ARG);
986 	}
987 
988 	/* Check to ensure service exists */
989 	if (psCheckService() != STMF_STATUS_SUCCESS) {
990 		return (STMF_ERROR_SERVICE_NOT_FOUND);
991 	}
992 
993 	/* call init */
994 	ret = initializeConfig();
995 	if (ret != STMF_STATUS_SUCCESS) {
996 		return (ret);
997 	}
998 
999 	/*
1000 	 * Open control node for stmf
1001 	 */
1002 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
1003 		return (ret);
1004 
1005 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
1006 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
1007 		goto done;
1008 	}
1009 
1010 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
1011 		goto done;
1012 	}
1013 
1014 	ret = psCreateHostGroup((char *)hostGroupName);
1015 	switch (ret) {
1016 		case STMF_PS_SUCCESS:
1017 			ret = STMF_STATUS_SUCCESS;
1018 			break;
1019 		case STMF_PS_ERROR_EXISTS:
1020 			ret = STMF_ERROR_EXISTS;
1021 			break;
1022 		case STMF_PS_ERROR_BUSY:
1023 			ret = STMF_ERROR_BUSY;
1024 			break;
1025 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
1026 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
1027 			break;
1028 		case STMF_PS_ERROR_VERSION_MISMATCH:
1029 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
1030 			break;
1031 		default:
1032 			syslog(LOG_DEBUG,
1033 			    "stmfCreateHostGroup:psCreateHostGroup:error(%d)",
1034 			    ret);
1035 			ret = STMF_STATUS_ERROR;
1036 			break;
1037 	}
1038 
1039 done:
1040 	(void) close(fd);
1041 	return (ret);
1042 }
1043 
1044 /*
1045  * stmfCreateLu
1046  *
1047  * Purpose: Create a logical unit
1048  *
1049  * hdl - handle to logical unit resource created via stmfCreateLuResource
1050  *
1051  * luGuid - If non-NULL, on success, contains the guid of the created logical
1052  *	    unit
1053  */
1054 int
stmfCreateLu(luResource hdl,stmfGuid * luGuid)1055 stmfCreateLu(luResource hdl, stmfGuid *luGuid)
1056 {
1057 	int ret = STMF_STATUS_SUCCESS;
1058 	luResourceImpl *luPropsHdl = hdl;
1059 
1060 	if (hdl == NULL) {
1061 		return (STMF_ERROR_INVALID_ARG);
1062 	}
1063 
1064 	if (luPropsHdl->type == STMF_DISK) {
1065 		ret = createDiskLu((diskResource *)luPropsHdl->resource,
1066 		    luGuid);
1067 	} else {
1068 		return (STMF_ERROR_INVALID_ARG);
1069 	}
1070 
1071 	return (ret);
1072 }
1073 
1074 /*
1075  * stmfCreateLuResource
1076  *
1077  * Purpose: Create resource handle for a logical unit
1078  *
1079  * dType - Type of logical unit resource to create
1080  *	   Can be: STMF_DISK
1081  *
1082  * hdl - pointer to luResource
1083  */
1084 int
stmfCreateLuResource(uint16_t dType,luResource * hdl)1085 stmfCreateLuResource(uint16_t dType, luResource *hdl)
1086 {
1087 	int ret = STMF_STATUS_SUCCESS;
1088 
1089 	if (dType != STMF_DISK || hdl == NULL) {
1090 		return (STMF_ERROR_INVALID_ARG);
1091 	}
1092 
1093 	*hdl = calloc(1, sizeof (luResourceImpl));
1094 	if (*hdl == NULL) {
1095 		return (STMF_ERROR_NOMEM);
1096 	}
1097 
1098 	ret = createDiskResource((luResourceImpl *)*hdl);
1099 	if (ret != STMF_STATUS_SUCCESS) {
1100 		free(*hdl);
1101 		return (ret);
1102 	}
1103 
1104 	return (STMF_STATUS_SUCCESS);
1105 }
1106 
1107 /*
1108  * Creates a disk logical unit
1109  *
1110  * disk - pointer to diskResource structure that represents the properties
1111  *        for the disk logical unit to be created.
1112  */
1113 static int
createDiskLu(diskResource * disk,stmfGuid * createdGuid)1114 createDiskLu(diskResource *disk, stmfGuid *createdGuid)
1115 {
1116 	int ret = STMF_STATUS_SUCCESS;
1117 	int dataFileNameLen = 0;
1118 	int metaFileNameLen = 0;
1119 	int serialNumLen = 0;
1120 	int luAliasLen = 0;
1121 	int luMgmtUrlLen = 0;
1122 	int sluBufSize = 0;
1123 	int bufOffset = 0;
1124 	int fd = 0;
1125 	int ioctlRet;
1126 	int savedErrno;
1127 	stmfGuid guid;
1128 	stmf_iocdata_t sbdIoctl = {0};
1129 
1130 	sbd_create_and_reg_lu_t *sbdLu = NULL;
1131 
1132 	/*
1133 	 * Open control node for sbd
1134 	 */
1135 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1136 		return (ret);
1137 
1138 	/* data file name must be specified */
1139 	if (disk->luDataFileNameValid) {
1140 		dataFileNameLen = strlen(disk->luDataFileName);
1141 	} else {
1142 		(void) close(fd);
1143 		return (STMF_ERROR_MISSING_PROP_VAL);
1144 	}
1145 
1146 	sluBufSize += dataFileNameLen + 1;
1147 
1148 	if (disk->luMetaFileNameValid) {
1149 		metaFileNameLen = strlen(disk->luMetaFileName);
1150 		sluBufSize += metaFileNameLen + 1;
1151 	}
1152 
1153 	serialNumLen = strlen(disk->serialNum);
1154 	sluBufSize += serialNumLen;
1155 
1156 	if (disk->luAliasValid) {
1157 		luAliasLen = strlen(disk->luAlias);
1158 		sluBufSize += luAliasLen + 1;
1159 	}
1160 
1161 	if (disk->luMgmtUrlValid) {
1162 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
1163 		sluBufSize += luMgmtUrlLen + 1;
1164 	}
1165 
1166 	/*
1167 	 * 8 is the size of the buffer set aside for
1168 	 * concatenation of variable length fields
1169 	 */
1170 	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
1171 	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
1172 	if (sbdLu == NULL) {
1173 		return (STMF_ERROR_NOMEM);
1174 	}
1175 
1176 	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
1177 	    sluBufSize - 8;
1178 
1179 	if (metaFileNameLen) {
1180 		sbdLu->slu_meta_fname_valid = 1;
1181 		sbdLu->slu_meta_fname_off = bufOffset;
1182 		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
1183 		    metaFileNameLen + 1);
1184 		bufOffset += metaFileNameLen + 1;
1185 	}
1186 
1187 	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
1188 	    dataFileNameLen + 1);
1189 	sbdLu->slu_data_fname_off = bufOffset;
1190 	bufOffset += dataFileNameLen + 1;
1191 
1192 	/* currently, serial # is not passed null terminated to the driver */
1193 	if (disk->serialNumValid) {
1194 		sbdLu->slu_serial_valid = 1;
1195 		sbdLu->slu_serial_off = bufOffset;
1196 		sbdLu->slu_serial_size = serialNumLen;
1197 		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
1198 		    serialNumLen);
1199 		bufOffset += serialNumLen;
1200 	}
1201 
1202 	if (disk->luAliasValid) {
1203 		sbdLu->slu_alias_valid = 1;
1204 		sbdLu->slu_alias_off = bufOffset;
1205 		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
1206 		    luAliasLen + 1);
1207 		bufOffset += luAliasLen + 1;
1208 	}
1209 
1210 	if (disk->luMgmtUrlValid) {
1211 		sbdLu->slu_mgmt_url_valid = 1;
1212 		sbdLu->slu_mgmt_url_off = bufOffset;
1213 		bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
1214 		    luMgmtUrlLen + 1);
1215 		bufOffset += luMgmtUrlLen + 1;
1216 	}
1217 
1218 	if (disk->luSizeValid) {
1219 		sbdLu->slu_lu_size_valid = 1;
1220 		sbdLu->slu_lu_size = disk->luSize;
1221 	}
1222 
1223 	if (disk->luGuidValid) {
1224 		sbdLu->slu_guid_valid = 1;
1225 		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
1226 	}
1227 
1228 	if (disk->vidValid) {
1229 		sbdLu->slu_vid_valid = 1;
1230 		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
1231 	}
1232 
1233 	if (disk->pidValid) {
1234 		sbdLu->slu_pid_valid = 1;
1235 		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
1236 	}
1237 
1238 	if (disk->revValid) {
1239 		sbdLu->slu_rev_valid = 1;
1240 		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
1241 	}
1242 
1243 	if (disk->companyIdValid) {
1244 		sbdLu->slu_company_id_valid = 1;
1245 		sbdLu->slu_company_id = disk->companyId;
1246 	}
1247 
1248 	if (disk->hostIdValid) {
1249 		sbdLu->slu_host_id_valid = 1;
1250 		sbdLu->slu_host_id = disk->hostId;
1251 	}
1252 
1253 	if (disk->blkSizeValid) {
1254 		sbdLu->slu_blksize_valid = 1;
1255 		sbdLu->slu_blksize = disk->blkSize;
1256 	}
1257 
1258 	if (disk->writeProtectEnableValid) {
1259 		if (disk->writeProtectEnable) {
1260 			sbdLu->slu_write_protected = 1;
1261 		}
1262 	}
1263 
1264 	if (disk->writebackCacheDisableValid) {
1265 		sbdLu->slu_writeback_cache_disable_valid = 1;
1266 		if (disk->writebackCacheDisable) {
1267 			sbdLu->slu_writeback_cache_disable = 1;
1268 		}
1269 	}
1270 
1271 	sbdIoctl.stmf_version = STMF_VERSION_1;
1272 	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
1273 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1274 	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
1275 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1276 
1277 	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
1278 	if (ioctlRet != 0) {
1279 		savedErrno = errno;
1280 		switch (savedErrno) {
1281 			case EBUSY:
1282 				ret = STMF_ERROR_BUSY;
1283 				break;
1284 			case EPERM:
1285 			case EACCES:
1286 				ret = STMF_ERROR_PERM;
1287 				break;
1288 			default:
1289 				diskError(sbdIoctl.stmf_error, &ret);
1290 				if (ret == STMF_STATUS_ERROR) {
1291 					syslog(LOG_DEBUG,
1292 					"createDiskLu:ioctl "
1293 					"error(%d) (%d) (%d)", ioctlRet,
1294 					    sbdIoctl.stmf_error, savedErrno);
1295 				}
1296 				break;
1297 		}
1298 	}
1299 
1300 	if (ret != STMF_STATUS_SUCCESS) {
1301 		goto done;
1302 	}
1303 
1304 	/*
1305 	 * on success, copy the resulting guid into the caller's guid if not
1306 	 * NULL
1307 	 */
1308 	if (createdGuid) {
1309 		bcopy(sbdLu->slu_guid, createdGuid->guid,
1310 		    sizeof (sbdLu->slu_guid));
1311 	}
1312 
1313 	bcopy(sbdLu->slu_guid, guid.guid, sizeof (sbdLu->slu_guid));
1314 	if (disk->luMetaFileNameValid) {
1315 		ret = addGuidToDiskStore(&guid, disk->luMetaFileName);
1316 	} else {
1317 		ret = addGuidToDiskStore(&guid, disk->luDataFileName);
1318 	}
1319 done:
1320 	free(sbdLu);
1321 	(void) close(fd);
1322 	return (ret);
1323 }
1324 
1325 
1326 /*
1327  * stmfImportLu
1328  *
1329  * Purpose: Import a previously created logical unit
1330  *
1331  * dType - Type of logical unit
1332  *         Can be: STMF_DISK
1333  *
1334  * luGuid - If non-NULL, on success, contains the guid of the imported logical
1335  *	    unit
1336  *
1337  * fname - A file name where the metadata resides
1338  *
1339  */
1340 int
stmfImportLu(uint16_t dType,char * fname,stmfGuid * luGuid)1341 stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid)
1342 {
1343 	int ret = STMF_STATUS_SUCCESS;
1344 
1345 	if (dType == STMF_DISK) {
1346 		ret = importDiskLu(fname, luGuid);
1347 	} else {
1348 		return (STMF_ERROR_INVALID_ARG);
1349 	}
1350 
1351 	return (ret);
1352 }
1353 
1354 /*
1355  * importDiskLu
1356  *
1357  * filename - filename to import
1358  * createdGuid - if not NULL, on success contains the imported guid
1359  *
1360  */
1361 static int
importDiskLu(char * fname,stmfGuid * createdGuid)1362 importDiskLu(char *fname, stmfGuid *createdGuid)
1363 {
1364 	int ret = STMF_STATUS_SUCCESS;
1365 	int fd = 0;
1366 	int ioctlRet;
1367 	int savedErrno;
1368 	int metaFileNameLen;
1369 	stmfGuid iGuid;
1370 	int iluBufSize = 0;
1371 	sbd_import_lu_t *sbdLu = NULL;
1372 	stmf_iocdata_t sbdIoctl = {0};
1373 
1374 	if (fname == NULL) {
1375 		return (STMF_ERROR_INVALID_ARG);
1376 	}
1377 
1378 	/*
1379 	 * Open control node for sbd
1380 	 */
1381 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1382 		return (ret);
1383 
1384 	metaFileNameLen = strlen(fname);
1385 	iluBufSize += metaFileNameLen + 1;
1386 
1387 	/*
1388 	 * 8 is the size of the buffer set aside for
1389 	 * concatenation of variable length fields
1390 	 */
1391 	sbdLu = (sbd_import_lu_t *)calloc(1,
1392 	    sizeof (sbd_import_lu_t) + iluBufSize - 8);
1393 	if (sbdLu == NULL) {
1394 		(void) close(fd);
1395 		return (STMF_ERROR_NOMEM);
1396 	}
1397 
1398 	/*
1399 	 * Accept either a data file or meta data file.
1400 	 * sbd will do the right thing here either way.
1401 	 * i.e. if it's a data file, it assumes that the
1402 	 * meta data is shared with the data.
1403 	 */
1404 	(void) strncpy(sbdLu->ilu_meta_fname, fname, metaFileNameLen);
1405 
1406 	sbdLu->ilu_struct_size = sizeof (sbd_import_lu_t) + iluBufSize - 8;
1407 
1408 	sbdIoctl.stmf_version = STMF_VERSION_1;
1409 	sbdIoctl.stmf_ibuf_size = sbdLu->ilu_struct_size;
1410 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1411 	sbdIoctl.stmf_obuf_size = sbdLu->ilu_struct_size;
1412 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
1413 
1414 	ioctlRet = ioctl(fd, SBD_IOCTL_IMPORT_LU, &sbdIoctl);
1415 	if (ioctlRet != 0) {
1416 
1417 		if (createdGuid && sbdIoctl.stmf_error ==
1418 		    SBD_RET_FILE_ALREADY_REGISTERED) {
1419 			bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
1420 			    sizeof (sbdLu->ilu_ret_guid));
1421 		}
1422 
1423 		savedErrno = errno;
1424 		switch (savedErrno) {
1425 			case EBUSY:
1426 				ret = STMF_ERROR_BUSY;
1427 				break;
1428 			case EPERM:
1429 			case EACCES:
1430 				ret = STMF_ERROR_PERM;
1431 				break;
1432 			default:
1433 				diskError(sbdIoctl.stmf_error, &ret);
1434 				if (ret == STMF_STATUS_ERROR) {
1435 					syslog(LOG_DEBUG,
1436 					"importDiskLu:ioctl "
1437 					"error(%d) (%d) (%d)", ioctlRet,
1438 					    sbdIoctl.stmf_error, savedErrno);
1439 				}
1440 				break;
1441 		}
1442 	}
1443 
1444 
1445 	if (ret != STMF_STATUS_SUCCESS) {
1446 		goto done;
1447 	}
1448 
1449 	/*
1450 	 * on success, copy the resulting guid into the caller's guid if not
1451 	 * NULL and add it to the persistent store for sbd
1452 	 */
1453 	if (createdGuid) {
1454 		bcopy(sbdLu->ilu_ret_guid, createdGuid->guid,
1455 		    sizeof (sbdLu->ilu_ret_guid));
1456 		ret = addGuidToDiskStore(createdGuid, fname);
1457 	} else {
1458 		bcopy(sbdLu->ilu_ret_guid, iGuid.guid,
1459 		    sizeof (sbdLu->ilu_ret_guid));
1460 		ret = addGuidToDiskStore(&iGuid, fname);
1461 	}
1462 done:
1463 	free(sbdLu);
1464 	(void) close(fd);
1465 	return (ret);
1466 }
1467 
1468 /*
1469  * diskError
1470  *
1471  * Purpose: Translate sbd driver error
1472  */
1473 static void
diskError(uint32_t stmfError,int * ret)1474 diskError(uint32_t stmfError, int *ret)
1475 {
1476 	switch (stmfError) {
1477 		case SBD_RET_META_CREATION_FAILED:
1478 		case SBD_RET_ZFS_META_CREATE_FAILED:
1479 			*ret = STMF_ERROR_META_CREATION;
1480 			break;
1481 		case SBD_RET_INVALID_BLKSIZE:
1482 			*ret = STMF_ERROR_INVALID_BLKSIZE;
1483 			break;
1484 		case SBD_RET_FILE_ALREADY_REGISTERED:
1485 			*ret = STMF_ERROR_FILE_IN_USE;
1486 			break;
1487 		case SBD_RET_GUID_ALREADY_REGISTERED:
1488 			*ret = STMF_ERROR_GUID_IN_USE;
1489 			break;
1490 		case SBD_RET_META_PATH_NOT_ABSOLUTE:
1491 		case SBD_RET_META_FILE_LOOKUP_FAILED:
1492 		case SBD_RET_META_FILE_OPEN_FAILED:
1493 		case SBD_RET_META_FILE_GETATTR_FAILED:
1494 		case SBD_RET_NO_META:
1495 			*ret = STMF_ERROR_META_FILE_NAME;
1496 			break;
1497 		case SBD_RET_DATA_PATH_NOT_ABSOLUTE:
1498 		case SBD_RET_DATA_FILE_LOOKUP_FAILED:
1499 		case SBD_RET_DATA_FILE_OPEN_FAILED:
1500 		case SBD_RET_DATA_FILE_GETATTR_FAILED:
1501 			*ret = STMF_ERROR_DATA_FILE_NAME;
1502 			break;
1503 		case SBD_RET_FILE_SIZE_ERROR:
1504 			*ret = STMF_ERROR_FILE_SIZE_INVALID;
1505 			break;
1506 		case SBD_RET_SIZE_OUT_OF_RANGE:
1507 			*ret = STMF_ERROR_SIZE_OUT_OF_RANGE;
1508 			break;
1509 		case SBD_RET_LU_BUSY:
1510 			*ret = STMF_ERROR_LU_BUSY;
1511 			break;
1512 		case SBD_RET_WRITE_CACHE_SET_FAILED:
1513 			*ret = STMF_ERROR_WRITE_CACHE_SET;
1514 			break;
1515 		case SBD_RET_ACCESS_STATE_FAILED:
1516 			*ret = STMF_ERROR_ACCESS_STATE_SET;
1517 			break;
1518 		default:
1519 			*ret = STMF_STATUS_ERROR;
1520 			break;
1521 	}
1522 }
1523 
1524 /*
1525  * Creates a logical unit resource of type STMF_DISK.
1526  *
1527  * No defaults should be set here as all defaults are derived from the
1528  * driver's default settings.
1529  */
1530 static int
createDiskResource(luResourceImpl * hdl)1531 createDiskResource(luResourceImpl *hdl)
1532 {
1533 	hdl->type = STMF_DISK;
1534 
1535 	hdl->resource = calloc(1, sizeof (diskResource));
1536 	if (hdl->resource == NULL) {
1537 		return (STMF_ERROR_NOMEM);
1538 	}
1539 
1540 	return (STMF_STATUS_SUCCESS);
1541 }
1542 
1543 /*
1544  * stmfDeleteLu
1545  *
1546  * Purpose: Delete a logical unit
1547  *
1548  * hdl - handle to logical unit resource created via stmfCreateLuResource
1549  *
1550  * luGuid - If non-NULL, on success, contains the guid of the created logical
1551  *	    unit
1552  */
1553 int
stmfDeleteLu(stmfGuid * luGuid)1554 stmfDeleteLu(stmfGuid *luGuid)
1555 {
1556 	int ret = STMF_STATUS_SUCCESS;
1557 	stmfLogicalUnitProperties luProps;
1558 
1559 	if (luGuid == NULL) {
1560 		return (STMF_ERROR_INVALID_ARG);
1561 	}
1562 
1563 	/* Check logical unit provider name to call correct dtype function */
1564 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1565 	    != STMF_STATUS_SUCCESS) {
1566 		return (ret);
1567 	} else {
1568 		if (strcmp(luProps.providerName, "sbd") == 0) {
1569 			ret = deleteDiskLu(luGuid);
1570 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1571 			return (STMF_ERROR_NOT_FOUND);
1572 		} else {
1573 			return (STMF_ERROR_INVALID_ARG);
1574 		}
1575 	}
1576 
1577 	return (ret);
1578 }
1579 
1580 static int
deleteDiskLu(stmfGuid * luGuid)1581 deleteDiskLu(stmfGuid *luGuid)
1582 {
1583 	int ret = STMF_STATUS_SUCCESS;
1584 	int fd;
1585 	int savedErrno;
1586 	int ioctlRet;
1587 	sbd_delete_lu_t deleteLu = {0};
1588 
1589 	stmf_iocdata_t sbdIoctl = {0};
1590 
1591 	/*
1592 	 * Open control node for sbd
1593 	 */
1594 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1595 		return (ret);
1596 
1597 	ret = removeGuidFromDiskStore(luGuid);
1598 	if (ret != STMF_STATUS_SUCCESS) {
1599 		goto done;
1600 	}
1601 
1602 	bcopy(luGuid, deleteLu.dlu_guid, sizeof (deleteLu.dlu_guid));
1603 	deleteLu.dlu_by_guid = 1;
1604 
1605 	sbdIoctl.stmf_version = STMF_VERSION_1;
1606 	sbdIoctl.stmf_ibuf_size = sizeof (deleteLu);
1607 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&deleteLu;
1608 	ioctlRet = ioctl(fd, SBD_IOCTL_DELETE_LU, &sbdIoctl);
1609 	if (ioctlRet != 0) {
1610 		savedErrno = errno;
1611 		switch (savedErrno) {
1612 			case EBUSY:
1613 				ret = STMF_ERROR_BUSY;
1614 				break;
1615 			case EPERM:
1616 			case EACCES:
1617 				ret = STMF_ERROR_PERM;
1618 				break;
1619 			case ENOENT:
1620 				ret = STMF_ERROR_NOT_FOUND;
1621 				break;
1622 			default:
1623 				syslog(LOG_DEBUG,
1624 				    "deleteDiskLu:ioctl error(%d) (%d) (%d)",
1625 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
1626 				ret = STMF_STATUS_ERROR;
1627 				break;
1628 		}
1629 	}
1630 
1631 done:
1632 	(void) close(fd);
1633 	return (ret);
1634 }
1635 
1636 /*
1637  * stmfLuStandby
1638  *
1639  * Purpose: Sets access state to standby
1640  *
1641  * luGuid - guid of registered logical unit
1642  *
1643  */
1644 int
stmfLuStandby(stmfGuid * luGuid)1645 stmfLuStandby(stmfGuid *luGuid)
1646 {
1647 	int ret = STMF_STATUS_SUCCESS;
1648 	stmfLogicalUnitProperties luProps;
1649 
1650 	if (luGuid == NULL) {
1651 		return (STMF_ERROR_INVALID_ARG);
1652 	}
1653 
1654 	/* Check logical unit provider name to call correct dtype function */
1655 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1656 	    != STMF_STATUS_SUCCESS) {
1657 		return (ret);
1658 	} else {
1659 		if (strcmp(luProps.providerName, "sbd") == 0) {
1660 			ret = setDiskStandby(luGuid);
1661 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1662 			return (STMF_ERROR_NOT_FOUND);
1663 		} else {
1664 			return (STMF_ERROR_INVALID_ARG);
1665 		}
1666 	}
1667 
1668 	return (ret);
1669 }
1670 
1671 static int
setDiskStandby(stmfGuid * luGuid)1672 setDiskStandby(stmfGuid *luGuid)
1673 {
1674 	int ret = STMF_STATUS_SUCCESS;
1675 	stmf_iocdata_t sbdIoctl = {0};
1676 	sbd_set_lu_standby_t sbdLu = {0};
1677 	int ioctlRet;
1678 	int savedErrno;
1679 	int fd = 0;
1680 
1681 	/*
1682 	 * Open control node for sbd
1683 	 */
1684 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1685 		return (ret);
1686 
1687 	bcopy(luGuid, &sbdLu.stlu_guid, sizeof (stmfGuid));
1688 
1689 	sbdIoctl.stmf_version = STMF_VERSION_1;
1690 	sbdIoctl.stmf_ibuf_size = sizeof (sbd_set_lu_standby_t);
1691 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)&sbdLu;
1692 
1693 	ioctlRet = ioctl(fd, SBD_IOCTL_SET_LU_STANDBY, &sbdIoctl);
1694 	if (ioctlRet != 0) {
1695 		savedErrno = errno;
1696 		switch (savedErrno) {
1697 			case EBUSY:
1698 				ret = STMF_ERROR_BUSY;
1699 				break;
1700 			case EPERM:
1701 			case EACCES:
1702 				ret = STMF_ERROR_PERM;
1703 				break;
1704 			default:
1705 				diskError(sbdIoctl.stmf_error, &ret);
1706 				if (ret == STMF_STATUS_ERROR) {
1707 					syslog(LOG_DEBUG,
1708 					"setDiskStandby:ioctl "
1709 					"error(%d) (%d) (%d)", ioctlRet,
1710 					    sbdIoctl.stmf_error, savedErrno);
1711 				}
1712 				break;
1713 		}
1714 	}
1715 	(void) close(fd);
1716 	return (ret);
1717 }
1718 
1719 /*
1720  * stmfModifyLu
1721  *
1722  * Purpose: Modify properties of a logical unit
1723  *
1724  * luGuid - guid of registered logical unit
1725  * prop - property to modify
1726  * propVal - property value to set
1727  *
1728  */
1729 int
stmfModifyLu(stmfGuid * luGuid,uint32_t prop,const char * propVal)1730 stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal)
1731 {
1732 	int ret = STMF_STATUS_SUCCESS;
1733 	stmfLogicalUnitProperties luProps;
1734 
1735 	if (luGuid == NULL) {
1736 		return (STMF_ERROR_INVALID_ARG);
1737 	}
1738 
1739 	/* Check logical unit provider name to call correct dtype function */
1740 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
1741 	    != STMF_STATUS_SUCCESS) {
1742 		return (ret);
1743 	} else {
1744 		if (strcmp(luProps.providerName, "sbd") == 0) {
1745 			ret = modifyDiskLuProp(luGuid, NULL, prop, propVal);
1746 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
1747 			return (STMF_ERROR_NOT_FOUND);
1748 		} else {
1749 			return (STMF_ERROR_INVALID_ARG);
1750 		}
1751 	}
1752 
1753 	return (ret);
1754 }
1755 
1756 /*
1757  * stmfModifyLuByFname
1758  *
1759  * Purpose: Modify a device by filename. Device does not need to be registered.
1760  *
1761  * dType - type of device to modify
1762  *         STMF_DISK
1763  *
1764  * fname - filename or meta filename
1765  * prop - valid property identifier
1766  * propVal - property value
1767  *
1768  */
1769 int
stmfModifyLuByFname(uint16_t dType,const char * fname,uint32_t prop,const char * propVal)1770 stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
1771     const char *propVal)
1772 {
1773 	int ret = STMF_STATUS_SUCCESS;
1774 	if (fname == NULL) {
1775 		return (STMF_ERROR_INVALID_ARG);
1776 	}
1777 
1778 	if (dType == STMF_DISK) {
1779 		ret = modifyDiskLuProp(NULL, fname, prop, propVal);
1780 	} else {
1781 		return (STMF_ERROR_INVALID_ARG);
1782 	}
1783 
1784 	return (ret);
1785 }
1786 
1787 static int
modifyDiskLuProp(stmfGuid * luGuid,const char * fname,uint32_t prop,const char * propVal)1788 modifyDiskLuProp(stmfGuid *luGuid, const char *fname, uint32_t prop,
1789     const char *propVal)
1790 {
1791 	int ret = STMF_STATUS_SUCCESS;
1792 	luResource hdl = NULL;
1793 	luResourceImpl *luPropsHdl;
1794 
1795 	ret = stmfCreateLuResource(STMF_DISK, &hdl);
1796 	if (ret != STMF_STATUS_SUCCESS) {
1797 		return (ret);
1798 	}
1799 	ret = validateModifyDiskProp(prop);
1800 	if (ret != STMF_STATUS_SUCCESS) {
1801 		(void) stmfFreeLuResource(hdl);
1802 		return (STMF_ERROR_INVALID_PROP);
1803 	}
1804 	ret = stmfSetLuProp(hdl, prop, propVal);
1805 	if (ret != STMF_STATUS_SUCCESS) {
1806 		(void) stmfFreeLuResource(hdl);
1807 		return (ret);
1808 	}
1809 	luPropsHdl = hdl;
1810 	ret = modifyDiskLu((diskResource *)luPropsHdl->resource, luGuid, fname);
1811 	(void) stmfFreeLuResource(hdl);
1812 	return (ret);
1813 }
1814 
1815 static int
validateModifyDiskProp(uint32_t prop)1816 validateModifyDiskProp(uint32_t prop)
1817 {
1818 	switch (prop) {
1819 		case STMF_LU_PROP_ALIAS:
1820 		case STMF_LU_PROP_SIZE:
1821 		case STMF_LU_PROP_MGMT_URL:
1822 		case STMF_LU_PROP_WRITE_PROTECT:
1823 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
1824 			return (STMF_STATUS_SUCCESS);
1825 		default:
1826 			return (STMF_STATUS_ERROR);
1827 	}
1828 }
1829 
1830 static int
modifyDiskLu(diskResource * disk,stmfGuid * luGuid,const char * fname)1831 modifyDiskLu(diskResource *disk, stmfGuid *luGuid, const char *fname)
1832 {
1833 	int ret = STMF_STATUS_SUCCESS;
1834 	int luAliasLen = 0;
1835 	int luMgmtUrlLen = 0;
1836 	int mluBufSize = 0;
1837 	int bufOffset = 0;
1838 	int fd = 0;
1839 	int ioctlRet;
1840 	int savedErrno;
1841 	int fnameSize = 0;
1842 	stmf_iocdata_t sbdIoctl = {0};
1843 
1844 	sbd_modify_lu_t *sbdLu = NULL;
1845 
1846 	if (luGuid == NULL && fname == NULL) {
1847 		return (STMF_ERROR_INVALID_ARG);
1848 	}
1849 
1850 	if (fname) {
1851 		fnameSize = strlen(fname) + 1;
1852 		mluBufSize += fnameSize;
1853 	}
1854 
1855 	/*
1856 	 * Open control node for sbd
1857 	 */
1858 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
1859 		return (ret);
1860 
1861 	if (disk->luAliasValid) {
1862 		luAliasLen = strlen(disk->luAlias);
1863 		mluBufSize += luAliasLen + 1;
1864 	}
1865 
1866 	if (disk->luMgmtUrlValid) {
1867 		luMgmtUrlLen = strlen(disk->luMgmtUrl);
1868 		mluBufSize += luMgmtUrlLen + 1;
1869 	}
1870 
1871 	/*
1872 	 * 8 is the size of the buffer set aside for
1873 	 * concatenation of variable length fields
1874 	 */
1875 	sbdLu = (sbd_modify_lu_t *)calloc(1,
1876 	    sizeof (sbd_modify_lu_t) + mluBufSize - 8 + fnameSize);
1877 	if (sbdLu == NULL) {
1878 		(void) close(fd);
1879 		return (STMF_ERROR_NOMEM);
1880 	}
1881 
1882 	sbdLu->mlu_struct_size = sizeof (sbd_modify_lu_t) +
1883 	    mluBufSize - 8 + fnameSize;
1884 
1885 	if (disk->luAliasValid) {
1886 		sbdLu->mlu_alias_valid = 1;
1887 		sbdLu->mlu_alias_off = bufOffset;
1888 		bcopy(disk->luAlias, &(sbdLu->mlu_buf[bufOffset]),
1889 		    luAliasLen + 1);
1890 		bufOffset += luAliasLen + 1;
1891 	}
1892 
1893 	if (disk->luMgmtUrlValid) {
1894 		sbdLu->mlu_mgmt_url_valid = 1;
1895 		sbdLu->mlu_mgmt_url_off = bufOffset;
1896 		bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
1897 		    luMgmtUrlLen + 1);
1898 		bufOffset += luMgmtUrlLen + 1;
1899 	}
1900 
1901 	if (disk->luSizeValid) {
1902 		sbdLu->mlu_lu_size_valid = 1;
1903 		sbdLu->mlu_lu_size = disk->luSize;
1904 	}
1905 
1906 	if (disk->writeProtectEnableValid) {
1907 		sbdLu->mlu_write_protected_valid = 1;
1908 		if (disk->writeProtectEnable) {
1909 			sbdLu->mlu_write_protected = 1;
1910 		}
1911 	}
1912 
1913 	if (disk->writebackCacheDisableValid) {
1914 		sbdLu->mlu_writeback_cache_disable_valid = 1;
1915 		if (disk->writebackCacheDisable) {
1916 			sbdLu->mlu_writeback_cache_disable = 1;
1917 		}
1918 	}
1919 
1920 	if (luGuid) {
1921 		bcopy(luGuid, sbdLu->mlu_input_guid, sizeof (stmfGuid));
1922 		sbdLu->mlu_by_guid = 1;
1923 	} else {
1924 		sbdLu->mlu_fname_off = bufOffset;
1925 		bcopy(fname, &(sbdLu->mlu_buf[bufOffset]), fnameSize + 1);
1926 		sbdLu->mlu_by_fname = 1;
1927 	}
1928 
1929 	sbdIoctl.stmf_version = STMF_VERSION_1;
1930 	sbdIoctl.stmf_ibuf_size = sbdLu->mlu_struct_size;
1931 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
1932 
1933 	ioctlRet = ioctl(fd, SBD_IOCTL_MODIFY_LU, &sbdIoctl);
1934 	if (ioctlRet != 0) {
1935 		savedErrno = errno;
1936 		switch (savedErrno) {
1937 			case EBUSY:
1938 				ret = STMF_ERROR_BUSY;
1939 				break;
1940 			case EPERM:
1941 			case EACCES:
1942 				ret = STMF_ERROR_PERM;
1943 				break;
1944 			default:
1945 				diskError(sbdIoctl.stmf_error, &ret);
1946 				if (ret == STMF_STATUS_ERROR) {
1947 					syslog(LOG_DEBUG,
1948 					"modifyDiskLu:ioctl "
1949 					"error(%d) (%d) (%d)", ioctlRet,
1950 					    sbdIoctl.stmf_error, savedErrno);
1951 				}
1952 				break;
1953 		}
1954 	}
1955 
1956 	if (ret != STMF_STATUS_SUCCESS) {
1957 		goto done;
1958 	}
1959 
1960 done:
1961 	free(sbdLu);
1962 	(void) close(fd);
1963 	return (ret);
1964 }
1965 
1966 /*
1967  * removeGuidFromDiskStore
1968  *
1969  * Purpose: delete a logical unit from the sbd provider data
1970  */
1971 static int
removeGuidFromDiskStore(stmfGuid * guid)1972 removeGuidFromDiskStore(stmfGuid *guid)
1973 {
1974 	return (persistDiskGuid(guid, NULL, B_FALSE));
1975 }
1976 
1977 
1978 /*
1979  * addGuidToDiskStore
1980  *
1981  * Purpose: add a logical unit to the sbd provider data
1982  */
1983 static int
addGuidToDiskStore(stmfGuid * guid,char * filename)1984 addGuidToDiskStore(stmfGuid *guid, char *filename)
1985 {
1986 	return (persistDiskGuid(guid, filename, B_TRUE));
1987 }
1988 
1989 
1990 /*
1991  * persistDiskGuid
1992  *
1993  * Purpose: Persist or unpersist a guid for the sbd provider data
1994  *
1995  */
1996 static int
persistDiskGuid(stmfGuid * guid,char * filename,boolean_t persist)1997 persistDiskGuid(stmfGuid *guid, char *filename, boolean_t persist)
1998 {
1999 	char	    guidAsciiBuf[LU_ASCII_GUID_SIZE + 1] = {0};
2000 	nvlist_t    *nvl = NULL;
2001 
2002 	uint64_t    setToken;
2003 	boolean_t   retryGetProviderData = B_FALSE;
2004 	boolean_t   newData = B_FALSE;
2005 	int	    ret = STMF_STATUS_SUCCESS;
2006 	int	    retryCnt = 0;
2007 	int	    stmfRet;
2008 
2009 	/* if we're persisting a guid, there must be a filename */
2010 	if (persist && !filename) {
2011 		return (1);
2012 	}
2013 
2014 	/* guid is stored in lowercase ascii hex */
2015 	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
2016 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
2017 	    "%02x%02x%02x%02x%02x%02x",
2018 	    guid->guid[0], guid->guid[1], guid->guid[2], guid->guid[3],
2019 	    guid->guid[4], guid->guid[5], guid->guid[6], guid->guid[7],
2020 	    guid->guid[8], guid->guid[9], guid->guid[10], guid->guid[11],
2021 	    guid->guid[12], guid->guid[13], guid->guid[14], guid->guid[15]);
2022 
2023 
2024 	do {
2025 		retryGetProviderData = B_FALSE;
2026 		stmfRet = stmfGetProviderDataProt("sbd", &nvl,
2027 		    STMF_LU_PROVIDER_TYPE, &setToken);
2028 		if (stmfRet != STMF_STATUS_SUCCESS) {
2029 			if (persist && stmfRet == STMF_ERROR_NOT_FOUND) {
2030 				ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
2031 				if (ret != 0) {
2032 					syslog(LOG_DEBUG,
2033 					    "unpersistGuid:nvlist_alloc(%d)",
2034 					    ret);
2035 					ret = STMF_STATUS_ERROR;
2036 					goto done;
2037 				}
2038 				newData = B_TRUE;
2039 			} else {
2040 				/*
2041 				 * if we're persisting the data, it's
2042 				 * an error. Otherwise, just return
2043 				 */
2044 				if (persist) {
2045 					ret = stmfRet;
2046 				}
2047 				goto done;
2048 			}
2049 		}
2050 		if (persist) {
2051 			ret = nvlist_add_string(nvl, guidAsciiBuf, filename);
2052 		} else {
2053 			ret = nvlist_remove(nvl, guidAsciiBuf,
2054 			    DATA_TYPE_STRING);
2055 			if (ret == ENOENT) {
2056 				ret = 0;
2057 			}
2058 		}
2059 		if (ret == 0) {
2060 			if (newData) {
2061 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
2062 				    STMF_LU_PROVIDER_TYPE, NULL);
2063 			} else {
2064 				stmfRet = stmfSetProviderDataProt("sbd", nvl,
2065 				    STMF_LU_PROVIDER_TYPE, &setToken);
2066 			}
2067 			if (stmfRet != STMF_STATUS_SUCCESS) {
2068 				if (stmfRet == STMF_ERROR_BUSY) {
2069 					/* get/set failed, try again */
2070 					retryGetProviderData = B_TRUE;
2071 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
2072 						ret = stmfRet;
2073 						break;
2074 					}
2075 					continue;
2076 				} else if (stmfRet ==
2077 				    STMF_ERROR_PROV_DATA_STALE) {
2078 					/* update failed, try again */
2079 					nvlist_free(nvl);
2080 					nvl = NULL;
2081 					retryGetProviderData = B_TRUE;
2082 					if (retryCnt++ > MAX_PROVIDER_RETRY) {
2083 						ret = stmfRet;
2084 						break;
2085 					}
2086 					continue;
2087 				} else {
2088 					syslog(LOG_DEBUG,
2089 					    "unpersistGuid:error(%x)", stmfRet);
2090 					ret = stmfRet;
2091 				}
2092 				break;
2093 			}
2094 		} else {
2095 			syslog(LOG_DEBUG,
2096 			    "unpersistGuid:error nvlist_add/remove(%d)",
2097 			    ret);
2098 			ret = STMF_STATUS_ERROR;
2099 		}
2100 	} while (retryGetProviderData);
2101 
2102 done:
2103 	nvlist_free(nvl);
2104 	return (ret);
2105 }
2106 
2107 
2108 /*
2109  * stmfGetLuProp
2110  *
2111  * Purpose: Get current value for a resource property
2112  *
2113  * hdl - luResource from a previous call to stmfCreateLuResource
2114  *
2115  * resourceProp - a valid resource property type
2116  *
2117  * propVal - void pointer to a pointer of the value to be retrieved
2118  */
2119 int
stmfGetLuProp(luResource hdl,uint32_t prop,char * propVal,size_t * propLen)2120 stmfGetLuProp(luResource hdl, uint32_t prop, char *propVal, size_t *propLen)
2121 {
2122 	int ret = STMF_STATUS_SUCCESS;
2123 	luResourceImpl *luPropsHdl = hdl;
2124 	if (hdl == NULL || propLen == NULL || propVal == NULL) {
2125 		return (STMF_ERROR_INVALID_ARG);
2126 	}
2127 
2128 	if (luPropsHdl->type == STMF_DISK) {
2129 		ret = getDiskProp(luPropsHdl, prop, propVal, propLen);
2130 	} else {
2131 		return (STMF_ERROR_INVALID_ARG);
2132 	}
2133 
2134 	return (ret);
2135 }
2136 
2137 /*
2138  * stmfGetLuResource
2139  *
2140  * Purpose: Get a logical unit resource handle for a given logical unit.
2141  *
2142  * hdl - pointer to luResource
2143  */
2144 int
stmfGetLuResource(stmfGuid * luGuid,luResource * hdl)2145 stmfGetLuResource(stmfGuid *luGuid, luResource *hdl)
2146 {
2147 	int ret = STMF_STATUS_SUCCESS;
2148 	stmfLogicalUnitProperties luProps;
2149 
2150 	if (hdl == NULL) {
2151 		return (STMF_ERROR_INVALID_ARG);
2152 	}
2153 
2154 	/* Check logical unit provider name to call correct dtype function */
2155 	if ((ret = stmfGetLogicalUnitProperties(luGuid, &luProps))
2156 	    != STMF_STATUS_SUCCESS) {
2157 		return (ret);
2158 	} else {
2159 		if (strcmp(luProps.providerName, "sbd") == 0) {
2160 			ret = getDiskAllProps(luGuid, hdl);
2161 		} else if (luProps.status == STMF_LOGICAL_UNIT_UNREGISTERED) {
2162 			return (STMF_ERROR_NOT_FOUND);
2163 		} else {
2164 			return (STMF_ERROR_INVALID_ARG);
2165 		}
2166 	}
2167 
2168 	return (ret);
2169 }
2170 
2171 /*
2172  * getDiskAllProps
2173  *
2174  * Purpose: load all disk properties from sbd driver
2175  *
2176  * luGuid - guid of disk device for which properties are to be retrieved
2177  * hdl - allocated luResource into which properties are to be copied
2178  *
2179  */
2180 static int
getDiskAllProps(stmfGuid * luGuid,luResource * hdl)2181 getDiskAllProps(stmfGuid *luGuid, luResource *hdl)
2182 {
2183 	int ret = STMF_STATUS_SUCCESS;
2184 	int fd;
2185 	sbd_lu_props_t *sbdProps;
2186 	int ioctlRet;
2187 	int savedErrno;
2188 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
2189 	stmf_iocdata_t sbdIoctl = {0};
2190 
2191 	/*
2192 	 * Open control node for sbd
2193 	 */
2194 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2195 		return (ret);
2196 
2197 
2198 	*hdl = calloc(1, sizeof (luResourceImpl));
2199 	if (*hdl == NULL) {
2200 		(void) close(fd);
2201 		return (STMF_ERROR_NOMEM);
2202 	}
2203 
2204 	sbdProps = calloc(1, sbdPropsSize);
2205 	if (sbdProps == NULL) {
2206 		free(*hdl);
2207 		(void) close(fd);
2208 		return (STMF_ERROR_NOMEM);
2209 	}
2210 
2211 	ret = createDiskResource((luResourceImpl *)*hdl);
2212 	if (ret != STMF_STATUS_SUCCESS) {
2213 		free(*hdl);
2214 		free(sbdProps);
2215 		(void) close(fd);
2216 		return (ret);
2217 	}
2218 
2219 	sbdProps->slp_input_guid = 1;
2220 	bcopy(luGuid, sbdProps->slp_guid, sizeof (sbdProps->slp_guid));
2221 
2222 	sbdIoctl.stmf_version = STMF_VERSION_1;
2223 	sbdIoctl.stmf_ibuf_size = sbdPropsSize;
2224 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdProps;
2225 	sbdIoctl.stmf_obuf_size = sbdPropsSize;
2226 	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
2227 	ioctlRet = ioctl(fd, SBD_IOCTL_GET_LU_PROPS, &sbdIoctl);
2228 	if (ioctlRet != 0) {
2229 		savedErrno = errno;
2230 		switch (savedErrno) {
2231 			case EBUSY:
2232 				ret = STMF_ERROR_BUSY;
2233 				break;
2234 			case EPERM:
2235 			case EACCES:
2236 				ret = STMF_ERROR_PERM;
2237 				break;
2238 			case ENOENT:
2239 				ret = STMF_ERROR_NOT_FOUND;
2240 				break;
2241 			default:
2242 				syslog(LOG_DEBUG,
2243 				    "getDiskAllProps:ioctl error(%d) (%d) (%d)",
2244 				    ioctlRet, sbdIoctl.stmf_error, savedErrno);
2245 				ret = STMF_STATUS_ERROR;
2246 				break;
2247 		}
2248 	}
2249 
2250 	if (ret == STMF_STATUS_SUCCESS) {
2251 		ret = loadDiskPropsFromDriver((luResourceImpl *)*hdl, sbdProps);
2252 	}
2253 
2254 	free(sbdProps);
2255 	(void) close(fd);
2256 	return (ret);
2257 }
2258 
2259 /*
2260  * loadDiskPropsFromDriver
2261  *
2262  * Purpose: Retrieve all disk type properties from sbd driver
2263  *
2264  * hdl - Allocated luResourceImpl
2265  * sbdProps - sbd_lu_props_t structure returned from sbd driver
2266  *
2267  */
2268 static int
loadDiskPropsFromDriver(luResourceImpl * hdl,sbd_lu_props_t * sbdProps)2269 loadDiskPropsFromDriver(luResourceImpl *hdl, sbd_lu_props_t *sbdProps)
2270 {
2271 	int ret = STMF_STATUS_SUCCESS;
2272 	diskResource *diskLu = hdl->resource;
2273 	/* copy guid */
2274 	diskLu->luGuidValid = B_TRUE;
2275 	bcopy(sbdProps->slp_guid, diskLu->luGuid, sizeof (sbdProps->slp_guid));
2276 
2277 	if (sbdProps->slp_separate_meta && sbdProps->slp_meta_fname_valid) {
2278 		diskLu->luMetaFileNameValid = B_TRUE;
2279 		if (strlcpy(diskLu->luMetaFileName,
2280 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_meta_fname_off]),
2281 		    sizeof (diskLu->luMetaFileName)) >=
2282 		    sizeof (diskLu->luMetaFileName)) {
2283 			return (STMF_STATUS_ERROR);
2284 		}
2285 	}
2286 
2287 	if (sbdProps->slp_data_fname_valid) {
2288 		diskLu->luDataFileNameValid = B_TRUE;
2289 		if (strlcpy(diskLu->luDataFileName,
2290 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_data_fname_off]),
2291 		    sizeof (diskLu->luDataFileName)) >=
2292 		    sizeof (diskLu->luDataFileName)) {
2293 			return (STMF_STATUS_ERROR);
2294 		}
2295 	}
2296 
2297 	if (sbdProps->slp_serial_valid) {
2298 		diskLu->serialNumValid = B_TRUE;
2299 		bcopy(&(sbdProps->slp_buf[sbdProps->slp_serial_off]),
2300 		    diskLu->serialNum, sbdProps->slp_serial_size);
2301 	}
2302 
2303 	if (sbdProps->slp_mgmt_url_valid) {
2304 		diskLu->luMgmtUrlValid = B_TRUE;
2305 		if (strlcpy(diskLu->luMgmtUrl,
2306 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
2307 		    sizeof (diskLu->luMgmtUrl)) >=
2308 		    sizeof (diskLu->luMgmtUrl)) {
2309 			return (STMF_STATUS_ERROR);
2310 		}
2311 	}
2312 
2313 	if (sbdProps->slp_alias_valid) {
2314 		diskLu->luAliasValid = B_TRUE;
2315 		if (strlcpy(diskLu->luAlias,
2316 		    (char *)&(sbdProps->slp_buf[sbdProps->slp_alias_off]),
2317 		    sizeof (diskLu->luAlias)) >=
2318 		    sizeof (diskLu->luAlias)) {
2319 			return (STMF_STATUS_ERROR);
2320 		}
2321 	} else { /* set alias to data filename if not set */
2322 		if (sbdProps->slp_data_fname_valid) {
2323 			diskLu->luAliasValid = B_TRUE;
2324 			if (strlcpy(diskLu->luAlias,
2325 			    (char *)&(sbdProps->slp_buf[
2326 			    sbdProps->slp_data_fname_off]),
2327 			    sizeof (diskLu->luAlias)) >=
2328 			    sizeof (diskLu->luAlias)) {
2329 				return (STMF_STATUS_ERROR);
2330 			}
2331 		}
2332 	}
2333 
2334 	diskLu->vidValid = B_TRUE;
2335 	bcopy(sbdProps->slp_vid, diskLu->vid, sizeof (diskLu->vid));
2336 
2337 	diskLu->pidValid = B_TRUE;
2338 	bcopy(sbdProps->slp_pid, diskLu->pid, sizeof (diskLu->pid));
2339 
2340 	diskLu->revValid = B_TRUE;
2341 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
2342 
2343 	diskLu->writeProtectEnableValid = B_TRUE;
2344 	if (sbdProps->slp_write_protected) {
2345 		diskLu->writeProtectEnable = B_TRUE;
2346 	}
2347 
2348 	diskLu->writebackCacheDisableValid = B_TRUE;
2349 	if (sbdProps->slp_writeback_cache_disable_cur) {
2350 		diskLu->writebackCacheDisable = B_TRUE;
2351 	}
2352 
2353 	diskLu->blkSizeValid = B_TRUE;
2354 	diskLu->blkSize = sbdProps->slp_blksize;
2355 
2356 	diskLu->luSizeValid = B_TRUE;
2357 	diskLu->luSize = sbdProps->slp_lu_size;
2358 
2359 	diskLu->accessState = sbdProps->slp_access_state;
2360 
2361 	return (ret);
2362 }
2363 
2364 /*
2365  * stmfGetGlobalLuProp
2366  *
2367  * Purpose: get a global property for a device type
2368  *
2369  */
2370 int
stmfGetGlobalLuProp(uint16_t dType,uint32_t prop,char * propVal,size_t * propLen)2371 stmfGetGlobalLuProp(uint16_t dType, uint32_t prop, char *propVal,
2372     size_t *propLen)
2373 {
2374 	int ret = STMF_STATUS_SUCCESS;
2375 	if (dType != STMF_DISK || propVal == NULL) {
2376 		return (STMF_ERROR_INVALID_ARG);
2377 	}
2378 
2379 	ret = getDiskGlobalProp(prop, propVal, propLen);
2380 
2381 	return (ret);
2382 }
2383 
2384 /*
2385  * getDiskGlobalProp
2386  *
2387  * Purpose: get global property from sbd driver
2388  *
2389  */
2390 static int
getDiskGlobalProp(uint32_t prop,char * propVal,size_t * propLen)2391 getDiskGlobalProp(uint32_t prop, char *propVal, size_t *propLen)
2392 {
2393 	int ret = STMF_STATUS_SUCCESS;
2394 	int fd;
2395 	sbd_global_props_t *sbdProps;
2396 	void *sbd_realloc;
2397 	int retryCnt = 0;
2398 	boolean_t retry;
2399 	int ioctlRet;
2400 	int savedErrno;
2401 	int sbdPropsSize = sizeof (*sbdProps) + MAX_SBD_PROPS;
2402 	stmf_iocdata_t sbdIoctl = {0};
2403 	size_t reqLen;
2404 
2405 	switch (prop) {
2406 		case STMF_LU_PROP_MGMT_URL:
2407 			break;
2408 		default:
2409 			return (STMF_ERROR_INVALID_PROP);
2410 	}
2411 
2412 	/*
2413 	 * Open control node for sbd
2414 	 */
2415 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2416 		return (ret);
2417 
2418 	sbdProps = calloc(1, sbdPropsSize);
2419 	if (sbdProps == NULL) {
2420 		(void) close(fd);
2421 		return (STMF_ERROR_NOMEM);
2422 	}
2423 
2424 	do {
2425 		retry = B_FALSE;
2426 		sbdIoctl.stmf_version = STMF_VERSION_1;
2427 		sbdIoctl.stmf_obuf_size = sbdPropsSize;
2428 		sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdProps;
2429 		ioctlRet = ioctl(fd, SBD_IOCTL_GET_GLOBAL_LU, &sbdIoctl);
2430 		if (ioctlRet != 0) {
2431 			savedErrno = errno;
2432 			switch (savedErrno) {
2433 				case EBUSY:
2434 					ret = STMF_ERROR_BUSY;
2435 					break;
2436 				case EPERM:
2437 				case EACCES:
2438 					ret = STMF_ERROR_PERM;
2439 					break;
2440 				case ENOMEM:
2441 					if (sbdIoctl.stmf_error ==
2442 					    SBD_RET_INSUFFICIENT_BUF_SPACE &&
2443 					    retryCnt++ < 3) {
2444 						sbdPropsSize =
2445 						    sizeof (*sbdProps) +
2446 						    sbdProps->
2447 						    mlu_buf_size_needed;
2448 
2449 						sbd_realloc = sbdProps;
2450 						sbdProps = realloc(sbdProps,
2451 						    sbdPropsSize);
2452 						if (sbdProps == NULL) {
2453 							free(sbd_realloc);
2454 							ret = STMF_ERROR_NOMEM;
2455 							break;
2456 						}
2457 						retry = B_TRUE;
2458 					} else {
2459 						ret = STMF_ERROR_NOMEM;
2460 					}
2461 					break;
2462 				default:
2463 					syslog(LOG_DEBUG,
2464 					    "getDiskGlobalProp:ioctl error(%d)"
2465 					    "(%d)(%d)", ioctlRet,
2466 					    sbdIoctl.stmf_error, savedErrno);
2467 					ret = STMF_STATUS_ERROR;
2468 					break;
2469 			}
2470 
2471 		}
2472 	} while (retry);
2473 
2474 	if (ret != STMF_STATUS_SUCCESS) {
2475 		goto done;
2476 	}
2477 
2478 	switch (prop) {
2479 		case STMF_LU_PROP_MGMT_URL:
2480 			if (sbdProps->mlu_mgmt_url_valid == 0) {
2481 				ret = STMF_ERROR_NO_PROP;
2482 				goto done;
2483 			}
2484 			if ((reqLen = strlcpy(propVal, (char *)&(
2485 			    sbdProps->mlu_buf[sbdProps->mlu_mgmt_url_off]),
2486 			    *propLen)) >= *propLen) {
2487 				*propLen = reqLen + 1;
2488 				ret = STMF_ERROR_INVALID_ARG;
2489 				goto done;
2490 			}
2491 			break;
2492 	}
2493 
2494 done:
2495 	free(sbdProps);
2496 	(void) close(fd);
2497 	return (ret);
2498 }
2499 
2500 /*
2501  * stmfSetGlobalLuProp
2502  *
2503  * Purpose: set a global property for a device type
2504  *
2505  */
2506 int
stmfSetGlobalLuProp(uint16_t dType,uint32_t prop,const char * propVal)2507 stmfSetGlobalLuProp(uint16_t dType, uint32_t prop, const char *propVal)
2508 {
2509 	int ret = STMF_STATUS_SUCCESS;
2510 	if (dType != STMF_DISK || propVal == NULL) {
2511 		return (STMF_ERROR_INVALID_ARG);
2512 	}
2513 
2514 	ret = setDiskGlobalProp(prop, propVal);
2515 
2516 	return (ret);
2517 }
2518 
2519 /*
2520  * setDiskGlobalProp
2521  *
2522  * Purpose: set properties for resource of type disk
2523  *
2524  * resourceProp - valid resource identifier
2525  * propVal - valid resource value
2526  */
2527 static int
setDiskGlobalProp(uint32_t resourceProp,const char * propVal)2528 setDiskGlobalProp(uint32_t resourceProp, const char *propVal)
2529 {
2530 	int ret = STMF_STATUS_SUCCESS;
2531 	sbd_global_props_t *sbdGlobalProps = NULL;
2532 	int sbdGlobalPropsSize = 0;
2533 	int propLen;
2534 	int mluBufSize = 0;
2535 	int fd;
2536 	int savedErrno;
2537 	int ioctlRet;
2538 	stmf_iocdata_t sbdIoctl = {0};
2539 
2540 	switch (resourceProp) {
2541 		case STMF_LU_PROP_MGMT_URL:
2542 			break;
2543 		default:
2544 			return (STMF_ERROR_INVALID_PROP);
2545 	}
2546 
2547 	/*
2548 	 * Open control node for sbd
2549 	 */
2550 	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
2551 		return (ret);
2552 
2553 	propLen = strlen(propVal);
2554 	mluBufSize += propLen + 1;
2555 	sbdGlobalPropsSize += sizeof (sbd_global_props_t) - 8 +
2556 	    max(8, mluBufSize);
2557 	/*
2558 	 * 8 is the size of the buffer set aside for
2559 	 * concatenation of variable length fields
2560 	 */
2561 	sbdGlobalProps = (sbd_global_props_t *)calloc(1, sbdGlobalPropsSize);
2562 	if (sbdGlobalProps == NULL) {
2563 		(void) close(fd);
2564 		return (STMF_ERROR_NOMEM);
2565 	}
2566 
2567 	sbdGlobalProps->mlu_struct_size = sbdGlobalPropsSize;
2568 
2569 	switch (resourceProp) {
2570 		case STMF_LU_PROP_MGMT_URL:
2571 			sbdGlobalProps->mlu_mgmt_url_valid = 1;
2572 			bcopy(propVal, &(sbdGlobalProps->mlu_buf),
2573 			    propLen + 1);
2574 			break;
2575 		default:
2576 			ret = STMF_ERROR_NO_PROP;
2577 			goto done;
2578 	}
2579 
2580 	sbdIoctl.stmf_version = STMF_VERSION_1;
2581 	sbdIoctl.stmf_ibuf_size = sbdGlobalProps->mlu_struct_size;
2582 	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdGlobalProps;
2583 
2584 	ioctlRet = ioctl(fd, SBD_IOCTL_SET_GLOBAL_LU, &sbdIoctl);
2585 	if (ioctlRet != 0) {
2586 		savedErrno = errno;
2587 		switch (savedErrno) {
2588 			case EBUSY:
2589 				ret = STMF_ERROR_BUSY;
2590 				break;
2591 			case EPERM:
2592 			case EACCES:
2593 				ret = STMF_ERROR_PERM;
2594 				break;
2595 			default:
2596 				diskError(sbdIoctl.stmf_error, &ret);
2597 				if (ret == STMF_STATUS_ERROR) {
2598 					syslog(LOG_DEBUG,
2599 					"modifyDiskLu:ioctl "
2600 					"error(%d) (%d) (%d)", ioctlRet,
2601 					    sbdIoctl.stmf_error, savedErrno);
2602 				}
2603 				break;
2604 		}
2605 	}
2606 
2607 done:
2608 	free(sbdGlobalProps);
2609 	(void) close(fd);
2610 	return (ret);
2611 }
2612 
2613 
2614 /*
2615  * stmfSetLuProp
2616  *
2617  * Purpose: set a property on an luResource
2618  *
2619  * hdl - allocated luResource
2620  * prop - property identifier
2621  * propVal - property value to be set
2622  */
2623 int
stmfSetLuProp(luResource hdl,uint32_t prop,const char * propVal)2624 stmfSetLuProp(luResource hdl, uint32_t prop, const char *propVal)
2625 {
2626 	int ret = STMF_STATUS_SUCCESS;
2627 	luResourceImpl *luPropsHdl = hdl;
2628 	if (hdl == NULL) {
2629 		return (STMF_ERROR_INVALID_ARG);
2630 	}
2631 
2632 	if (luPropsHdl->type == STMF_DISK) {
2633 		ret = setDiskProp(luPropsHdl, prop, propVal);
2634 	} else {
2635 		return (STMF_ERROR_INVALID_ARG);
2636 	}
2637 
2638 	return (ret);
2639 }
2640 
2641 /*
2642  * getDiskProp
2643  *
2644  * Purpose: retrieve a given property from a logical unit resource of type disk
2645  *
2646  * hdl - allocated luResourceImpl
2647  * prop - property identifier
2648  * propVal - pointer to character to contain the retrieved property value
2649  * propLen - On input this is the length of propVal. On failure, it contains the
2650  *           number of bytes required for propVal
2651  */
2652 static int
getDiskProp(luResourceImpl * hdl,uint32_t prop,char * propVal,size_t * propLen)2653 getDiskProp(luResourceImpl *hdl, uint32_t prop, char *propVal, size_t *propLen)
2654 {
2655 	int ret = STMF_STATUS_SUCCESS;
2656 	diskResource *diskLu = hdl->resource;
2657 	char accessState[20];
2658 	size_t reqLen;
2659 
2660 	if (prop == STMF_LU_PROP_ACCESS_STATE) {
2661 		if (diskLu->accessState == SBD_LU_ACTIVE) {
2662 			(void) strlcpy(accessState, STMF_ACCESS_ACTIVE,
2663 			    sizeof (accessState));
2664 		} else if (diskLu->accessState == SBD_LU_TRANSITION_TO_ACTIVE) {
2665 			(void) strlcpy(accessState,
2666 			    STMF_ACCESS_STANDBY_TO_ACTIVE,
2667 			    sizeof (accessState));
2668 		} else if (diskLu->accessState == SBD_LU_STANDBY) {
2669 			(void) strlcpy(accessState, STMF_ACCESS_STANDBY,
2670 			    sizeof (accessState));
2671 		} else if (diskLu->accessState ==
2672 		    SBD_LU_TRANSITION_TO_STANDBY) {
2673 			(void) strlcpy(accessState,
2674 			    STMF_ACCESS_ACTIVE_TO_STANDBY,
2675 			    sizeof (accessState));
2676 		}
2677 		if ((reqLen = strlcpy(propVal, accessState,
2678 		    *propLen)) >= *propLen) {
2679 			*propLen = reqLen + 1;
2680 			return (STMF_ERROR_INVALID_ARG);
2681 		}
2682 		return (0);
2683 	}
2684 
2685 	if (diskLu->accessState != SBD_LU_ACTIVE) {
2686 		return (STMF_ERROR_NO_PROP_STANDBY);
2687 	}
2688 
2689 	switch (prop) {
2690 		case STMF_LU_PROP_BLOCK_SIZE:
2691 			if (diskLu->blkSizeValid == B_FALSE) {
2692 				return (STMF_ERROR_NO_PROP);
2693 			}
2694 			reqLen = snprintf(propVal, *propLen, "%llu",
2695 			    (u_longlong_t)diskLu->blkSize);
2696 			if (reqLen >= *propLen) {
2697 				*propLen = reqLen + 1;
2698 				return (STMF_ERROR_INVALID_ARG);
2699 			}
2700 			break;
2701 		case STMF_LU_PROP_FILENAME:
2702 			if (diskLu->luDataFileNameValid == B_FALSE) {
2703 				return (STMF_ERROR_NO_PROP);
2704 			}
2705 			if ((reqLen = strlcpy(propVal, diskLu->luDataFileName,
2706 			    *propLen)) >= *propLen) {
2707 				*propLen = reqLen + 1;
2708 				return (STMF_ERROR_INVALID_ARG);
2709 			}
2710 			break;
2711 		case STMF_LU_PROP_META_FILENAME:
2712 			if (diskLu->luMetaFileNameValid == B_FALSE) {
2713 				return (STMF_ERROR_NO_PROP);
2714 			}
2715 			if ((reqLen = strlcpy(propVal, diskLu->luMetaFileName,
2716 			    *propLen)) >= *propLen) {
2717 				*propLen = reqLen + 1;
2718 				return (STMF_ERROR_INVALID_ARG);
2719 			}
2720 			break;
2721 		case STMF_LU_PROP_MGMT_URL:
2722 			if (diskLu->luMgmtUrlValid == B_FALSE) {
2723 				return (STMF_ERROR_NO_PROP);
2724 			}
2725 			if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
2726 			    *propLen)) >= *propLen) {
2727 				*propLen = reqLen + 1;
2728 				return (STMF_ERROR_INVALID_ARG);
2729 			}
2730 			break;
2731 		case STMF_LU_PROP_GUID:
2732 			if (diskLu->luGuidValid == B_FALSE) {
2733 				return (STMF_ERROR_NO_PROP);
2734 			}
2735 			reqLen = snprintf(propVal, *propLen,
2736 			    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
2737 			    "%02X%02X%02X%02X",
2738 			    diskLu->luGuid[0], diskLu->luGuid[1],
2739 			    diskLu->luGuid[2], diskLu->luGuid[3],
2740 			    diskLu->luGuid[4], diskLu->luGuid[5],
2741 			    diskLu->luGuid[6], diskLu->luGuid[7],
2742 			    diskLu->luGuid[8], diskLu->luGuid[9],
2743 			    diskLu->luGuid[10], diskLu->luGuid[11],
2744 			    diskLu->luGuid[12], diskLu->luGuid[13],
2745 			    diskLu->luGuid[14], diskLu->luGuid[15]);
2746 			if (reqLen >= *propLen) {
2747 				*propLen = reqLen + 1;
2748 				return (STMF_ERROR_INVALID_ARG);
2749 			}
2750 			break;
2751 		case STMF_LU_PROP_SERIAL_NUM:
2752 			if (diskLu->serialNumValid == B_FALSE) {
2753 				return (STMF_ERROR_NO_PROP);
2754 			}
2755 			if ((reqLen = strlcpy(propVal, diskLu->serialNum,
2756 			    *propLen)) >= *propLen) {
2757 				*propLen = reqLen + 1;
2758 				return (STMF_ERROR_INVALID_ARG);
2759 			}
2760 			break;
2761 		case STMF_LU_PROP_SIZE:
2762 			if (diskLu->luSizeValid == B_FALSE) {
2763 				return (STMF_ERROR_NO_PROP);
2764 			}
2765 			(void) snprintf(propVal, *propLen, "%llu",
2766 			    (u_longlong_t)diskLu->luSize);
2767 			break;
2768 		case STMF_LU_PROP_ALIAS:
2769 			if (diskLu->luAliasValid == B_FALSE) {
2770 				return (STMF_ERROR_NO_PROP);
2771 			}
2772 			if ((reqLen = strlcpy(propVal, diskLu->luAlias,
2773 			    *propLen)) >= *propLen) {
2774 				*propLen = reqLen + 1;
2775 				return (STMF_ERROR_INVALID_ARG);
2776 			}
2777 			break;
2778 		case STMF_LU_PROP_VID:
2779 			if (diskLu->vidValid == B_FALSE) {
2780 				return (STMF_ERROR_NO_PROP);
2781 			}
2782 			if (*propLen <= sizeof (diskLu->vid)) {
2783 				return (STMF_ERROR_INVALID_ARG);
2784 			}
2785 			bcopy(diskLu->vid, propVal, sizeof (diskLu->vid));
2786 			propVal[sizeof (diskLu->vid)] = 0;
2787 			break;
2788 		case STMF_LU_PROP_PID:
2789 			if (diskLu->pidValid == B_FALSE) {
2790 				return (STMF_ERROR_NO_PROP);
2791 			}
2792 			if (*propLen <= sizeof (diskLu->pid)) {
2793 				return (STMF_ERROR_INVALID_ARG);
2794 			}
2795 			bcopy(diskLu->pid, propVal, sizeof (diskLu->pid));
2796 			propVal[sizeof (diskLu->pid)] = 0;
2797 			break;
2798 		case STMF_LU_PROP_WRITE_PROTECT:
2799 			if (diskLu->writeProtectEnableValid == B_FALSE) {
2800 				return (STMF_ERROR_NO_PROP);
2801 			}
2802 			if (diskLu->writeProtectEnable) {
2803 				if ((reqLen = strlcpy(propVal, "true",
2804 				    *propLen)) >= *propLen) {
2805 					*propLen = reqLen + 1;
2806 					return (STMF_ERROR_INVALID_ARG);
2807 				}
2808 			} else {
2809 				if ((reqLen = strlcpy(propVal, "false",
2810 				    *propLen)) >= *propLen) {
2811 					*propLen = reqLen + 1;
2812 					return (STMF_ERROR_INVALID_ARG);
2813 				}
2814 			}
2815 			break;
2816 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
2817 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
2818 				return (STMF_ERROR_NO_PROP);
2819 			}
2820 			if (diskLu->writebackCacheDisable) {
2821 				if ((reqLen = strlcpy(propVal, "true",
2822 				    *propLen)) >= *propLen) {
2823 					*propLen = reqLen + 1;
2824 					return (STMF_ERROR_INVALID_ARG);
2825 				}
2826 			} else {
2827 				if ((reqLen = strlcpy(propVal, "false",
2828 				    *propLen)) >= *propLen) {
2829 					*propLen = reqLen + 1;
2830 					return (STMF_ERROR_INVALID_ARG);
2831 				}
2832 			}
2833 			break;
2834 		default:
2835 			ret = STMF_ERROR_INVALID_PROP;
2836 			break;
2837 	}
2838 
2839 	return (ret);
2840 }
2841 
2842 /*
2843  * setDiskProp
2844  *
2845  * Purpose: set properties for resource of type disk
2846  *
2847  * hdl - allocated luResourceImpl
2848  * resourceProp - valid resource identifier
2849  * propVal - valid resource value
2850  */
2851 static int
setDiskProp(luResourceImpl * hdl,uint32_t resourceProp,const char * propVal)2852 setDiskProp(luResourceImpl *hdl, uint32_t resourceProp, const char *propVal)
2853 {
2854 	int ret = STMF_STATUS_SUCCESS;
2855 	int i;
2856 	diskResource *diskLu = hdl->resource;
2857 	unsigned long long numericProp = 0;
2858 	char guidProp[LU_ASCII_GUID_SIZE + 1];
2859 	char ouiProp[OUI_ASCII_SIZE + 1];
2860 	char hostIdProp[HOST_ID_ASCII_SIZE + 1];
2861 	unsigned int oui[OUI_SIZE];
2862 	unsigned int hostId[HOST_ID_SIZE];
2863 	unsigned int guid[LU_GUID_SIZE];
2864 	int propSize;
2865 
2866 
2867 	if (propVal == NULL) {
2868 		return (STMF_ERROR_INVALID_ARG);
2869 	}
2870 
2871 	switch (resourceProp) {
2872 		case STMF_LU_PROP_ALIAS:
2873 			if (strlcpy(diskLu->luAlias, propVal,
2874 			    sizeof (diskLu->luAlias)) >=
2875 			    sizeof (diskLu->luAlias)) {
2876 				return (STMF_ERROR_INVALID_PROPSIZE);
2877 			}
2878 			diskLu->luAliasValid = B_TRUE;
2879 			break;
2880 		case STMF_LU_PROP_BLOCK_SIZE: {
2881 			const char *tmp = propVal;
2882 			while (*tmp) {
2883 				if (!isdigit(*tmp++)) {
2884 					return (STMF_ERROR_INVALID_ARG);
2885 				}
2886 			}
2887 			(void) sscanf(propVal, "%llu", &numericProp);
2888 			if (numericProp > UINT16_MAX) {
2889 				return (STMF_ERROR_INVALID_PROPSIZE);
2890 			}
2891 			diskLu->blkSize = numericProp;
2892 			diskLu->blkSizeValid = B_TRUE;
2893 			break;
2894 		}
2895 		case STMF_LU_PROP_COMPANY_ID:
2896 			if ((strlcpy(ouiProp, propVal, sizeof (ouiProp))) >=
2897 			    sizeof (ouiProp)) {
2898 				return (STMF_ERROR_INVALID_ARG);
2899 			}
2900 			if (checkHexUpper(ouiProp) != 0) {
2901 				return (STMF_ERROR_INVALID_ARG);
2902 			}
2903 			(void) sscanf(ouiProp, "%2X%2X%2X",
2904 			    &oui[0], &oui[1], &oui[2]);
2905 
2906 			diskLu->companyId = 0;
2907 			diskLu->companyId += oui[0] << 16;
2908 			diskLu->companyId += oui[1] << 8;
2909 			diskLu->companyId += oui[2];
2910 			if (diskLu->companyId == 0) {
2911 				return (STMF_ERROR_INVALID_ARG);
2912 			}
2913 			diskLu->companyIdValid = B_TRUE;
2914 			break;
2915 		case STMF_LU_PROP_HOST_ID:
2916 			if ((strlcpy(hostIdProp, propVal,
2917 			    sizeof (hostIdProp))) >= sizeof (hostIdProp)) {
2918 				return (STMF_ERROR_INVALID_ARG);
2919 			}
2920 			if (checkHexUpper(hostIdProp) != 0) {
2921 				return (STMF_ERROR_INVALID_ARG);
2922 			}
2923 			(void) sscanf(hostIdProp, "%2X%2X%2X%2X",
2924 			    &hostId[0], &hostId[1], &hostId[2], &hostId[3]);
2925 
2926 			diskLu->hostId = 0;
2927 			diskLu->hostId += hostId[0] << 24;
2928 			diskLu->hostId += hostId[1] << 16;
2929 			diskLu->hostId += hostId[2] << 8;
2930 			diskLu->hostId += hostId[3];
2931 			if (diskLu->hostId == 0) {
2932 				return (STMF_ERROR_INVALID_ARG);
2933 			}
2934 			diskLu->hostIdValid = B_TRUE;
2935 			break;
2936 		case STMF_LU_PROP_GUID:
2937 			if (strlen(propVal) != LU_ASCII_GUID_SIZE) {
2938 				return (STMF_ERROR_INVALID_PROPSIZE);
2939 			}
2940 
2941 			if ((strlcpy(guidProp, propVal, sizeof (guidProp))) >=
2942 			    sizeof (guidProp)) {
2943 				return (STMF_ERROR_INVALID_ARG);
2944 			}
2945 
2946 			if (checkHexUpper(guidProp) != 0) {
2947 				return (STMF_ERROR_INVALID_ARG);
2948 			}
2949 
2950 			(void) sscanf(guidProp,
2951 			    "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
2952 			    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4],
2953 			    &guid[5], &guid[6], &guid[7], &guid[8], &guid[9],
2954 			    &guid[10], &guid[11], &guid[12], &guid[13],
2955 			    &guid[14], &guid[15]);
2956 			for (i = 0; i < sizeof (diskLu->luGuid); i++) {
2957 				diskLu->luGuid[i] = guid[i];
2958 			}
2959 			diskLu->luGuidValid = B_TRUE;
2960 			break;
2961 		case STMF_LU_PROP_FILENAME:
2962 			if ((strlcpy(diskLu->luDataFileName, propVal,
2963 			    sizeof (diskLu->luDataFileName))) >=
2964 			    sizeof (diskLu->luDataFileName)) {
2965 				return (STMF_ERROR_INVALID_PROPSIZE);
2966 			}
2967 			diskLu->luDataFileNameValid = B_TRUE;
2968 			break;
2969 		case STMF_LU_PROP_META_FILENAME:
2970 			if ((strlcpy(diskLu->luMetaFileName, propVal,
2971 			    sizeof (diskLu->luMetaFileName))) >=
2972 			    sizeof (diskLu->luMetaFileName)) {
2973 				return (STMF_ERROR_INVALID_PROPSIZE);
2974 			}
2975 			diskLu->luMetaFileNameValid = B_TRUE;
2976 			break;
2977 		case STMF_LU_PROP_MGMT_URL:
2978 			if ((strlcpy(diskLu->luMgmtUrl, propVal,
2979 			    sizeof (diskLu->luMgmtUrl))) >=
2980 			    sizeof (diskLu->luMgmtUrl)) {
2981 				return (STMF_ERROR_INVALID_PROPSIZE);
2982 			}
2983 			diskLu->luMgmtUrlValid = B_TRUE;
2984 			break;
2985 		case STMF_LU_PROP_PID:
2986 			if ((propSize = strlen(propVal)) >
2987 			    sizeof (diskLu->pid)) {
2988 				return (STMF_ERROR_INVALID_PROPSIZE);
2989 			}
2990 			(void) strncpy(diskLu->pid, propVal, propSize);
2991 			diskLu->pidValid = B_TRUE;
2992 			break;
2993 		case STMF_LU_PROP_SERIAL_NUM:
2994 			if ((propSize = strlen(propVal)) >
2995 			    (sizeof (diskLu->serialNum) - 1)) {
2996 				return (STMF_ERROR_INVALID_PROPSIZE);
2997 			}
2998 			(void) strncpy(diskLu->serialNum, propVal, propSize);
2999 			diskLu->serialNumValid = B_TRUE;
3000 			break;
3001 		case STMF_LU_PROP_SIZE:
3002 			if ((niceStrToNum(propVal, &diskLu->luSize) != 0)) {
3003 				return (STMF_ERROR_INVALID_ARG);
3004 			}
3005 			diskLu->luSizeValid = B_TRUE;
3006 			break;
3007 		case STMF_LU_PROP_VID:
3008 			if ((propSize = strlen(propVal)) >
3009 			    sizeof (diskLu->vid)) {
3010 				return (STMF_ERROR_INVALID_PROPSIZE);
3011 			}
3012 			(void) strncpy(diskLu->vid, propVal, propSize);
3013 			diskLu->vidValid = B_TRUE;
3014 			break;
3015 		case STMF_LU_PROP_WRITE_PROTECT:
3016 			if (strcasecmp(propVal, "TRUE") == 0) {
3017 				diskLu->writeProtectEnable = B_TRUE;
3018 			} else if (strcasecmp(propVal, "FALSE") == 0) {
3019 				diskLu->writeProtectEnable = B_FALSE;
3020 			} else {
3021 				return (STMF_ERROR_INVALID_ARG);
3022 			}
3023 			diskLu->writeProtectEnableValid = B_TRUE;
3024 			break;
3025 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
3026 			if (strcasecmp(propVal, "TRUE") == 0) {
3027 				diskLu->writebackCacheDisable = B_TRUE;
3028 			} else if (strcasecmp(propVal, "FALSE") == 0) {
3029 				diskLu->writebackCacheDisable = B_FALSE;
3030 			} else {
3031 				return (STMF_ERROR_INVALID_ARG);
3032 			}
3033 			diskLu->writebackCacheDisableValid = B_TRUE;
3034 			break;
3035 		case STMF_LU_PROP_ACCESS_STATE:
3036 			ret = STMF_ERROR_INVALID_PROP;
3037 			break;
3038 		default:
3039 			ret = STMF_ERROR_INVALID_PROP;
3040 			break;
3041 	}
3042 	return (ret);
3043 }
3044 
3045 static int
checkHexUpper(char * buf)3046 checkHexUpper(char *buf)
3047 {
3048 	int i;
3049 
3050 	for (i = 0; i < strlen(buf); i++) {
3051 		if (isxdigit(buf[i])) {
3052 			buf[i] = toupper(buf[i]);
3053 			continue;
3054 		}
3055 		return (-1);
3056 	}
3057 
3058 	return (0);
3059 }
3060 
3061 /*
3062  * Given a numeric suffix, convert the value into a number of bits that the
3063  * resulting value must be shifted.
3064  * Code lifted from libzfs_util.c
3065  */
3066 static int
strToShift(const char * buf)3067 strToShift(const char *buf)
3068 {
3069 	const char *ends = "BKMGTPE";
3070 	int i;
3071 
3072 	if (buf[0] == '\0')
3073 		return (0);
3074 
3075 	for (i = 0; i < strlen(ends); i++) {
3076 		if (toupper(buf[0]) == ends[i])
3077 			return (10*i);
3078 	}
3079 
3080 	return (-1);
3081 }
3082 
3083 int
stmfFreeLuResource(luResource hdl)3084 stmfFreeLuResource(luResource hdl)
3085 {
3086 	int ret = STMF_STATUS_SUCCESS;
3087 	if (hdl == NULL) {
3088 		return (STMF_ERROR_INVALID_ARG);
3089 	}
3090 
3091 	luResourceImpl *hdlImpl = hdl;
3092 	free(hdlImpl->resource);
3093 	free(hdlImpl);
3094 	return (ret);
3095 }
3096 
3097 /*
3098  * Convert a string of the form '100G' into a real number. Used when setting
3099  * the size of a logical unit.
3100  * Code lifted from libzfs_util.c
3101  */
3102 static int
niceStrToNum(const char * value,uint64_t * num)3103 niceStrToNum(const char *value, uint64_t *num)
3104 {
3105 	char *end;
3106 	int shift;
3107 
3108 	*num = 0;
3109 
3110 	/* Check to see if this looks like a number.  */
3111 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
3112 		return (-1);
3113 	}
3114 
3115 	/* Rely on stroull() to process the numeric portion.  */
3116 	errno = 0;
3117 	*num = strtoull(value, &end, 10);
3118 
3119 	/*
3120 	 * Check for ERANGE, which indicates that the value is too large to fit
3121 	 * in a 64-bit value.
3122 	 */
3123 	if (errno == ERANGE) {
3124 		return (-1);
3125 	}
3126 
3127 	/*
3128 	 * If we have a decimal value, then do the computation with floating
3129 	 * point arithmetic.  Otherwise, use standard arithmetic.
3130 	 */
3131 	if (*end == '.') {
3132 		double fval = strtod(value, &end);
3133 
3134 		if ((shift = strToShift(end)) == -1) {
3135 			return (-1);
3136 		}
3137 
3138 		fval *= pow(2, shift);
3139 
3140 		if (fval > UINT64_MAX) {
3141 			return (-1);
3142 		}
3143 
3144 		*num = (uint64_t)fval;
3145 	} else {
3146 		if ((shift = strToShift(end)) == -1) {
3147 			return (-1);
3148 		}
3149 
3150 		/* Check for overflow */
3151 		if (shift >= 64 || (*num << shift) >> shift != *num) {
3152 			return (-1);
3153 		}
3154 
3155 		*num <<= shift;
3156 	}
3157 
3158 	return (0);
3159 }
3160 
3161 /*
3162  * stmfCreateTargetGroup
3163  *
3164  * Purpose: Create a local port group
3165  *
3166  * targetGroupName - name of local port group to create
3167  */
3168 int
stmfCreateTargetGroup(stmfGroupName * targetGroupName)3169 stmfCreateTargetGroup(stmfGroupName *targetGroupName)
3170 {
3171 	int ret;
3172 	int fd;
3173 
3174 	if (targetGroupName == NULL ||
3175 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
3176 	    == sizeof (stmfGroupName))) {
3177 		return (STMF_ERROR_INVALID_ARG);
3178 	}
3179 
3180 	/* Check to ensure service exists */
3181 	if (psCheckService() != STMF_STATUS_SUCCESS) {
3182 		return (STMF_ERROR_SERVICE_NOT_FOUND);
3183 	}
3184 
3185 	/* call init */
3186 	ret = initializeConfig();
3187 	if (ret != STMF_STATUS_SUCCESS) {
3188 		return (ret);
3189 	}
3190 
3191 	/*
3192 	 * Open control node for stmf
3193 	 */
3194 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3195 		return (ret);
3196 
3197 	/*
3198 	 * Add the group to the driver
3199 	 */
3200 	if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
3201 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
3202 		goto done;
3203 	}
3204 
3205 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3206 		goto done;
3207 	}
3208 
3209 	/*
3210 	 * If the add to the driver was successful, add it to the persistent
3211 	 * store.
3212 	 */
3213 	ret = psCreateTargetGroup((char *)targetGroupName);
3214 	switch (ret) {
3215 		case STMF_PS_SUCCESS:
3216 			ret = STMF_STATUS_SUCCESS;
3217 			break;
3218 		case STMF_PS_ERROR_EXISTS:
3219 			ret = STMF_ERROR_EXISTS;
3220 			break;
3221 		case STMF_PS_ERROR_BUSY:
3222 			ret = STMF_ERROR_BUSY;
3223 			break;
3224 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3225 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3226 			break;
3227 		case STMF_PS_ERROR_VERSION_MISMATCH:
3228 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3229 			break;
3230 		default:
3231 			syslog(LOG_DEBUG,
3232 			    "stmfCreateTargetGroup:psCreateTargetGroup"
3233 			    ":error(%d)", ret);
3234 			ret = STMF_STATUS_ERROR;
3235 			break;
3236 	}
3237 
3238 done:
3239 	(void) close(fd);
3240 	return (ret);
3241 }
3242 
3243 /*
3244  * stmfDeleteHostGroup
3245  *
3246  * Purpose: Delete an initiator or local port group
3247  *
3248  * hostGroupName - group to delete
3249  */
3250 int
stmfDeleteHostGroup(stmfGroupName * hostGroupName)3251 stmfDeleteHostGroup(stmfGroupName *hostGroupName)
3252 {
3253 	int ret;
3254 	int fd;
3255 
3256 	if (hostGroupName == NULL) {
3257 		return (STMF_ERROR_INVALID_ARG);
3258 	}
3259 
3260 	/* Check to ensure service exists */
3261 	if (psCheckService() != STMF_STATUS_SUCCESS) {
3262 		return (STMF_ERROR_SERVICE_NOT_FOUND);
3263 	}
3264 
3265 	/* call init */
3266 	ret = initializeConfig();
3267 	if (ret != STMF_STATUS_SUCCESS) {
3268 		return (ret);
3269 	}
3270 
3271 	/*
3272 	 * Open control node for stmf
3273 	 */
3274 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3275 		return (ret);
3276 
3277 	/*
3278 	 * Remove the group from the driver
3279 	 */
3280 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_HOST_GROUP,
3281 	    hostGroupName)) != STMF_STATUS_SUCCESS) {
3282 		goto done;
3283 	}
3284 
3285 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3286 		goto done;
3287 	}
3288 
3289 	/*
3290 	 * If the remove from the driver was successful, remove it from the
3291 	 * persistent store.
3292 	 */
3293 	ret = psDeleteHostGroup((char *)hostGroupName);
3294 	switch (ret) {
3295 		case STMF_PS_SUCCESS:
3296 			ret = STMF_STATUS_SUCCESS;
3297 			break;
3298 		case STMF_PS_ERROR_NOT_FOUND:
3299 			ret = STMF_ERROR_NOT_FOUND;
3300 			break;
3301 		case STMF_PS_ERROR_BUSY:
3302 			ret = STMF_ERROR_BUSY;
3303 			break;
3304 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3305 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3306 			break;
3307 		case STMF_PS_ERROR_VERSION_MISMATCH:
3308 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3309 			break;
3310 		default:
3311 			syslog(LOG_DEBUG,
3312 			    "stmfDeleteHostGroup:psDeleteHostGroup:error(%d)",
3313 			    ret);
3314 			ret = STMF_STATUS_ERROR;
3315 			break;
3316 	}
3317 
3318 done:
3319 	(void) close(fd);
3320 	return (ret);
3321 }
3322 
3323 /*
3324  * stmfDeleteTargetGroup
3325  *
3326  * Purpose: Delete an initiator or local port group
3327  *
3328  * targetGroupName - group to delete
3329  */
3330 int
stmfDeleteTargetGroup(stmfGroupName * targetGroupName)3331 stmfDeleteTargetGroup(stmfGroupName *targetGroupName)
3332 {
3333 	int ret = STMF_STATUS_SUCCESS;
3334 	int fd;
3335 
3336 	if (targetGroupName == NULL) {
3337 		return (STMF_ERROR_INVALID_ARG);
3338 	}
3339 
3340 	/* Check to ensure service exists */
3341 	if (psCheckService() != STMF_STATUS_SUCCESS) {
3342 		return (STMF_ERROR_SERVICE_NOT_FOUND);
3343 	}
3344 
3345 	/* call init */
3346 	ret = initializeConfig();
3347 	if (ret != STMF_STATUS_SUCCESS) {
3348 		return (ret);
3349 	}
3350 
3351 	/*
3352 	 * Open control node for stmf
3353 	 */
3354 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3355 		return (ret);
3356 
3357 	/*
3358 	 * Remove the group from the driver
3359 	 */
3360 	if ((ret = groupIoctl(fd, STMF_IOCTL_REMOVE_TARGET_GROUP,
3361 	    targetGroupName)) != STMF_STATUS_SUCCESS) {
3362 		goto done;
3363 	}
3364 
3365 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
3366 		goto done;
3367 	}
3368 
3369 	/*
3370 	 * If the remove from the driver was successful, remove it from the
3371 	 * persistent store.
3372 	 */
3373 	ret = psDeleteTargetGroup((char *)targetGroupName);
3374 	switch (ret) {
3375 		case STMF_PS_SUCCESS:
3376 			ret = STMF_STATUS_SUCCESS;
3377 			break;
3378 		case STMF_PS_ERROR_NOT_FOUND:
3379 			ret = STMF_ERROR_NOT_FOUND;
3380 			break;
3381 		case STMF_PS_ERROR_BUSY:
3382 			ret = STMF_ERROR_BUSY;
3383 			break;
3384 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3385 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3386 			break;
3387 		case STMF_PS_ERROR_VERSION_MISMATCH:
3388 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3389 			break;
3390 		default:
3391 			syslog(LOG_DEBUG,
3392 			    "stmfDeleteTargetGroup:psDeleteTargetGroup"
3393 			    ":error(%d)", ret);
3394 			ret = STMF_STATUS_ERROR;
3395 			break;
3396 	}
3397 
3398 done:
3399 	(void) close(fd);
3400 	return (ret);
3401 }
3402 
3403 /*
3404  * stmfDevidFromIscsiName
3405  *
3406  * Purpose: convert an iSCSI name to an stmf devid
3407  *
3408  * iscsiName - unicode nul terminated utf-8 encoded iSCSI name
3409  * devid - on success, contains the converted iscsi name
3410  */
3411 int
stmfDevidFromIscsiName(char * iscsiName,stmfDevid * devid)3412 stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid)
3413 {
3414 	if (devid == NULL || iscsiName == NULL)
3415 		return (STMF_ERROR_INVALID_ARG);
3416 
3417 	bzero(devid, sizeof (stmfDevid));
3418 
3419 	/* Validate size of target */
3420 	if ((devid->identLength = strlen(iscsiName)) > MAX_ISCSI_NAME ||
3421 	    devid->identLength < strlen(EUI) ||
3422 	    devid->identLength < strlen(IQN)) {
3423 		return (STMF_ERROR_INVALID_ARG);
3424 	}
3425 
3426 	if ((strncmp(iscsiName, EUI, strlen(EUI)) != 0) &&
3427 	    strncmp(iscsiName, IQN, strlen(IQN)) != 0) {
3428 		return (STMF_ERROR_INVALID_ARG);
3429 	}
3430 
3431 	/* copy UTF-8 bytes to ident */
3432 	bcopy(iscsiName, devid->ident, devid->identLength);
3433 
3434 	return (STMF_STATUS_SUCCESS);
3435 }
3436 
3437 /*
3438  * stmfDevidFromWwn
3439  *
3440  * Purpose: convert a WWN to an stmf devid
3441  *
3442  * wwn - 8-byte wwn identifier
3443  * devid - on success, contains the converted wwn
3444  */
3445 int
stmfDevidFromWwn(uchar_t wwn[8],stmfDevid * devid)3446 stmfDevidFromWwn(uchar_t wwn[8], stmfDevid *devid)
3447 {
3448 	if (wwn == NULL || devid == NULL)
3449 		return (STMF_ERROR_INVALID_ARG);
3450 
3451 	bzero(devid, sizeof (stmfDevid));
3452 
3453 	/* Copy eui prefix */
3454 	(void) bcopy(WWN, devid->ident, strlen(WWN));
3455 
3456 	/* Convert to ASCII uppercase hexadecimal string */
3457 	(void) snprintf((char *)&devid->ident[strlen(WWN)],
3458 	    sizeof (devid->ident), "%02X%02X%02X%02X%02X%02X%02X%02X",
3459 	    wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
3460 
3461 	devid->identLength = strlen((char *)devid->ident);
3462 
3463 	return (STMF_STATUS_SUCCESS);
3464 }
3465 
3466 /*
3467  * stmfFreeMemory
3468  *
3469  * Purpose: Free memory allocated by this library
3470  *
3471  * memory - previously allocated pointer of memory managed by library
3472  */
3473 void
stmfFreeMemory(void * memory)3474 stmfFreeMemory(void *memory)
3475 {
3476 	free(memory);
3477 }
3478 
3479 /*
3480  * get host group, target group list from stmf
3481  *
3482  * groupType - HOST_GROUP, TARGET_GROUP
3483  */
3484 static int
groupListIoctl(stmfGroupList ** groupList,int groupType)3485 groupListIoctl(stmfGroupList **groupList, int groupType)
3486 {
3487 	int ret;
3488 	int fd;
3489 	int ioctlRet;
3490 	int i;
3491 	int cmd;
3492 	stmf_iocdata_t stmfIoctl;
3493 	/* framework group list */
3494 	stmf_group_name_t *iGroupList = NULL;
3495 	uint32_t groupListSize;
3496 
3497 	if (groupList == NULL) {
3498 		return (STMF_ERROR_INVALID_ARG);
3499 	}
3500 
3501 	if (groupType == HOST_GROUP) {
3502 		cmd = STMF_IOCTL_GET_HG_LIST;
3503 	} else if (groupType == TARGET_GROUP) {
3504 		cmd = STMF_IOCTL_GET_TG_LIST;
3505 	} else {
3506 		return (STMF_ERROR_INVALID_ARG);
3507 	}
3508 
3509 	/* call init */
3510 	ret = initializeConfig();
3511 	if (ret != STMF_STATUS_SUCCESS) {
3512 		return (ret);
3513 	}
3514 
3515 	/*
3516 	 * Open control node for stmf
3517 	 */
3518 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3519 		return (ret);
3520 
3521 	/*
3522 	 * Allocate ioctl input buffer
3523 	 */
3524 	groupListSize = ALLOC_GROUP;
3525 	groupListSize = groupListSize * (sizeof (stmf_group_name_t));
3526 	iGroupList = (stmf_group_name_t *)calloc(1, groupListSize);
3527 	if (iGroupList == NULL) {
3528 		ret = STMF_ERROR_NOMEM;
3529 		goto done;
3530 	}
3531 
3532 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3533 	/*
3534 	 * Issue ioctl to get the group list
3535 	 */
3536 	stmfIoctl.stmf_version = STMF_VERSION_1;
3537 	stmfIoctl.stmf_obuf_size = groupListSize;
3538 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3539 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3540 	if (ioctlRet != 0) {
3541 		switch (errno) {
3542 			case EBUSY:
3543 				ret = STMF_ERROR_BUSY;
3544 				break;
3545 			case EPERM:
3546 			case EACCES:
3547 				ret = STMF_ERROR_PERM;
3548 				break;
3549 			default:
3550 				syslog(LOG_DEBUG,
3551 				    "groupListIoctl:ioctl errno(%d)",
3552 				    errno);
3553 				ret = STMF_STATUS_ERROR;
3554 				break;
3555 		}
3556 		goto done;
3557 	}
3558 	/*
3559 	 * Check whether input buffer was large enough
3560 	 */
3561 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GROUP) {
3562 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3563 		    sizeof (stmf_group_name_t);
3564 		iGroupList = realloc(iGroupList, groupListSize);
3565 		if (iGroupList == NULL) {
3566 			ret = STMF_ERROR_NOMEM;
3567 			goto done;
3568 		}
3569 		stmfIoctl.stmf_obuf_size = groupListSize;
3570 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupList;
3571 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3572 		if (ioctlRet != 0) {
3573 			switch (errno) {
3574 				case EBUSY:
3575 					ret = STMF_ERROR_BUSY;
3576 					break;
3577 				case EPERM:
3578 				case EACCES:
3579 					ret = STMF_ERROR_PERM;
3580 					break;
3581 				default:
3582 					syslog(LOG_DEBUG,
3583 					    "groupListIoctl:ioctl errno(%d)",
3584 					    errno);
3585 					ret = STMF_STATUS_ERROR;
3586 					break;
3587 			}
3588 			goto done;
3589 		}
3590 	}
3591 
3592 	/* allocate and copy to caller's buffer */
3593 	*groupList = (stmfGroupList *)calloc(1, sizeof (stmfGroupList) +
3594 	    sizeof (stmfGroupName) * stmfIoctl.stmf_obuf_nentries);
3595 	if (*groupList == NULL) {
3596 		ret = STMF_ERROR_NOMEM;
3597 		goto done;
3598 	}
3599 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
3600 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3601 		bcopy(iGroupList[i].name, (*groupList)->name[i],
3602 		    sizeof (stmfGroupName));
3603 	}
3604 
3605 done:
3606 	free(iGroupList);
3607 	(void) close(fd);
3608 	return (ret);
3609 }
3610 
3611 /*
3612  * get host group members, target group members from stmf
3613  *
3614  * groupProps - allocated on success
3615  *
3616  * groupType - HOST_GROUP, TARGET_GROUP
3617  */
3618 static int
groupMemberListIoctl(stmfGroupName * groupName,stmfGroupProperties ** groupProps,int groupType)3619 groupMemberListIoctl(stmfGroupName *groupName, stmfGroupProperties **groupProps,
3620     int groupType)
3621 {
3622 	int ret;
3623 	int fd;
3624 	int ioctlRet;
3625 	int i;
3626 	int cmd;
3627 	stmf_iocdata_t stmfIoctl;
3628 	/* framework group list */
3629 	stmf_group_name_t iGroupName;
3630 	stmf_ge_ident_t *iGroupMembers;
3631 	uint32_t groupListSize;
3632 
3633 	if (groupName == NULL) {
3634 		return (STMF_ERROR_INVALID_ARG);
3635 	}
3636 
3637 	if (groupType == HOST_GROUP) {
3638 		cmd = STMF_IOCTL_GET_HG_ENTRIES;
3639 	} else if (groupType == TARGET_GROUP) {
3640 		cmd = STMF_IOCTL_GET_TG_ENTRIES;
3641 	} else {
3642 		return (STMF_ERROR_INVALID_ARG);
3643 	}
3644 
3645 	/* call init */
3646 	ret = initializeConfig();
3647 	if (ret != STMF_STATUS_SUCCESS) {
3648 		return (ret);
3649 	}
3650 
3651 	/*
3652 	 * Open control node for stmf
3653 	 */
3654 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
3655 		return (ret);
3656 
3657 	bzero(&iGroupName, sizeof (iGroupName));
3658 
3659 	bcopy(groupName, &iGroupName.name, strlen((char *)groupName));
3660 
3661 	iGroupName.name_size = strlen((char *)groupName);
3662 
3663 	/*
3664 	 * Allocate ioctl input buffer
3665 	 */
3666 	groupListSize = ALLOC_GRP_MEMBER;
3667 	groupListSize = groupListSize * (sizeof (stmf_ge_ident_t));
3668 	iGroupMembers = (stmf_ge_ident_t *)calloc(1, groupListSize);
3669 	if (iGroupMembers == NULL) {
3670 		ret = STMF_ERROR_NOMEM;
3671 		goto done;
3672 	}
3673 
3674 	bzero(&stmfIoctl, sizeof (stmfIoctl));
3675 	/*
3676 	 * Issue ioctl to get the group list
3677 	 */
3678 	stmfIoctl.stmf_version = STMF_VERSION_1;
3679 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3680 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3681 	stmfIoctl.stmf_obuf_size = groupListSize;
3682 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3683 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3684 	if (ioctlRet != 0) {
3685 		switch (errno) {
3686 			case EBUSY:
3687 				ret = STMF_ERROR_BUSY;
3688 				break;
3689 			case EPERM:
3690 			case EACCES:
3691 				ret = STMF_ERROR_PERM;
3692 				break;
3693 			default:
3694 				syslog(LOG_DEBUG,
3695 				    "groupListIoctl:ioctl errno(%d)",
3696 				    errno);
3697 				ret = STMF_STATUS_ERROR;
3698 				break;
3699 		}
3700 		goto done;
3701 	}
3702 	/*
3703 	 * Check whether input buffer was large enough
3704 	 */
3705 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_GRP_MEMBER) {
3706 		groupListSize = stmfIoctl.stmf_obuf_max_nentries *
3707 		    sizeof (stmf_ge_ident_t);
3708 		iGroupMembers = realloc(iGroupMembers, groupListSize);
3709 		if (iGroupMembers == NULL) {
3710 			ret = STMF_ERROR_NOMEM;
3711 			goto done;
3712 		}
3713 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&iGroupName;
3714 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_group_name_t);
3715 		stmfIoctl.stmf_obuf_size = groupListSize;
3716 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)iGroupMembers;
3717 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
3718 		if (ioctlRet != 0) {
3719 			switch (errno) {
3720 				case EBUSY:
3721 					ret = STMF_ERROR_BUSY;
3722 					break;
3723 				case EPERM:
3724 				case EACCES:
3725 					ret = STMF_ERROR_PERM;
3726 					break;
3727 				default:
3728 					syslog(LOG_DEBUG,
3729 					    "groupListIoctl:ioctl errno(%d)",
3730 					    errno);
3731 					ret = STMF_STATUS_ERROR;
3732 					break;
3733 			}
3734 			goto done;
3735 		}
3736 	}
3737 
3738 	/* allocate and copy to caller's buffer */
3739 	*groupProps = (stmfGroupProperties *)calloc(1,
3740 	    sizeof (stmfGroupProperties) +
3741 	    sizeof (stmfDevid) * stmfIoctl.stmf_obuf_nentries);
3742 	if (*groupProps == NULL) {
3743 		ret = STMF_ERROR_NOMEM;
3744 		goto done;
3745 	}
3746 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
3747 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
3748 		(*groupProps)->name[i].identLength =
3749 		    iGroupMembers[i].ident_size;
3750 		bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
3751 		    iGroupMembers[i].ident_size);
3752 	}
3753 
3754 done:
3755 	free(iGroupMembers);
3756 	(void) close(fd);
3757 	return (ret);
3758 }
3759 
3760 /*
3761  * Purpose: access persistent config data for host groups and target groups
3762  */
3763 static int
iLoadGroupFromPs(stmfGroupList ** groupList,int type)3764 iLoadGroupFromPs(stmfGroupList **groupList, int type)
3765 {
3766 	int ret;
3767 
3768 	if (groupList == NULL) {
3769 		return (STMF_ERROR_INVALID_ARG);
3770 	}
3771 
3772 	if (type == HOST_GROUP) {
3773 		ret = psGetHostGroupList(groupList);
3774 	} else if (type == TARGET_GROUP) {
3775 		ret = psGetTargetGroupList(groupList);
3776 	} else {
3777 		return (STMF_ERROR_INVALID_ARG);
3778 	}
3779 	switch (ret) {
3780 		case STMF_PS_SUCCESS:
3781 			ret = STMF_STATUS_SUCCESS;
3782 			break;
3783 		case STMF_PS_ERROR_NOT_FOUND:
3784 			ret = STMF_ERROR_NOT_FOUND;
3785 			break;
3786 		case STMF_PS_ERROR_BUSY:
3787 			ret = STMF_ERROR_BUSY;
3788 			break;
3789 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3790 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3791 			break;
3792 		case STMF_PS_ERROR_VERSION_MISMATCH:
3793 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3794 			break;
3795 		default:
3796 			syslog(LOG_DEBUG,
3797 			    "stmfGetHostGroupList:psGetHostGroupList:error(%d)",
3798 			    ret);
3799 			ret = STMF_STATUS_ERROR;
3800 			break;
3801 	}
3802 
3803 	return (ret);
3804 }
3805 
3806 /*
3807  * stmfGetHostGroupList
3808  *
3809  * Purpose: Retrieves the list of initiator group oids
3810  *
3811  * hostGroupList - pointer to pointer to hostGroupList structure
3812  *                 on success, this contains the host group list.
3813  */
3814 int
stmfGetHostGroupList(stmfGroupList ** hostGroupList)3815 stmfGetHostGroupList(stmfGroupList **hostGroupList)
3816 {
3817 	int ret = STMF_STATUS_ERROR;
3818 
3819 	if (hostGroupList == NULL) {
3820 		return (STMF_ERROR_INVALID_ARG);
3821 	}
3822 
3823 	ret = groupListIoctl(hostGroupList, HOST_GROUP);
3824 	return (ret);
3825 }
3826 
3827 
3828 /*
3829  * Purpose: access persistent config data for host groups and target groups
3830  */
3831 static int
iLoadGroupMembersFromPs(stmfGroupName * groupName,stmfGroupProperties ** groupProp,int type)3832 iLoadGroupMembersFromPs(stmfGroupName *groupName,
3833     stmfGroupProperties **groupProp, int type)
3834 {
3835 	int ret;
3836 
3837 	if (groupName == NULL) {
3838 		return (STMF_ERROR_INVALID_ARG);
3839 	}
3840 
3841 	if (type == HOST_GROUP) {
3842 		ret = psGetHostGroupMemberList((char *)groupName, groupProp);
3843 	} else if (type == TARGET_GROUP) {
3844 		ret = psGetTargetGroupMemberList((char *)groupName, groupProp);
3845 	} else {
3846 		return (STMF_ERROR_INVALID_ARG);
3847 	}
3848 	switch (ret) {
3849 		case STMF_PS_SUCCESS:
3850 			ret = STMF_STATUS_SUCCESS;
3851 			break;
3852 		case STMF_PS_ERROR_NOT_FOUND:
3853 			ret = STMF_ERROR_NOT_FOUND;
3854 			break;
3855 		case STMF_PS_ERROR_BUSY:
3856 			ret = STMF_ERROR_BUSY;
3857 			break;
3858 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3859 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3860 			break;
3861 		case STMF_PS_ERROR_VERSION_MISMATCH:
3862 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3863 			break;
3864 		default:
3865 			syslog(LOG_DEBUG,
3866 			    "iLoadGroupMembersFromPs:psGetHostGroupList:"
3867 			    "error(%d)", ret);
3868 			ret = STMF_STATUS_ERROR;
3869 			break;
3870 	}
3871 
3872 	return (ret);
3873 }
3874 
3875 /*
3876  * stmfGetHostGroupMembers
3877  *
3878  * Purpose: Retrieves the group properties for a host group
3879  *
3880  * groupName - name of group for which to retrieve host group members.
3881  * groupProp - pointer to pointer to stmfGroupProperties structure
3882  *             on success, this contains the list of group members.
3883  */
3884 int
stmfGetHostGroupMembers(stmfGroupName * groupName,stmfGroupProperties ** groupProp)3885 stmfGetHostGroupMembers(stmfGroupName *groupName,
3886     stmfGroupProperties **groupProp)
3887 {
3888 	int ret;
3889 
3890 	if (groupName == NULL || groupProp == NULL) {
3891 		return (STMF_ERROR_INVALID_ARG);
3892 	}
3893 
3894 	ret = groupMemberListIoctl(groupName, groupProp, HOST_GROUP);
3895 
3896 	return (ret);
3897 }
3898 
3899 /*
3900  * stmfGetProviderData
3901  *
3902  * Purpose: Get provider data list
3903  *
3904  * providerName - name of provider for which to retrieve the data
3905  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3906  *       retrieved.
3907  * providerType - type of provider for which to retrieve data.
3908  *		    STMF_LU_PROVIDER_TYPE
3909  *		    STMF_PORT_PROVIDER_TYPE
3910  */
3911 int
stmfGetProviderData(char * providerName,nvlist_t ** nvl,int providerType)3912 stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType)
3913 {
3914 	return (stmfGetProviderDataProt(providerName, nvl, providerType,
3915 	    NULL));
3916 }
3917 
3918 /*
3919  * stmfGetProviderDataProt
3920  *
3921  * Purpose: Get provider data list with token
3922  *
3923  * providerName - name of provider for which to retrieve the data
3924  * nvl - pointer to nvlist_t pointer which will contain the nvlist data
3925  *       retrieved.
3926  * providerType - type of provider for which to retrieve data.
3927  *		    STMF_LU_PROVIDER_TYPE
3928  *		    STMF_PORT_PROVIDER_TYPE
3929  * setToken - Returns the stale data token
3930  */
3931 int
stmfGetProviderDataProt(char * providerName,nvlist_t ** nvl,int providerType,uint64_t * setToken)3932 stmfGetProviderDataProt(char *providerName, nvlist_t **nvl, int providerType,
3933     uint64_t *setToken)
3934 {
3935 	int ret;
3936 
3937 	if (providerName == NULL || nvl == NULL) {
3938 		return (STMF_ERROR_INVALID_ARG);
3939 	}
3940 	if (providerType != STMF_LU_PROVIDER_TYPE &&
3941 	    providerType != STMF_PORT_PROVIDER_TYPE) {
3942 		return (STMF_ERROR_INVALID_ARG);
3943 	}
3944 	/* call init */
3945 	ret = initializeConfig();
3946 	if (ret != STMF_STATUS_SUCCESS) {
3947 		return (ret);
3948 	}
3949 	return (getProviderData(providerName, nvl, providerType, setToken));
3950 }
3951 
3952 /*
3953  * stmfGetProviderDataList
3954  *
3955  * Purpose: Get the list of providers currently persisting data
3956  *
3957  * providerList - pointer to pointer to an stmfProviderList structure allocated
3958  *                by the caller. Will contain the list of providers on success.
3959  */
3960 int
stmfGetProviderDataList(stmfProviderList ** providerList)3961 stmfGetProviderDataList(stmfProviderList **providerList)
3962 {
3963 	int ret;
3964 
3965 	ret = psGetProviderDataList(providerList);
3966 	switch (ret) {
3967 		case STMF_PS_SUCCESS:
3968 			ret = STMF_STATUS_SUCCESS;
3969 			break;
3970 		case STMF_PS_ERROR_BUSY:
3971 			ret = STMF_ERROR_BUSY;
3972 			break;
3973 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
3974 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
3975 			break;
3976 		case STMF_PS_ERROR_VERSION_MISMATCH:
3977 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
3978 			break;
3979 		default:
3980 			syslog(LOG_DEBUG,
3981 			    "stmfGetProviderDataList:psGetProviderDataList"
3982 			    ":error(%d)", ret);
3983 			ret = STMF_STATUS_ERROR;
3984 			break;
3985 	}
3986 
3987 	return (ret);
3988 }
3989 
3990 
3991 /*
3992  * stmfGetSessionList
3993  *
3994  * Purpose: Retrieves the session list for a target (devid)
3995  *
3996  * devid - devid of target for which to retrieve session information.
3997  * sessionList - pointer to pointer to stmfSessionList structure
3998  *             on success, this contains the list of initiator sessions.
3999  */
4000 int
stmfGetSessionList(stmfDevid * devid,stmfSessionList ** sessionList)4001 stmfGetSessionList(stmfDevid *devid, stmfSessionList **sessionList)
4002 {
4003 	int ret = STMF_STATUS_SUCCESS;
4004 	int fd;
4005 	int ioctlRet;
4006 	int cmd = STMF_IOCTL_SESSION_LIST;
4007 	int i;
4008 	stmf_iocdata_t stmfIoctl;
4009 	slist_scsi_session_t *fSessionList, *fSessionListP = NULL;
4010 	uint8_t ident[260];
4011 	uint32_t fSessionListSize;
4012 
4013 	if (sessionList == NULL || devid == NULL) {
4014 		ret = STMF_ERROR_INVALID_ARG;
4015 	}
4016 
4017 	/* call init */
4018 	ret = initializeConfig();
4019 	if (ret != STMF_STATUS_SUCCESS) {
4020 		return (ret);
4021 	}
4022 
4023 	/*
4024 	 * Open control node for stmf
4025 	 */
4026 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4027 		return (ret);
4028 
4029 	/*
4030 	 * Allocate ioctl input buffer
4031 	 */
4032 	fSessionListSize = ALLOC_SESSION;
4033 	fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t));
4034 	fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize);
4035 	fSessionListP = fSessionList;
4036 	if (fSessionList == NULL) {
4037 		ret = STMF_ERROR_NOMEM;
4038 		goto done;
4039 	}
4040 
4041 	ident[IDENT_LENGTH_BYTE] = devid->identLength;
4042 	bcopy(&(devid->ident), &ident[IDENT_LENGTH_BYTE + 1],
4043 	    devid->identLength);
4044 
4045 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4046 	/*
4047 	 * Issue ioctl to get the session list
4048 	 */
4049 	stmfIoctl.stmf_version = STMF_VERSION_1;
4050 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ident;
4051 	stmfIoctl.stmf_ibuf_size = sizeof (ident);
4052 	stmfIoctl.stmf_obuf_size = fSessionListSize;
4053 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
4054 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4055 	if (ioctlRet != 0) {
4056 		switch (errno) {
4057 			case EBUSY:
4058 				ret = STMF_ERROR_BUSY;
4059 				break;
4060 			case EPERM:
4061 			case EACCES:
4062 				ret = STMF_ERROR_PERM;
4063 				break;
4064 			default:
4065 				syslog(LOG_DEBUG,
4066 				    "stmfGetSessionList:ioctl errno(%d)",
4067 				    errno);
4068 				ret = STMF_STATUS_ERROR;
4069 				break;
4070 		}
4071 		goto done;
4072 	}
4073 	/*
4074 	 * Check whether input buffer was large enough
4075 	 */
4076 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_SESSION) {
4077 		fSessionListSize = stmfIoctl.stmf_obuf_max_nentries *
4078 		    sizeof (slist_scsi_session_t);
4079 		fSessionList = realloc(fSessionList, fSessionListSize);
4080 		if (fSessionList == NULL) {
4081 			ret = STMF_ERROR_NOMEM;
4082 			goto done;
4083 		}
4084 		fSessionListP = fSessionList;
4085 		stmfIoctl.stmf_obuf_size = fSessionListSize;
4086 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList;
4087 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4088 		if (ioctlRet != 0) {
4089 			switch (errno) {
4090 				case EBUSY:
4091 					ret = STMF_ERROR_BUSY;
4092 					break;
4093 				case EPERM:
4094 				case EACCES:
4095 					ret = STMF_ERROR_PERM;
4096 					break;
4097 				default:
4098 					syslog(LOG_DEBUG,
4099 					    "stmfGetSessionList:ioctl "
4100 					    "errno(%d)", errno);
4101 					ret = STMF_STATUS_ERROR;
4102 					break;
4103 			}
4104 			goto done;
4105 		}
4106 	}
4107 
4108 	/*
4109 	 * allocate caller's buffer with the final size
4110 	 */
4111 	*sessionList = (stmfSessionList *)calloc(1, sizeof (stmfSessionList) +
4112 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfSession));
4113 	if (*sessionList == NULL) {
4114 		ret = STMF_ERROR_NOMEM;
4115 		free(sessionList);
4116 		goto done;
4117 	}
4118 
4119 	(*sessionList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
4120 
4121 	/*
4122 	 * copy session info to caller's buffer
4123 	 */
4124 	for (i = 0; i < (*sessionList)->cnt; i++) {
4125 		(*sessionList)->session[i].initiator.identLength =
4126 		    fSessionList->initiator[IDENT_LENGTH_BYTE];
4127 		bcopy(&(fSessionList->initiator[IDENT_LENGTH_BYTE + 1]),
4128 		    (*sessionList)->session[i].initiator.ident,
4129 		    STMF_IDENT_LENGTH);
4130 		bcopy(&(fSessionList->alias),
4131 		    &((*sessionList)->session[i].alias),
4132 		    sizeof ((*sessionList)->session[i].alias));
4133 		bcopy(&(fSessionList++->creation_time),
4134 		    &((*sessionList)->session[i].creationTime),
4135 		    sizeof (time_t));
4136 	}
4137 done:
4138 	(void) close(fd);
4139 	free(fSessionListP);
4140 	return (ret);
4141 }
4142 
4143 /*
4144  * stmfGetTargetGroupList
4145  *
4146  * Purpose: Retrieves the list of target groups
4147  *
4148  * targetGroupList - pointer to a pointer to an stmfGroupList structure. On
4149  *		     success, it contains the list of target groups.
4150  */
4151 int
stmfGetTargetGroupList(stmfGroupList ** targetGroupList)4152 stmfGetTargetGroupList(stmfGroupList **targetGroupList)
4153 {
4154 	int ret;
4155 
4156 	if (targetGroupList == NULL) {
4157 		return (STMF_ERROR_INVALID_ARG);
4158 	}
4159 
4160 	ret = groupListIoctl(targetGroupList, TARGET_GROUP);
4161 	return (ret);
4162 }
4163 
4164 /*
4165  * stmfGetTargetGroupMembers
4166  *
4167  * Purpose: Retrieves the group members for a target group
4168  *
4169  * groupName - name of target group for which to retrieve members.
4170  * groupProp - pointer to pointer to stmfGroupProperties structure
4171  *             on success, this contains the list of group members.
4172  */
4173 int
stmfGetTargetGroupMembers(stmfGroupName * groupName,stmfGroupProperties ** groupProp)4174 stmfGetTargetGroupMembers(stmfGroupName *groupName,
4175     stmfGroupProperties **groupProp)
4176 {
4177 	int ret;
4178 
4179 	if (groupName == NULL || groupProp == NULL) {
4180 		return (STMF_ERROR_INVALID_ARG);
4181 	}
4182 
4183 	ret = groupMemberListIoctl(groupName, groupProp, TARGET_GROUP);
4184 
4185 	return (ret);
4186 }
4187 
4188 /*
4189  * stmfGetTargetList
4190  *
4191  * Purpose: Retrieves the list of target ports
4192  *
4193  * targetList - pointer to a pointer to an stmfDevidList structure.
4194  *		    On success, it contains the list of local ports (target).
4195  */
4196 int
stmfGetTargetList(stmfDevidList ** targetList)4197 stmfGetTargetList(stmfDevidList **targetList)
4198 {
4199 	int ret;
4200 	int fd;
4201 	int ioctlRet;
4202 	int i;
4203 	stmf_iocdata_t stmfIoctl;
4204 	/* framework target port list */
4205 	slist_target_port_t *fTargetList, *fTargetListP = NULL;
4206 	uint32_t fTargetListSize;
4207 
4208 	if (targetList == NULL) {
4209 		return (STMF_ERROR_INVALID_ARG);
4210 	}
4211 
4212 	/* call init */
4213 	ret = initializeConfig();
4214 	if (ret != STMF_STATUS_SUCCESS) {
4215 		return (ret);
4216 	}
4217 
4218 	/*
4219 	 * Open control node for stmf
4220 	 */
4221 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4222 		return (ret);
4223 
4224 	/*
4225 	 * Allocate ioctl input buffer
4226 	 */
4227 	fTargetListSize = ALLOC_TARGET_PORT * sizeof (slist_target_port_t);
4228 	fTargetListP = fTargetList =
4229 	    (slist_target_port_t *)calloc(1, fTargetListSize);
4230 	if (fTargetList == NULL) {
4231 		ret = STMF_ERROR_NOMEM;
4232 		goto done;
4233 	}
4234 
4235 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4236 	/*
4237 	 * Issue ioctl to retrieve target list
4238 	 */
4239 	stmfIoctl.stmf_version = STMF_VERSION_1;
4240 	stmfIoctl.stmf_obuf_size = fTargetListSize;
4241 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
4242 	ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST, &stmfIoctl);
4243 	if (ioctlRet != 0) {
4244 		switch (errno) {
4245 			case EBUSY:
4246 				ret = STMF_ERROR_BUSY;
4247 				break;
4248 			case EPERM:
4249 			case EACCES:
4250 				ret = STMF_ERROR_PERM;
4251 				break;
4252 			default:
4253 				syslog(LOG_DEBUG,
4254 				    "stmfGetTargetList:ioctl errno(%d)", errno);
4255 				ret = STMF_STATUS_ERROR;
4256 				break;
4257 		}
4258 		goto done;
4259 	}
4260 	/*
4261 	 * Check whether input buffer was large enough
4262 	 */
4263 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_TARGET_PORT) {
4264 		fTargetListSize = stmfIoctl.stmf_obuf_max_nentries *
4265 		    sizeof (slist_target_port_t);
4266 		fTargetListP = fTargetList =
4267 		    realloc(fTargetList, fTargetListSize);
4268 		if (fTargetList == NULL) {
4269 			ret = STMF_ERROR_NOMEM;
4270 			goto done;
4271 		}
4272 		stmfIoctl.stmf_obuf_size = fTargetListSize;
4273 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fTargetList;
4274 		ioctlRet = ioctl(fd, STMF_IOCTL_TARGET_PORT_LIST,
4275 		    &stmfIoctl);
4276 		if (ioctlRet != 0) {
4277 			switch (errno) {
4278 				case EBUSY:
4279 					ret = STMF_ERROR_BUSY;
4280 					break;
4281 				case EPERM:
4282 				case EACCES:
4283 					ret = STMF_ERROR_PERM;
4284 					break;
4285 				default:
4286 					syslog(LOG_DEBUG,
4287 					    "stmfGetTargetList:ioctl errno(%d)",
4288 					    errno);
4289 					ret = STMF_STATUS_ERROR;
4290 					break;
4291 			}
4292 			goto done;
4293 		}
4294 	}
4295 
4296 	*targetList = (stmfDevidList *)calloc(1,
4297 	    stmfIoctl.stmf_obuf_max_nentries * sizeof (stmfDevid) +
4298 	    sizeof (stmfDevidList));
4299 	if (*targetList == NULL) {
4300 		ret = STMF_ERROR_NOMEM;
4301 		goto done;
4302 	}
4303 
4304 	(*targetList)->cnt = stmfIoctl.stmf_obuf_max_nentries;
4305 	for (i = 0; i < stmfIoctl.stmf_obuf_max_nentries; i++, fTargetList++) {
4306 		(*targetList)->devid[i].identLength =
4307 		    fTargetList->target[IDENT_LENGTH_BYTE];
4308 		bcopy(&fTargetList->target[IDENT_LENGTH_BYTE + 1],
4309 		    &(*targetList)->devid[i].ident,
4310 		    fTargetList->target[IDENT_LENGTH_BYTE]);
4311 	}
4312 
4313 done:
4314 	(void) close(fd);
4315 	free(fTargetListP);
4316 	return (ret);
4317 }
4318 
4319 /*
4320  * stmfGetTargetProperties
4321  *
4322  * Purpose:  Retrieves the properties for a logical unit
4323  *
4324  * devid - devid of the target for which to retrieve properties
4325  * targetProps - pointer to an stmfTargetProperties structure.
4326  *		On success, it contains the target properties for
4327  *		the specified devid.
4328  */
4329 int
stmfGetTargetProperties(stmfDevid * devid,stmfTargetProperties * targetProps)4330 stmfGetTargetProperties(stmfDevid *devid, stmfTargetProperties *targetProps)
4331 {
4332 	int ret = STMF_STATUS_SUCCESS;
4333 	int fd;
4334 	int ioctlRet;
4335 	stmf_iocdata_t stmfIoctl;
4336 	sioc_target_port_props_t targetProperties;
4337 	scsi_devid_desc_t *scsiDevid;
4338 
4339 	if (devid == NULL || targetProps == NULL) {
4340 		return (STMF_ERROR_INVALID_ARG);
4341 	}
4342 
4343 	/* call init */
4344 	ret = initializeConfig();
4345 	if (ret != STMF_STATUS_SUCCESS) {
4346 		return (ret);
4347 	}
4348 
4349 	/*
4350 	 * Open control node for stmf
4351 	 */
4352 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4353 		return (ret);
4354 
4355 	targetProperties.tgt_id[IDENT_LENGTH_BYTE] = devid->identLength;
4356 	bcopy(&(devid->ident), &targetProperties.tgt_id[IDENT_LENGTH_BYTE + 1],
4357 	    devid->identLength);
4358 
4359 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4360 	/*
4361 	 * Issue ioctl to add to the host group
4362 	 */
4363 	stmfIoctl.stmf_version = STMF_VERSION_1;
4364 	stmfIoctl.stmf_ibuf_size = sizeof (targetProperties.tgt_id);
4365 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&targetProperties.tgt_id;
4366 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&targetProperties;
4367 	stmfIoctl.stmf_obuf_size = sizeof (targetProperties);
4368 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_TARGET_PORT_PROPERTIES,
4369 	    &stmfIoctl);
4370 	if (ioctlRet != 0) {
4371 		switch (errno) {
4372 			case EBUSY:
4373 				ret = STMF_ERROR_BUSY;
4374 				break;
4375 			case EPERM:
4376 			case EACCES:
4377 				ret = STMF_ERROR_PERM;
4378 				break;
4379 			case ENOENT:
4380 				ret = STMF_ERROR_NOT_FOUND;
4381 				break;
4382 			default:
4383 				syslog(LOG_DEBUG,
4384 				    "stmfGetTargetProperties:ioctl errno(%d)",
4385 				    errno);
4386 				ret = STMF_STATUS_ERROR;
4387 				break;
4388 		}
4389 		goto done;
4390 	}
4391 
4392 	bcopy(targetProperties.tgt_provider_name, targetProps->providerName,
4393 	    sizeof (targetProperties.tgt_provider_name));
4394 	if (targetProperties.tgt_state == STMF_STATE_ONLINE) {
4395 		targetProps->status = STMF_TARGET_PORT_ONLINE;
4396 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINE) {
4397 		targetProps->status = STMF_TARGET_PORT_OFFLINE;
4398 	} else if (targetProperties.tgt_state == STMF_STATE_ONLINING) {
4399 		targetProps->status = STMF_TARGET_PORT_ONLINING;
4400 	} else if (targetProperties.tgt_state == STMF_STATE_OFFLINING) {
4401 		targetProps->status = STMF_TARGET_PORT_OFFLINING;
4402 	}
4403 	bcopy(targetProperties.tgt_alias, targetProps->alias,
4404 	    sizeof (targetProps->alias));
4405 
4406 	scsiDevid = (scsi_devid_desc_t *)&targetProperties.tgt_id;
4407 	targetProps->protocol = scsiDevid->protocol_id;
4408 
4409 done:
4410 	(void) close(fd);
4411 	return (ret);
4412 }
4413 
4414 /*
4415  * stmfGetLogicalUnitList
4416  *
4417  * Purpose: Retrieves list of logical unit Object IDs
4418  *
4419  * luList - pointer to a pointer to a stmfGuidList structure. On success,
4420  *          it contains the list of logical unit guids.
4421  *
4422  */
4423 int
stmfGetLogicalUnitList(stmfGuidList ** luList)4424 stmfGetLogicalUnitList(stmfGuidList **luList)
4425 {
4426 	int ret;
4427 	int fd;
4428 	int ioctlRet;
4429 	int cmd = STMF_IOCTL_LU_LIST;
4430 	int i;
4431 	stmf_iocdata_t stmfIoctl;
4432 	slist_lu_t *fLuList;
4433 	uint32_t fLuListSize;
4434 	uint32_t listCnt;
4435 
4436 	if (luList == NULL) {
4437 		return (STMF_ERROR_INVALID_ARG);
4438 	}
4439 
4440 	/* call init */
4441 	ret = initializeConfig();
4442 	if (ret != STMF_STATUS_SUCCESS) {
4443 		return (ret);
4444 	}
4445 
4446 	/*
4447 	 * Open control node for stmf
4448 	 */
4449 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4450 		return (ret);
4451 
4452 	/*
4453 	 * Allocate ioctl input buffer
4454 	 */
4455 	fLuListSize = ALLOC_LU;
4456 	fLuListSize = fLuListSize * (sizeof (slist_lu_t));
4457 	fLuList = (slist_lu_t *)calloc(1, fLuListSize);
4458 	if (fLuList == NULL) {
4459 		ret = STMF_ERROR_NOMEM;
4460 		goto done;
4461 	}
4462 
4463 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4464 	/*
4465 	 * Issue ioctl to get the LU list
4466 	 */
4467 	stmfIoctl.stmf_version = STMF_VERSION_1;
4468 	stmfIoctl.stmf_obuf_size = fLuListSize;
4469 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
4470 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4471 	if (ioctlRet != 0) {
4472 		switch (errno) {
4473 			case EBUSY:
4474 				ret = STMF_ERROR_BUSY;
4475 				break;
4476 			case EPERM:
4477 			case EACCES:
4478 				ret = STMF_ERROR_PERM;
4479 				break;
4480 			default:
4481 				syslog(LOG_DEBUG,
4482 				    "stmfGetLogicalUnitList:ioctl errno(%d)",
4483 				    errno);
4484 				ret = STMF_STATUS_ERROR;
4485 				break;
4486 		}
4487 		goto done;
4488 	}
4489 	/*
4490 	 * Check whether input buffer was large enough
4491 	 */
4492 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_LU) {
4493 		fLuListSize = stmfIoctl.stmf_obuf_max_nentries *
4494 		    sizeof (slist_lu_t);
4495 		free(fLuList);
4496 		fLuList = (slist_lu_t *)calloc(1, fLuListSize);
4497 		if (fLuList == NULL) {
4498 			ret = STMF_ERROR_NOMEM;
4499 			goto done;
4500 		}
4501 		stmfIoctl.stmf_obuf_size = fLuListSize;
4502 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fLuList;
4503 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4504 		if (ioctlRet != 0) {
4505 			switch (errno) {
4506 				case EBUSY:
4507 					ret = STMF_ERROR_BUSY;
4508 					break;
4509 				case EPERM:
4510 				case EACCES:
4511 					ret = STMF_ERROR_PERM;
4512 					break;
4513 				default:
4514 					syslog(LOG_DEBUG,
4515 					    "stmfGetLogicalUnitList:"
4516 					    "ioctl errno(%d)", errno);
4517 					ret = STMF_STATUS_ERROR;
4518 					break;
4519 			}
4520 			goto done;
4521 		}
4522 	}
4523 
4524 	if (ret != STMF_STATUS_SUCCESS) {
4525 		goto done;
4526 	}
4527 
4528 	listCnt = stmfIoctl.stmf_obuf_nentries;
4529 
4530 	/*
4531 	 * allocate caller's buffer with the final size
4532 	 */
4533 	*luList = (stmfGuidList *)calloc(1, sizeof (stmfGuidList) +
4534 	    listCnt * sizeof (stmfGuid));
4535 	if (*luList == NULL) {
4536 		ret = STMF_ERROR_NOMEM;
4537 		goto done;
4538 	}
4539 
4540 	(*luList)->cnt = listCnt;
4541 
4542 	/* copy to caller's buffer */
4543 	for (i = 0; i < listCnt; i++) {
4544 		bcopy(&fLuList[i].lu_guid, (*luList)->guid[i].guid,
4545 		    sizeof (stmfGuid));
4546 	}
4547 
4548 	/*
4549 	 * sort the list. This gives a consistent view across gets
4550 	 */
4551 	qsort((void *)&((*luList)->guid[0]), (*luList)->cnt,
4552 	    sizeof (stmfGuid), guidCompare);
4553 
4554 done:
4555 	(void) close(fd);
4556 	/*
4557 	 * free internal buffers
4558 	 */
4559 	free(fLuList);
4560 	return (ret);
4561 }
4562 
4563 /*
4564  * stmfGetLogicalUnitProperties
4565  *
4566  * Purpose:  Retrieves the properties for a logical unit
4567  *
4568  * lu - guid of the logical unit for which to retrieve properties
4569  * stmfLuProps - pointer to an stmfLogicalUnitProperties structure. On success,
4570  *               it contains the logical unit properties for the specified guid.
4571  */
4572 int
stmfGetLogicalUnitProperties(stmfGuid * lu,stmfLogicalUnitProperties * luProps)4573 stmfGetLogicalUnitProperties(stmfGuid *lu, stmfLogicalUnitProperties *luProps)
4574 {
4575 	int ret = STMF_STATUS_SUCCESS;
4576 	int stmfRet;
4577 	int fd;
4578 	int ioctlRet;
4579 	int cmd = STMF_IOCTL_GET_LU_PROPERTIES;
4580 	stmfViewEntryList *viewEntryList = NULL;
4581 	stmf_iocdata_t stmfIoctl;
4582 	sioc_lu_props_t fLuProps;
4583 
4584 	if (lu == NULL || luProps == NULL) {
4585 		return (STMF_ERROR_INVALID_ARG);
4586 	}
4587 
4588 	bzero(luProps, sizeof (stmfLogicalUnitProperties));
4589 
4590 	/* call init */
4591 	ret = initializeConfig();
4592 	if (ret != STMF_STATUS_SUCCESS) {
4593 		return (ret);
4594 	}
4595 
4596 	/*
4597 	 * Open control node for stmf
4598 	 */
4599 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4600 		return (ret);
4601 
4602 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4603 	/*
4604 	 * Issue ioctl to add to the host group
4605 	 */
4606 	stmfIoctl.stmf_version = STMF_VERSION_1;
4607 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4608 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4609 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&fLuProps;
4610 	stmfIoctl.stmf_obuf_size = sizeof (fLuProps);
4611 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4612 	if (ioctlRet != 0) {
4613 		switch (errno) {
4614 			case EBUSY:
4615 				ret = STMF_ERROR_BUSY;
4616 				break;
4617 			case EPERM:
4618 			case EACCES:
4619 				ret = STMF_ERROR_PERM;
4620 				break;
4621 			case ENOENT:
4622 				stmfRet = stmfGetViewEntryList(lu,
4623 				    &viewEntryList);
4624 				if (stmfRet == STMF_STATUS_SUCCESS) {
4625 					luProps->status =
4626 					    STMF_LOGICAL_UNIT_UNREGISTERED;
4627 					if (viewEntryList->cnt > 0) {
4628 						ret = STMF_STATUS_SUCCESS;
4629 					} else {
4630 						ret = STMF_ERROR_NOT_FOUND;
4631 					}
4632 				} else {
4633 					ret = STMF_ERROR_NOT_FOUND;
4634 				}
4635 				stmfFreeMemory(viewEntryList);
4636 				break;
4637 			default:
4638 				syslog(LOG_DEBUG,
4639 				    "stmfGetLogicalUnit:ioctl errno(%d)",
4640 				    errno);
4641 				ret = STMF_STATUS_ERROR;
4642 				break;
4643 		}
4644 		goto done;
4645 	}
4646 
4647 	bcopy(fLuProps.lu_provider_name, luProps->providerName,
4648 	    sizeof (fLuProps.lu_provider_name));
4649 	if (fLuProps.lu_state == STMF_STATE_ONLINE) {
4650 		luProps->status = STMF_LOGICAL_UNIT_ONLINE;
4651 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINE) {
4652 		luProps->status = STMF_LOGICAL_UNIT_OFFLINE;
4653 	} else if (fLuProps.lu_state == STMF_STATE_ONLINING) {
4654 		luProps->status = STMF_LOGICAL_UNIT_ONLINING;
4655 	} else if (fLuProps.lu_state == STMF_STATE_OFFLINING) {
4656 		luProps->status = STMF_LOGICAL_UNIT_OFFLINING;
4657 	}
4658 	bcopy(fLuProps.lu_alias, luProps->alias, sizeof (luProps->alias));
4659 done:
4660 	(void) close(fd);
4661 	return (ret);
4662 }
4663 
4664 /*
4665  * stmfGetState
4666  *
4667  * Purpose: retrieve the current state of the stmf module
4668  *
4669  * state - pointer to stmfState structure allocated by the caller
4670  *         On success, contains the state of stmf
4671  */
4672 int
stmfGetState(stmfState * state)4673 stmfGetState(stmfState *state)
4674 {
4675 	int ret;
4676 	stmf_state_desc_t iState;
4677 
4678 	if (state == NULL) {
4679 		return (STMF_ERROR_INVALID_ARG);
4680 	}
4681 
4682 	ret = getStmfState(&iState);
4683 	if (ret != STMF_STATUS_SUCCESS) {
4684 		return (ret);
4685 	}
4686 	switch (iState.state) {
4687 		case STMF_STATE_ONLINE:
4688 			state->operationalState =
4689 			    STMF_SERVICE_STATE_ONLINE;
4690 			break;
4691 		case STMF_STATE_OFFLINE:
4692 			state->operationalState =
4693 			    STMF_SERVICE_STATE_OFFLINE;
4694 			break;
4695 		case STMF_STATE_ONLINING:
4696 			state->operationalState =
4697 			    STMF_SERVICE_STATE_ONLINING;
4698 			break;
4699 		case STMF_STATE_OFFLINING:
4700 			state->operationalState =
4701 			    STMF_SERVICE_STATE_OFFLINING;
4702 			break;
4703 		default:
4704 			state->operationalState =
4705 			    STMF_SERVICE_STATE_UNKNOWN;
4706 			break;
4707 	}
4708 	switch (iState.config_state) {
4709 		case STMF_CONFIG_NONE:
4710 			state->configState = STMF_CONFIG_STATE_NONE;
4711 			break;
4712 		case STMF_CONFIG_INIT:
4713 			state->configState = STMF_CONFIG_STATE_INIT;
4714 			break;
4715 		case STMF_CONFIG_INIT_DONE:
4716 			state->configState =
4717 			    STMF_CONFIG_STATE_INIT_DONE;
4718 			break;
4719 		default:
4720 			state->configState =
4721 			    STMF_CONFIG_STATE_UNKNOWN;
4722 			break;
4723 	}
4724 	return (STMF_STATUS_SUCCESS);
4725 }
4726 
4727 /*
4728  * stmfGetViewEntryList
4729  *
4730  * Purpose: Retrieves the list of view entries for the specified
4731  *          logical unit.
4732  *
4733  * lu - the guid of the logical unit for which to retrieve the view entry list
4734  * viewEntryList - a pointer to a pointer to a stmfViewEntryList structure. On
4735  *                 success, contains the list of view entries.
4736  */
4737 int
stmfGetViewEntryList(stmfGuid * lu,stmfViewEntryList ** viewEntryList)4738 stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList)
4739 {
4740 	int ret;
4741 	int fd;
4742 	int ioctlRet;
4743 	int cmd = STMF_IOCTL_LU_VE_LIST;
4744 	int i;
4745 	stmf_iocdata_t stmfIoctl;
4746 	stmf_view_op_entry_t *fVeList;
4747 	uint32_t fVeListSize;
4748 	uint32_t listCnt;
4749 
4750 	if (lu == NULL || viewEntryList == NULL) {
4751 		return (STMF_ERROR_INVALID_ARG);
4752 	}
4753 
4754 	/* call init */
4755 	ret = initializeConfig();
4756 	if (ret != STMF_STATUS_SUCCESS) {
4757 		return (ret);
4758 	}
4759 
4760 	/*
4761 	 * Open control node for stmf
4762 	 */
4763 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
4764 		return (ret);
4765 
4766 	/*
4767 	 * Allocate ioctl input buffer
4768 	 */
4769 	fVeListSize = ALLOC_VE;
4770 	fVeListSize = fVeListSize * (sizeof (stmf_view_op_entry_t));
4771 	fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4772 	if (fVeList == NULL) {
4773 		ret = STMF_ERROR_NOMEM;
4774 		goto done;
4775 	}
4776 
4777 	bzero(&stmfIoctl, sizeof (stmfIoctl));
4778 	/*
4779 	 * Issue ioctl to get the LU list
4780 	 */
4781 	stmfIoctl.stmf_version = STMF_VERSION_1;
4782 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)lu;
4783 	stmfIoctl.stmf_ibuf_size = sizeof (stmfGuid);
4784 	stmfIoctl.stmf_obuf_size = fVeListSize;
4785 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4786 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4787 	if (ioctlRet != 0) {
4788 		switch (errno) {
4789 			case EBUSY:
4790 				ret = STMF_ERROR_BUSY;
4791 				break;
4792 			case EPERM:
4793 			case EACCES:
4794 				ret = STMF_ERROR_PERM;
4795 				break;
4796 			default:
4797 				syslog(LOG_DEBUG,
4798 				    "stmfGetViewEntryList:ioctl errno(%d)",
4799 				    errno);
4800 				ret = STMF_STATUS_ERROR;
4801 				break;
4802 		}
4803 		goto done;
4804 	}
4805 	/*
4806 	 * Check whether input buffer was large enough
4807 	 */
4808 	if (stmfIoctl.stmf_obuf_max_nentries > ALLOC_VE) {
4809 		bzero(&stmfIoctl, sizeof (stmfIoctl));
4810 		fVeListSize = stmfIoctl.stmf_obuf_max_nentries *
4811 		    sizeof (stmf_view_op_entry_t);
4812 		free(fVeList);
4813 		fVeList = (stmf_view_op_entry_t *)calloc(1, fVeListSize);
4814 		if (fVeList == NULL) {
4815 			return (STMF_ERROR_NOMEM);
4816 		}
4817 		stmfIoctl.stmf_obuf_size = fVeListSize;
4818 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fVeList;
4819 		ioctlRet = ioctl(fd, cmd, &stmfIoctl);
4820 		if (ioctlRet != 0) {
4821 			switch (errno) {
4822 				case EBUSY:
4823 					ret = STMF_ERROR_BUSY;
4824 					break;
4825 				case EPERM:
4826 				case EACCES:
4827 					ret = STMF_ERROR_PERM;
4828 					break;
4829 				default:
4830 					syslog(LOG_DEBUG,
4831 					    "stmfGetLogicalUnitList:"
4832 					    "ioctl errno(%d)", errno);
4833 					ret = STMF_STATUS_ERROR;
4834 					break;
4835 			}
4836 			goto done;
4837 		}
4838 	}
4839 
4840 	if (ret != STMF_STATUS_SUCCESS) {
4841 		goto done;
4842 	}
4843 
4844 	listCnt = stmfIoctl.stmf_obuf_nentries;
4845 
4846 	/*
4847 	 * allocate caller's buffer with the final size
4848 	 */
4849 	*viewEntryList = (stmfViewEntryList *)calloc(1,
4850 	    sizeof (stmfViewEntryList) + listCnt * sizeof (stmfViewEntry));
4851 	if (*viewEntryList == NULL) {
4852 		ret = STMF_ERROR_NOMEM;
4853 		goto done;
4854 	}
4855 
4856 	(*viewEntryList)->cnt = listCnt;
4857 
4858 	/* copy to caller's buffer */
4859 	for (i = 0; i < listCnt; i++) {
4860 		(*viewEntryList)->ve[i].veIndexValid = B_TRUE;
4861 		(*viewEntryList)->ve[i].veIndex = fVeList[i].ve_ndx;
4862 		if (fVeList[i].ve_all_hosts == 1) {
4863 			(*viewEntryList)->ve[i].allHosts = B_TRUE;
4864 		} else {
4865 			bcopy(fVeList[i].ve_host_group.name,
4866 			    (*viewEntryList)->ve[i].hostGroup,
4867 			    fVeList[i].ve_host_group.name_size);
4868 		}
4869 		if (fVeList[i].ve_all_targets == 1) {
4870 			(*viewEntryList)->ve[i].allTargets = B_TRUE;
4871 		} else {
4872 			bcopy(fVeList[i].ve_target_group.name,
4873 			    (*viewEntryList)->ve[i].targetGroup,
4874 			    fVeList[i].ve_target_group.name_size);
4875 		}
4876 		bcopy(fVeList[i].ve_lu_nbr, (*viewEntryList)->ve[i].luNbr,
4877 		    sizeof ((*viewEntryList)->ve[i].luNbr));
4878 		(*viewEntryList)->ve[i].luNbrValid = B_TRUE;
4879 	}
4880 
4881 	/*
4882 	 * sort the list. This gives a consistent view across gets
4883 	 */
4884 	qsort((void *)&((*viewEntryList)->ve[0]), (*viewEntryList)->cnt,
4885 	    sizeof (stmfViewEntry), viewEntryCompare);
4886 
4887 done:
4888 	(void) close(fd);
4889 	/*
4890 	 * free internal buffers
4891 	 */
4892 	free(fVeList);
4893 	return (ret);
4894 }
4895 
4896 
4897 /*
4898  * loadHostGroups
4899  *
4900  * Purpose - issues the ioctl to load the host groups into stmf
4901  *
4902  * fd - file descriptor for the control node of stmf.
4903  * groupList - populated host group list
4904  */
4905 static int
loadHostGroups(int fd,stmfGroupList * groupList)4906 loadHostGroups(int fd, stmfGroupList *groupList)
4907 {
4908 	int i, j;
4909 	int ret = STMF_STATUS_SUCCESS;
4910 	stmfGroupProperties *groupProps = NULL;
4911 
4912 	for (i = 0; i < groupList->cnt; i++) {
4913 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_HOST_GROUP,
4914 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
4915 			goto out;
4916 		}
4917 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4918 		    &groupProps, HOST_GROUP);
4919 		for (j = 0; j < groupProps->cnt; j++) {
4920 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_HG_ENTRY,
4921 			    &(groupList->name[i]), &(groupProps->name[j])))
4922 			    != STMF_STATUS_SUCCESS) {
4923 				goto out;
4924 			}
4925 		}
4926 	}
4927 
4928 
4929 out:
4930 	stmfFreeMemory(groupProps);
4931 	return (ret);
4932 }
4933 
4934 /*
4935  * loadTargetGroups
4936  *
4937  * Purpose - issues the ioctl to load the target groups into stmf
4938  *
4939  * fd - file descriptor for the control node of stmf.
4940  * groupList - populated target group list.
4941  */
4942 static int
loadTargetGroups(int fd,stmfGroupList * groupList)4943 loadTargetGroups(int fd, stmfGroupList *groupList)
4944 {
4945 	int i, j;
4946 	int ret = STMF_STATUS_SUCCESS;
4947 	stmfGroupProperties *groupProps = NULL;
4948 
4949 	for (i = 0; i < groupList->cnt; i++) {
4950 		if ((ret = groupIoctl(fd, STMF_IOCTL_CREATE_TARGET_GROUP,
4951 		    &(groupList->name[i]))) != STMF_STATUS_SUCCESS) {
4952 			goto out;
4953 		}
4954 		ret = iLoadGroupMembersFromPs(&(groupList->name[i]),
4955 		    &groupProps, TARGET_GROUP);
4956 		for (j = 0; j < groupProps->cnt; j++) {
4957 			if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
4958 			    &(groupList->name[i]), &(groupProps->name[j])))
4959 			    != STMF_STATUS_SUCCESS) {
4960 				goto out;
4961 			}
4962 		}
4963 	}
4964 
4965 
4966 out:
4967 	stmfFreeMemory(groupProps);
4968 	return (ret);
4969 }
4970 
4971 
4972 /*
4973  * loadStore
4974  *
4975  * Purpose: Load the configuration data from the store
4976  *
4977  * First load the host groups and target groups, then the view entries
4978  * and finally the provider data
4979  *
4980  * fd - file descriptor of control node for stmf.
4981  */
4982 static int
loadStore(int fd)4983 loadStore(int fd)
4984 {
4985 	int ret;
4986 	int i, j;
4987 	stmfGroupList *groupList = NULL;
4988 	stmfGuidList *guidList = NULL;
4989 	stmfViewEntryList *viewEntryList = NULL;
4990 	stmfProviderList *providerList = NULL;
4991 	int providerType;
4992 	nvlist_t *nvl = NULL;
4993 
4994 
4995 
4996 	/* load host groups */
4997 	ret = iLoadGroupFromPs(&groupList, HOST_GROUP);
4998 	if (ret != STMF_STATUS_SUCCESS) {
4999 		return (ret);
5000 	}
5001 	ret = loadHostGroups(fd, groupList);
5002 	if (ret != STMF_STATUS_SUCCESS) {
5003 		goto out;
5004 	}
5005 
5006 	stmfFreeMemory(groupList);
5007 	groupList = NULL;
5008 
5009 	/* load target groups */
5010 	ret = iLoadGroupFromPs(&groupList, TARGET_GROUP);
5011 	if (ret != STMF_STATUS_SUCCESS) {
5012 		goto out;
5013 	}
5014 	ret = loadTargetGroups(fd, groupList);
5015 	if (ret != STMF_STATUS_SUCCESS) {
5016 		goto out;
5017 	}
5018 
5019 	stmfFreeMemory(groupList);
5020 	groupList = NULL;
5021 
5022 	/* Get the guid list */
5023 	ret = psGetLogicalUnitList(&guidList);
5024 	switch (ret) {
5025 		case STMF_PS_SUCCESS:
5026 			ret = STMF_STATUS_SUCCESS;
5027 			break;
5028 		case STMF_PS_ERROR_NOT_FOUND:
5029 			ret = STMF_ERROR_NOT_FOUND;
5030 			break;
5031 		case STMF_PS_ERROR_BUSY:
5032 			ret = STMF_ERROR_BUSY;
5033 			break;
5034 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5035 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5036 			break;
5037 		case STMF_PS_ERROR_VERSION_MISMATCH:
5038 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5039 			break;
5040 		default:
5041 			ret = STMF_STATUS_ERROR;
5042 			break;
5043 	}
5044 
5045 	if (ret != STMF_STATUS_SUCCESS) {
5046 		goto out;
5047 	}
5048 
5049 	/*
5050 	 * We have the guid list, now get the corresponding
5051 	 * view entries for each guid
5052 	 */
5053 	for (i = 0; i < guidList->cnt; i++) {
5054 		ret = psGetViewEntryList(&guidList->guid[i], &viewEntryList);
5055 		switch (ret) {
5056 			case STMF_PS_SUCCESS:
5057 				ret = STMF_STATUS_SUCCESS;
5058 				break;
5059 			case STMF_PS_ERROR_NOT_FOUND:
5060 				ret = STMF_ERROR_NOT_FOUND;
5061 				break;
5062 			case STMF_PS_ERROR_BUSY:
5063 				ret = STMF_ERROR_BUSY;
5064 				break;
5065 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5066 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
5067 				break;
5068 			case STMF_PS_ERROR_VERSION_MISMATCH:
5069 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
5070 				break;
5071 			default:
5072 				ret = STMF_STATUS_ERROR;
5073 				break;
5074 		}
5075 		if (ret != STMF_STATUS_SUCCESS) {
5076 			goto out;
5077 		}
5078 		for (j = 0; j < viewEntryList->cnt; j++) {
5079 			ret = addViewEntryIoctl(fd, &guidList->guid[i],
5080 			    &viewEntryList->ve[j]);
5081 			if (ret != STMF_STATUS_SUCCESS) {
5082 				goto out;
5083 			}
5084 		}
5085 	}
5086 
5087 	/* get the list of providers that have data */
5088 	ret = psGetProviderDataList(&providerList);
5089 	switch (ret) {
5090 		case STMF_PS_SUCCESS:
5091 			ret = STMF_STATUS_SUCCESS;
5092 			break;
5093 		case STMF_PS_ERROR_NOT_FOUND:
5094 			ret = STMF_ERROR_NOT_FOUND;
5095 			break;
5096 		case STMF_PS_ERROR_BUSY:
5097 			ret = STMF_ERROR_BUSY;
5098 			break;
5099 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5100 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
5101 			break;
5102 		case STMF_PS_ERROR_VERSION_MISMATCH:
5103 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
5104 			break;
5105 		default:
5106 			ret = STMF_STATUS_ERROR;
5107 			break;
5108 	}
5109 	if (ret != STMF_STATUS_SUCCESS) {
5110 		goto out;
5111 	}
5112 
5113 	for (i = 0; i < providerList->cnt; i++) {
5114 		providerType = providerList->provider[i].providerType;
5115 		ret = psGetProviderData(providerList->provider[i].name,
5116 		    &nvl, providerType, NULL);
5117 		switch (ret) {
5118 			case STMF_PS_SUCCESS:
5119 				ret = STMF_STATUS_SUCCESS;
5120 				break;
5121 			case STMF_PS_ERROR_NOT_FOUND:
5122 				ret = STMF_ERROR_NOT_FOUND;
5123 				break;
5124 			case STMF_PS_ERROR_BUSY:
5125 				ret = STMF_ERROR_BUSY;
5126 				break;
5127 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5128 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
5129 				break;
5130 			case STMF_PS_ERROR_VERSION_MISMATCH:
5131 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
5132 				break;
5133 			default:
5134 				ret = STMF_STATUS_ERROR;
5135 				break;
5136 		}
5137 		if (ret != STMF_STATUS_SUCCESS) {
5138 			goto out;
5139 		}
5140 
5141 		/* call setProviderData */
5142 		ret = setProviderData(fd, providerList->provider[i].name, nvl,
5143 		    providerType, NULL);
5144 		switch (ret) {
5145 			case STMF_PS_SUCCESS:
5146 				ret = STMF_STATUS_SUCCESS;
5147 				break;
5148 			case STMF_PS_ERROR_NOT_FOUND:
5149 				ret = STMF_ERROR_NOT_FOUND;
5150 				break;
5151 			case STMF_PS_ERROR_BUSY:
5152 				ret = STMF_ERROR_BUSY;
5153 				break;
5154 			case STMF_PS_ERROR_SERVICE_NOT_FOUND:
5155 				ret = STMF_ERROR_SERVICE_NOT_FOUND;
5156 				break;
5157 			case STMF_PS_ERROR_VERSION_MISMATCH:
5158 				ret = STMF_ERROR_SERVICE_DATA_VERSION;
5159 				break;
5160 			default:
5161 				ret = STMF_STATUS_ERROR;
5162 				break;
5163 		}
5164 		if (ret != STMF_STATUS_SUCCESS) {
5165 			goto out;
5166 		}
5167 
5168 		nvlist_free(nvl);
5169 		nvl = NULL;
5170 	}
5171 out:
5172 	if (groupList != NULL) {
5173 		free(groupList);
5174 	}
5175 	if (guidList != NULL) {
5176 		free(guidList);
5177 	}
5178 	if (viewEntryList != NULL) {
5179 		free(viewEntryList);
5180 	}
5181 	if (nvl != NULL) {
5182 		nvlist_free(nvl);
5183 	}
5184 	return (ret);
5185 }
5186 
5187 /*
5188  * stmfGetAluaState
5189  *
5190  * Purpose - Get the alua state
5191  *
5192  */
5193 int
stmfGetAluaState(boolean_t * enabled,uint32_t * node)5194 stmfGetAluaState(boolean_t *enabled, uint32_t *node)
5195 {
5196 	int ret = STMF_STATUS_SUCCESS;
5197 	int fd;
5198 	stmf_iocdata_t stmfIoctl = {0};
5199 	stmf_alua_state_desc_t alua_state = {0};
5200 	int ioctlRet;
5201 
5202 	if (enabled == NULL || node == NULL) {
5203 		return (STMF_ERROR_INVALID_ARG);
5204 	}
5205 
5206 	/*
5207 	 * Open control node for stmf
5208 	 */
5209 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5210 		return (ret);
5211 
5212 	/*
5213 	 * Issue ioctl to get the stmf state
5214 	 */
5215 	stmfIoctl.stmf_version = STMF_VERSION_1;
5216 	stmfIoctl.stmf_obuf_size = sizeof (alua_state);
5217 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&alua_state;
5218 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_ALUA_STATE, &stmfIoctl);
5219 
5220 	(void) close(fd);
5221 
5222 	if (ioctlRet != 0) {
5223 		switch (errno) {
5224 			case EBUSY:
5225 				ret = STMF_ERROR_BUSY;
5226 				break;
5227 			case EPERM:
5228 			case EACCES:
5229 				ret = STMF_ERROR_PERM;
5230 				break;
5231 			default:
5232 				syslog(LOG_DEBUG,
5233 				    "getStmfState:ioctl errno(%d)", errno);
5234 				ret = STMF_STATUS_ERROR;
5235 				break;
5236 		}
5237 	} else {
5238 		if (alua_state.alua_state == 1) {
5239 			*enabled = B_TRUE;
5240 		} else {
5241 			*enabled = B_FALSE;
5242 		}
5243 		*node = alua_state.alua_node;
5244 	}
5245 
5246 	return (ret);
5247 }
5248 
5249 /*
5250  * stmfSetAluaState
5251  *
5252  * Purpose - set the alua state to enabled/disabled
5253  *
5254  */
5255 int
stmfSetAluaState(boolean_t enabled,uint32_t node)5256 stmfSetAluaState(boolean_t enabled, uint32_t node)
5257 {
5258 	int ret = STMF_STATUS_SUCCESS;
5259 	int fd;
5260 	stmf_iocdata_t stmfIoctl = {0};
5261 	stmf_alua_state_desc_t alua_state = {0};
5262 	int ioctlRet;
5263 
5264 	if ((enabled != B_TRUE && enabled != B_FALSE) || (node > 1)) {
5265 		return (STMF_ERROR_INVALID_ARG);
5266 	}
5267 
5268 	if (enabled) {
5269 		alua_state.alua_state = 1;
5270 	}
5271 
5272 	alua_state.alua_node = node;
5273 
5274 	/*
5275 	 * Open control node for stmf
5276 	 */
5277 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5278 		return (ret);
5279 
5280 	/*
5281 	 * Issue ioctl to get the stmf state
5282 	 */
5283 	stmfIoctl.stmf_version = STMF_VERSION_1;
5284 	stmfIoctl.stmf_ibuf_size = sizeof (alua_state);
5285 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&alua_state;
5286 	ioctlRet = ioctl(fd, STMF_IOCTL_SET_ALUA_STATE, &stmfIoctl);
5287 
5288 	(void) close(fd);
5289 
5290 	if (ioctlRet != 0) {
5291 		switch (errno) {
5292 			case EBUSY:
5293 				ret = STMF_ERROR_BUSY;
5294 				break;
5295 			case EPERM:
5296 			case EACCES:
5297 				ret = STMF_ERROR_PERM;
5298 				break;
5299 			default:
5300 				syslog(LOG_DEBUG,
5301 				    "getStmfState:ioctl errno(%d)", errno);
5302 				ret = STMF_STATUS_ERROR;
5303 				break;
5304 		}
5305 	}
5306 	if (!enabled && ret == STMF_STATUS_SUCCESS) {
5307 		deleteNonActiveLus();
5308 	}
5309 
5310 	return (ret);
5311 }
5312 
5313 static void
deleteNonActiveLus()5314 deleteNonActiveLus()
5315 {
5316 	int stmfRet;
5317 	int i;
5318 	stmfGuidList *luList;
5319 	luResource hdl = NULL;
5320 	char propVal[10];
5321 	size_t propValSize = sizeof (propVal);
5322 
5323 	stmfRet = stmfGetLogicalUnitList(&luList);
5324 	if (stmfRet != STMF_STATUS_SUCCESS) {
5325 		return;
5326 	}
5327 
5328 	for (i = 0; i < luList->cnt; i++) {
5329 		stmfRet = stmfGetLuResource(&luList->guid[i], &hdl);
5330 		if (stmfRet != STMF_STATUS_SUCCESS) {
5331 			goto err;
5332 		}
5333 		stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_ACCESS_STATE, propVal,
5334 		    &propValSize);
5335 		if (stmfRet != STMF_STATUS_SUCCESS) {
5336 			goto err;
5337 		}
5338 		if (propVal[0] == '0') {
5339 			(void) stmfFreeLuResource(hdl);
5340 			hdl = NULL;
5341 			continue;
5342 		}
5343 		(void) stmfDeleteLu(&luList->guid[i]);
5344 		(void) stmfFreeLuResource(hdl);
5345 		hdl = NULL;
5346 	}
5347 
5348 err:
5349 	stmfFreeMemory(luList);
5350 	(void) stmfFreeLuResource(hdl);
5351 }
5352 
5353 /*
5354  * stmfLoadConfig
5355  *
5356  * Purpose - load the configuration data from smf into stmf
5357  *
5358  */
5359 int
stmfLoadConfig(void)5360 stmfLoadConfig(void)
5361 {
5362 	int ret = STMF_STATUS_SUCCESS;
5363 	int fd;
5364 	stmf_state_desc_t stmfStateSet;
5365 	stmfState state;
5366 
5367 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5368 		stmfStateSet.state = STMF_STATE_OFFLINE;
5369 
5370 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
5371 		    != STMF_STATUS_SUCCESS) {
5372 			return (ret);
5373 		}
5374 		/*
5375 		 * Configuration not stored persistently; nothing to
5376 		 * initialize so do not set to STMF_CONFIG_INIT.
5377 		 */
5378 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
5379 		goto done;
5380 	}
5381 
5382 	/* Check to ensure service exists */
5383 	if (psCheckService() != STMF_STATUS_SUCCESS) {
5384 		return (STMF_ERROR_SERVICE_NOT_FOUND);
5385 	}
5386 
5387 	ret = stmfGetState(&state);
5388 	if (ret == STMF_STATUS_SUCCESS) {
5389 		if (state.operationalState != STMF_SERVICE_STATE_OFFLINE) {
5390 			return (STMF_ERROR_SERVICE_ONLINE);
5391 		}
5392 	} else {
5393 		return (STMF_STATUS_ERROR);
5394 	}
5395 
5396 
5397 	stmfStateSet.state = STMF_STATE_OFFLINE;
5398 	stmfStateSet.config_state = STMF_CONFIG_INIT;
5399 
5400 	/*
5401 	 * Open control node for stmf
5402 	 */
5403 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5404 		return (ret);
5405 
5406 	ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
5407 	if (ret != STMF_STATUS_SUCCESS) {
5408 		goto done;
5409 	}
5410 
5411 	/* Load the persistent configuration data */
5412 	ret = loadStore(fd);
5413 	if (ret != 0) {
5414 		goto done;
5415 	}
5416 
5417 	stmfStateSet.state = STMF_STATE_OFFLINE;
5418 	stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
5419 
5420 done:
5421 	if (ret == STMF_STATUS_SUCCESS) {
5422 		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
5423 	}
5424 	(void) close(fd);
5425 	return (ret);
5426 }
5427 
5428 
5429 /*
5430  * getStmfState
5431  *
5432  * stmfState - pointer to stmf_state_desc_t structure. Will contain the state
5433  *             information of the stmf service on success.
5434  */
5435 static int
getStmfState(stmf_state_desc_t * stmfState)5436 getStmfState(stmf_state_desc_t *stmfState)
5437 {
5438 	int ret = STMF_STATUS_SUCCESS;
5439 	int fd;
5440 	int ioctlRet;
5441 	stmf_iocdata_t stmfIoctl;
5442 
5443 	/*
5444 	 * Open control node for stmf
5445 	 */
5446 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5447 		return (ret);
5448 
5449 	bzero(&stmfIoctl, sizeof (stmfIoctl));
5450 	/*
5451 	 * Issue ioctl to get the stmf state
5452 	 */
5453 	stmfIoctl.stmf_version = STMF_VERSION_1;
5454 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
5455 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
5456 	stmfIoctl.stmf_obuf_size = sizeof (stmf_state_desc_t);
5457 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)stmfState;
5458 	ioctlRet = ioctl(fd, STMF_IOCTL_GET_STMF_STATE, &stmfIoctl);
5459 
5460 	(void) close(fd);
5461 
5462 	if (ioctlRet != 0) {
5463 		switch (errno) {
5464 			case EBUSY:
5465 				ret = STMF_ERROR_BUSY;
5466 				break;
5467 			case EPERM:
5468 			case EACCES:
5469 				ret = STMF_ERROR_PERM;
5470 				break;
5471 			default:
5472 				syslog(LOG_DEBUG,
5473 				    "getStmfState:ioctl errno(%d)", errno);
5474 				ret = STMF_STATUS_ERROR;
5475 				break;
5476 		}
5477 	}
5478 	return (ret);
5479 }
5480 
5481 
5482 /*
5483  * setStmfState
5484  *
5485  * stmfState - pointer to caller set state structure
5486  * objectType - one of:
5487  *		LOGICAL_UNIT_TYPE
5488  *		TARGET_TYPE
5489  *		STMF_SERVICE_TYPE
5490  */
5491 static int
setStmfState(int fd,stmf_state_desc_t * stmfState,int objectType)5492 setStmfState(int fd, stmf_state_desc_t *stmfState, int objectType)
5493 {
5494 	int ret = STMF_STATUS_SUCCESS;
5495 	int ioctlRet;
5496 	int cmd;
5497 	stmf_iocdata_t stmfIoctl;
5498 
5499 	switch (objectType) {
5500 		case LOGICAL_UNIT_TYPE:
5501 			cmd = STMF_IOCTL_SET_LU_STATE;
5502 			break;
5503 		case TARGET_TYPE:
5504 			cmd = STMF_IOCTL_SET_TARGET_PORT_STATE;
5505 			break;
5506 		case STMF_SERVICE_TYPE:
5507 			cmd = STMF_IOCTL_SET_STMF_STATE;
5508 			break;
5509 		default:
5510 			ret = STMF_STATUS_ERROR;
5511 			goto done;
5512 	}
5513 
5514 	bzero(&stmfIoctl, sizeof (stmfIoctl));
5515 	/*
5516 	 * Issue ioctl to set the stmf state
5517 	 */
5518 	stmfIoctl.stmf_version = STMF_VERSION_1;
5519 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_state_desc_t);
5520 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)stmfState;
5521 	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
5522 	if (ioctlRet != 0) {
5523 		switch (errno) {
5524 			case EBUSY:
5525 				ret = STMF_ERROR_BUSY;
5526 				break;
5527 			case EPERM:
5528 			case EACCES:
5529 				ret = STMF_ERROR_PERM;
5530 				break;
5531 			case ENOENT:
5532 				ret = STMF_ERROR_NOT_FOUND;
5533 				break;
5534 			default:
5535 				syslog(LOG_DEBUG,
5536 				    "setStmfState:ioctl errno(%d)", errno);
5537 				ret = STMF_STATUS_ERROR;
5538 				break;
5539 		}
5540 	}
5541 done:
5542 	return (ret);
5543 }
5544 int
stmfSetStmfProp(uint8_t propType,char * propVal)5545 stmfSetStmfProp(uint8_t propType, char *propVal)
5546 {
5547 	int ret = STMF_STATUS_SUCCESS;
5548 	switch (propType) {
5549 		case STMF_DEFAULT_LU_STATE:
5550 			break;
5551 		case STMF_DEFAULT_TARGET_PORT_STATE:
5552 			break;
5553 		default:
5554 			return (STMF_ERROR_INVALID_ARG);
5555 	}
5556 	ret = psSetStmfProp(propType, propVal);
5557 	switch (ret) {
5558 		case STMF_PS_SUCCESS:
5559 			ret = STMF_STATUS_SUCCESS;
5560 			break;
5561 		case STMF_PS_ERROR_BUSY:
5562 			ret = STMF_ERROR_BUSY;
5563 			break;
5564 		default:
5565 			syslog(LOG_DEBUG,
5566 			    "stmfSetStmfProp:psSetStmfProp:error(%d)",
5567 			    ret);
5568 			ret = STMF_STATUS_ERROR;
5569 			break;
5570 	}
5571 	return (ret);
5572 }
5573 
5574 
5575 int
stmfGetStmfProp(uint8_t propType,char * propVal,size_t * propLen)5576 stmfGetStmfProp(uint8_t propType, char *propVal, size_t *propLen)
5577 {
5578 	int ret = STMF_STATUS_SUCCESS;
5579 	char prop[MAXNAMELEN] = {0};
5580 	size_t reqLen;
5581 
5582 	if (propVal == NULL || propLen == NULL) {
5583 		return (STMF_ERROR_INVALID_ARG);
5584 	}
5585 	switch (propType) {
5586 		case STMF_DEFAULT_LU_STATE:
5587 			break;
5588 		case STMF_DEFAULT_TARGET_PORT_STATE:
5589 			break;
5590 		default:
5591 			return (STMF_ERROR_INVALID_ARG);
5592 	}
5593 	ret = psGetStmfProp(propType, prop);
5594 	if ((reqLen = strlcpy(propVal, prop, *propLen)) >= *propLen) {
5595 		*propLen = reqLen + 1;
5596 		return (STMF_ERROR_INVALID_ARG);
5597 	}
5598 
5599 	switch (ret) {
5600 		case STMF_PS_SUCCESS:
5601 			ret = STMF_STATUS_SUCCESS;
5602 			break;
5603 		case STMF_PS_ERROR_BUSY:
5604 			ret = STMF_ERROR_BUSY;
5605 			break;
5606 		case STMF_PS_ERROR_NOT_FOUND:
5607 			ret = STMF_ERROR_NOT_FOUND;
5608 			break;
5609 		default:
5610 			syslog(LOG_DEBUG,
5611 			    "stmfGetStmfProp:psGetStmfProp:error(%d)",
5612 			    ret);
5613 			ret = STMF_STATUS_ERROR;
5614 			break;
5615 	}
5616 	return (ret);
5617 }
5618 
5619 static int
setStmfProp(stmf_set_props_t * stmf_set_props)5620 setStmfProp(stmf_set_props_t *stmf_set_props)
5621 {
5622 	char propVal[MAXNAMELEN] = {0};
5623 	int ret;
5624 	if ((ret = psGetStmfProp(STMF_DEFAULT_LU_STATE, propVal)) ==
5625 	    STMF_PS_SUCCESS) {
5626 		if (strncmp(propVal, "offline", strlen(propVal)) == 0) {
5627 			stmf_set_props->default_lu_state_value =
5628 			    STMF_STATE_OFFLINE;
5629 		} else {
5630 			stmf_set_props->default_lu_state_value =
5631 			    STMF_STATE_ONLINE;
5632 		}
5633 	} else {
5634 		syslog(LOG_DEBUG,
5635 		    "DefaultLuState:psSetStmfProp:error(%d)", ret);
5636 		goto done;
5637 	}
5638 
5639 	if ((ret = psGetStmfProp(STMF_DEFAULT_TARGET_PORT_STATE, propVal)) ==
5640 	    STMF_PS_SUCCESS) {
5641 		if (strncmp(propVal, "offline", strlen(propVal)) == 0) {
5642 			stmf_set_props->default_target_state_value =
5643 			    STMF_STATE_OFFLINE;
5644 		} else {
5645 			stmf_set_props->default_target_state_value =
5646 			    STMF_STATE_ONLINE;
5647 		}
5648 	} else {
5649 		syslog(LOG_DEBUG,
5650 		    "DefaultTargetPortState:psSetStmfProp:error(%d)", ret);
5651 		goto done;
5652 	}
5653 done:
5654 	switch (ret) {
5655 		case STMF_PS_SUCCESS:
5656 			ret = STMF_STATUS_SUCCESS;
5657 			break;
5658 		case STMF_PS_ERROR_NOT_FOUND:
5659 			ret = STMF_ERROR_NOT_FOUND;
5660 			break;
5661 		case STMF_PS_ERROR_BUSY:
5662 			ret = STMF_ERROR_BUSY;
5663 			break;
5664 		default:
5665 			ret = STMF_STATUS_ERROR;
5666 			break;
5667 	}
5668 	return (ret);
5669 }
5670 
5671 static int
loadStmfProp(int fd)5672 loadStmfProp(int fd)
5673 {
5674 	int ret = STMF_STATUS_SUCCESS;
5675 	int ioctlRet;
5676 	stmf_iocdata_t stmfIoctl = {0};
5677 	stmf_set_props_t *stmf_set_props = NULL;
5678 
5679 	stmf_set_props = (stmf_set_props_t *)
5680 	    calloc(1, (sizeof (stmf_set_props_t)));
5681 	if (stmf_set_props == NULL) {
5682 		ret = STMF_ERROR_NOMEM;
5683 		goto done;
5684 	}
5685 
5686 	/* Loading the default property values from smf */
5687 
5688 	if ((ret = setStmfProp(stmf_set_props)) != STMF_STATUS_SUCCESS)
5689 		goto done;
5690 
5691 	stmfIoctl.stmf_version = STMF_VERSION_1;
5692 	stmfIoctl.stmf_ibuf_size = sizeof (stmf_set_props_t);
5693 	stmfIoctl.stmf_ibuf =
5694 	    (uint64_t)(unsigned long)stmf_set_props;
5695 
5696 	ioctlRet = ioctl(fd, STMF_IOCTL_SET_STMF_PROPS,
5697 	    &stmfIoctl);
5698 
5699 	if (ioctlRet != 0) {
5700 		switch (errno) {
5701 			case EBUSY:
5702 				ret = STMF_ERROR_BUSY;
5703 				break;
5704 			case EPERM:
5705 			case EACCES:
5706 				ret = STMF_ERROR_PERM;
5707 				break;
5708 			case ENOENT:
5709 				ret = STMF_ERROR_NOT_FOUND;
5710 				break;
5711 			default:
5712 				syslog(LOG_DEBUG,
5713 				    "setDefaultStmfState:"
5714 				    "ioctl errno(%d)", errno);
5715 				ret = STMF_STATUS_ERROR;
5716 				break;
5717 		}
5718 	}
5719 done:
5720 	if (stmf_set_props != NULL) {
5721 		free(stmf_set_props);
5722 	}
5723 	return (ret);
5724 }
5725 
5726 int
stmfLoadStmfProps(void)5727 stmfLoadStmfProps(void)
5728 {
5729 	int ret = STMF_STATUS_SUCCESS;
5730 	int fd;
5731 	/* open control node for stmf */
5732 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
5733 	    != STMF_STATUS_SUCCESS) {
5734 		goto done;
5735 	}
5736 	ret = loadStmfProp(fd);
5737 
5738 	(void) close(fd);
5739 done:
5740 	if (ret != STMF_STATUS_SUCCESS) {
5741 		syslog(LOG_DEBUG,
5742 		    "stmfLoadStmfProps:Failed");
5743 	}
5744 	return (ret);
5745 }
5746 
5747 /*
5748  * stmfOnline
5749  *
5750  * Purpose: Online stmf service
5751  *
5752  */
5753 int
stmfOnline(void)5754 stmfOnline(void)
5755 {
5756 	int ret;
5757 	int fd;
5758 	stmfState state;
5759 	stmf_state_desc_t iState;
5760 
5761 	ret = stmfGetState(&state);
5762 	if (ret == STMF_STATUS_SUCCESS) {
5763 		if (state.operationalState == STMF_SERVICE_STATE_ONLINE) {
5764 			return (STMF_ERROR_SERVICE_ONLINE);
5765 		}
5766 	} else {
5767 		return (STMF_STATUS_ERROR);
5768 	}
5769 	iState.state = STMF_STATE_ONLINE;
5770 	iState.config_state = STMF_CONFIG_NONE;
5771 	/*
5772 	 * Open control node for stmf
5773 	 * to make call to setStmfState()
5774 	 */
5775 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5776 		return (ret);
5777 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
5778 	(void) close(fd);
5779 	return (ret);
5780 }
5781 
5782 /*
5783  * stmfOffline
5784  *
5785  * Purpose: Offline stmf service
5786  *
5787  */
5788 int
stmfOffline(void)5789 stmfOffline(void)
5790 {
5791 	int ret;
5792 	int fd;
5793 	stmfState state;
5794 	stmf_state_desc_t iState;
5795 
5796 	ret = stmfGetState(&state);
5797 	if (ret == STMF_STATUS_SUCCESS) {
5798 		if (state.operationalState == STMF_SERVICE_STATE_OFFLINE) {
5799 			return (STMF_ERROR_SERVICE_OFFLINE);
5800 		}
5801 	} else {
5802 		return (STMF_STATUS_ERROR);
5803 	}
5804 	iState.state = STMF_STATE_OFFLINE;
5805 	iState.config_state = STMF_CONFIG_NONE;
5806 
5807 	/*
5808 	 * Open control node for stmf
5809 	 * to make call to setStmfState()
5810 	 */
5811 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5812 		return (ret);
5813 	ret = setStmfState(fd, &iState, STMF_SERVICE_TYPE);
5814 	(void) close(fd);
5815 	return (ret);
5816 }
5817 
5818 
5819 /*
5820  * stmfOfflineTarget
5821  *
5822  * Purpose: Change state of target to offline
5823  *
5824  * devid - devid of the target to offline
5825  */
5826 int
stmfOfflineTarget(stmfDevid * devid)5827 stmfOfflineTarget(stmfDevid *devid)
5828 {
5829 	stmf_state_desc_t targetState;
5830 	int ret = STMF_STATUS_SUCCESS;
5831 	int fd;
5832 
5833 	if (devid == NULL) {
5834 		return (STMF_ERROR_INVALID_ARG);
5835 	}
5836 	bzero(&targetState, sizeof (targetState));
5837 
5838 	targetState.state = STMF_STATE_OFFLINE;
5839 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
5840 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
5841 	    devid->identLength);
5842 	/*
5843 	 * Open control node for stmf
5844 	 * to make call to setStmfState()
5845 	 */
5846 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5847 		return (ret);
5848 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
5849 	(void) close(fd);
5850 	return (ret);
5851 }
5852 
5853 /*
5854  * stmfOfflineLogicalUnit
5855  *
5856  * Purpose: Change state of logical unit to offline
5857  *
5858  * lu - guid of the logical unit to offline
5859  */
5860 int
stmfOfflineLogicalUnit(stmfGuid * lu)5861 stmfOfflineLogicalUnit(stmfGuid *lu)
5862 {
5863 	stmf_state_desc_t luState;
5864 	int ret = STMF_STATUS_SUCCESS;
5865 	int fd;
5866 
5867 	if (lu == NULL) {
5868 		return (STMF_ERROR_INVALID_ARG);
5869 	}
5870 
5871 	bzero(&luState, sizeof (luState));
5872 
5873 	luState.state = STMF_STATE_OFFLINE;
5874 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
5875 	/*
5876 	 * Open control node for stmf
5877 	 * to make call to setStmfState()
5878 	 */
5879 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5880 		return (ret);
5881 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
5882 	(void) close(fd);
5883 	return (ret);
5884 }
5885 
5886 /*
5887  * stmfOnlineTarget
5888  *
5889  * Purpose: Change state of target to online
5890  *
5891  * devid - devid of the target to online
5892  */
5893 int
stmfOnlineTarget(stmfDevid * devid)5894 stmfOnlineTarget(stmfDevid *devid)
5895 {
5896 	stmf_state_desc_t targetState;
5897 	int ret = STMF_STATUS_SUCCESS;
5898 	int fd;
5899 
5900 	if (devid == NULL) {
5901 		return (STMF_ERROR_INVALID_ARG);
5902 	}
5903 	bzero(&targetState, sizeof (targetState));
5904 
5905 	targetState.state = STMF_STATE_ONLINE;
5906 	targetState.ident[IDENT_LENGTH_BYTE] = devid->identLength;
5907 	bcopy(&(devid->ident), &targetState.ident[IDENT_LENGTH_BYTE + 1],
5908 	    devid->identLength);
5909 	/*
5910 	 * Open control node for stmf
5911 	 * to make call to setStmfState()
5912 	 */
5913 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5914 		return (ret);
5915 	ret = setStmfState(fd, &targetState, TARGET_TYPE);
5916 	(void) close(fd);
5917 	return (ret);
5918 }
5919 
5920 /*
5921  * stmfOnlineLogicalUnit
5922  *
5923  * Purpose: Change state of logical unit to online
5924  *
5925  * lu - guid of the logical unit to online
5926  */
5927 int
stmfOnlineLogicalUnit(stmfGuid * lu)5928 stmfOnlineLogicalUnit(stmfGuid *lu)
5929 {
5930 	stmf_state_desc_t luState;
5931 	int ret = STMF_STATUS_SUCCESS;
5932 	int fd;
5933 
5934 	if (lu == NULL) {
5935 		return (STMF_ERROR_INVALID_ARG);
5936 	}
5937 
5938 	bzero(&luState, sizeof (luState));
5939 
5940 	luState.state = STMF_STATE_ONLINE;
5941 	bcopy(lu, &luState.ident, sizeof (stmfGuid));
5942 	/*
5943 	 * Open control node for stmf
5944 	 * to make call to setStmfState()
5945 	 */
5946 	if ((ret = openStmf(OPEN_EXCL_STMF, &fd)) != STMF_STATUS_SUCCESS)
5947 		return (ret);
5948 	ret = setStmfState(fd, &luState, LOGICAL_UNIT_TYPE);
5949 	(void) close(fd);
5950 	return (ret);
5951 }
5952 
5953 /*
5954  * stmfRemoveFromHostGroup
5955  *
5956  * Purpose: Removes an initiator from an initiator group
5957  *
5958  * hostGroupName - name of an initiator group
5959  * hostName - name of host group member to remove
5960  */
5961 int
stmfRemoveFromHostGroup(stmfGroupName * hostGroupName,stmfDevid * hostName)5962 stmfRemoveFromHostGroup(stmfGroupName *hostGroupName, stmfDevid *hostName)
5963 {
5964 	int ret;
5965 	int fd;
5966 
5967 	if (hostGroupName == NULL ||
5968 	    (strnlen((char *)hostGroupName, sizeof (stmfGroupName))
5969 	    == sizeof (stmfGroupName)) || hostName == NULL) {
5970 		return (STMF_ERROR_INVALID_ARG);
5971 	}
5972 
5973 	/* call init */
5974 	ret = initializeConfig();
5975 	if (ret != STMF_STATUS_SUCCESS) {
5976 		return (ret);
5977 	}
5978 
5979 	/*
5980 	 * Open control node for stmf
5981 	 */
5982 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
5983 		return (ret);
5984 
5985 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_HG_ENTRY,
5986 	    hostGroupName, hostName)) != STMF_STATUS_SUCCESS) {
5987 		goto done;
5988 	}
5989 
5990 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
5991 		goto done;
5992 	}
5993 
5994 	ret = psRemoveHostGroupMember((char *)hostGroupName,
5995 	    (char *)hostName->ident);
5996 	switch (ret) {
5997 		case STMF_PS_SUCCESS:
5998 			ret = STMF_STATUS_SUCCESS;
5999 			break;
6000 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
6001 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
6002 			break;
6003 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
6004 			ret = STMF_ERROR_GROUP_NOT_FOUND;
6005 			break;
6006 		case STMF_PS_ERROR_BUSY:
6007 			ret = STMF_ERROR_BUSY;
6008 			break;
6009 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6010 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
6011 			break;
6012 		case STMF_PS_ERROR_VERSION_MISMATCH:
6013 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
6014 			break;
6015 		default:
6016 			syslog(LOG_DEBUG,
6017 			    "stmfRemoveFromHostGroup"
6018 			    "psRemoveHostGroupMember:error(%d)", ret);
6019 			ret = STMF_STATUS_ERROR;
6020 			break;
6021 	}
6022 
6023 done:
6024 	(void) close(fd);
6025 	return (ret);
6026 }
6027 
6028 /*
6029  * stmfRemoveFromTargetGroup
6030  *
6031  * Purpose: Removes a local port from a local port group
6032  *
6033  * targetGroupName - name of a target group
6034  * targetName - name of target to remove
6035  */
6036 int
stmfRemoveFromTargetGroup(stmfGroupName * targetGroupName,stmfDevid * targetName)6037 stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName, stmfDevid *targetName)
6038 {
6039 	int ret;
6040 	int fd;
6041 
6042 	if (targetGroupName == NULL ||
6043 	    (strnlen((char *)targetGroupName, sizeof (stmfGroupName))
6044 	    == sizeof (stmfGroupName)) || targetName == NULL) {
6045 		return (STMF_ERROR_INVALID_ARG);
6046 	}
6047 
6048 	/* call init */
6049 	ret = initializeConfig();
6050 	if (ret != STMF_STATUS_SUCCESS) {
6051 		return (ret);
6052 	}
6053 
6054 	/*
6055 	 * Open control node for stmf
6056 	 */
6057 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6058 		return (ret);
6059 
6060 	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_REMOVE_TG_ENTRY,
6061 	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
6062 		goto done;
6063 	}
6064 
6065 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6066 		goto done;
6067 	}
6068 
6069 	ret = psRemoveTargetGroupMember((char *)targetGroupName,
6070 	    (char *)targetName->ident);
6071 	switch (ret) {
6072 		case STMF_PS_SUCCESS:
6073 			ret = STMF_STATUS_SUCCESS;
6074 			break;
6075 		case STMF_PS_ERROR_MEMBER_NOT_FOUND:
6076 			ret = STMF_ERROR_MEMBER_NOT_FOUND;
6077 			break;
6078 		case STMF_PS_ERROR_GROUP_NOT_FOUND:
6079 			ret = STMF_ERROR_GROUP_NOT_FOUND;
6080 			break;
6081 		case STMF_PS_ERROR_BUSY:
6082 			ret = STMF_ERROR_BUSY;
6083 			break;
6084 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6085 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
6086 			break;
6087 		case STMF_PS_ERROR_VERSION_MISMATCH:
6088 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
6089 			break;
6090 		default:
6091 			syslog(LOG_DEBUG,
6092 			    "stmfRemoveFromTargetGroup"
6093 			    "psRemoveTargetGroupMember:error(%d)", ret);
6094 			ret = STMF_STATUS_ERROR;
6095 			break;
6096 	}
6097 
6098 done:
6099 	(void) close(fd);
6100 	return (ret);
6101 }
6102 
6103 /*
6104  * stmfRemoveViewEntry
6105  *
6106  * Purpose: Removes a view entry from a logical unit
6107  *
6108  * lu - guid of lu for which view entry is being removed
6109  * viewEntryIndex - index of view entry to remove
6110  *
6111  */
6112 int
stmfRemoveViewEntry(stmfGuid * lu,uint32_t viewEntryIndex)6113 stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex)
6114 {
6115 	int ret = STMF_STATUS_SUCCESS;
6116 	int fd;
6117 	int ioctlRet;
6118 	stmf_iocdata_t stmfIoctl;
6119 	stmf_view_op_entry_t ioctlViewEntry;
6120 
6121 	if (lu == NULL) {
6122 		return (STMF_ERROR_INVALID_ARG);
6123 	}
6124 
6125 	/* call init */
6126 	ret = initializeConfig();
6127 	if (ret != STMF_STATUS_SUCCESS) {
6128 		return (ret);
6129 	}
6130 
6131 	/*
6132 	 * Open control node for stmf
6133 	 */
6134 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6135 		return (ret);
6136 
6137 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
6138 	ioctlViewEntry.ve_ndx_valid = B_TRUE;
6139 	ioctlViewEntry.ve_ndx = viewEntryIndex;
6140 	bcopy(lu, &ioctlViewEntry.ve_guid, sizeof (stmfGuid));
6141 
6142 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6143 	/*
6144 	 * Issue ioctl to add to the view entry
6145 	 */
6146 	stmfIoctl.stmf_version = STMF_VERSION_1;
6147 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6148 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6149 	ioctlRet = ioctl(fd, STMF_IOCTL_REMOVE_VIEW_ENTRY, &stmfIoctl);
6150 	if (ioctlRet != 0) {
6151 		switch (errno) {
6152 			case EBUSY:
6153 				ret = STMF_ERROR_BUSY;
6154 				break;
6155 			case EPERM:
6156 				ret = STMF_ERROR_PERM;
6157 				break;
6158 			case EACCES:
6159 				switch (stmfIoctl.stmf_error) {
6160 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6161 						ret = STMF_ERROR_CONFIG_NONE;
6162 						break;
6163 					default:
6164 						ret = STMF_ERROR_PERM;
6165 						break;
6166 				}
6167 				break;
6168 			case ENODEV:
6169 			case ENOENT:
6170 				ret = STMF_ERROR_NOT_FOUND;
6171 				break;
6172 			default:
6173 				syslog(LOG_DEBUG,
6174 				    "stmfRemoveViewEntry:ioctl errno(%d)",
6175 				    errno);
6176 				ret = STMF_STATUS_ERROR;
6177 				break;
6178 		}
6179 		goto done;
6180 	}
6181 
6182 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6183 		goto done;
6184 	}
6185 
6186 	ret = psRemoveViewEntry(lu, viewEntryIndex);
6187 	switch (ret) {
6188 		case STMF_PS_SUCCESS:
6189 			ret = STMF_STATUS_SUCCESS;
6190 			break;
6191 		case STMF_PS_ERROR_NOT_FOUND:
6192 			ret = STMF_ERROR_NOT_FOUND;
6193 			break;
6194 		case STMF_PS_ERROR_BUSY:
6195 			ret = STMF_ERROR_BUSY;
6196 			break;
6197 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6198 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
6199 			break;
6200 		case STMF_PS_ERROR_VERSION_MISMATCH:
6201 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
6202 			break;
6203 		default:
6204 			syslog(LOG_DEBUG,
6205 			    "stmfRemoveViewEntry" "psRemoveViewEntry:error(%d)",
6206 			    ret);
6207 			ret = STMF_STATUS_ERROR;
6208 			break;
6209 	}
6210 
6211 done:
6212 	(void) close(fd);
6213 	return (ret);
6214 }
6215 
6216 /*
6217  * stmfSetProviderData
6218  *
6219  * Purpose: set the provider data
6220  *
6221  * providerName - unique name of provider
6222  * nvl - nvlist to set
6223  * providerType - type of provider for which to set data
6224  *		STMF_LU_PROVIDER_TYPE
6225  *		STMF_PORT_PROVIDER_TYPE
6226  */
6227 int
stmfSetProviderData(char * providerName,nvlist_t * nvl,int providerType)6228 stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType)
6229 {
6230 	return (stmfSetProviderDataProt(providerName, nvl, providerType,
6231 	    NULL));
6232 }
6233 
6234 /*
6235  * stmfSetProviderDataProt
6236  *
6237  * Purpose: set the provider data
6238  *
6239  * providerName - unique name of provider
6240  * nvl - nvlist to set
6241  * providerType - type of provider for which to set data
6242  *		STMF_LU_PROVIDER_TYPE
6243  *		STMF_PORT_PROVIDER_TYPE
6244  * setToken - Stale data token returned in the stmfGetProviderDataProt()
6245  *	      call or NULL.
6246  */
6247 int
stmfSetProviderDataProt(char * providerName,nvlist_t * nvl,int providerType,uint64_t * setToken)6248 stmfSetProviderDataProt(char *providerName, nvlist_t *nvl, int providerType,
6249     uint64_t *setToken)
6250 {
6251 	int ret;
6252 	int fd;
6253 
6254 	if (providerName == NULL || nvl == NULL) {
6255 		return (STMF_ERROR_INVALID_ARG);
6256 	}
6257 
6258 	if (providerType != STMF_LU_PROVIDER_TYPE &&
6259 	    providerType != STMF_PORT_PROVIDER_TYPE) {
6260 		return (STMF_ERROR_INVALID_ARG);
6261 	}
6262 
6263 	/* call init */
6264 	ret = initializeConfig();
6265 	if (ret != STMF_STATUS_SUCCESS) {
6266 		return (ret);
6267 	}
6268 
6269 	/*
6270 	 * Open control node for stmf
6271 	 */
6272 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6273 		return (ret);
6274 
6275 	ret = setProviderData(fd, providerName, nvl, providerType, setToken);
6276 
6277 	(void) close(fd);
6278 
6279 	if (ret != STMF_STATUS_SUCCESS) {
6280 		goto done;
6281 	}
6282 
6283 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
6284 		goto done;
6285 	}
6286 
6287 	/* setting driver provider data successful. Now persist it */
6288 	ret = psSetProviderData(providerName, nvl, providerType, NULL);
6289 	switch (ret) {
6290 		case STMF_PS_SUCCESS:
6291 			ret = STMF_STATUS_SUCCESS;
6292 			break;
6293 		case STMF_PS_ERROR_EXISTS:
6294 			ret = STMF_ERROR_EXISTS;
6295 			break;
6296 		case STMF_PS_ERROR_BUSY:
6297 			ret = STMF_ERROR_BUSY;
6298 			break;
6299 		case STMF_PS_ERROR_SERVICE_NOT_FOUND:
6300 			ret = STMF_ERROR_SERVICE_NOT_FOUND;
6301 			break;
6302 		case STMF_PS_ERROR_VERSION_MISMATCH:
6303 			ret = STMF_ERROR_SERVICE_DATA_VERSION;
6304 			break;
6305 		case STMF_PS_ERROR_PROV_DATA_STALE:
6306 			ret = STMF_ERROR_PROV_DATA_STALE;
6307 			break;
6308 		default:
6309 			syslog(LOG_DEBUG,
6310 			    "stmfSetProviderData"
6311 			    "psSetProviderData:error(%d)", ret);
6312 			ret = STMF_STATUS_ERROR;
6313 			break;
6314 	}
6315 
6316 done:
6317 	return (ret);
6318 }
6319 
6320 /*
6321  * getProviderData
6322  *
6323  * Purpose: set the provider data from stmf
6324  *
6325  * providerName - unique name of provider
6326  * nvl - nvlist to load/retrieve
6327  * providerType - logical unit or port provider
6328  * setToken - returned stale data token
6329  */
6330 int
getProviderData(char * providerName,nvlist_t ** nvl,int providerType,uint64_t * setToken)6331 getProviderData(char *providerName, nvlist_t **nvl, int providerType,
6332     uint64_t *setToken)
6333 {
6334 	int ret = STMF_STATUS_SUCCESS;
6335 	int fd;
6336 	int ioctlRet;
6337 	size_t nvlistSize = ALLOC_PP_DATA_SIZE;
6338 	int retryCnt = 0;
6339 	int retryCntMax = MAX_PROVIDER_RETRY;
6340 	stmf_ppioctl_data_t ppi = {0}, *ppi_out = NULL;
6341 	boolean_t retry = B_TRUE;
6342 	stmf_iocdata_t stmfIoctl;
6343 
6344 	if (providerName == NULL) {
6345 		return (STMF_ERROR_INVALID_ARG);
6346 	}
6347 
6348 	/*
6349 	 * Open control node for stmf
6350 	 */
6351 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6352 		return (ret);
6353 
6354 	/* set provider name and provider type */
6355 	if (strlcpy(ppi.ppi_name, providerName,
6356 	    sizeof (ppi.ppi_name)) >=
6357 	    sizeof (ppi.ppi_name)) {
6358 		ret = STMF_ERROR_INVALID_ARG;
6359 		goto done;
6360 	}
6361 	switch (providerType) {
6362 		case STMF_LU_PROVIDER_TYPE:
6363 			ppi.ppi_lu_provider = 1;
6364 			break;
6365 		case STMF_PORT_PROVIDER_TYPE:
6366 			ppi.ppi_port_provider = 1;
6367 			break;
6368 		default:
6369 			ret = STMF_ERROR_INVALID_ARG;
6370 			goto done;
6371 	}
6372 
6373 	do {
6374 		/* allocate memory for ioctl */
6375 		ppi_out = (stmf_ppioctl_data_t *)calloc(1, nvlistSize +
6376 		    sizeof (stmf_ppioctl_data_t));
6377 		if (ppi_out == NULL) {
6378 			ret = STMF_ERROR_NOMEM;
6379 			goto done;
6380 
6381 		}
6382 
6383 		/* set the size of the ioctl data to allocated buffer */
6384 		ppi.ppi_data_size = nvlistSize;
6385 
6386 		bzero(&stmfIoctl, sizeof (stmfIoctl));
6387 
6388 		stmfIoctl.stmf_version = STMF_VERSION_1;
6389 		stmfIoctl.stmf_ibuf_size = sizeof (stmf_ppioctl_data_t);
6390 		stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ppi;
6391 		stmfIoctl.stmf_obuf_size = sizeof (stmf_ppioctl_data_t) +
6392 		    nvlistSize;
6393 		stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)ppi_out;
6394 		ioctlRet = ioctl(fd, STMF_IOCTL_GET_PP_DATA, &stmfIoctl);
6395 		if (ioctlRet != 0) {
6396 			switch (errno) {
6397 				case EBUSY:
6398 					ret = STMF_ERROR_BUSY;
6399 					break;
6400 				case EPERM:
6401 				case EACCES:
6402 					ret = STMF_ERROR_PERM;
6403 					break;
6404 				case EINVAL:
6405 					if (stmfIoctl.stmf_error ==
6406 					    STMF_IOCERR_INSUFFICIENT_BUF) {
6407 						nvlistSize =
6408 						    ppi_out->ppi_data_size;
6409 						free(ppi_out);
6410 						ppi_out = NULL;
6411 						if (retryCnt++ > retryCntMax) {
6412 							retry = B_FALSE;
6413 							ret = STMF_ERROR_BUSY;
6414 						} else {
6415 							ret =
6416 							    STMF_STATUS_SUCCESS;
6417 						}
6418 					} else {
6419 						syslog(LOG_DEBUG,
6420 						    "getProviderData:ioctl"
6421 						    "unable to retrieve "
6422 						    "nvlist");
6423 						ret = STMF_STATUS_ERROR;
6424 					}
6425 					break;
6426 				case ENOENT:
6427 					ret = STMF_ERROR_NOT_FOUND;
6428 					break;
6429 				default:
6430 					syslog(LOG_DEBUG,
6431 					    "getProviderData:ioctl errno(%d)",
6432 					    errno);
6433 					ret = STMF_STATUS_ERROR;
6434 					break;
6435 			}
6436 			if (ret != STMF_STATUS_SUCCESS)
6437 				goto done;
6438 		}
6439 	} while (retry && stmfIoctl.stmf_error == STMF_IOCERR_INSUFFICIENT_BUF);
6440 
6441 	if ((ret = nvlist_unpack((char *)ppi_out->ppi_data,
6442 	    ppi_out->ppi_data_size, nvl, 0)) != 0) {
6443 		ret = STMF_STATUS_ERROR;
6444 		goto done;
6445 	}
6446 
6447 	/* caller has asked for new token */
6448 	if (setToken) {
6449 		*setToken = ppi_out->ppi_token;
6450 	}
6451 done:
6452 	free(ppi_out);
6453 	(void) close(fd);
6454 	return (ret);
6455 }
6456 
6457 /*
6458  * setProviderData
6459  *
6460  * Purpose: set the provider data in stmf
6461  *
6462  * providerName - unique name of provider
6463  * nvl - nvlist to set
6464  * providerType - logical unit or port provider
6465  * setToken - stale data token to check if not NULL
6466  */
6467 static int
setProviderData(int fd,char * providerName,nvlist_t * nvl,int providerType,uint64_t * setToken)6468 setProviderData(int fd, char *providerName, nvlist_t *nvl, int providerType,
6469     uint64_t *setToken)
6470 {
6471 	int ret = STMF_STATUS_SUCCESS;
6472 	int ioctlRet;
6473 	size_t nvlistEncodedSize;
6474 	stmf_ppioctl_data_t *ppi = NULL;
6475 	uint64_t outToken;
6476 	char *allocatedNvBuffer;
6477 	stmf_iocdata_t stmfIoctl;
6478 
6479 	if (providerName == NULL) {
6480 		return (STMF_ERROR_INVALID_ARG);
6481 	}
6482 
6483 	/* get size of encoded nvlist */
6484 	if (nvlist_size(nvl, &nvlistEncodedSize, NV_ENCODE_XDR) != 0) {
6485 		return (STMF_STATUS_ERROR);
6486 	}
6487 
6488 	/* allocate memory for ioctl */
6489 	ppi = (stmf_ppioctl_data_t *)calloc(1, nvlistEncodedSize +
6490 	    sizeof (stmf_ppioctl_data_t));
6491 	if (ppi == NULL) {
6492 		return (STMF_ERROR_NOMEM);
6493 	}
6494 
6495 	if (setToken) {
6496 		ppi->ppi_token_valid = 1;
6497 		ppi->ppi_token = *setToken;
6498 	}
6499 
6500 	allocatedNvBuffer = (char *)&ppi->ppi_data;
6501 	if (nvlist_pack(nvl, &allocatedNvBuffer, &nvlistEncodedSize,
6502 	    NV_ENCODE_XDR, 0) != 0) {
6503 		return (STMF_STATUS_ERROR);
6504 	}
6505 
6506 	/* set provider name and provider type */
6507 	(void) strncpy(ppi->ppi_name, providerName, sizeof (ppi->ppi_name));
6508 	switch (providerType) {
6509 		case STMF_LU_PROVIDER_TYPE:
6510 			ppi->ppi_lu_provider = 1;
6511 			break;
6512 		case STMF_PORT_PROVIDER_TYPE:
6513 			ppi->ppi_port_provider = 1;
6514 			break;
6515 		default:
6516 			return (STMF_ERROR_INVALID_ARG);
6517 	}
6518 
6519 	/* set the size of the ioctl data to packed data size */
6520 	ppi->ppi_data_size = nvlistEncodedSize;
6521 
6522 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6523 
6524 	stmfIoctl.stmf_version = STMF_VERSION_1;
6525 	/*
6526 	 * Subtracting 8 from the size as that is the size of the last member
6527 	 * of the structure where the packed data resides
6528 	 */
6529 	stmfIoctl.stmf_ibuf_size = nvlistEncodedSize +
6530 	    sizeof (stmf_ppioctl_data_t) - 8;
6531 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)ppi;
6532 	stmfIoctl.stmf_obuf_size = sizeof (uint64_t);
6533 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&outToken;
6534 	ioctlRet = ioctl(fd, STMF_IOCTL_LOAD_PP_DATA, &stmfIoctl);
6535 	if (ioctlRet != 0) {
6536 		switch (errno) {
6537 			case EBUSY:
6538 				ret = STMF_ERROR_BUSY;
6539 				break;
6540 			case EPERM:
6541 			case EACCES:
6542 				ret = STMF_ERROR_PERM;
6543 				break;
6544 			case EINVAL:
6545 				if (stmfIoctl.stmf_error ==
6546 				    STMF_IOCERR_PPD_UPDATED) {
6547 					ret = STMF_ERROR_PROV_DATA_STALE;
6548 				} else {
6549 					ret = STMF_STATUS_ERROR;
6550 				}
6551 				break;
6552 			default:
6553 				syslog(LOG_DEBUG,
6554 				    "setProviderData:ioctl errno(%d)", errno);
6555 				ret = STMF_STATUS_ERROR;
6556 				break;
6557 		}
6558 		if (ret != STMF_STATUS_SUCCESS)
6559 			goto done;
6560 	}
6561 
6562 	/* caller has asked for new token */
6563 	if (setToken) {
6564 		*setToken = outToken;
6565 	}
6566 done:
6567 	free(ppi);
6568 	return (ret);
6569 }
6570 
6571 /*
6572  * set the persistence method in the library only or library and service
6573  */
6574 int
stmfSetPersistMethod(uint8_t persistType,boolean_t serviceSet)6575 stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet)
6576 {
6577 	int ret = STMF_STATUS_SUCCESS;
6578 	int oldPersist;
6579 
6580 	(void) pthread_mutex_lock(&persistenceTypeLock);
6581 	oldPersist = iPersistType;
6582 	if (persistType == STMF_PERSIST_NONE ||
6583 	    persistType == STMF_PERSIST_SMF) {
6584 		iLibSetPersist = B_TRUE;
6585 		iPersistType = persistType;
6586 	} else {
6587 		(void) pthread_mutex_unlock(&persistenceTypeLock);
6588 		return (STMF_ERROR_INVALID_ARG);
6589 	}
6590 	/* Is this for this library open or in SMF */
6591 	if (serviceSet == B_TRUE) {
6592 		ret = psSetServicePersist(persistType);
6593 		if (ret != STMF_PS_SUCCESS) {
6594 			ret = STMF_ERROR_PERSIST_TYPE;
6595 			/* Set to old value */
6596 			iPersistType = oldPersist;
6597 		}
6598 	}
6599 	(void) pthread_mutex_unlock(&persistenceTypeLock);
6600 
6601 	return (ret);
6602 }
6603 
6604 /*
6605  * Only returns internal state for persist. If unset, goes to ps. If that
6606  * fails, returns default setting
6607  */
6608 static uint8_t
iGetPersistMethod()6609 iGetPersistMethod()
6610 {
6611 
6612 	uint8_t persistType = 0;
6613 
6614 	(void) pthread_mutex_lock(&persistenceTypeLock);
6615 	if (iLibSetPersist) {
6616 		persistType = iPersistType;
6617 	} else {
6618 		int ret;
6619 		ret = psGetServicePersist(&persistType);
6620 		if (ret != STMF_PS_SUCCESS) {
6621 			/* set to default */
6622 			persistType = STMF_DEFAULT_PERSIST;
6623 		}
6624 	}
6625 	(void) pthread_mutex_unlock(&persistenceTypeLock);
6626 	return (persistType);
6627 }
6628 
6629 /*
6630  * Returns either library state or persistent config state depending on
6631  * serviceState
6632  */
6633 int
stmfGetPersistMethod(uint8_t * persistType,boolean_t serviceState)6634 stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState)
6635 {
6636 	int ret = STMF_STATUS_SUCCESS;
6637 
6638 	if (persistType == NULL) {
6639 		return (STMF_ERROR_INVALID_ARG);
6640 	}
6641 	if (serviceState) {
6642 		ret = psGetServicePersist(persistType);
6643 		if (ret != STMF_PS_SUCCESS) {
6644 			ret = STMF_ERROR_PERSIST_TYPE;
6645 		}
6646 	} else {
6647 		(void) pthread_mutex_lock(&persistenceTypeLock);
6648 		if (iLibSetPersist) {
6649 			*persistType = iPersistType;
6650 		} else {
6651 			*persistType = STMF_DEFAULT_PERSIST;
6652 		}
6653 		(void) pthread_mutex_unlock(&persistenceTypeLock);
6654 	}
6655 
6656 	return (ret);
6657 }
6658 
6659 /*
6660  * stmfPostProxyMsg
6661  *
6662  * Purpose: Post a message to the proxy port provider
6663  *
6664  * buf - buffer containing message to post
6665  * buflen - buffer length
6666  */
6667 int
stmfPostProxyMsg(int hdl,void * buf,uint32_t buflen)6668 stmfPostProxyMsg(int hdl, void *buf, uint32_t buflen)
6669 {
6670 	int ret = STMF_STATUS_SUCCESS;
6671 	int ioctlRet;
6672 	pppt_iocdata_t ppptIoctl = {0};
6673 
6674 	if (buf == NULL) {
6675 		return (STMF_ERROR_INVALID_ARG);
6676 	}
6677 
6678 	/*
6679 	 * Issue ioctl to post the message
6680 	 */
6681 	ppptIoctl.pppt_version = PPPT_VERSION_1;
6682 	ppptIoctl.pppt_buf_size = buflen;
6683 	ppptIoctl.pppt_buf = (uint64_t)(unsigned long)buf;
6684 	ioctlRet = ioctl(hdl, PPPT_MESSAGE, &ppptIoctl);
6685 	if (ioctlRet != 0) {
6686 		switch (errno) {
6687 			case EPERM:
6688 			case EACCES:
6689 				ret = STMF_ERROR_PERM;
6690 				break;
6691 			default:
6692 				ret = STMF_ERROR_POST_MSG_FAILED;
6693 				break;
6694 		}
6695 	}
6696 
6697 	return (ret);
6698 }
6699 
6700 /*
6701  * stmfInitProxyDoor
6702  *
6703  * Purpose: Install door in proxy
6704  *
6705  * hdl - pointer to returned handle
6706  * fd - door from door_create()
6707  */
6708 int
stmfInitProxyDoor(int * hdl,int door)6709 stmfInitProxyDoor(int *hdl, int door)
6710 {
6711 	int ret = STMF_STATUS_SUCCESS;
6712 	int ioctlRet;
6713 	int fd;
6714 	pppt_iocdata_t ppptIoctl = {0};
6715 
6716 	if (hdl == NULL) {
6717 		return (STMF_ERROR_INVALID_ARG);
6718 	}
6719 
6720 	/*
6721 	 * Open control node for pppt
6722 	 */
6723 	if ((ret = openPppt(OPEN_PPPT, &fd)) != STMF_STATUS_SUCCESS) {
6724 		return (ret);
6725 	}
6726 
6727 	/*
6728 	 * Issue ioctl to install the door
6729 	 */
6730 	ppptIoctl.pppt_version = PPPT_VERSION_1;
6731 	ppptIoctl.pppt_door_fd = (uint32_t)door;
6732 	ioctlRet = ioctl(fd, PPPT_INSTALL_DOOR, &ppptIoctl);
6733 	if (ioctlRet != 0) {
6734 		switch (errno) {
6735 			case EPERM:
6736 			case EACCES:
6737 				ret = STMF_ERROR_PERM;
6738 				break;
6739 			case EINVAL:
6740 				ret = STMF_ERROR_INVALID_ARG;
6741 				break;
6742 			case EBUSY:
6743 				ret = STMF_ERROR_DOOR_INSTALLED;
6744 				break;
6745 			default:
6746 				ret = STMF_STATUS_ERROR;
6747 				break;
6748 		}
6749 	}
6750 
6751 	/* return driver fd to caller */
6752 	*hdl = fd;
6753 	return (ret);
6754 }
6755 
6756 void
stmfDestroyProxyDoor(int hdl)6757 stmfDestroyProxyDoor(int hdl)
6758 {
6759 	(void) close(hdl);
6760 }
6761 
6762 /*
6763  * validateLunNumIoctl
6764  *
6765  * Purpose: Issues ioctl to check and get available lun# in view entry
6766  *
6767  * viewEntry - view entry to use
6768  */
6769 static int
validateLunNumIoctl(int fd,stmfViewEntry * viewEntry)6770 validateLunNumIoctl(int fd, stmfViewEntry *viewEntry)
6771 {
6772 	int ret = STMF_STATUS_SUCCESS;
6773 	int ioctlRet;
6774 	stmf_iocdata_t stmfIoctl;
6775 	stmf_view_op_entry_t ioctlViewEntry;
6776 
6777 	bzero(&ioctlViewEntry, sizeof (ioctlViewEntry));
6778 	/*
6779 	 * don't set ve_ndx or ve_ndx_valid as ve_ndx_valid should be
6780 	 * false on input
6781 	 */
6782 	ioctlViewEntry.ve_lu_number_valid = viewEntry->luNbrValid;
6783 	ioctlViewEntry.ve_all_hosts = viewEntry->allHosts;
6784 	ioctlViewEntry.ve_all_targets = viewEntry->allTargets;
6785 
6786 	if (viewEntry->allHosts == B_FALSE) {
6787 		bcopy(viewEntry->hostGroup, &ioctlViewEntry.ve_host_group.name,
6788 		    sizeof (stmfGroupName));
6789 		ioctlViewEntry.ve_host_group.name_size =
6790 		    strlen((char *)viewEntry->hostGroup);
6791 	}
6792 	if (viewEntry->allTargets == B_FALSE) {
6793 		bcopy(viewEntry->targetGroup,
6794 		    &ioctlViewEntry.ve_target_group.name,
6795 		    sizeof (stmfGroupName));
6796 		ioctlViewEntry.ve_target_group.name_size =
6797 		    strlen((char *)viewEntry->targetGroup);
6798 	}
6799 	/* Validating the lun number */
6800 	if (viewEntry->luNbrValid) {
6801 		bcopy(viewEntry->luNbr, &ioctlViewEntry.ve_lu_nbr,
6802 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6803 	}
6804 
6805 	bzero(&stmfIoctl, sizeof (stmfIoctl));
6806 	/*
6807 	 * Issue ioctl to validate lun# in the view entry
6808 	 */
6809 	stmfIoctl.stmf_version = STMF_VERSION_1;
6810 	stmfIoctl.stmf_ibuf_size = sizeof (ioctlViewEntry);
6811 	stmfIoctl.stmf_ibuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6812 	stmfIoctl.stmf_obuf_size = sizeof (ioctlViewEntry);
6813 	stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)&ioctlViewEntry;
6814 	ioctlRet = ioctl(fd, STMF_IOCTL_VALIDATE_VIEW, &stmfIoctl);
6815 
6816 	/* save available lun number */
6817 	if (!viewEntry->luNbrValid) {
6818 		bcopy(ioctlViewEntry.ve_lu_nbr, viewEntry->luNbr,
6819 		    sizeof (ioctlViewEntry.ve_lu_nbr));
6820 	}
6821 	if (ioctlRet != 0) {
6822 		switch (errno) {
6823 			case EBUSY:
6824 				ret = STMF_ERROR_BUSY;
6825 				break;
6826 			case EPERM:
6827 				ret = STMF_ERROR_PERM;
6828 				break;
6829 			case EACCES:
6830 				switch (stmfIoctl.stmf_error) {
6831 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6832 						ret = STMF_ERROR_CONFIG_NONE;
6833 						break;
6834 					default:
6835 						ret = STMF_ERROR_PERM;
6836 						break;
6837 				}
6838 				break;
6839 			default:
6840 				switch (stmfIoctl.stmf_error) {
6841 					case STMF_IOCERR_LU_NUMBER_IN_USE:
6842 						ret = STMF_ERROR_LUN_IN_USE;
6843 						break;
6844 					case STMF_IOCERR_VIEW_ENTRY_CONFLICT:
6845 						ret = STMF_ERROR_VE_CONFLICT;
6846 						break;
6847 					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
6848 						ret = STMF_ERROR_CONFIG_NONE;
6849 						break;
6850 					case STMF_IOCERR_INVALID_HG:
6851 						ret = STMF_ERROR_INVALID_HG;
6852 						break;
6853 					case STMF_IOCERR_INVALID_TG:
6854 						ret = STMF_ERROR_INVALID_TG;
6855 						break;
6856 					default:
6857 						syslog(LOG_DEBUG,
6858 						    "addViewEntryIoctl"
6859 						    ":error(%d)",
6860 						    stmfIoctl.stmf_error);
6861 						ret = STMF_STATUS_ERROR;
6862 						break;
6863 				}
6864 				break;
6865 		}
6866 	}
6867 	return (ret);
6868 }
6869 
6870 /*
6871  * stmfValidateView
6872  *
6873  * Purpose: Validate or get lun # base on TG, HG of view entry
6874  *
6875  * viewEntry - view entry structure to use
6876  */
6877 int
stmfValidateView(stmfViewEntry * viewEntry)6878 stmfValidateView(stmfViewEntry *viewEntry)
6879 {
6880 	int ret;
6881 	int fd;
6882 	stmfViewEntry iViewEntry;
6883 
6884 	if (viewEntry == NULL) {
6885 		return (STMF_ERROR_INVALID_ARG);
6886 	}
6887 
6888 	/* initialize and set internal view entry */
6889 	bzero(&iViewEntry, sizeof (iViewEntry));
6890 
6891 	if (!viewEntry->allHosts) {
6892 		bcopy(viewEntry->hostGroup, iViewEntry.hostGroup,
6893 		    sizeof (iViewEntry.hostGroup));
6894 	} else {
6895 		iViewEntry.allHosts = B_TRUE;
6896 	}
6897 
6898 	if (!viewEntry->allTargets) {
6899 		bcopy(viewEntry->targetGroup, iViewEntry.targetGroup,
6900 		    sizeof (iViewEntry.targetGroup));
6901 	} else {
6902 		iViewEntry.allTargets = B_TRUE;
6903 	}
6904 
6905 	if (viewEntry->luNbrValid) {
6906 		iViewEntry.luNbrValid = B_TRUE;
6907 		bcopy(viewEntry->luNbr, iViewEntry.luNbr,
6908 		    sizeof (iViewEntry.luNbr));
6909 	}
6910 
6911 	/*
6912 	 * set users return view entry index valid flag to false
6913 	 * in case of failure
6914 	 */
6915 	viewEntry->veIndexValid = B_FALSE;
6916 
6917 	/* Check to ensure service exists */
6918 	if (psCheckService() != STMF_STATUS_SUCCESS) {
6919 		return (STMF_ERROR_SERVICE_NOT_FOUND);
6920 	}
6921 
6922 	/* call init */
6923 	ret = initializeConfig();
6924 	if (ret != STMF_STATUS_SUCCESS) {
6925 		return (ret);
6926 	}
6927 
6928 	/*
6929 	 * Open control node for stmf
6930 	 */
6931 	if ((ret = openStmf(OPEN_STMF, &fd)) != STMF_STATUS_SUCCESS)
6932 		return (ret);
6933 
6934 	/*
6935 	 * Validate lun# in the view entry from the driver
6936 	 */
6937 	ret = validateLunNumIoctl(fd, &iViewEntry);
6938 	(void) close(fd);
6939 
6940 	/* save available lun number */
6941 	if (!viewEntry->luNbrValid) {
6942 		bcopy(iViewEntry.luNbr, viewEntry->luNbr,
6943 		    sizeof (iViewEntry.luNbr));
6944 	}
6945 
6946 	return (ret);
6947 }
6948