1*12967Sgavin.maltby@oracle.com /*
2*12967Sgavin.maltby@oracle.com * CDDL HEADER START
3*12967Sgavin.maltby@oracle.com *
4*12967Sgavin.maltby@oracle.com * The contents of this file are subject to the terms of the
5*12967Sgavin.maltby@oracle.com * Common Development and Distribution License (the "License").
6*12967Sgavin.maltby@oracle.com * You may not use this file except in compliance with the License.
7*12967Sgavin.maltby@oracle.com *
8*12967Sgavin.maltby@oracle.com * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12967Sgavin.maltby@oracle.com * or http://www.opensolaris.org/os/licensing.
10*12967Sgavin.maltby@oracle.com * See the License for the specific language governing permissions
11*12967Sgavin.maltby@oracle.com * and limitations under the License.
12*12967Sgavin.maltby@oracle.com *
13*12967Sgavin.maltby@oracle.com * When distributing Covered Code, include this CDDL HEADER in each
14*12967Sgavin.maltby@oracle.com * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12967Sgavin.maltby@oracle.com * If applicable, add the following below this CDDL HEADER, with the
16*12967Sgavin.maltby@oracle.com * fields enclosed by brackets "[]" replaced with your own identifying
17*12967Sgavin.maltby@oracle.com * information: Portions Copyright [yyyy] [name of copyright owner]
18*12967Sgavin.maltby@oracle.com *
19*12967Sgavin.maltby@oracle.com * CDDL HEADER END
20*12967Sgavin.maltby@oracle.com */
21*12967Sgavin.maltby@oracle.com
22*12967Sgavin.maltby@oracle.com /*
23*12967Sgavin.maltby@oracle.com * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*12967Sgavin.maltby@oracle.com */
25*12967Sgavin.maltby@oracle.com
26*12967Sgavin.maltby@oracle.com #include <sys/fm/protocol.h>
27*12967Sgavin.maltby@oracle.com #include <fm/fmd_snmp.h>
28*12967Sgavin.maltby@oracle.com #include <fm/fmd_msg.h>
29*12967Sgavin.maltby@oracle.com #include <fm/libfmevent.h>
30*12967Sgavin.maltby@oracle.com #include <net-snmp/net-snmp-config.h>
31*12967Sgavin.maltby@oracle.com #include <net-snmp/net-snmp-includes.h>
32*12967Sgavin.maltby@oracle.com #include <net-snmp/agent/net-snmp-agent-includes.h>
33*12967Sgavin.maltby@oracle.com #include <errno.h>
34*12967Sgavin.maltby@oracle.com #include <locale.h>
35*12967Sgavin.maltby@oracle.com #include <netdb.h>
36*12967Sgavin.maltby@oracle.com #include <signal.h>
37*12967Sgavin.maltby@oracle.com #include <strings.h>
38*12967Sgavin.maltby@oracle.com #include <stdlib.h>
39*12967Sgavin.maltby@oracle.com #include <unistd.h>
40*12967Sgavin.maltby@oracle.com #include <limits.h>
41*12967Sgavin.maltby@oracle.com #include <alloca.h>
42*12967Sgavin.maltby@oracle.com #include <priv_utils.h>
43*12967Sgavin.maltby@oracle.com #include <zone.h>
44*12967Sgavin.maltby@oracle.com #include "libfmnotify.h"
45*12967Sgavin.maltby@oracle.com
46*12967Sgavin.maltby@oracle.com /*
47*12967Sgavin.maltby@oracle.com * Debug messages can be enabled by setting the debug property to true
48*12967Sgavin.maltby@oracle.com *
49*12967Sgavin.maltby@oracle.com * # svccfg -s svc:/system/fm/snmp-notify setprop config/debug=true
50*12967Sgavin.maltby@oracle.com */
51*12967Sgavin.maltby@oracle.com #define SVCNAME "system/fm/snmp-notify"
52*12967Sgavin.maltby@oracle.com
53*12967Sgavin.maltby@oracle.com typedef struct ireport_trap {
54*12967Sgavin.maltby@oracle.com char *host;
55*12967Sgavin.maltby@oracle.com char *msgid;
56*12967Sgavin.maltby@oracle.com char *desc;
57*12967Sgavin.maltby@oracle.com long long tstamp;
58*12967Sgavin.maltby@oracle.com char *fmri;
59*12967Sgavin.maltby@oracle.com uint32_t from_state;
60*12967Sgavin.maltby@oracle.com uint32_t to_state;
61*12967Sgavin.maltby@oracle.com char *reason;
62*12967Sgavin.maltby@oracle.com boolean_t is_stn_event;
63*12967Sgavin.maltby@oracle.com } ireport_trap_t;
64*12967Sgavin.maltby@oracle.com
65*12967Sgavin.maltby@oracle.com static nd_hdl_t *nhdl;
66*12967Sgavin.maltby@oracle.com static const char optstr[] = "dfR:";
67*12967Sgavin.maltby@oracle.com static const char SNMP_SUPPCONF[] = "fmd-trapgen";
68*12967Sgavin.maltby@oracle.com static char hostname[MAXHOSTNAMELEN + 1];
69*12967Sgavin.maltby@oracle.com
70*12967Sgavin.maltby@oracle.com static int
usage(const char * pname)71*12967Sgavin.maltby@oracle.com usage(const char *pname)
72*12967Sgavin.maltby@oracle.com {
73*12967Sgavin.maltby@oracle.com (void) fprintf(stderr, "Usage: %s [-df] [-R <altroot>]\n", pname);
74*12967Sgavin.maltby@oracle.com
75*12967Sgavin.maltby@oracle.com (void) fprintf(stderr,
76*12967Sgavin.maltby@oracle.com "\t-d enable debug mode\n"
77*12967Sgavin.maltby@oracle.com "\t-f stay in foreground\n"
78*12967Sgavin.maltby@oracle.com "\t-R specify alternate root\n");
79*12967Sgavin.maltby@oracle.com
80*12967Sgavin.maltby@oracle.com return (1);
81*12967Sgavin.maltby@oracle.com }
82*12967Sgavin.maltby@oracle.com
83*12967Sgavin.maltby@oracle.com /*
84*12967Sgavin.maltby@oracle.com * If someone does an "svcadm refresh" on us, then this function gets called,
85*12967Sgavin.maltby@oracle.com * which rereads our service configuration.
86*12967Sgavin.maltby@oracle.com */
87*12967Sgavin.maltby@oracle.com static void
get_svc_config()88*12967Sgavin.maltby@oracle.com get_svc_config()
89*12967Sgavin.maltby@oracle.com {
90*12967Sgavin.maltby@oracle.com int s = 0;
91*12967Sgavin.maltby@oracle.com uint8_t val;
92*12967Sgavin.maltby@oracle.com
93*12967Sgavin.maltby@oracle.com s = nd_get_boolean_prop(nhdl, SVCNAME, "config", "debug", &val);
94*12967Sgavin.maltby@oracle.com nhdl->nh_debug = val;
95*12967Sgavin.maltby@oracle.com
96*12967Sgavin.maltby@oracle.com s += nd_get_astring_prop(nhdl, SVCNAME, "config", "rootdir",
97*12967Sgavin.maltby@oracle.com &(nhdl->nh_rootdir));
98*12967Sgavin.maltby@oracle.com
99*12967Sgavin.maltby@oracle.com if (s != 0)
100*12967Sgavin.maltby@oracle.com nd_error(nhdl, "Failed to read retrieve service "
101*12967Sgavin.maltby@oracle.com "properties");
102*12967Sgavin.maltby@oracle.com }
103*12967Sgavin.maltby@oracle.com
104*12967Sgavin.maltby@oracle.com static void
nd_sighandler(int sig)105*12967Sgavin.maltby@oracle.com nd_sighandler(int sig)
106*12967Sgavin.maltby@oracle.com {
107*12967Sgavin.maltby@oracle.com if (sig == SIGHUP)
108*12967Sgavin.maltby@oracle.com get_svc_config();
109*12967Sgavin.maltby@oracle.com else
110*12967Sgavin.maltby@oracle.com nd_cleanup(nhdl);
111*12967Sgavin.maltby@oracle.com }
112*12967Sgavin.maltby@oracle.com
113*12967Sgavin.maltby@oracle.com static int
get_snmp_prefs(nd_hdl_t * nhdl,nvlist_t ** pref_nvl,uint_t npref)114*12967Sgavin.maltby@oracle.com get_snmp_prefs(nd_hdl_t *nhdl, nvlist_t **pref_nvl, uint_t npref)
115*12967Sgavin.maltby@oracle.com {
116*12967Sgavin.maltby@oracle.com boolean_t *a1, *a2;
117*12967Sgavin.maltby@oracle.com uint_t n;
118*12967Sgavin.maltby@oracle.com int r;
119*12967Sgavin.maltby@oracle.com
120*12967Sgavin.maltby@oracle.com /*
121*12967Sgavin.maltby@oracle.com * For SMF state transition events, pref_nvl contain two sets of
122*12967Sgavin.maltby@oracle.com * preferences, which will have to be merged.
123*12967Sgavin.maltby@oracle.com *
124*12967Sgavin.maltby@oracle.com * The "snmp" nvlist currently only supports a single boolean member,
125*12967Sgavin.maltby@oracle.com * "active" which will be set to true, if it is true in either set
126*12967Sgavin.maltby@oracle.com */
127*12967Sgavin.maltby@oracle.com if (npref == 2) {
128*12967Sgavin.maltby@oracle.com r = nvlist_lookup_boolean_array(pref_nvl[0], "active", &a1, &n);
129*12967Sgavin.maltby@oracle.com r += nvlist_lookup_boolean_array(pref_nvl[1], "active", &a2,
130*12967Sgavin.maltby@oracle.com &n);
131*12967Sgavin.maltby@oracle.com if (r != 0) {
132*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Malformed snmp notification "
133*12967Sgavin.maltby@oracle.com "preferences");
134*12967Sgavin.maltby@oracle.com nd_dump_nvlist(nhdl, pref_nvl[0]);
135*12967Sgavin.maltby@oracle.com nd_dump_nvlist(nhdl, pref_nvl[1]);
136*12967Sgavin.maltby@oracle.com return (-1);
137*12967Sgavin.maltby@oracle.com } else if (!a1[0] && !a2[0]) {
138*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "SNMP notification is disabled");
139*12967Sgavin.maltby@oracle.com return (-1);
140*12967Sgavin.maltby@oracle.com }
141*12967Sgavin.maltby@oracle.com } else {
142*12967Sgavin.maltby@oracle.com if (nvlist_lookup_boolean_array(pref_nvl[0], "active",
143*12967Sgavin.maltby@oracle.com &a1, &n)) {
144*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Malformed snmp notification "
145*12967Sgavin.maltby@oracle.com "preferences");
146*12967Sgavin.maltby@oracle.com nd_dump_nvlist(nhdl, pref_nvl[0]);
147*12967Sgavin.maltby@oracle.com return (-1);
148*12967Sgavin.maltby@oracle.com } else if (!a1[0]) {
149*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "SNMP notification is disabled");
150*12967Sgavin.maltby@oracle.com return (-1);
151*12967Sgavin.maltby@oracle.com }
152*12967Sgavin.maltby@oracle.com }
153*12967Sgavin.maltby@oracle.com return (0);
154*12967Sgavin.maltby@oracle.com }
155*12967Sgavin.maltby@oracle.com
156*12967Sgavin.maltby@oracle.com static void
send_ireport_trap(ireport_trap_t * t)157*12967Sgavin.maltby@oracle.com send_ireport_trap(ireport_trap_t *t)
158*12967Sgavin.maltby@oracle.com {
159*12967Sgavin.maltby@oracle.com static const oid sunIreportTrap_oid[] =
160*12967Sgavin.maltby@oracle.com { SUNIREPORTTRAP_OID };
161*12967Sgavin.maltby@oracle.com const size_t sunIreportTrap_len =
162*12967Sgavin.maltby@oracle.com OID_LENGTH(sunIreportTrap_oid);
163*12967Sgavin.maltby@oracle.com
164*12967Sgavin.maltby@oracle.com static const oid sunIreportHostname_oid[] =
165*12967Sgavin.maltby@oracle.com { SUNIREPORTHOSTNAME_OID };
166*12967Sgavin.maltby@oracle.com static const oid sunIreportMsgid_oid[] =
167*12967Sgavin.maltby@oracle.com { SUNIREPORTMSGID_OID };
168*12967Sgavin.maltby@oracle.com static const oid sunIreportDescription_oid[] =
169*12967Sgavin.maltby@oracle.com { SUNIREPORTDESCRIPTION_OID };
170*12967Sgavin.maltby@oracle.com static const oid sunIreportTime_oid[] =
171*12967Sgavin.maltby@oracle.com { SUNIREPORTTIME_OID };
172*12967Sgavin.maltby@oracle.com
173*12967Sgavin.maltby@oracle.com static const oid sunIreportSmfFmri_oid[] =
174*12967Sgavin.maltby@oracle.com { SUNIREPORTSMFFMRI_OID };
175*12967Sgavin.maltby@oracle.com static const oid sunIreportSmfFromState_oid[] =
176*12967Sgavin.maltby@oracle.com { SUNIREPORTSMFFROMSTATE_OID };
177*12967Sgavin.maltby@oracle.com static const oid sunIreportSmfToState_oid[] =
178*12967Sgavin.maltby@oracle.com { SUNIREPORTSMFTOSTATE_OID };
179*12967Sgavin.maltby@oracle.com static const oid sunIreportSmfTransitionReason_oid[] =
180*12967Sgavin.maltby@oracle.com { SUNIREPORTTRANSITIONREASON_OID };
181*12967Sgavin.maltby@oracle.com const size_t
182*12967Sgavin.maltby@oracle.com sunIreport_base_len = OID_LENGTH(sunIreportHostname_oid);
183*12967Sgavin.maltby@oracle.com
184*12967Sgavin.maltby@oracle.com size_t var_len = sunIreport_base_len + 1;
185*12967Sgavin.maltby@oracle.com oid var_name[MAX_OID_LEN];
186*12967Sgavin.maltby@oracle.com
187*12967Sgavin.maltby@oracle.com netsnmp_variable_list *notification_vars = NULL;
188*12967Sgavin.maltby@oracle.com
189*12967Sgavin.maltby@oracle.com size_t dt_len;
190*12967Sgavin.maltby@oracle.com uchar_t dt[11], *tdt;
191*12967Sgavin.maltby@oracle.com time_t ts = t->tstamp;
192*12967Sgavin.maltby@oracle.com
193*12967Sgavin.maltby@oracle.com tdt = date_n_time(&ts, &dt_len);
194*12967Sgavin.maltby@oracle.com /*
195*12967Sgavin.maltby@oracle.com * We know date_n_time is broken, it returns a buffer from
196*12967Sgavin.maltby@oracle.com * its stack. So we copy before we step over it!
197*12967Sgavin.maltby@oracle.com */
198*12967Sgavin.maltby@oracle.com for (int i = 0; i < dt_len; ++i)
199*12967Sgavin.maltby@oracle.com dt[i] = tdt[i];
200*12967Sgavin.maltby@oracle.com
201*12967Sgavin.maltby@oracle.com if (var_len > MAX_OID_LEN) {
202*12967Sgavin.maltby@oracle.com nd_error(nhdl, "var_len %d > MAX_OID_LEN %d\n", var_len,
203*12967Sgavin.maltby@oracle.com MAX_OID_LEN);
204*12967Sgavin.maltby@oracle.com return;
205*12967Sgavin.maltby@oracle.com }
206*12967Sgavin.maltby@oracle.com
207*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportHostname_oid, sunIreport_base_len *
208*12967Sgavin.maltby@oracle.com sizeof (oid));
209*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
210*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_OCTET_STR, (uchar_t *)t->host,
211*12967Sgavin.maltby@oracle.com strlen(t->host));
212*12967Sgavin.maltby@oracle.com
213*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportMsgid_oid,
214*12967Sgavin.maltby@oracle.com sunIreport_base_len * sizeof (oid));
215*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
216*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_OCTET_STR, (uchar_t *)t->msgid,
217*12967Sgavin.maltby@oracle.com strlen(t->msgid));
218*12967Sgavin.maltby@oracle.com
219*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportDescription_oid,
220*12967Sgavin.maltby@oracle.com sunIreport_base_len * sizeof (oid));
221*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
222*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_OCTET_STR, (uchar_t *)t->desc,
223*12967Sgavin.maltby@oracle.com strlen(t->desc));
224*12967Sgavin.maltby@oracle.com
225*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportTime_oid, sunIreport_base_len *
226*12967Sgavin.maltby@oracle.com sizeof (oid));
227*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
228*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_OCTET_STR, dt, dt_len);
229*12967Sgavin.maltby@oracle.com
230*12967Sgavin.maltby@oracle.com if (t->is_stn_event) {
231*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportSmfFmri_oid,
232*12967Sgavin.maltby@oracle.com sunIreport_base_len * sizeof (oid));
233*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
234*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_OCTET_STR, (uchar_t *)t->fmri,
235*12967Sgavin.maltby@oracle.com strlen(t->fmri));
236*12967Sgavin.maltby@oracle.com
237*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportSmfFromState_oid,
238*12967Sgavin.maltby@oracle.com sunIreport_base_len * sizeof (oid));
239*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
240*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_INTEGER,
241*12967Sgavin.maltby@oracle.com (uchar_t *)&t->from_state, sizeof (uint32_t));
242*12967Sgavin.maltby@oracle.com
243*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportSmfToState_oid,
244*12967Sgavin.maltby@oracle.com sunIreport_base_len * sizeof (oid));
245*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
246*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_INTEGER,
247*12967Sgavin.maltby@oracle.com (uchar_t *)&t->to_state, sizeof (uint32_t));
248*12967Sgavin.maltby@oracle.com
249*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunIreportSmfTransitionReason_oid,
250*12967Sgavin.maltby@oracle.com sunIreport_base_len * sizeof (oid));
251*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name,
252*12967Sgavin.maltby@oracle.com sunIreport_base_len + 1, ASN_OCTET_STR,
253*12967Sgavin.maltby@oracle.com (uchar_t *)t->reason, strlen(t->reason));
254*12967Sgavin.maltby@oracle.com }
255*12967Sgavin.maltby@oracle.com
256*12967Sgavin.maltby@oracle.com /*
257*12967Sgavin.maltby@oracle.com * This function is capable of sending both v1 and v2/v3 traps.
258*12967Sgavin.maltby@oracle.com * Which is sent to a specific destination is determined by the
259*12967Sgavin.maltby@oracle.com * configuration file(s).
260*12967Sgavin.maltby@oracle.com */
261*12967Sgavin.maltby@oracle.com send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC,
262*12967Sgavin.maltby@oracle.com sunIreportTrap_oid[sunIreportTrap_len - 1],
263*12967Sgavin.maltby@oracle.com (oid *)sunIreportTrap_oid, sunIreportTrap_len - 2,
264*12967Sgavin.maltby@oracle.com notification_vars);
265*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Sent SNMP trap for %s", t->msgid);
266*12967Sgavin.maltby@oracle.com
267*12967Sgavin.maltby@oracle.com snmp_free_varbind(notification_vars);
268*12967Sgavin.maltby@oracle.com
269*12967Sgavin.maltby@oracle.com }
270*12967Sgavin.maltby@oracle.com
271*12967Sgavin.maltby@oracle.com /*ARGSUSED*/
272*12967Sgavin.maltby@oracle.com static void
send_fm_trap(const char * uuid,const char * code,const char * url)273*12967Sgavin.maltby@oracle.com send_fm_trap(const char *uuid, const char *code, const char *url)
274*12967Sgavin.maltby@oracle.com {
275*12967Sgavin.maltby@oracle.com static const oid sunFmProblemTrap_oid[] = { SUNFMPROBLEMTRAP_OID };
276*12967Sgavin.maltby@oracle.com const size_t sunFmProblemTrap_len = OID_LENGTH(sunFmProblemTrap_oid);
277*12967Sgavin.maltby@oracle.com
278*12967Sgavin.maltby@oracle.com static const oid sunFmProblemUUID_oid[] =
279*12967Sgavin.maltby@oracle.com { SUNFMPROBLEMTABLE_OID, 1, SUNFMPROBLEM_COL_UUID };
280*12967Sgavin.maltby@oracle.com static const oid sunFmProblemCode_oid[] =
281*12967Sgavin.maltby@oracle.com { SUNFMPROBLEMTABLE_OID, 1, SUNFMPROBLEM_COL_CODE };
282*12967Sgavin.maltby@oracle.com static const oid sunFmProblemURL_oid[] =
283*12967Sgavin.maltby@oracle.com { SUNFMPROBLEMTABLE_OID, 1, SUNFMPROBLEM_COL_URL };
284*12967Sgavin.maltby@oracle.com
285*12967Sgavin.maltby@oracle.com const size_t sunFmProblem_base_len = OID_LENGTH(sunFmProblemUUID_oid);
286*12967Sgavin.maltby@oracle.com
287*12967Sgavin.maltby@oracle.com size_t uuid_len = strlen(uuid);
288*12967Sgavin.maltby@oracle.com size_t var_len = sunFmProblem_base_len + 1 + uuid_len;
289*12967Sgavin.maltby@oracle.com oid var_name[MAX_OID_LEN];
290*12967Sgavin.maltby@oracle.com
291*12967Sgavin.maltby@oracle.com netsnmp_variable_list *notification_vars = NULL;
292*12967Sgavin.maltby@oracle.com
293*12967Sgavin.maltby@oracle.com /*
294*12967Sgavin.maltby@oracle.com * The format of our trap varbinds' oids is as follows:
295*12967Sgavin.maltby@oracle.com *
296*12967Sgavin.maltby@oracle.com * +-----------------------+---+--------+----------+------+
297*12967Sgavin.maltby@oracle.com * | SUNFMPROBLEMTABLE_OID | 1 | column | uuid_len | uuid |
298*12967Sgavin.maltby@oracle.com * +-----------------------+---+--------+----------+------+
299*12967Sgavin.maltby@oracle.com * \---- index ----/
300*12967Sgavin.maltby@oracle.com *
301*12967Sgavin.maltby@oracle.com * A common mistake here is to send the trap with varbinds that
302*12967Sgavin.maltby@oracle.com * do not contain the index. All the indices are the same, and
303*12967Sgavin.maltby@oracle.com * all the oids are the same length, so the only thing we need to
304*12967Sgavin.maltby@oracle.com * do for each varbind is set the table and column parts of the
305*12967Sgavin.maltby@oracle.com * variable name.
306*12967Sgavin.maltby@oracle.com */
307*12967Sgavin.maltby@oracle.com
308*12967Sgavin.maltby@oracle.com if (var_len > MAX_OID_LEN)
309*12967Sgavin.maltby@oracle.com return;
310*12967Sgavin.maltby@oracle.com
311*12967Sgavin.maltby@oracle.com var_name[sunFmProblem_base_len] = (oid)uuid_len;
312*12967Sgavin.maltby@oracle.com for (int i = 0; i < uuid_len; i++)
313*12967Sgavin.maltby@oracle.com var_name[i + sunFmProblem_base_len + 1] = (oid)uuid[i];
314*12967Sgavin.maltby@oracle.com
315*12967Sgavin.maltby@oracle.com /*
316*12967Sgavin.maltby@oracle.com * Ordinarily, we would need to add the OID of the trap itself
317*12967Sgavin.maltby@oracle.com * to the head of the variable list; this is required by SNMP v2.
318*12967Sgavin.maltby@oracle.com * However, send_enterprise_trap_vars does this for us as a part
319*12967Sgavin.maltby@oracle.com * of converting between v1 and v2 traps, so we skip directly to
320*12967Sgavin.maltby@oracle.com * the objects we're sending.
321*12967Sgavin.maltby@oracle.com */
322*12967Sgavin.maltby@oracle.com
323*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunFmProblemUUID_oid,
324*12967Sgavin.maltby@oracle.com sunFmProblem_base_len * sizeof (oid));
325*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name, var_len,
326*12967Sgavin.maltby@oracle.com ASN_OCTET_STR, (uchar_t *)uuid, strlen(uuid));
327*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunFmProblemCode_oid,
328*12967Sgavin.maltby@oracle.com sunFmProblem_base_len * sizeof (oid));
329*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name, var_len,
330*12967Sgavin.maltby@oracle.com ASN_OCTET_STR, (uchar_t *)code, strlen(code));
331*12967Sgavin.maltby@oracle.com (void) memcpy(var_name, sunFmProblemURL_oid,
332*12967Sgavin.maltby@oracle.com sunFmProblem_base_len * sizeof (oid));
333*12967Sgavin.maltby@oracle.com (void) snmp_varlist_add_variable(¬ification_vars, var_name, var_len,
334*12967Sgavin.maltby@oracle.com ASN_OCTET_STR, (uchar_t *)url, strlen(url));
335*12967Sgavin.maltby@oracle.com
336*12967Sgavin.maltby@oracle.com /*
337*12967Sgavin.maltby@oracle.com * This function is capable of sending both v1 and v2/v3 traps.
338*12967Sgavin.maltby@oracle.com * Which is sent to a specific destination is determined by the
339*12967Sgavin.maltby@oracle.com * configuration file(s).
340*12967Sgavin.maltby@oracle.com */
341*12967Sgavin.maltby@oracle.com send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC,
342*12967Sgavin.maltby@oracle.com sunFmProblemTrap_oid[sunFmProblemTrap_len - 1],
343*12967Sgavin.maltby@oracle.com (oid *)sunFmProblemTrap_oid, sunFmProblemTrap_len - 2,
344*12967Sgavin.maltby@oracle.com notification_vars);
345*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Sent SNMP trap for %s", code);
346*12967Sgavin.maltby@oracle.com
347*12967Sgavin.maltby@oracle.com snmp_free_varbind(notification_vars);
348*12967Sgavin.maltby@oracle.com }
349*12967Sgavin.maltby@oracle.com
350*12967Sgavin.maltby@oracle.com /*
351*12967Sgavin.maltby@oracle.com * The SUN-IREPORT-MIB declares the following enum to represent SMF service
352*12967Sgavin.maltby@oracle.com * states.
353*12967Sgavin.maltby@oracle.com *
354*12967Sgavin.maltby@oracle.com * offline(0), online(1), degraded(2), disabled(3), maintenance(4),
355*12967Sgavin.maltby@oracle.com * uninitialized(5)
356*12967Sgavin.maltby@oracle.com *
357*12967Sgavin.maltby@oracle.com * This function converts a string representation of an SMF service state
358*12967Sgavin.maltby@oracle.com * to it's corresponding enum val.
359*12967Sgavin.maltby@oracle.com */
360*12967Sgavin.maltby@oracle.com static int
state_to_val(char * statestr,uint32_t * stateval)361*12967Sgavin.maltby@oracle.com state_to_val(char *statestr, uint32_t *stateval)
362*12967Sgavin.maltby@oracle.com {
363*12967Sgavin.maltby@oracle.com if (strcmp(statestr, "offline") == 0)
364*12967Sgavin.maltby@oracle.com *stateval = 0;
365*12967Sgavin.maltby@oracle.com else if (strcmp(statestr, "online") == 0)
366*12967Sgavin.maltby@oracle.com *stateval = 1;
367*12967Sgavin.maltby@oracle.com else if (strcmp(statestr, "degraded") == 0)
368*12967Sgavin.maltby@oracle.com *stateval = 2;
369*12967Sgavin.maltby@oracle.com else if (strcmp(statestr, "disabled") == 0)
370*12967Sgavin.maltby@oracle.com *stateval = 3;
371*12967Sgavin.maltby@oracle.com else if (strcmp(statestr, "maintenance") == 0)
372*12967Sgavin.maltby@oracle.com *stateval = 4;
373*12967Sgavin.maltby@oracle.com else if (strcmp(statestr, "uninitialized") == 0)
374*12967Sgavin.maltby@oracle.com *stateval = 5;
375*12967Sgavin.maltby@oracle.com else
376*12967Sgavin.maltby@oracle.com return (-1);
377*12967Sgavin.maltby@oracle.com return (0);
378*12967Sgavin.maltby@oracle.com }
379*12967Sgavin.maltby@oracle.com
380*12967Sgavin.maltby@oracle.com /*ARGSUSED*/
381*12967Sgavin.maltby@oracle.com static void
ireport_cb(fmev_t ev,const char * class,nvlist_t * nvl,void * arg)382*12967Sgavin.maltby@oracle.com ireport_cb(fmev_t ev, const char *class, nvlist_t *nvl, void *arg)
383*12967Sgavin.maltby@oracle.com {
384*12967Sgavin.maltby@oracle.com nvlist_t **pref_nvl = NULL;
385*12967Sgavin.maltby@oracle.com nd_ev_info_t *ev_info = NULL;
386*12967Sgavin.maltby@oracle.com ireport_trap_t swtrap;
387*12967Sgavin.maltby@oracle.com uint_t npref;
388*12967Sgavin.maltby@oracle.com int ret;
389*12967Sgavin.maltby@oracle.com
390*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Received event of class %s", class);
391*12967Sgavin.maltby@oracle.com
392*12967Sgavin.maltby@oracle.com ret = nd_get_notify_prefs(nhdl, "snmp", ev, &pref_nvl, &npref);
393*12967Sgavin.maltby@oracle.com if (ret == SCF_ERROR_NOT_FOUND) {
394*12967Sgavin.maltby@oracle.com /*
395*12967Sgavin.maltby@oracle.com * No snmp notification preferences specified for this type of
396*12967Sgavin.maltby@oracle.com * event, so we're done
397*12967Sgavin.maltby@oracle.com */
398*12967Sgavin.maltby@oracle.com return;
399*12967Sgavin.maltby@oracle.com } else if (ret != 0) {
400*12967Sgavin.maltby@oracle.com nd_error(nhdl, "Failed to retrieve notification preferences "
401*12967Sgavin.maltby@oracle.com "for this event");
402*12967Sgavin.maltby@oracle.com return;
403*12967Sgavin.maltby@oracle.com }
404*12967Sgavin.maltby@oracle.com
405*12967Sgavin.maltby@oracle.com if (get_snmp_prefs(nhdl, pref_nvl, npref) != 0)
406*12967Sgavin.maltby@oracle.com goto irpt_done;
407*12967Sgavin.maltby@oracle.com
408*12967Sgavin.maltby@oracle.com if (nd_get_event_info(nhdl, class, ev, &ev_info) != 0)
409*12967Sgavin.maltby@oracle.com goto irpt_done;
410*12967Sgavin.maltby@oracle.com
411*12967Sgavin.maltby@oracle.com swtrap.host = hostname;
412*12967Sgavin.maltby@oracle.com swtrap.msgid = ev_info->ei_diagcode;
413*12967Sgavin.maltby@oracle.com swtrap.desc = ev_info->ei_descr;
414*12967Sgavin.maltby@oracle.com swtrap.tstamp = (time_t)fmev_time_sec(ev);
415*12967Sgavin.maltby@oracle.com
416*12967Sgavin.maltby@oracle.com if (strncmp(class, "ireport.os.smf", 14) == 0) {
417*12967Sgavin.maltby@oracle.com swtrap.fmri = ev_info->ei_fmri;
418*12967Sgavin.maltby@oracle.com if (state_to_val(ev_info->ei_from_state, &swtrap.from_state)
419*12967Sgavin.maltby@oracle.com < 0 ||
420*12967Sgavin.maltby@oracle.com state_to_val(ev_info->ei_to_state, &swtrap.to_state) < 0) {
421*12967Sgavin.maltby@oracle.com nd_error(nhdl, "Malformed event - invalid svc state");
422*12967Sgavin.maltby@oracle.com nd_dump_nvlist(nhdl, ev_info->ei_payload);
423*12967Sgavin.maltby@oracle.com goto irpt_done;
424*12967Sgavin.maltby@oracle.com }
425*12967Sgavin.maltby@oracle.com swtrap.reason = ev_info->ei_reason;
426*12967Sgavin.maltby@oracle.com swtrap.is_stn_event = B_TRUE;
427*12967Sgavin.maltby@oracle.com }
428*12967Sgavin.maltby@oracle.com send_ireport_trap(&swtrap);
429*12967Sgavin.maltby@oracle.com irpt_done:
430*12967Sgavin.maltby@oracle.com if (ev_info)
431*12967Sgavin.maltby@oracle.com nd_free_event_info(ev_info);
432*12967Sgavin.maltby@oracle.com nd_free_nvlarray(pref_nvl, npref);
433*12967Sgavin.maltby@oracle.com }
434*12967Sgavin.maltby@oracle.com
435*12967Sgavin.maltby@oracle.com /*ARGSUSED*/
436*12967Sgavin.maltby@oracle.com static void
list_cb(fmev_t ev,const char * class,nvlist_t * nvl,void * arg)437*12967Sgavin.maltby@oracle.com list_cb(fmev_t ev, const char *class, nvlist_t *nvl, void *arg)
438*12967Sgavin.maltby@oracle.com {
439*12967Sgavin.maltby@oracle.com char *uuid;
440*12967Sgavin.maltby@oracle.com uint8_t version;
441*12967Sgavin.maltby@oracle.com nd_ev_info_t *ev_info = NULL;
442*12967Sgavin.maltby@oracle.com nvlist_t **pref_nvl = NULL;
443*12967Sgavin.maltby@oracle.com uint_t npref;
444*12967Sgavin.maltby@oracle.com int ret;
445*12967Sgavin.maltby@oracle.com boolean_t domsg;
446*12967Sgavin.maltby@oracle.com
447*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Received event of class %s", class);
448*12967Sgavin.maltby@oracle.com
449*12967Sgavin.maltby@oracle.com ret = nd_get_notify_prefs(nhdl, "snmp", ev, &pref_nvl, &npref);
450*12967Sgavin.maltby@oracle.com if (ret == SCF_ERROR_NOT_FOUND) {
451*12967Sgavin.maltby@oracle.com /*
452*12967Sgavin.maltby@oracle.com * No snmp notification preferences specified for this type of
453*12967Sgavin.maltby@oracle.com * event, so we're done
454*12967Sgavin.maltby@oracle.com */
455*12967Sgavin.maltby@oracle.com return;
456*12967Sgavin.maltby@oracle.com } else if (ret != 0) {
457*12967Sgavin.maltby@oracle.com nd_error(nhdl, "Failed to retrieve notification preferences "
458*12967Sgavin.maltby@oracle.com "for this event");
459*12967Sgavin.maltby@oracle.com return;
460*12967Sgavin.maltby@oracle.com }
461*12967Sgavin.maltby@oracle.com
462*12967Sgavin.maltby@oracle.com if (get_snmp_prefs(nhdl, pref_nvl, npref) != 0)
463*12967Sgavin.maltby@oracle.com goto listcb_done;
464*12967Sgavin.maltby@oracle.com
465*12967Sgavin.maltby@oracle.com if (nd_get_event_info(nhdl, class, ev, &ev_info) != 0)
466*12967Sgavin.maltby@oracle.com goto listcb_done;
467*12967Sgavin.maltby@oracle.com
468*12967Sgavin.maltby@oracle.com /*
469*12967Sgavin.maltby@oracle.com * If the message payload member is set to 0, then it's an event we
470*12967Sgavin.maltby@oracle.com * typically suppress messaging on, so we won't send a trap for it.
471*12967Sgavin.maltby@oracle.com */
472*12967Sgavin.maltby@oracle.com if (nvlist_lookup_boolean_value(ev_info->ei_payload, FM_SUSPECT_MESSAGE,
473*12967Sgavin.maltby@oracle.com &domsg) == 0 && !domsg) {
474*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Messaging suppressed for this event");
475*12967Sgavin.maltby@oracle.com goto listcb_done;
476*12967Sgavin.maltby@oracle.com }
477*12967Sgavin.maltby@oracle.com
478*12967Sgavin.maltby@oracle.com if (nvlist_lookup_uint8(ev_info->ei_payload, FM_VERSION, &version)
479*12967Sgavin.maltby@oracle.com != 0 || version > FM_SUSPECT_VERSION) {
480*12967Sgavin.maltby@oracle.com nd_error(nhdl, "invalid event version: %u", version);
481*12967Sgavin.maltby@oracle.com goto listcb_done;
482*12967Sgavin.maltby@oracle.com }
483*12967Sgavin.maltby@oracle.com
484*12967Sgavin.maltby@oracle.com (void) nvlist_lookup_string(ev_info->ei_payload, FM_SUSPECT_UUID,
485*12967Sgavin.maltby@oracle.com &uuid);
486*12967Sgavin.maltby@oracle.com
487*12967Sgavin.maltby@oracle.com if (strcmp(ev_info->ei_url, ND_UNKNOWN) != 0)
488*12967Sgavin.maltby@oracle.com send_fm_trap(uuid, ev_info->ei_diagcode, ev_info->ei_url);
489*12967Sgavin.maltby@oracle.com else
490*12967Sgavin.maltby@oracle.com nd_error(nhdl, "failed to format url for %s", uuid);
491*12967Sgavin.maltby@oracle.com listcb_done:
492*12967Sgavin.maltby@oracle.com nd_free_nvlarray(pref_nvl, npref);
493*12967Sgavin.maltby@oracle.com if (ev_info)
494*12967Sgavin.maltby@oracle.com nd_free_event_info(ev_info);
495*12967Sgavin.maltby@oracle.com }
496*12967Sgavin.maltby@oracle.com
497*12967Sgavin.maltby@oracle.com static int
init_sma(void)498*12967Sgavin.maltby@oracle.com init_sma(void)
499*12967Sgavin.maltby@oracle.com {
500*12967Sgavin.maltby@oracle.com int err;
501*12967Sgavin.maltby@oracle.com
502*12967Sgavin.maltby@oracle.com /*
503*12967Sgavin.maltby@oracle.com * The only place we could possibly log is syslog, but the
504*12967Sgavin.maltby@oracle.com * full agent doesn't normally log there. It would be confusing
505*12967Sgavin.maltby@oracle.com * if this agent did so; therefore we disable logging entirely.
506*12967Sgavin.maltby@oracle.com */
507*12967Sgavin.maltby@oracle.com snmp_disable_log();
508*12967Sgavin.maltby@oracle.com
509*12967Sgavin.maltby@oracle.com /*
510*12967Sgavin.maltby@oracle.com * Net-SNMP has a provision for reading an arbitrary number of
511*12967Sgavin.maltby@oracle.com * configuration files. A configuration file is read if it has
512*12967Sgavin.maltby@oracle.com * had any handlers registered for it, or if it's the value in
513*12967Sgavin.maltby@oracle.com * of NETSNMP_DS_LIB_APPTYPE. Our objective here is to read
514*12967Sgavin.maltby@oracle.com * both snmpd.conf and fmd-trapgen.conf.
515*12967Sgavin.maltby@oracle.com */
516*12967Sgavin.maltby@oracle.com if ((err = netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
517*12967Sgavin.maltby@oracle.com NETSNMP_DS_AGENT_ROLE, 0 /* MASTER_AGENT */)) != SNMPERR_SUCCESS)
518*12967Sgavin.maltby@oracle.com return (err);
519*12967Sgavin.maltby@oracle.com
520*12967Sgavin.maltby@oracle.com init_agent_read_config("snmpd");
521*12967Sgavin.maltby@oracle.com if ((err = netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
522*12967Sgavin.maltby@oracle.com NETSNMP_DS_LIB_APPTYPE, SNMP_SUPPCONF)) != SNMPERR_SUCCESS)
523*12967Sgavin.maltby@oracle.com return (err);
524*12967Sgavin.maltby@oracle.com if (register_app_config_handler("trapsink", snmpd_parse_config_trapsink,
525*12967Sgavin.maltby@oracle.com snmpd_free_trapsinks, "host [community] [port]") == NULL)
526*12967Sgavin.maltby@oracle.com return (SNMPERR_MALLOC);
527*12967Sgavin.maltby@oracle.com if (register_app_config_handler("trap2sink",
528*12967Sgavin.maltby@oracle.com snmpd_parse_config_trap2sink, NULL, "host [community] [port]") ==
529*12967Sgavin.maltby@oracle.com NULL)
530*12967Sgavin.maltby@oracle.com return (SNMPERR_MALLOC);
531*12967Sgavin.maltby@oracle.com if (register_app_config_handler("trapsess", snmpd_parse_config_trapsess,
532*12967Sgavin.maltby@oracle.com NULL, "[snmpcmdargs] host") == NULL)
533*12967Sgavin.maltby@oracle.com return (SNMPERR_MALLOC);
534*12967Sgavin.maltby@oracle.com
535*12967Sgavin.maltby@oracle.com init_traps();
536*12967Sgavin.maltby@oracle.com init_snmp(SNMP_SUPPCONF);
537*12967Sgavin.maltby@oracle.com
538*12967Sgavin.maltby@oracle.com return (SNMPERR_SUCCESS);
539*12967Sgavin.maltby@oracle.com }
540*12967Sgavin.maltby@oracle.com
541*12967Sgavin.maltby@oracle.com int
main(int argc,char * argv[])542*12967Sgavin.maltby@oracle.com main(int argc, char *argv[])
543*12967Sgavin.maltby@oracle.com {
544*12967Sgavin.maltby@oracle.com struct rlimit rlim;
545*12967Sgavin.maltby@oracle.com struct sigaction act;
546*12967Sgavin.maltby@oracle.com sigset_t set;
547*12967Sgavin.maltby@oracle.com char c;
548*12967Sgavin.maltby@oracle.com boolean_t run_fg = B_FALSE;
549*12967Sgavin.maltby@oracle.com
550*12967Sgavin.maltby@oracle.com if ((nhdl = malloc(sizeof (nd_hdl_t))) == NULL) {
551*12967Sgavin.maltby@oracle.com (void) fprintf(stderr, "Failed to allocate space for notifyd "
552*12967Sgavin.maltby@oracle.com "handle (%s)", strerror(errno));
553*12967Sgavin.maltby@oracle.com return (1);
554*12967Sgavin.maltby@oracle.com }
555*12967Sgavin.maltby@oracle.com bzero(nhdl, sizeof (nd_hdl_t));
556*12967Sgavin.maltby@oracle.com nhdl->nh_keep_running = B_TRUE;
557*12967Sgavin.maltby@oracle.com nhdl->nh_log_fd = stderr;
558*12967Sgavin.maltby@oracle.com nhdl->nh_pname = argv[0];
559*12967Sgavin.maltby@oracle.com
560*12967Sgavin.maltby@oracle.com get_svc_config();
561*12967Sgavin.maltby@oracle.com
562*12967Sgavin.maltby@oracle.com /*
563*12967Sgavin.maltby@oracle.com * In the case where we get started outside of SMF, args passed on the
564*12967Sgavin.maltby@oracle.com * command line override SMF property setting
565*12967Sgavin.maltby@oracle.com */
566*12967Sgavin.maltby@oracle.com while (optind < argc) {
567*12967Sgavin.maltby@oracle.com while ((c = getopt(argc, argv, optstr)) != -1) {
568*12967Sgavin.maltby@oracle.com switch (c) {
569*12967Sgavin.maltby@oracle.com case 'd':
570*12967Sgavin.maltby@oracle.com nhdl->nh_debug = B_TRUE;
571*12967Sgavin.maltby@oracle.com break;
572*12967Sgavin.maltby@oracle.com case 'f':
573*12967Sgavin.maltby@oracle.com run_fg = B_TRUE;
574*12967Sgavin.maltby@oracle.com break;
575*12967Sgavin.maltby@oracle.com case 'R':
576*12967Sgavin.maltby@oracle.com nhdl->nh_rootdir = strdup(optarg);
577*12967Sgavin.maltby@oracle.com break;
578*12967Sgavin.maltby@oracle.com default:
579*12967Sgavin.maltby@oracle.com free(nhdl);
580*12967Sgavin.maltby@oracle.com return (usage(nhdl->nh_pname));
581*12967Sgavin.maltby@oracle.com }
582*12967Sgavin.maltby@oracle.com }
583*12967Sgavin.maltby@oracle.com }
584*12967Sgavin.maltby@oracle.com
585*12967Sgavin.maltby@oracle.com /*
586*12967Sgavin.maltby@oracle.com * Set up a signal handler for SIGTERM (and SIGINT if we'll
587*12967Sgavin.maltby@oracle.com * be running in the foreground) to ensure sure we get a chance to exit
588*12967Sgavin.maltby@oracle.com * in an orderly fashion. We also catch SIGHUP, which will be sent to
589*12967Sgavin.maltby@oracle.com * us by SMF if the service is refreshed.
590*12967Sgavin.maltby@oracle.com */
591*12967Sgavin.maltby@oracle.com (void) sigfillset(&set);
592*12967Sgavin.maltby@oracle.com (void) sigfillset(&act.sa_mask);
593*12967Sgavin.maltby@oracle.com act.sa_handler = nd_sighandler;
594*12967Sgavin.maltby@oracle.com act.sa_flags = 0;
595*12967Sgavin.maltby@oracle.com
596*12967Sgavin.maltby@oracle.com (void) sigaction(SIGTERM, &act, NULL);
597*12967Sgavin.maltby@oracle.com (void) sigdelset(&set, SIGTERM);
598*12967Sgavin.maltby@oracle.com (void) sigaction(SIGHUP, &act, NULL);
599*12967Sgavin.maltby@oracle.com (void) sigdelset(&set, SIGHUP);
600*12967Sgavin.maltby@oracle.com
601*12967Sgavin.maltby@oracle.com if (run_fg) {
602*12967Sgavin.maltby@oracle.com (void) sigaction(SIGINT, &act, NULL);
603*12967Sgavin.maltby@oracle.com (void) sigdelset(&set, SIGINT);
604*12967Sgavin.maltby@oracle.com } else
605*12967Sgavin.maltby@oracle.com nd_daemonize(nhdl);
606*12967Sgavin.maltby@oracle.com
607*12967Sgavin.maltby@oracle.com rlim.rlim_cur = RLIM_INFINITY;
608*12967Sgavin.maltby@oracle.com rlim.rlim_max = RLIM_INFINITY;
609*12967Sgavin.maltby@oracle.com (void) setrlimit(RLIMIT_CORE, &rlim);
610*12967Sgavin.maltby@oracle.com
611*12967Sgavin.maltby@oracle.com /*
612*12967Sgavin.maltby@oracle.com * We need to be root initialize our libfmevent handle (because that
613*12967Sgavin.maltby@oracle.com * involves reading/writing to /dev/sysevent), so we do this before
614*12967Sgavin.maltby@oracle.com * calling __init_daemon_priv.
615*12967Sgavin.maltby@oracle.com */
616*12967Sgavin.maltby@oracle.com nhdl->nh_evhdl = fmev_shdl_init(LIBFMEVENT_VERSION_2, NULL, NULL, NULL);
617*12967Sgavin.maltby@oracle.com if (nhdl->nh_evhdl == NULL) {
618*12967Sgavin.maltby@oracle.com (void) sleep(5);
619*12967Sgavin.maltby@oracle.com nd_abort(nhdl, "failed to initialize libfmevent: %s",
620*12967Sgavin.maltby@oracle.com fmev_strerror(fmev_errno));
621*12967Sgavin.maltby@oracle.com }
622*12967Sgavin.maltby@oracle.com
623*12967Sgavin.maltby@oracle.com /*
624*12967Sgavin.maltby@oracle.com * If we're in the global zone, reset all of our privilege sets to
625*12967Sgavin.maltby@oracle.com * the minimum set of required privileges. We also change our
626*12967Sgavin.maltby@oracle.com * uid/gid to noaccess/noaccess
627*12967Sgavin.maltby@oracle.com *
628*12967Sgavin.maltby@oracle.com * __init_daemon_priv will also set the process core path for us
629*12967Sgavin.maltby@oracle.com *
630*12967Sgavin.maltby@oracle.com */
631*12967Sgavin.maltby@oracle.com if (getzoneid() == GLOBAL_ZONEID)
632*12967Sgavin.maltby@oracle.com if (__init_daemon_priv(
633*12967Sgavin.maltby@oracle.com PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS,
634*12967Sgavin.maltby@oracle.com 60002, 60002, PRIV_FILE_DAC_READ, NULL) != 0)
635*12967Sgavin.maltby@oracle.com nd_abort(nhdl, "additional privileges required to run");
636*12967Sgavin.maltby@oracle.com
637*12967Sgavin.maltby@oracle.com nhdl->nh_msghdl = fmd_msg_init(nhdl->nh_rootdir, FMD_MSG_VERSION);
638*12967Sgavin.maltby@oracle.com if (nhdl->nh_msghdl == NULL)
639*12967Sgavin.maltby@oracle.com nd_abort(nhdl, "failed to initialize libfmd_msg");
640*12967Sgavin.maltby@oracle.com
641*12967Sgavin.maltby@oracle.com if (init_sma() != SNMPERR_SUCCESS)
642*12967Sgavin.maltby@oracle.com nd_abort(nhdl, "SNMP initialization failed");
643*12967Sgavin.maltby@oracle.com
644*12967Sgavin.maltby@oracle.com (void) gethostname(hostname, MAXHOSTNAMELEN + 1);
645*12967Sgavin.maltby@oracle.com /*
646*12967Sgavin.maltby@oracle.com * Set up our event subscriptions. We subscribe to everything and then
647*12967Sgavin.maltby@oracle.com * consult libscf when we receive an event to determine what (if any)
648*12967Sgavin.maltby@oracle.com * notification to send.
649*12967Sgavin.maltby@oracle.com */
650*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Subscribing to ireport.os.smf.* events");
651*12967Sgavin.maltby@oracle.com if (fmev_shdl_subscribe(nhdl->nh_evhdl, "ireport.os.smf.*",
652*12967Sgavin.maltby@oracle.com ireport_cb, NULL) != FMEV_SUCCESS) {
653*12967Sgavin.maltby@oracle.com nd_abort(nhdl, "fmev_shdl_subscribe failed: %s",
654*12967Sgavin.maltby@oracle.com fmev_strerror(fmev_errno));
655*12967Sgavin.maltby@oracle.com }
656*12967Sgavin.maltby@oracle.com
657*12967Sgavin.maltby@oracle.com nd_debug(nhdl, "Subscribing to list.* events");
658*12967Sgavin.maltby@oracle.com if (fmev_shdl_subscribe(nhdl->nh_evhdl, "list.*", list_cb,
659*12967Sgavin.maltby@oracle.com NULL) != FMEV_SUCCESS) {
660*12967Sgavin.maltby@oracle.com nd_abort(nhdl, "fmev_shdl_subscribe failed: %s",
661*12967Sgavin.maltby@oracle.com fmev_strerror(fmev_errno));
662*12967Sgavin.maltby@oracle.com }
663*12967Sgavin.maltby@oracle.com
664*12967Sgavin.maltby@oracle.com /*
665*12967Sgavin.maltby@oracle.com * We run until someone kills us
666*12967Sgavin.maltby@oracle.com */
667*12967Sgavin.maltby@oracle.com while (nhdl->nh_keep_running)
668*12967Sgavin.maltby@oracle.com (void) sigsuspend(&set);
669*12967Sgavin.maltby@oracle.com
670*12967Sgavin.maltby@oracle.com /*
671*12967Sgavin.maltby@oracle.com * snmp_shutdown, which we would normally use here, calls free_slots,
672*12967Sgavin.maltby@oracle.com * a callback that is supposed to tear down the pkcs11 state; however,
673*12967Sgavin.maltby@oracle.com * it abuses C_Finalize, causing fmd to drop core on shutdown. Avoid
674*12967Sgavin.maltby@oracle.com * this by shutting down the library piecemeal.
675*12967Sgavin.maltby@oracle.com */
676*12967Sgavin.maltby@oracle.com snmp_store(SNMP_SUPPCONF);
677*12967Sgavin.maltby@oracle.com snmp_alarm_unregister_all();
678*12967Sgavin.maltby@oracle.com (void) snmp_close_sessions();
679*12967Sgavin.maltby@oracle.com shutdown_mib();
680*12967Sgavin.maltby@oracle.com unregister_all_config_handlers();
681*12967Sgavin.maltby@oracle.com netsnmp_ds_shutdown();
682*12967Sgavin.maltby@oracle.com
683*12967Sgavin.maltby@oracle.com free(nhdl->nh_rootdir);
684*12967Sgavin.maltby@oracle.com free(nhdl);
685*12967Sgavin.maltby@oracle.com
686*12967Sgavin.maltby@oracle.com return (0);
687*12967Sgavin.maltby@oracle.com }
688