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 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Disk & Indicator Monitor configuration file support routines
29  */
30 
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <errno.h>
38 #include <limits.h>
39 #include <pthread.h>
40 
41 #include "disk_monitor.h"
42 #include "util.h"
43 #include "topo_gather.h"
44 
45 extern log_class_t g_verbose;
46 
47 const char *
hotplug_state_string(hotplug_state_t state)48 hotplug_state_string(hotplug_state_t state)
49 {
50 	switch (state & ~HPS_FAULTED) {
51 	default:
52 	case HPS_UNKNOWN:
53 		return ("Unknown");
54 	case HPS_ABSENT:
55 		return ("Absent");
56 	case HPS_PRESENT:
57 		return ("Present");
58 	case HPS_CONFIGURED:
59 		return ("Configured");
60 	case HPS_UNCONFIGURED:
61 		return ("Unconfigured");
62 	}
63 }
64 
65 void
conf_error_msg(conf_err_t err,char * buf,int buflen,void * arg)66 conf_error_msg(conf_err_t err, char *buf, int buflen, void *arg)
67 {
68 	switch (err) {
69 	case E_MULTIPLE_IND_LISTS_DEFINED:
70 		(void) snprintf(buf, buflen, "Multiple Indicator lists "
71 		    "defined");
72 		break;
73 	case E_MULTIPLE_INDRULE_LISTS_DEFINED:
74 		(void) snprintf(buf, buflen, "Multiple Indicator rule lists "
75 		    "defined");
76 		break;
77 	case E_INVALID_STATE_CHANGE:
78 		(void) snprintf(buf, buflen, "Invalid state change");
79 		break;
80 	case E_IND_MULTIPLY_DEFINED:
81 		(void) snprintf(buf, buflen,
82 		    "Multiple Indicator definitions (name & state) detected");
83 		break;
84 	case E_IND_ACTION_REDUNDANT:
85 		(void) snprintf(buf, buflen, "Redundant Indicator actions "
86 		    "specified");
87 		break;
88 	case E_IND_ACTION_CONFLICT:
89 		(void) snprintf(buf, buflen, "Indicator action conflict (+/- "
90 		    "same Indicator) found");
91 		break;
92 	case E_IND_MISSING_FAULT_ON:
93 		(void) snprintf(buf, buflen, "Missing declaration of `+"
94 		    INDICATOR_FAULT_IDENTIFIER "'");
95 		break;
96 	case E_IND_MISSING_FAULT_OFF:
97 		(void) snprintf(buf, buflen, "Missing declaration of `-"
98 		    INDICATOR_FAULT_IDENTIFIER "'");
99 		break;
100 	case E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION:
101 		(void) snprintf(buf, buflen, "`%c%s': Undefined Indicator in "
102 		    BAY_IND_ACTION " property",
103 		    (((ind_action_t *)arg)->ind_state == INDICATOR_ON)
104 		    ? '+' : '-',
105 		    ((ind_action_t *)arg)->ind_name);
106 		break;
107 	case E_DUPLICATE_STATE_TRANSITION:
108 		(void) snprintf(buf, buflen, "Duplicate state transition "
109 		    "(%s -> %s)",
110 		    hotplug_state_string(((state_transition_t *)arg)->begin),
111 		    hotplug_state_string(((state_transition_t *)arg)->end));
112 		break;
113 	default:
114 		(void) snprintf(buf, buflen, "Unknown error");
115 		break;
116 	}
117 }
118 
119 static int
string_to_integer(const char * prop,int * value)120 string_to_integer(const char *prop, int *value)
121 {
122 	long val;
123 
124 	errno = 0;
125 
126 	val = strtol(prop, NULL, 0);
127 
128 	if (val == 0 && errno != 0)
129 		return (-1);
130 	else if (val > INT_MAX || val < INT_MIN) {
131 		errno = ERANGE;
132 		return (-1);
133 	}
134 
135 	if (value != NULL)
136 		*value = (int)val;
137 
138 	return (0);
139 }
140 
141 const char *
dm_prop_lookup(nvlist_t * props,const char * prop_name)142 dm_prop_lookup(nvlist_t *props, const char *prop_name)
143 {
144 	char *str;
145 
146 	if (nvlist_lookup_string(props, prop_name, &str) == 0)
147 		return ((const char *)str);
148 	else
149 		return (NULL);
150 }
151 
152 int
dm_prop_lookup_int(nvlist_t * props,const char * prop_name,int * value)153 dm_prop_lookup_int(nvlist_t *props, const char *prop_name, int *value)
154 {
155 	const char *prop = dm_prop_lookup(props, prop_name);
156 
157 	if (prop == NULL)
158 		return (-1);
159 
160 	return (string_to_integer(prop, value));
161 }
162 
163 nvlist_t *
namevalpr_to_nvlist(namevalpr_t * nvprp)164 namevalpr_to_nvlist(namevalpr_t *nvprp)
165 {
166 	nvlist_t *nvlp = NULL;
167 
168 	if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0) != 0) {
169 		return (NULL);
170 	}
171 
172 	if (nvlist_add_string(nvlp, nvprp->name, nvprp->value) != 0) {
173 		nvlist_free(nvlp);
174 		return (NULL);
175 	}
176 
177 	return (nvlp);
178 }
179 
180 indicator_t *
new_indicator(ind_state_t lstate,char * namep,char * actionp)181 new_indicator(ind_state_t lstate, char *namep, char *actionp)
182 {
183 	indicator_t *newindicator =
184 	    (indicator_t *)dmalloc(sizeof (indicator_t));
185 	newindicator->ind_state = lstate;
186 	newindicator->ind_name = namep ? dstrdup(namep) : NULL;
187 	newindicator->ind_instr_spec = actionp ? dstrdup(actionp) : NULL;
188 	newindicator->next = NULL;
189 	return (newindicator);
190 }
191 
192 void
link_indicator(indicator_t ** first,indicator_t * to_add)193 link_indicator(indicator_t **first, indicator_t *to_add)
194 {
195 	indicator_t *travptr;
196 	dm_assert(first != NULL);
197 
198 	if (*first == NULL)
199 		*first = to_add;
200 	else {
201 		travptr = *first;
202 		while (travptr->next != NULL) {
203 			travptr = travptr->next;
204 		}
205 		travptr->next = to_add;
206 	}
207 }
208 
209 void
ind_free(indicator_t * indp)210 ind_free(indicator_t *indp)
211 {
212 	indicator_t *nextp;
213 
214 	while (indp != NULL) {
215 		nextp = indp->next;
216 		if (indp->ind_name)
217 			dstrfree(indp->ind_name);
218 		if (indp->ind_instr_spec)
219 			dstrfree(indp->ind_instr_spec);
220 		dfree(indp, sizeof (indicator_t));
221 		indp = nextp;
222 	}
223 }
224 
225 ind_action_t *
new_indaction(ind_state_t state,char * namep)226 new_indaction(ind_state_t state, char *namep)
227 {
228 	ind_action_t *lap = (ind_action_t *)dmalloc(sizeof (ind_action_t));
229 	lap->ind_state = state;
230 	lap->ind_name = namep ? dstrdup(namep) : NULL;
231 	lap->next = NULL;
232 	return (lap);
233 }
234 
235 void
link_indaction(ind_action_t ** first,ind_action_t * to_add)236 link_indaction(ind_action_t **first, ind_action_t *to_add)
237 {
238 	ind_action_t *travptr;
239 	dm_assert(first != NULL);
240 
241 	if (*first == NULL)
242 		*first = to_add;
243 	else {
244 		travptr = *first;
245 		while (travptr->next != NULL) {
246 			travptr = travptr->next;
247 		}
248 		travptr->next = to_add;
249 	}
250 }
251 
252 void
indaction_free(ind_action_t * lap)253 indaction_free(ind_action_t *lap)
254 {
255 	ind_action_t *nextp;
256 
257 	/* Free the whole list */
258 	while (lap != NULL) {
259 		nextp = lap->next;
260 		if (lap->ind_name)
261 			dstrfree(lap->ind_name);
262 		dfree(lap, sizeof (ind_action_t));
263 		lap = nextp;
264 	}
265 }
266 
267 indrule_t *
new_indrule(state_transition_t * st,ind_action_t * actionp)268 new_indrule(state_transition_t *st, ind_action_t *actionp)
269 {
270 	indrule_t *lrp = (indrule_t *)dmalloc(sizeof (indrule_t));
271 	if (st != NULL)
272 		lrp->strans = *st;
273 	lrp->action_list = actionp;
274 	lrp->next = NULL;
275 	return (lrp);
276 }
277 
278 void
link_indrule(indrule_t ** first,indrule_t * to_add)279 link_indrule(indrule_t **first, indrule_t *to_add)
280 {
281 	indrule_t *travptr;
282 	dm_assert(first != NULL);
283 
284 	if (*first == NULL)
285 		*first = to_add;
286 	else {
287 		travptr = *first;
288 		while (travptr->next != NULL) {
289 			travptr = travptr->next;
290 		}
291 		travptr->next = to_add;
292 	}
293 }
294 
295 void
indrule_free(indrule_t * lrp)296 indrule_free(indrule_t *lrp)
297 {
298 	indrule_t *nextp;
299 
300 	/* Free the whole list */
301 	while (lrp != NULL) {
302 		nextp = lrp->next;
303 		if (lrp->action_list)
304 			indaction_free(lrp->action_list);
305 		dfree(lrp, sizeof (indrule_t));
306 		lrp = nextp;
307 	}
308 }
309 
310 dm_fru_t *
new_dmfru(char * manu,char * modl,char * firmrev,char * serno,uint64_t capa)311 new_dmfru(char *manu, char *modl, char *firmrev, char *serno, uint64_t capa)
312 {
313 	dm_fru_t *frup = (dm_fru_t *)dzmalloc(sizeof (dm_fru_t));
314 
315 	bcopy(manu, frup->manuf, MIN(sizeof (frup->manuf), strlen(manu) + 1));
316 	bcopy(modl, frup->model, MIN(sizeof (frup->model), strlen(modl) + 1));
317 	bcopy(firmrev, frup->rev, MIN(sizeof (frup->rev), strlen(firmrev) + 1));
318 	bcopy(serno, frup->serial,
319 	    MIN(sizeof (frup->serial), strlen(serno) + 1));
320 	frup->size_in_bytes = capa;
321 	return (frup);
322 }
323 
324 void
dmfru_free(dm_fru_t * frup)325 dmfru_free(dm_fru_t *frup)
326 {
327 	dfree(frup, sizeof (dm_fru_t));
328 }
329 
330 diskmon_t *
new_diskmon(nvlist_t * app_props,indicator_t * indp,indrule_t * indrp,nvlist_t * nvlp)331 new_diskmon(nvlist_t *app_props, indicator_t *indp, indrule_t *indrp,
332     nvlist_t *nvlp)
333 {
334 	diskmon_t *dmp = (diskmon_t *)dmalloc(sizeof (diskmon_t));
335 
336 	if (nvlp != NULL)
337 		dmp->props = nvlp;
338 	else
339 		(void) nvlist_alloc(&dmp->props, NV_UNIQUE_NAME, 0);
340 
341 	if (app_props)
342 		dmp->app_props = app_props;
343 	else
344 		(void) nvlist_alloc(&dmp->app_props, NV_UNIQUE_NAME, 0);
345 	dmp->ind_list = indp;
346 	dmp->indrule_list = indrp;
347 
348 	dm_assert(pthread_mutex_init(&dmp->manager_mutex, NULL) == 0);
349 
350 	dmp->state = HPS_UNKNOWN;
351 
352 	dmp->initial_configuration = B_TRUE;
353 
354 	dm_assert(pthread_mutex_init(&dmp->fault_indicator_mutex, NULL) == 0);
355 	dmp->fault_indicator_state = INDICATOR_UNKNOWN;
356 
357 	dmp->configured_yet = B_FALSE;
358 	dmp->state_change_count = 0;
359 
360 	dm_assert(pthread_mutex_init(&dmp->fru_mutex, NULL) == 0);
361 	dmp->frup = NULL;
362 
363 	dmp->next = NULL;
364 	return (dmp);
365 }
366 
367 void
diskmon_free(diskmon_t * dmp)368 diskmon_free(diskmon_t *dmp)
369 {
370 	diskmon_t *nextp;
371 
372 	/* Free the whole list */
373 	while (dmp != NULL) {
374 		nextp = dmp->next;
375 
376 		nvlist_free(dmp->props);
377 		if (dmp->location)
378 			dstrfree(dmp->location);
379 		if (dmp->ind_list)
380 			ind_free(dmp->ind_list);
381 		if (dmp->indrule_list)
382 			indrule_free(dmp->indrule_list);
383 		nvlist_free(dmp->app_props);
384 		if (dmp->frup)
385 			dmfru_free(dmp->frup);
386 		dfree(dmp, sizeof (diskmon_t));
387 
388 		dmp = nextp;
389 	}
390 }
391 
392 static cfgdata_t *
new_cfgdata(namevalpr_t * nvp,diskmon_t * dmp)393 new_cfgdata(namevalpr_t *nvp, diskmon_t *dmp)
394 {
395 	cfgdata_t *cdp = (cfgdata_t *)dzmalloc(sizeof (cfgdata_t));
396 
397 	if (nvp != NULL)
398 		cdp->props = namevalpr_to_nvlist(nvp);
399 	else if (nvlist_alloc(&cdp->props, NV_UNIQUE_NAME, 0) != 0) {
400 		return (NULL);
401 	}
402 
403 	if (dmp != NULL)
404 		cdp->disk_list = dmp;
405 	return (cdp);
406 
407 }
408 
409 static void
cfgdata_add_namevalpr(cfgdata_t * cfgp,namevalpr_t * nvp)410 cfgdata_add_namevalpr(cfgdata_t *cfgp, namevalpr_t *nvp)
411 {
412 	if (cfgp->props == NULL) {
413 		(void) nvlist_alloc(&cfgp->props, NV_UNIQUE_NAME, 0);
414 	}
415 	(void) nvlist_add_string(cfgp->props, nvp->name, nvp->value);
416 }
417 
418 void
cfgdata_add_diskmon(cfgdata_t * cfgp,diskmon_t * dmp)419 cfgdata_add_diskmon(cfgdata_t *cfgp, diskmon_t *dmp)
420 {
421 	if (cfgp->disk_list == NULL) {
422 		cfgp->disk_list = dmp;
423 	} else {
424 		diskmon_t *disklist = cfgp->disk_list;
425 
426 		while (disklist->next != NULL)
427 			disklist = disklist->next;
428 
429 		disklist->next = dmp;
430 	}
431 }
432 
433 static void
cfgdata_free(cfgdata_t * cdp)434 cfgdata_free(cfgdata_t *cdp)
435 {
436 	nvlist_free(cdp->props);
437 	diskmon_free(cdp->disk_list);
438 	dfree(cdp, sizeof (cfgdata_t));
439 }
440 
441 conf_err_t
check_indactions(ind_action_t * indrp)442 check_indactions(ind_action_t *indrp)
443 {
444 	char *buf;
445 	conf_err_t rv = E_NO_ERROR;
446 	nvlist_t *nvp = NULL;
447 	int len;
448 
449 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
450 
451 	/*
452 	 * Check indicator actions for conflicts
453 	 */
454 	while (indrp != NULL && rv == E_NO_ERROR) {
455 		len = strlen(indrp->ind_name) + 2;
456 		buf = dmalloc(len);
457 		(void) snprintf(buf, len, "%c%s",
458 		    indrp->ind_state == INDICATOR_ON ? '+' : '-',
459 		    indrp->ind_name);
460 		switch (nvlist_lookup_boolean(nvp, buf)) {
461 		case ENOENT:
462 			(void) nvlist_add_boolean(nvp, buf);
463 			break;
464 		case 0:
465 			rv = E_IND_ACTION_REDUNDANT;
466 			break;
467 		default:
468 			break;
469 		}
470 
471 		/* Look for the opposite action.  If found, that's an error */
472 		(void) snprintf(buf, len, "%c%s",
473 		    indrp->ind_state == INDICATOR_ON ? '-' : '+',
474 		    indrp->ind_name);
475 		switch (nvlist_lookup_boolean(nvp, buf)) {
476 		case ENOENT:
477 			break;
478 		case 0:
479 			rv = E_IND_ACTION_CONFLICT;
480 			break;
481 		default:
482 			break;
483 		}
484 		dfree(buf, len);
485 		indrp = indrp->next;
486 	}
487 
488 	nvlist_free(nvp);
489 	return (rv);
490 }
491 
492 conf_err_t
check_inds(indicator_t * indp)493 check_inds(indicator_t *indp)
494 {
495 	char *buf;
496 	conf_err_t rv = E_NO_ERROR;
497 	nvlist_t *nvp = NULL;
498 	int len;
499 	boolean_t fault_on = B_FALSE, fault_off = B_FALSE;
500 
501 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
502 
503 	/*
504 	 * Check inds for multiple definitions (same identifier or same action)
505 	 */
506 	while (indp != NULL && rv == E_NO_ERROR) {
507 		len = strlen(indp->ind_name) + 2;
508 		buf = dmalloc(len);
509 		(void) snprintf(buf, len, "%c%s",
510 		    indp->ind_state == INDICATOR_ON ? '+' : '-',
511 		    indp->ind_name);
512 
513 		/* Keep track of the +/-FAULT for checking later */
514 		if (strcasecmp(buf, "+" INDICATOR_FAULT_IDENTIFIER) == 0)
515 			fault_on = B_TRUE;
516 		else if (strcasecmp(buf, "-" INDICATOR_FAULT_IDENTIFIER) == 0)
517 			fault_off = B_TRUE;
518 
519 		switch (nvlist_lookup_boolean(nvp, buf)) {
520 		case ENOENT:
521 			(void) nvlist_add_boolean(nvp, buf);
522 			break;
523 		case 0:
524 			rv = E_IND_MULTIPLY_DEFINED;
525 			break;
526 		default:
527 			break;
528 		}
529 		dfree(buf, len);
530 		indp = indp->next;
531 	}
532 
533 	/*
534 	 * Make sure we have a -FAULT and +FAULT
535 	 */
536 	if (!fault_on)
537 		rv = E_IND_MISSING_FAULT_ON;
538 	else if (!fault_off)
539 		rv = E_IND_MISSING_FAULT_OFF;
540 
541 	nvlist_free(nvp);
542 	return (rv);
543 }
544 
545 conf_err_t
check_indrules(indrule_t * indrp,state_transition_t ** offender)546 check_indrules(indrule_t *indrp, state_transition_t **offender)
547 {
548 	char buf[32];
549 	conf_err_t rv = E_NO_ERROR;
550 	nvlist_t *nvp = NULL;
551 
552 	/*
553 	 * Ensure that no two rules have the same state transitions.
554 	 */
555 
556 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
557 
558 	while (indrp != NULL && rv == E_NO_ERROR) {
559 		(void) snprintf(buf, sizeof (buf), "%d-%d",
560 		    (int)indrp->strans.begin, (int)indrp->strans.end);
561 		switch (nvlist_lookup_boolean(nvp, buf)) {
562 		case 0:
563 			*offender = &indrp->strans;
564 			rv = E_DUPLICATE_STATE_TRANSITION;
565 			break;
566 		case ENOENT:
567 			(void) nvlist_add_boolean(nvp, buf);
568 			break;
569 		default:
570 			break;
571 		}
572 		indrp = indrp->next;
573 	}
574 
575 	nvlist_free(nvp);
576 	return (rv);
577 }
578 
579 
580 conf_err_t
check_consistent_ind_indrules(indicator_t * indp,indrule_t * indrp,ind_action_t ** offender)581 check_consistent_ind_indrules(indicator_t *indp, indrule_t *indrp,
582     ind_action_t **offender)
583 {
584 	char *buf;
585 	conf_err_t rv = E_NO_ERROR;
586 	nvlist_t *nvp = NULL;
587 	ind_action_t *alp;
588 	int len;
589 
590 	/*
591 	 * Ensure that every indicator action referenced in each ruleset
592 	 * exists in the indicator list given.
593 	 */
594 
595 	(void) nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0);
596 
597 	while (indp != NULL) {
598 		len = strlen(indp->ind_name) + 2;
599 		buf = dmalloc(len);
600 		(void) snprintf(buf, len, "%c%s",
601 		    indp->ind_state == INDICATOR_ON ? '+' : '-',
602 		    indp->ind_name);
603 		(void) nvlist_add_boolean(nvp, buf);
604 		dfree(buf, len);
605 		indp = indp->next;
606 	}
607 
608 	while (indrp != NULL && rv == E_NO_ERROR) {
609 		alp = indrp->action_list;
610 		while (alp != NULL && rv == E_NO_ERROR) {
611 			len = strlen(alp->ind_name) + 2;
612 			buf = dmalloc(len);
613 			(void) snprintf(buf, len, "%c%s",
614 			    alp->ind_state == INDICATOR_ON ? '+' : '-',
615 			    alp->ind_name);
616 
617 			switch (nvlist_lookup_boolean(nvp, buf)) {
618 			case 0:		/* Normal case */
619 				break;
620 			case ENOENT:
621 				*offender = alp;
622 				rv =
623 				    E_INDRULE_REFERENCES_NONEXISTENT_IND_ACTION;
624 				break;
625 			default:
626 				break;
627 			}
628 			dfree(buf, len);
629 			alp = alp->next;
630 		}
631 		indrp = indrp->next;
632 	}
633 
634 	nvlist_free(nvp);
635 	return (rv);
636 }
637 
638 conf_err_t
check_state_transition(hotplug_state_t s1,hotplug_state_t s2)639 check_state_transition(hotplug_state_t s1, hotplug_state_t s2)
640 {
641 	/*
642 	 * The following are valid transitions:
643 	 *
644 	 * HPS_ABSENT -> HPS_PRESENT
645 	 * HPS_ABSENT -> HPS_CONFIGURED
646 	 * HPS_PRESENT -> HPS_CONFIGURED
647 	 * HPS_PRESENT -> HPS_ABSENT
648 	 * HPS_CONFIGURED -> HPS_UNCONFIGURED
649 	 * HPS_CONFIGURED -> HPS_ABSENT
650 	 * HPS_UNCONFIGURED -> HPS_ABSENT
651 	 * HPS_UNCONFIGURED -> HPS_CONFIGURED
652 	 *
653 	 */
654 	if (s1 == HPS_ABSENT && s2 != HPS_PRESENT && s2 != HPS_CONFIGURED)
655 		return (E_INVALID_STATE_CHANGE);
656 	else if (s1 == HPS_PRESENT && (s2 != HPS_CONFIGURED &&
657 	    s2 != HPS_ABSENT))
658 		return (E_INVALID_STATE_CHANGE);
659 	else if (s1 == HPS_CONFIGURED && (s2 != HPS_UNCONFIGURED &&
660 	    s2 != HPS_ABSENT))
661 		return (E_INVALID_STATE_CHANGE);
662 	else if (s1 == HPS_UNCONFIGURED && (s2 != HPS_ABSENT &&
663 	    s2 != HPS_CONFIGURED))
664 		return (E_INVALID_STATE_CHANGE);
665 	else
666 		return (E_NO_ERROR);
667 }
668 
669 static void
print_inds(indicator_t * indp,FILE * fp,char * prefix)670 print_inds(indicator_t *indp, FILE *fp, char *prefix)
671 {
672 	char plusminus;
673 
674 	(void) fprintf(fp, "%sindicators {\n", prefix);
675 	while (indp != NULL) {
676 		plusminus = (indp->ind_state == INDICATOR_ON) ? '+' : '-';
677 		(void) fprintf(fp, "%s\t%c%s = \"%s\"\n", prefix, plusminus,
678 		    indp->ind_name, indp->ind_instr_spec);
679 		indp = indp->next;
680 	}
681 	(void) fprintf(fp, "%s}\n", prefix);
682 }
683 
684 static void
print_indrules(indrule_t * lrp,FILE * fp,char * prefix)685 print_indrules(indrule_t *lrp, FILE *fp, char *prefix)
686 {
687 	char plusminus;
688 	ind_action_t *lap;
689 
690 	(void) fprintf(fp, "%sindicator_rules {\n", prefix);
691 	while (lrp != NULL) {
692 		(void) fprintf(fp, "%s\t%12s -> %12s\t{ ", prefix,
693 		    hotplug_state_string(lrp->strans.begin),
694 		    hotplug_state_string(lrp->strans.end));
695 		lap = lrp->action_list;
696 		while (lap != NULL) {
697 			plusminus = (lap->ind_state == INDICATOR_ON)
698 			    ? '+' : '-';
699 			(void) fprintf(fp, "%c%s", plusminus, lap->ind_name);
700 			lap = lap->next;
701 			if (lap != NULL)
702 				(void) fprintf(fp, ", ");
703 		}
704 		(void) fprintf(fp, " }\n");
705 		lrp = lrp->next;
706 	}
707 	(void) fprintf(fp, "%s}\n", prefix);
708 }
709 
710 static void
print_props(nvlist_t * nvlp,FILE * fp,char * prefix)711 print_props(nvlist_t *nvlp, FILE *fp, char *prefix)
712 {
713 	nvpair_t *nvp = nvlist_next_nvpair(nvlp, NULL);
714 	char *name, *str;
715 
716 	while (nvp != NULL) {
717 		dm_assert(nvpair_type(nvp) == DATA_TYPE_STRING);
718 		name = nvpair_name(nvp);
719 		(void) nvlist_lookup_string(nvlp, name, &str);
720 		(void) fprintf(fp, "%s%s = \"%s\"\n", prefix, name, str);
721 		nvp = nvlist_next_nvpair(nvlp, nvp);
722 	}
723 }
724 
725 static void
print_ap(nvlist_t * dpp,FILE * fp,char * prefix)726 print_ap(nvlist_t *dpp, FILE *fp, char *prefix)
727 {
728 	int len = strlen(prefix) + 2;
729 	char *buf = dmalloc(len);
730 
731 	(void) snprintf(buf, len, "%s\t", prefix);
732 
733 	(void) fprintf(fp, "%sap_props {\n", prefix);
734 	print_props(dpp, fp, buf);
735 	(void) fprintf(fp, "%s}\n", prefix);
736 
737 	dfree(buf, len);
738 }
739 
740 static void
print_disks(diskmon_t * dmp,FILE * fp,char * prefix)741 print_disks(diskmon_t *dmp, FILE *fp, char *prefix)
742 {
743 	int len = strlen(prefix) + 2;
744 	char *buf = dmalloc(len);
745 
746 	(void) snprintf(buf, len, "%s\t", prefix);
747 
748 	while (dmp != NULL) {
749 		(void) fprintf(fp, "%sdisk \"%s\" {\n", prefix, dmp->location);
750 		if (dmp->props) {
751 			print_props(dmp->props, fp, buf);
752 		}
753 		if (dmp->app_props) {
754 			print_ap(dmp->app_props, fp, buf);
755 		}
756 		(void) fprintf(fp, "%s\n", prefix);
757 		print_inds(dmp->ind_list, fp, buf);
758 		(void) fprintf(fp, "%s\n", prefix);
759 		print_indrules(dmp->indrule_list, fp, buf);
760 		(void) fprintf(fp, "%s}\n", prefix);
761 
762 		if (dmp->next != NULL)
763 			(void) fprintf(fp, "%s\n", prefix);
764 
765 		dmp = dmp->next;
766 	}
767 
768 	dfree(buf, len);
769 }
770 
771 static void
print_cfgdata(cfgdata_t * cfgp,FILE * fp,char * prefix)772 print_cfgdata(cfgdata_t *cfgp, FILE *fp, char *prefix)
773 {
774 	/* First, print the properties, then the disks */
775 
776 	print_props(cfgp->props, fp, prefix);
777 	(void) fprintf(fp, "%s\n", prefix);
778 	print_disks(cfgp->disk_list, fp, prefix);
779 }
780 
781 int
config_init(void)782 config_init(void)
783 {
784 	if (init_configuration_from_topo() == 0) {
785 		config_data = new_cfgdata(NULL, NULL);
786 		return (0);
787 	}
788 	return (-1);
789 }
790 
791 int
config_get(fmd_hdl_t * hdl,const fmd_prop_t * fmd_props)792 config_get(fmd_hdl_t *hdl, const fmd_prop_t *fmd_props)
793 {
794 	int err, i = 0;
795 	char *str = NULL;
796 	namevalpr_t nvp;
797 	uint64_t u64;
798 	boolean_t intfound = B_FALSE, strfound = B_FALSE;
799 #define	INT64_BUF_LEN 128
800 	char buf[INT64_BUF_LEN];
801 
802 	u64 = fmd_prop_get_int32(hdl, GLOBAL_PROP_LOG_LEVEL);
803 	g_verbose = (int)u64;
804 
805 	err = update_configuration_from_topo(hdl, NULL);
806 
807 	/* Pull in the properties from the DE configuration file */
808 	while (fmd_props[i].fmdp_name != NULL) {
809 
810 		nvp.name = (char *)fmd_props[i].fmdp_name;
811 
812 		switch (fmd_props[i].fmdp_type) {
813 		case FMD_TYPE_UINT32:
814 		case FMD_TYPE_INT32:
815 			intfound = B_TRUE;
816 			u64 = fmd_prop_get_int32(hdl, fmd_props[i].fmdp_name);
817 			break;
818 		case FMD_TYPE_UINT64:
819 		case FMD_TYPE_INT64:
820 			intfound = B_TRUE;
821 			u64 = fmd_prop_get_int64(hdl, fmd_props[i].fmdp_name);
822 			break;
823 		case FMD_TYPE_STRING:
824 			strfound = B_TRUE;
825 			str = fmd_prop_get_string(hdl, fmd_props[i].fmdp_name);
826 			break;
827 
828 		}
829 
830 		if (intfound) {
831 			(void) snprintf(buf, INT64_BUF_LEN, "0x%llx", u64);
832 			nvp.value = buf;
833 			intfound = B_FALSE;
834 		} else if (strfound) {
835 			nvp.value = str;
836 		}
837 
838 		log_msg(MM_CONF, "Adding property `%s' with value `%s'\n",
839 		    nvp.name, nvp.value);
840 
841 		cfgdata_add_namevalpr(config_data, &nvp);
842 
843 		if (strfound) {
844 			strfound = B_FALSE;
845 			fmd_prop_free_string(hdl, str);
846 		}
847 
848 
849 		i++;
850 	}
851 
852 	if ((g_verbose & (MM_CONF|MM_OTHER)) == (MM_CONF|MM_OTHER))
853 		print_cfgdata(config_data, stderr, "");
854 
855 	return (err);
856 }
857 
858 void
config_fini(void)859 config_fini(void)
860 {
861 	fini_configuration_from_topo();
862 	cfgdata_free(config_data);
863 	config_data = NULL;
864 }
865 
866 nvlist_t *
dm_global_proplist(void)867 dm_global_proplist(void)
868 {
869 	return (config_data->props);
870 }
871