1/*
2 * This file is part of the ZFS Event Daemon (ZED).
3 *
4 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
5 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
6 * Refer to the OpenZFS git commit log for authoritative copyright attribution.
7 *
8 * The contents of this file are subject to the terms of the
9 * Common Development and Distribution License Version 1.0 (CDDL-1.0).
10 * You can obtain a copy of the license from the top-level file
11 * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
12 * You may not use this file except in compliance with the license.
13 */
14
15#include <ctype.h>
16#include <errno.h>
17#include <fcntl.h>
18#include <libzfs_core.h>
19#include <paths.h>
20#include <stdarg.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/zfs_ioctl.h>
25#include <time.h>
26#include <unistd.h>
27#include <sys/fm/fs/zfs.h>
28#include "zed.h"
29#include "zed_conf.h"
30#include "zed_disk_event.h"
31#include "zed_event.h"
32#include "zed_exec.h"
33#include "zed_file.h"
34#include "zed_log.h"
35#include "zed_strings.h"
36
37#include "agents/zfs_agents.h"
38
39#define	MAXBUF	4096
40
41/*
42 * Open the libzfs interface.
43 */
44int
45zed_event_init(struct zed_conf *zcp)
46{
47	if (!zcp)
48		zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
49
50	zcp->zfs_hdl = libzfs_init();
51	if (!zcp->zfs_hdl) {
52		if (zcp->do_idle)
53			return (-1);
54		zed_log_die("Failed to initialize libzfs");
55	}
56
57	zcp->zevent_fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC);
58	if (zcp->zevent_fd < 0) {
59		if (zcp->do_idle)
60			return (-1);
61		zed_log_die("Failed to open \"%s\": %s",
62		    ZFS_DEV, strerror(errno));
63	}
64
65	zfs_agent_init(zcp->zfs_hdl);
66
67	if (zed_disk_event_init() != 0) {
68		if (zcp->do_idle)
69			return (-1);
70		zed_log_die("Failed to initialize disk events");
71	}
72
73	return (0);
74}
75
76/*
77 * Close the libzfs interface.
78 */
79void
80zed_event_fini(struct zed_conf *zcp)
81{
82	if (!zcp)
83		zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL));
84
85	zed_disk_event_fini();
86	zfs_agent_fini();
87
88	if (zcp->zevent_fd >= 0) {
89		if (close(zcp->zevent_fd) < 0)
90			zed_log_msg(LOG_WARNING, "Failed to close \"%s\": %s",
91			    ZFS_DEV, strerror(errno));
92
93		zcp->zevent_fd = -1;
94	}
95	if (zcp->zfs_hdl) {
96		libzfs_fini(zcp->zfs_hdl);
97		zcp->zfs_hdl = NULL;
98	}
99
100	zed_exec_fini();
101}
102
103static void
104_bump_event_queue_length(void)
105{
106	int zzlm = -1, wr;
107	char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
108	long int qlen;
109
110	zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
111	if (zzlm < 0)
112		goto done;
113
114	if (read(zzlm, qlen_buf, sizeof (qlen_buf)) < 0)
115		goto done;
116	qlen_buf[sizeof (qlen_buf) - 1] = '\0';
117
118	errno = 0;
119	qlen = strtol(qlen_buf, NULL, 10);
120	if (errno == ERANGE)
121		goto done;
122
123	if (qlen <= 0)
124		qlen = 512; /* default zfs_zevent_len_max value */
125	else
126		qlen *= 2;
127
128	if (qlen > INT_MAX)
129		qlen = INT_MAX;
130	wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
131
132	if (pwrite(zzlm, qlen_buf, wr, 0) < 0)
133		goto done;
134
135	zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen);
136
137done:
138	if (zzlm > -1)
139		(void) close(zzlm);
140}
141
142/*
143 * Seek to the event specified by [saved_eid] and [saved_etime].
144 * This protects against processing a given event more than once.
145 * Return 0 upon a successful seek to the specified event, or -1 otherwise.
146 *
147 * A zevent is considered to be uniquely specified by its (eid,time) tuple.
148 * The unsigned 64b eid is set to 1 when the kernel module is loaded, and
149 * incremented by 1 for each new event.  Since the state file can persist
150 * across a kernel module reload, the time must be checked to ensure a match.
151 */
152int
153zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid, int64_t saved_etime[])
154{
155	uint64_t eid;
156	int found;
157	nvlist_t *nvl;
158	int n_dropped;
159	int64_t *etime;
160	uint_t nelem;
161	int rv;
162
163	if (!zcp) {
164		errno = EINVAL;
165		zed_log_msg(LOG_ERR, "Failed to seek zevent: %s",
166		    strerror(errno));
167		return (-1);
168	}
169	eid = 0;
170	found = 0;
171	while ((eid < saved_eid) && !found) {
172		rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped,
173		    ZEVENT_NONBLOCK, zcp->zevent_fd);
174
175		if ((rv != 0) || !nvl)
176			break;
177
178		if (n_dropped > 0) {
179			zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
180			_bump_event_queue_length();
181		}
182		if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
183			zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
184		} else if (nvlist_lookup_int64_array(nvl, "time",
185		    &etime, &nelem) != 0) {
186			zed_log_msg(LOG_WARNING,
187			    "Failed to lookup zevent time (eid=%llu)", eid);
188		} else if (nelem != 2) {
189			zed_log_msg(LOG_WARNING,
190			    "Failed to lookup zevent time (eid=%llu, nelem=%u)",
191			    eid, nelem);
192		} else if ((eid != saved_eid) ||
193		    (etime[0] != saved_etime[0]) ||
194		    (etime[1] != saved_etime[1])) {
195			/* no-op */
196		} else {
197			found = 1;
198		}
199		free(nvl);
200	}
201	if (!found && (saved_eid > 0)) {
202		if (zpool_events_seek(zcp->zfs_hdl, ZEVENT_SEEK_START,
203		    zcp->zevent_fd) < 0)
204			zed_log_msg(LOG_WARNING, "Failed to seek to eid=0");
205		else
206			eid = 0;
207	}
208	zed_log_msg(LOG_NOTICE, "Processing events since eid=%llu", eid);
209	return (found ? 0 : -1);
210}
211
212/*
213 * Return non-zero if nvpair [name] should be formatted in hex; o/w, return 0.
214 */
215static int
216_zed_event_value_is_hex(const char *name)
217{
218	const char *hex_suffix[] = {
219		"_guid",
220		"_guids",
221		NULL
222	};
223	const char **pp;
224	char *p;
225
226	if (!name)
227		return (0);
228
229	for (pp = hex_suffix; *pp; pp++) {
230		p = strstr(name, *pp);
231		if (p && strlen(p) == strlen(*pp))
232			return (1);
233	}
234	return (0);
235}
236
237/*
238 * Add an environment variable for [eid] to the container [zsp].
239 *
240 * The variable name is the concatenation of [prefix] and [name] converted to
241 * uppercase with non-alphanumeric characters converted to underscores;
242 * [prefix] is optional, and [name] must begin with an alphabetic character.
243 * If the converted variable name already exists within the container [zsp],
244 * its existing value will be replaced with the new value.
245 *
246 * The variable value is specified by the format string [fmt].
247 *
248 * Returns 0 on success, and -1 on error (with errno set).
249 *
250 * All environment variables in [zsp] should be added through this function.
251 */
252static __attribute__((format(printf, 5, 6))) int
253_zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
254    const char *prefix, const char *name, const char *fmt, ...)
255{
256	char keybuf[MAXBUF];
257	char valbuf[MAXBUF];
258	char *dstp;
259	const char *srcp;
260	const char *lastp;
261	int n;
262	int buflen;
263	va_list vargs;
264
265	assert(zsp != NULL);
266	assert(fmt != NULL);
267
268	if (!name) {
269		errno = EINVAL;
270		zed_log_msg(LOG_WARNING,
271		    "Failed to add variable for eid=%llu: Name is empty", eid);
272		return (-1);
273	} else if (!isalpha(name[0])) {
274		errno = EINVAL;
275		zed_log_msg(LOG_WARNING,
276		    "Failed to add variable for eid=%llu: "
277		    "Name \"%s\" is invalid", eid, name);
278		return (-1);
279	}
280	/*
281	 * Construct the string key by converting PREFIX (if present) and NAME.
282	 */
283	dstp = keybuf;
284	lastp = keybuf + sizeof (keybuf);
285	if (prefix) {
286		for (srcp = prefix; *srcp && (dstp < lastp); srcp++)
287			*dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
288	}
289	for (srcp = name; *srcp && (dstp < lastp); srcp++)
290		*dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
291
292	if (dstp == lastp) {
293		errno = ENAMETOOLONG;
294		zed_log_msg(LOG_WARNING,
295		    "Failed to add variable for eid=%llu: Name too long", eid);
296		return (-1);
297	}
298	*dstp = '\0';
299	/*
300	 * Construct the string specified by "[PREFIX][NAME]=[FMT]".
301	 */
302	dstp = valbuf;
303	buflen = sizeof (valbuf);
304	n = strlcpy(dstp, keybuf, buflen);
305	if (n >= sizeof (valbuf)) {
306		errno = EMSGSIZE;
307		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
308		    keybuf, eid, "Exceeded buffer size");
309		return (-1);
310	}
311	dstp += n;
312	buflen -= n;
313
314	*dstp++ = '=';
315	buflen--;
316
317	if (buflen <= 0) {
318		errno = EMSGSIZE;
319		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
320		    keybuf, eid, "Exceeded buffer size");
321		return (-1);
322	}
323
324	va_start(vargs, fmt);
325	n = vsnprintf(dstp, buflen, fmt, vargs);
326	va_end(vargs);
327
328	if ((n < 0) || (n >= buflen)) {
329		errno = EMSGSIZE;
330		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
331		    keybuf, eid, "Exceeded buffer size");
332		return (-1);
333	} else if (zed_strings_add(zsp, keybuf, valbuf) < 0) {
334		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
335		    keybuf, eid, strerror(errno));
336		return (-1);
337	}
338	return (0);
339}
340
341static int
342_zed_event_add_array_err(uint64_t eid, const char *name)
343{
344	errno = EMSGSIZE;
345	zed_log_msg(LOG_WARNING,
346	    "Failed to convert nvpair \"%s\" for eid=%llu: "
347	    "Exceeded buffer size", name, eid);
348	return (-1);
349}
350
351static int
352_zed_event_add_int8_array(uint64_t eid, zed_strings_t *zsp,
353    const char *prefix, nvpair_t *nvp)
354{
355	char buf[MAXBUF];
356	int buflen = sizeof (buf);
357	const char *name;
358	int8_t *i8p;
359	uint_t nelem;
360	uint_t i;
361	char *p;
362	int n;
363
364	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT8_ARRAY));
365
366	name = nvpair_name(nvp);
367	(void) nvpair_value_int8_array(nvp, &i8p, &nelem);
368	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
369		n = snprintf(p, buflen, "%d ", i8p[i]);
370		if ((n < 0) || (n >= buflen))
371			return (_zed_event_add_array_err(eid, name));
372		p += n;
373		buflen -= n;
374	}
375	if (nelem > 0)
376		*--p = '\0';
377
378	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
379}
380
381static int
382_zed_event_add_uint8_array(uint64_t eid, zed_strings_t *zsp,
383    const char *prefix, nvpair_t *nvp)
384{
385	char buf[MAXBUF];
386	int buflen = sizeof (buf);
387	const char *name;
388	uint8_t *u8p;
389	uint_t nelem;
390	uint_t i;
391	char *p;
392	int n;
393
394	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT8_ARRAY));
395
396	name = nvpair_name(nvp);
397	(void) nvpair_value_uint8_array(nvp, &u8p, &nelem);
398	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
399		n = snprintf(p, buflen, "%u ", u8p[i]);
400		if ((n < 0) || (n >= buflen))
401			return (_zed_event_add_array_err(eid, name));
402		p += n;
403		buflen -= n;
404	}
405	if (nelem > 0)
406		*--p = '\0';
407
408	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
409}
410
411static int
412_zed_event_add_int16_array(uint64_t eid, zed_strings_t *zsp,
413    const char *prefix, nvpair_t *nvp)
414{
415	char buf[MAXBUF];
416	int buflen = sizeof (buf);
417	const char *name;
418	int16_t *i16p;
419	uint_t nelem;
420	uint_t i;
421	char *p;
422	int n;
423
424	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT16_ARRAY));
425
426	name = nvpair_name(nvp);
427	(void) nvpair_value_int16_array(nvp, &i16p, &nelem);
428	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
429		n = snprintf(p, buflen, "%d ", i16p[i]);
430		if ((n < 0) || (n >= buflen))
431			return (_zed_event_add_array_err(eid, name));
432		p += n;
433		buflen -= n;
434	}
435	if (nelem > 0)
436		*--p = '\0';
437
438	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
439}
440
441static int
442_zed_event_add_uint16_array(uint64_t eid, zed_strings_t *zsp,
443    const char *prefix, nvpair_t *nvp)
444{
445	char buf[MAXBUF];
446	int buflen = sizeof (buf);
447	const char *name;
448	uint16_t *u16p;
449	uint_t nelem;
450	uint_t i;
451	char *p;
452	int n;
453
454	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY));
455
456	name = nvpair_name(nvp);
457	(void) nvpair_value_uint16_array(nvp, &u16p, &nelem);
458	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
459		n = snprintf(p, buflen, "%u ", u16p[i]);
460		if ((n < 0) || (n >= buflen))
461			return (_zed_event_add_array_err(eid, name));
462		p += n;
463		buflen -= n;
464	}
465	if (nelem > 0)
466		*--p = '\0';
467
468	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
469}
470
471static int
472_zed_event_add_int32_array(uint64_t eid, zed_strings_t *zsp,
473    const char *prefix, nvpair_t *nvp)
474{
475	char buf[MAXBUF];
476	int buflen = sizeof (buf);
477	const char *name;
478	int32_t *i32p;
479	uint_t nelem;
480	uint_t i;
481	char *p;
482	int n;
483
484	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT32_ARRAY));
485
486	name = nvpair_name(nvp);
487	(void) nvpair_value_int32_array(nvp, &i32p, &nelem);
488	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
489		n = snprintf(p, buflen, "%d ", i32p[i]);
490		if ((n < 0) || (n >= buflen))
491			return (_zed_event_add_array_err(eid, name));
492		p += n;
493		buflen -= n;
494	}
495	if (nelem > 0)
496		*--p = '\0';
497
498	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
499}
500
501static int
502_zed_event_add_uint32_array(uint64_t eid, zed_strings_t *zsp,
503    const char *prefix, nvpair_t *nvp)
504{
505	char buf[MAXBUF];
506	int buflen = sizeof (buf);
507	const char *name;
508	uint32_t *u32p;
509	uint_t nelem;
510	uint_t i;
511	char *p;
512	int n;
513
514	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT32_ARRAY));
515
516	name = nvpair_name(nvp);
517	(void) nvpair_value_uint32_array(nvp, &u32p, &nelem);
518	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
519		n = snprintf(p, buflen, "%u ", u32p[i]);
520		if ((n < 0) || (n >= buflen))
521			return (_zed_event_add_array_err(eid, name));
522		p += n;
523		buflen -= n;
524	}
525	if (nelem > 0)
526		*--p = '\0';
527
528	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
529}
530
531static int
532_zed_event_add_int64_array(uint64_t eid, zed_strings_t *zsp,
533    const char *prefix, nvpair_t *nvp)
534{
535	char buf[MAXBUF];
536	int buflen = sizeof (buf);
537	const char *name;
538	int64_t *i64p;
539	uint_t nelem;
540	uint_t i;
541	char *p;
542	int n;
543
544	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_INT64_ARRAY));
545
546	name = nvpair_name(nvp);
547	(void) nvpair_value_int64_array(nvp, &i64p, &nelem);
548	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
549		n = snprintf(p, buflen, "%lld ", (u_longlong_t)i64p[i]);
550		if ((n < 0) || (n >= buflen))
551			return (_zed_event_add_array_err(eid, name));
552		p += n;
553		buflen -= n;
554	}
555	if (nelem > 0)
556		*--p = '\0';
557
558	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
559}
560
561static int
562_zed_event_add_uint64_array(uint64_t eid, zed_strings_t *zsp,
563    const char *prefix, nvpair_t *nvp)
564{
565	char buf[MAXBUF];
566	int buflen = sizeof (buf);
567	const char *name;
568	const char *fmt;
569	uint64_t *u64p;
570	uint_t nelem;
571	uint_t i;
572	char *p;
573	int n;
574
575	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_UINT64_ARRAY));
576
577	name = nvpair_name(nvp);
578	fmt = _zed_event_value_is_hex(name) ? "0x%.16llX " : "%llu ";
579	(void) nvpair_value_uint64_array(nvp, &u64p, &nelem);
580	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
581		n = snprintf(p, buflen, fmt, (u_longlong_t)u64p[i]);
582		if ((n < 0) || (n >= buflen))
583			return (_zed_event_add_array_err(eid, name));
584		p += n;
585		buflen -= n;
586	}
587	if (nelem > 0)
588		*--p = '\0';
589
590	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
591}
592
593static int
594_zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
595    const char *prefix, nvpair_t *nvp)
596{
597	char buf[MAXBUF];
598	int buflen = sizeof (buf);
599	const char *name;
600	char **strp;
601	uint_t nelem;
602	uint_t i;
603	char *p;
604	int n;
605
606	assert((nvp != NULL) && (nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY));
607
608	name = nvpair_name(nvp);
609	(void) nvpair_value_string_array(nvp, &strp, &nelem);
610	for (i = 0, p = buf; (i < nelem) && (buflen > 0); i++) {
611		n = snprintf(p, buflen, "%s ", strp[i] ? strp[i] : "<NULL>");
612		if ((n < 0) || (n >= buflen))
613			return (_zed_event_add_array_err(eid, name));
614		p += n;
615		buflen -= n;
616	}
617	if (nelem > 0)
618		*--p = '\0';
619
620	return (_zed_event_add_var(eid, zsp, prefix, name, "%s", buf));
621}
622
623/*
624 * Convert the nvpair [nvp] to a string which is added to the environment
625 * of the child process.
626 * Return 0 on success, -1 on error.
627 */
628static void
629_zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
630{
631	const char *name;
632	data_type_t type;
633	const char *prefix = ZEVENT_VAR_PREFIX;
634	boolean_t b;
635	double d;
636	uint8_t i8;
637	uint16_t i16;
638	uint32_t i32;
639	uint64_t i64;
640	char *str;
641
642	assert(zsp != NULL);
643	assert(nvp != NULL);
644
645	name = nvpair_name(nvp);
646	type = nvpair_type(nvp);
647
648	switch (type) {
649	case DATA_TYPE_BOOLEAN:
650		_zed_event_add_var(eid, zsp, prefix, name, "%s", "1");
651		break;
652	case DATA_TYPE_BOOLEAN_VALUE:
653		(void) nvpair_value_boolean_value(nvp, &b);
654		_zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0");
655		break;
656	case DATA_TYPE_BYTE:
657		(void) nvpair_value_byte(nvp, &i8);
658		_zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
659		break;
660	case DATA_TYPE_INT8:
661		(void) nvpair_value_int8(nvp, (int8_t *)&i8);
662		_zed_event_add_var(eid, zsp, prefix, name, "%d", i8);
663		break;
664	case DATA_TYPE_UINT8:
665		(void) nvpair_value_uint8(nvp, &i8);
666		_zed_event_add_var(eid, zsp, prefix, name, "%u", i8);
667		break;
668	case DATA_TYPE_INT16:
669		(void) nvpair_value_int16(nvp, (int16_t *)&i16);
670		_zed_event_add_var(eid, zsp, prefix, name, "%d", i16);
671		break;
672	case DATA_TYPE_UINT16:
673		(void) nvpair_value_uint16(nvp, &i16);
674		_zed_event_add_var(eid, zsp, prefix, name, "%u", i16);
675		break;
676	case DATA_TYPE_INT32:
677		(void) nvpair_value_int32(nvp, (int32_t *)&i32);
678		_zed_event_add_var(eid, zsp, prefix, name, "%d", i32);
679		break;
680	case DATA_TYPE_UINT32:
681		(void) nvpair_value_uint32(nvp, &i32);
682		_zed_event_add_var(eid, zsp, prefix, name, "%u", i32);
683		break;
684	case DATA_TYPE_INT64:
685		(void) nvpair_value_int64(nvp, (int64_t *)&i64);
686		_zed_event_add_var(eid, zsp, prefix, name,
687		    "%lld", (longlong_t)i64);
688		break;
689	case DATA_TYPE_UINT64:
690		(void) nvpair_value_uint64(nvp, &i64);
691		_zed_event_add_var(eid, zsp, prefix, name,
692		    (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"),
693		    (u_longlong_t)i64);
694		/*
695		 * shadow readable strings for vdev state pairs
696		 */
697		if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 ||
698		    strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) {
699			char alt[32];
700
701			(void) snprintf(alt, sizeof (alt), "%s_str", name);
702			_zed_event_add_var(eid, zsp, prefix, alt, "%s",
703			    zpool_state_to_name(i64, VDEV_AUX_NONE));
704		} else
705		/*
706		 * shadow readable strings for pool state
707		 */
708		if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_POOL_STATE) == 0) {
709			char alt[32];
710
711			(void) snprintf(alt, sizeof (alt), "%s_str", name);
712			_zed_event_add_var(eid, zsp, prefix, alt, "%s",
713			    zpool_pool_state_to_name(i64));
714		}
715		break;
716	case DATA_TYPE_DOUBLE:
717		(void) nvpair_value_double(nvp, &d);
718		_zed_event_add_var(eid, zsp, prefix, name, "%g", d);
719		break;
720	case DATA_TYPE_HRTIME:
721		(void) nvpair_value_hrtime(nvp, (hrtime_t *)&i64);
722		_zed_event_add_var(eid, zsp, prefix, name,
723		    "%llu", (u_longlong_t)i64);
724		break;
725	case DATA_TYPE_STRING:
726		(void) nvpair_value_string(nvp, &str);
727		_zed_event_add_var(eid, zsp, prefix, name,
728		    "%s", (str ? str : "<NULL>"));
729		break;
730	case DATA_TYPE_INT8_ARRAY:
731		_zed_event_add_int8_array(eid, zsp, prefix, nvp);
732		break;
733	case DATA_TYPE_UINT8_ARRAY:
734		_zed_event_add_uint8_array(eid, zsp, prefix, nvp);
735		break;
736	case DATA_TYPE_INT16_ARRAY:
737		_zed_event_add_int16_array(eid, zsp, prefix, nvp);
738		break;
739	case DATA_TYPE_UINT16_ARRAY:
740		_zed_event_add_uint16_array(eid, zsp, prefix, nvp);
741		break;
742	case DATA_TYPE_INT32_ARRAY:
743		_zed_event_add_int32_array(eid, zsp, prefix, nvp);
744		break;
745	case DATA_TYPE_UINT32_ARRAY:
746		_zed_event_add_uint32_array(eid, zsp, prefix, nvp);
747		break;
748	case DATA_TYPE_INT64_ARRAY:
749		_zed_event_add_int64_array(eid, zsp, prefix, nvp);
750		break;
751	case DATA_TYPE_UINT64_ARRAY:
752		_zed_event_add_uint64_array(eid, zsp, prefix, nvp);
753		break;
754	case DATA_TYPE_STRING_ARRAY:
755		_zed_event_add_string_array(eid, zsp, prefix, nvp);
756		break;
757	case DATA_TYPE_NVLIST:
758	case DATA_TYPE_BOOLEAN_ARRAY:
759	case DATA_TYPE_BYTE_ARRAY:
760	case DATA_TYPE_NVLIST_ARRAY:
761		_zed_event_add_var(eid, zsp, prefix, name, "_NOT_IMPLEMENTED_");
762		break;
763	default:
764		errno = EINVAL;
765		zed_log_msg(LOG_WARNING,
766		    "Failed to convert nvpair \"%s\" for eid=%llu: "
767		    "Unrecognized type=%u", name, eid, (unsigned int) type);
768		break;
769	}
770}
771
772/*
773 * Restrict various environment variables to safe and sane values
774 * when constructing the environment for the child process, unless
775 * we're running with a custom $PATH (like under the ZFS test suite).
776 *
777 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
778 */
779static void
780_zed_event_add_env_restrict(uint64_t eid, zed_strings_t *zsp,
781    const char *path)
782{
783	const char *env_restrict[][2] = {
784		{ "IFS",		" \t\n" },
785		{ "PATH",		_PATH_STDPATH },
786		{ "ZDB",		SBINDIR "/zdb" },
787		{ "ZED",		SBINDIR "/zed" },
788		{ "ZFS",		SBINDIR "/zfs" },
789		{ "ZINJECT",		SBINDIR "/zinject" },
790		{ "ZPOOL",		SBINDIR "/zpool" },
791		{ "ZFS_ALIAS",		ZFS_META_ALIAS },
792		{ "ZFS_VERSION",	ZFS_META_VERSION },
793		{ "ZFS_RELEASE",	ZFS_META_RELEASE },
794		{ NULL,			NULL }
795	};
796
797	/*
798	 * If we have a custom $PATH, use the default ZFS binary locations
799	 * instead of the hard-coded ones.
800	 */
801	const char *env_path[][2] = {
802		{ "IFS",		" \t\n" },
803		{ "PATH",		NULL }, /* $PATH copied in later on */
804		{ "ZDB",		"zdb" },
805		{ "ZED",		"zed" },
806		{ "ZFS",		"zfs" },
807		{ "ZINJECT",		"zinject" },
808		{ "ZPOOL",		"zpool" },
809		{ "ZFS_ALIAS",		ZFS_META_ALIAS },
810		{ "ZFS_VERSION",	ZFS_META_VERSION },
811		{ "ZFS_RELEASE",	ZFS_META_RELEASE },
812		{ NULL,			NULL }
813	};
814	const char *(*pa)[2];
815
816	assert(zsp != NULL);
817
818	pa = path != NULL ? env_path : env_restrict;
819
820	for (; *(*pa); pa++) {
821		/* Use our custom $PATH if we have one */
822		if (path != NULL && strcmp((*pa)[0], "PATH") == 0)
823			(*pa)[1] = path;
824
825		_zed_event_add_var(eid, zsp, NULL, (*pa)[0], "%s", (*pa)[1]);
826	}
827}
828
829/*
830 * Preserve specified variables from the parent environment
831 * when constructing the environment for the child process.
832 *
833 * Reference: Secure Programming Cookbook by Viega & Messier, Section 1.1.
834 */
835static void
836_zed_event_add_env_preserve(uint64_t eid, zed_strings_t *zsp)
837{
838	const char *env_preserve[] = {
839		"TZ",
840		NULL
841	};
842	const char **keyp;
843	const char *val;
844
845	assert(zsp != NULL);
846
847	for (keyp = env_preserve; *keyp; keyp++) {
848		if ((val = getenv(*keyp)))
849			_zed_event_add_var(eid, zsp, NULL, *keyp, "%s", val);
850	}
851}
852
853/*
854 * Compute the "subclass" by removing the first 3 components of [class]
855 * (which will always be of the form "*.fs.zfs").  Return a pointer inside
856 * the string [class], or NULL if insufficient components exist.
857 */
858static const char *
859_zed_event_get_subclass(const char *class)
860{
861	const char *p;
862	int i;
863
864	if (!class)
865		return (NULL);
866
867	p = class;
868	for (i = 0; i < 3; i++) {
869		p = strchr(p, '.');
870		if (!p)
871			break;
872		p++;
873	}
874	return (p);
875}
876
877/*
878 * Convert the zevent time from a 2-element array of 64b integers
879 * into a more convenient form:
880 * - TIME_SECS is the second component of the time.
881 * - TIME_NSECS is the nanosecond component of the time.
882 * - TIME_STRING is an almost-RFC3339-compliant string representation.
883 */
884static void
885_zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
886{
887	struct tm *stp;
888	char buf[32];
889
890	assert(zsp != NULL);
891	assert(etime != NULL);
892
893	_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS",
894	    "%lld", (long long int) etime[0]);
895	_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS",
896	    "%lld", (long long int) etime[1]);
897
898	if (!(stp = localtime((const time_t *) &etime[0]))) {
899		zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
900		    ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error");
901	} else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", stp)) {
902		zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
903		    ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error");
904	} else {
905		_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_STRING",
906		    "%s", buf);
907	}
908}
909
910/*
911 * Service the next zevent, blocking until one is available.
912 */
913int
914zed_event_service(struct zed_conf *zcp)
915{
916	nvlist_t *nvl;
917	nvpair_t *nvp;
918	int n_dropped;
919	zed_strings_t *zsp;
920	uint64_t eid;
921	int64_t *etime;
922	uint_t nelem;
923	char *class;
924	const char *subclass;
925	int rv;
926
927	if (!zcp) {
928		errno = EINVAL;
929		zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
930		    strerror(errno));
931		return (EINVAL);
932	}
933	rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
934	    zcp->zevent_fd);
935
936	if ((rv != 0) || !nvl)
937		return (errno);
938
939	if (n_dropped > 0) {
940		zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
941		_bump_event_queue_length();
942	}
943	if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
944		zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
945	} else if (nvlist_lookup_int64_array(
946	    nvl, "time", &etime, &nelem) != 0) {
947		zed_log_msg(LOG_WARNING,
948		    "Failed to lookup zevent time (eid=%llu)", eid);
949	} else if (nelem != 2) {
950		zed_log_msg(LOG_WARNING,
951		    "Failed to lookup zevent time (eid=%llu, nelem=%u)",
952		    eid, nelem);
953	} else if (nvlist_lookup_string(nvl, "class", &class) != 0) {
954		zed_log_msg(LOG_WARNING,
955		    "Failed to lookup zevent class (eid=%llu)", eid);
956	} else {
957		/* let internal modules see this event first */
958		zfs_agent_post_event(class, NULL, nvl);
959
960		zsp = zed_strings_create();
961
962		nvp = NULL;
963		while ((nvp = nvlist_next_nvpair(nvl, nvp)))
964			_zed_event_add_nvpair(eid, zsp, nvp);
965
966		_zed_event_add_env_restrict(eid, zsp, zcp->path);
967		_zed_event_add_env_preserve(eid, zsp);
968
969		_zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "PID",
970		    "%d", (int)getpid());
971		_zed_event_add_var(eid, zsp, ZED_VAR_PREFIX, "ZEDLET_DIR",
972		    "%s", zcp->zedlet_dir);
973		subclass = _zed_event_get_subclass(class);
974		_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "SUBCLASS",
975		    "%s", (subclass ? subclass : class));
976
977		_zed_event_add_time_strings(eid, zsp, etime);
978
979		zed_exec_process(eid, class, subclass, zcp, zsp);
980
981		zed_conf_write_state(zcp, eid, etime);
982
983		zed_strings_destroy(zsp);
984	}
985	nvlist_free(nvl);
986	return (0);
987}
988