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