Print this page
patch tsoome-feedback
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/modules/common/ext-event-transport/fmevt_inbound.c
+++ new/usr/src/cmd/fm/modules/common/ext-event-transport/fmevt_inbound.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
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 26 /*
27 27 * Receive (on GPEC channels) raw events published by a few select producers
28 28 * using the private libfmevent publication interfaces, and massage those
29 29 * raw events into full protocol events. Each raw event selects a "ruleset"
30 30 * by which to perform the transformation into a protocol event.
31 31 *
32 32 * Only publication from userland running privileged is supported; two
33 33 * channels are used - one for high-value and one for low-value events.
34 34 * There is some planning in the implementation below for kernel hi and low
35 35 * value channels, and for non-privileged userland low and hi value channels.
36 36 */
37 37
38 38 #include <fm/fmd_api.h>
39 39 #include <fm/libfmevent.h>
40 40 #include <uuid/uuid.h>
41 41 #include <libsysevent.h>
42 42 #include <pthread.h>
43 43 #include <libnvpair.h>
44 44 #include <strings.h>
45 45 #include <zone.h>
46 46
47 47 #include "fmevt.h"
48 48
49 49 static struct fmevt_inbound_stats {
50 50 fmd_stat_t raw_callbacks;
51 51 fmd_stat_t raw_noattrlist;
52 52 fmd_stat_t raw_nodetector;
53 53 fmd_stat_t pp_bad_ruleset;
54 54 fmd_stat_t pp_explicitdrop;
55 55 fmd_stat_t pp_fallthrurule;
56 56 fmd_stat_t pp_fanoutmax;
57 57 fmd_stat_t pp_intldrop;
58 58 fmd_stat_t pp_badclass;
59 59 fmd_stat_t pp_nvlallocfail;
60 60 fmd_stat_t pp_nvlbuildfail;
61 61 fmd_stat_t pp_badreturn;
62 62 fmd_stat_t xprt_posted;
63 63 } inbound_stats = {
64 64 { "raw_callbacks", FMD_TYPE_UINT64,
65 65 "total raw event callbacks from producers" },
66 66 { "raw_noattrlist", FMD_TYPE_UINT64,
67 67 "missing attribute list" },
68 68 { "raw_nodetector", FMD_TYPE_UINT64,
69 69 "unable to add detector" },
70 70 { "pp_bad_ruleset", FMD_TYPE_UINT64,
71 71 "post-process bad ruleset" },
72 72 { "pp_explicitdrop", FMD_TYPE_UINT64,
73 73 "ruleset drops event with NULL func" },
74 74 { "pp_fanoutmax", FMD_TYPE_UINT64,
75 75 "post-processing produced too many events" },
76 76 { "pp_intldrop", FMD_TYPE_UINT64,
77 77 "post-processing requested event drop" },
78 78 { "pp_badclass", FMD_TYPE_UINT64,
79 79 "post-processing produced invalid event class" },
80 80 { "pp_nvlallocfail", FMD_TYPE_UINT64,
81 81 "fmd_nvl_alloc failed" },
82 82 { "pp_nvlbuildfail", FMD_TYPE_UINT64,
83 83 "nvlist_add_foo failed in building event" },
84 84 { "pp_badreturn", FMD_TYPE_UINT64,
85 85 "inconsistent number of events returned" },
86 86 { "xprt_posted", FMD_TYPE_UINT64,
87 87 "protocol events posted with fmd_xprt_post" },
88 88 };
89 89
90 90 static int isglobalzone;
91 91 static char zonename[ZONENAME_MAX];
92 92
93 93 #define BUMPSTAT(stat) inbound_stats.stat.fmds_value.ui64++
94 94
95 95 #define CBF_USER 0x1U
96 96 #define CBF_PRIV 0x2U
97 97 #define CBF_LV 0x4U
98 98 #define CBF_HV 0x8U
99 99 #define CBF_ALL (CBF_USER | CBF_PRIV | CBF_LV | CBF_HV)
100 100
101 101 static struct fmevt_chaninfo {
102 102 const char *ci_propname; /* property to get channel name */
103 103 evchan_t *ci_binding; /* GPEC binding for this channel */
104 104 char ci_sid[MAX_SUBID_LEN]; /* subscriber id */
105 105 uint32_t ci_cbarg; /* callback cookie */
106 106 uint32_t ci_sflags; /* subscription flags to use */
107 107 } chaninfo[] = {
108 108 { "user_priv_highval_channel", NULL, { 0 },
109 109 CBF_USER | CBF_PRIV | CBF_HV, EVCH_SUB_KEEP },
110 110 { "user_priv_lowval_channel", NULL, { 0 },
111 111 CBF_USER | CBF_PRIV | CBF_LV, EVCH_SUB_KEEP },
112 112 };
113 113
114 114 static pthread_cond_t fmevt_cv = PTHREAD_COND_INITIALIZER;
115 115 static pthread_mutex_t fmevt_lock = PTHREAD_MUTEX_INITIALIZER;
116 116 static int fmevt_exiting;
117 117
118 118 static fmd_xprt_t *fmevt_xprt;
119 119 static uint32_t fmevt_xprt_refcnt;
120 120 static sysevent_subattr_t *subattr;
121 121
122 122 /*
123 123 * Rulesets we recognize and who handles them. Additions and changes
124 124 * must follow the Portfolio Review process. At ths time only
125 125 * the FMEV_RULESET_ON_SUNOS and FMEVT_RULESET_SMF rulesets are
126 126 * formally recognized by that process - the others here are experimental.
127 127 */
128 128 static struct fmevt_rs {
129 129 char *rs_pat;
130 130 fmevt_pp_func_t *rs_ppfunc;
131 131 char *rs_namespace;
132 132 char *rs_subsys;
133 133 } rulelist[] = {
134 134 { FMEV_RULESET_SMF, fmevt_pp_smf },
135 135 { FMEV_RULESET_ON_EREPORT, fmevt_pp_on_ereport },
136 136 { FMEV_RULESET_ON_SUNOS, fmevt_pp_on_sunos },
137 137 { FMEV_RULESET_ON_PRIVATE, fmevt_pp_on_private },
138 138 { FMEV_RULESET_UNREGISTERED, fmevt_pp_unregistered }
139 139 };
140 140
141 141 /*
142 142 * Take a ruleset specification string and separate it into namespace
143 143 * and subsystem components.
144 144 */
145 145 static int
146 146 fmevt_rs_burst(fmd_hdl_t *hdl, char *ruleset, char **nsp, char **subsysp,
147 147 boolean_t alloc)
148 148 {
149 149 char *ns, *s;
150 150 size_t len;
151 151
152 152 if (ruleset == NULL || *ruleset == '\0' ||
153 153 strnlen(ruleset, FMEV_MAX_RULESET_LEN) == FMEV_MAX_RULESET_LEN)
154 154 return (0);
155 155
156 156 if (alloc == B_FALSE) {
157 157 s = ruleset;
158 158 ns = strsep(&s, FMEV_RS_SEPARATOR);
159 159
160 160 if (s == NULL || s == ns + 1)
161 161 return (0);
162 162 } else {
163 163 if ((s = strstr(ruleset, FMEV_RS_SEPARATOR)) == NULL ||
164 164 s == ruleset + strlen(ruleset) - 1)
165 165 return (0);
166 166
167 167 len = s - ruleset;
168 168
169 169 ns = fmd_hdl_alloc(hdl, len + 1, FMD_SLEEP);
170 170 (void) strncpy(ns, ruleset, len);
171 171 ns[len] = '\0';
172 172
173 173 s++;
174 174 }
175 175
176 176 if (nsp)
177 177 *nsp = ns; /* caller must free if alloc == B_TRUE */
178 178
179 179 if (subsysp)
180 180 *subsysp = s; /* always within original ruleset string */
181 181
182 182 return (1);
183 183 }
184 184
185 185 static int
186 186 fmevt_rs_init(fmd_hdl_t *hdl)
187 187 {
188 188 int i;
189 189
190 190 for (i = 0; i < sizeof (rulelist) / sizeof (rulelist[0]); i++) {
191 191 struct fmevt_rs *rsp = &rulelist[i];
192 192
193 193 if (!fmevt_rs_burst(hdl, rsp->rs_pat, &rsp->rs_namespace,
194 194 &rsp->rs_subsys, B_TRUE))
195 195 return (0);
196 196 }
197 197
198 198 return (1);
199 199 }
200 200
201 201 /*
202 202 * Construct a "sw" scheme detector FMRI.
203 203 *
204 204 * We make no use of priv or pri.
205 205 */
206 206 /*ARGSUSED3*/
207 207 static nvlist_t *
208 208 fmevt_detector(nvlist_t *attr, char *ruleset, int user, int priv,
209 209 fmev_pri_t pri)
210 210 {
211 211 char buf[FMEV_MAX_RULESET_LEN + 1];
212 212 char *ns, *subsys;
213 213 nvlist_t *obj, *dtcr, *site, *ctxt;
214 214 char *execname = NULL;
215 215 int32_t i32;
216 216 int64_t i64;
217 217 int err = 0;
218 218 char *str;
219 219
220 220 (void) strncpy(buf, ruleset, sizeof (buf));
221 221 if (!fmevt_rs_burst(NULL, buf, &ns, &subsys, B_FALSE))
222 222 return (NULL);
223 223
224 224 obj = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
225 225 dtcr = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
226 226 site = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
227 227 ctxt = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP);
228 228
229 229 if (obj == NULL || dtcr == NULL || site == NULL || ctxt == NULL) {
230 230 err++;
231 231 goto done;
232 232 }
233 233
234 234 /*
235 235 * Build up 'object' nvlist.
236 236 */
237 237 if (nvlist_lookup_string(attr, "__fmev_execname", &execname) == 0)
238 238 err += nvlist_add_string(obj, FM_FMRI_SW_OBJ_PATH, execname);
239 239
240 240 /*
241 241 * Build up 'site' nvlist. We should have source file and line
242 242 * number and, if the producer was compiled with C99, function name.
243 243 */
244 244 if (nvlist_lookup_string(attr, "__fmev_file", &str) == 0) {
245 245 err += nvlist_add_string(site, FM_FMRI_SW_SITE_FILE, str);
246 246 (void) nvlist_remove(attr, "__fmev_file", DATA_TYPE_STRING);
247 247 }
248 248
249 249 if (nvlist_lookup_string(attr, "__fmev_func", &str) == 0) {
250 250 err += nvlist_add_string(site, FM_FMRI_SW_SITE_FUNC, str);
251 251 (void) nvlist_remove(attr, "__fmev_func", DATA_TYPE_STRING);
252 252 }
253 253
254 254 if (nvlist_lookup_int64(attr, "__fmev_line", &i64) == 0) {
255 255 err += nvlist_add_int64(site, FM_FMRI_SW_SITE_LINE, i64);
256 256 (void) nvlist_remove(attr, "__fmev_line", DATA_TYPE_INT64);
257 257 }
258 258
259 259 /*
260 260 * Build up 'context' nvlist. We do not include contract id at
261 261 * this time.
262 262 */
263 263
264 264 err += nvlist_add_string(ctxt, FM_FMRI_SW_CTXT_ORIGIN,
265 265 user ? "userland" : "kernel");
266 266
267 267 if (execname) {
268 268 err += nvlist_add_string(ctxt, FM_FMRI_SW_CTXT_EXECNAME,
269 269 execname);
270 270 (void) nvlist_remove(attr, "__fmev_execname", DATA_TYPE_STRING);
271 271 }
272 272
273 273 if (nvlist_lookup_int32(attr, "__fmev_pid", &i32) == 0) {
274 274 err += nvlist_add_int32(ctxt, FM_FMRI_SW_CTXT_PID, i32);
275 275 (void) nvlist_remove(attr, "__fmev_pid", DATA_TYPE_INT32);
276 276 }
277 277
278 278 if (!isglobalzone)
279 279 err += nvlist_add_string(ctxt, FM_FMRI_SW_CTXT_ZONE, zonename);
↓ open down ↓ |
279 lines elided |
↑ open up ↑ |
280 280
281 281 /* Put it all together */
282 282
283 283 err += nvlist_add_uint8(dtcr, FM_VERSION, SW_SCHEME_VERSION0);
284 284 err += nvlist_add_string(dtcr, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);
285 285 err += nvlist_add_nvlist(dtcr, FM_FMRI_SW_OBJ, obj);
286 286 err += nvlist_add_nvlist(dtcr, FM_FMRI_SW_SITE, site);
287 287 err += nvlist_add_nvlist(dtcr, FM_FMRI_SW_CTXT, ctxt);
288 288
289 289 done:
290 - if (obj != NULL)
291 - nvlist_free(obj);
292 - if (site != NULL)
293 - nvlist_free(site);
294 - if (ctxt != NULL)
295 - nvlist_free(ctxt);
290 + nvlist_free(obj);
291 + nvlist_free(site);
292 + nvlist_free(ctxt);
296 293
297 294 if (err == 0) {
298 295 return (dtcr);
299 296 } else {
300 297 nvlist_free(dtcr);
301 298 return (NULL);
302 299 }
303 300 }
304 301
305 302 static int
306 303 class_ok(char *class)
307 304 {
308 305 static const char *approved[] = {
309 306 FM_IREPORT_CLASS ".",
310 307 FM_EREPORT_CLASS "."
311 308 };
312 309
313 310 int i;
314 311
315 312 for (i = 0; i < sizeof (approved) / sizeof (approved[0]); i++) {
316 313 if (strncmp(class, approved[i], strlen(approved[i])) == 0)
317 314 return (1);
318 315 }
319 316
320 317 return (0);
321 318 }
322 319
323 320 static void
324 321 fmevt_postprocess(char *ruleset, nvlist_t *dtcr, nvlist_t *rawattr,
325 322 struct fmevt_ppargs *eap)
326 323 {
327 324 uint_t expected = 0, processed = 0;
328 325 char rs2burst[FMEV_MAX_RULESET_LEN + 1];
329 326 char *class[FMEVT_FANOUT_MAX];
330 327 nvlist_t *attr[FMEVT_FANOUT_MAX];
331 328 fmevt_pp_func_t *dispf = NULL;
332 329 char buf[FMEV_MAX_CLASS];
333 330 char *ns, *subsys;
334 331 int i, found = 0;
335 332 uuid_t uu;
336 333
337 334 (void) strncpy(rs2burst, ruleset, sizeof (rs2burst));
338 335 if (!fmevt_rs_burst(NULL, rs2burst, &ns, &subsys, B_FALSE)) {
339 336 BUMPSTAT(pp_bad_ruleset);
340 337 return;
341 338 }
342 339
343 340 /*
344 341 * Lookup a matching rule in our table.
345 342 */
346 343 for (i = 0; i < sizeof (rulelist) / sizeof (rulelist[0]); i++) {
347 344 struct fmevt_rs *rsp = &rulelist[i];
348 345
349 346 if (*ns != '*' && *rsp->rs_namespace != '*' &&
350 347 strcmp(ns, rsp->rs_namespace) != 0)
351 348 continue;
352 349
353 350 if (*subsys != '*' && *rsp->rs_subsys != '*' &&
354 351 strcmp(subsys, rsp->rs_subsys) != 0)
355 352 continue;
356 353
357 354 dispf = rsp->rs_ppfunc;
358 355 found = 1;
359 356 break;
360 357
361 358 }
362 359
363 360 /*
364 361 * If a ruleset matches but specifies a NULL function then
365 362 * it's electing to drop the event. If no rule was matched
366 363 * then default to unregistered processing.
367 364 */
368 365 if (dispf == NULL) {
369 366 if (found) {
370 367 BUMPSTAT(pp_explicitdrop);
371 368 return;
372 369 } else {
373 370 BUMPSTAT(pp_fallthrurule);
374 371 dispf = fmevt_pp_unregistered;
375 372 }
376 373 }
377 374
378 375 /*
379 376 * Clear the arrays in which class strings and attribute
380 377 * nvlists can be returned. Pass a pointer to our stack buffer
381 378 * that the callee can use for the first event class (for others
382 379 * it must fmd_hdl_alloc and we'll free below). We will free
383 380 * and nvlists that are returned.
384 381 */
385 382 bzero(class, sizeof (class));
386 383 bzero(attr, sizeof (attr));
387 384 class[0] = buf;
388 385
389 386 /*
390 387 * Generate an event UUID which will be used for the first
391 388 * event generated by post-processing; if post-processing
392 389 * fans out into more than one event the additional events
393 390 * can reference this uuid (but we don't generate their
394 391 * UUIDs until later).
395 392 */
396 393 uuid_generate(uu);
397 394 uuid_unparse(uu, eap->pp_uuidstr);
398 395
399 396 /*
400 397 * Call selected post-processing function. See block comment
401 398 * in fmevt.h for a description of this process.
402 399 */
403 400 expected = (*dispf)(class, attr, ruleset,
404 401 (const nvlist_t *)dtcr, rawattr,
405 402 (const struct fmevt_ppargs *)eap);
406 403
407 404 if (expected > FMEVT_FANOUT_MAX) {
408 405 BUMPSTAT(pp_fanoutmax);
409 406 return; /* without freeing class and nvl - could leak */
410 407 } else if (expected == 0) {
411 408 BUMPSTAT(pp_intldrop);
412 409 return;
413 410 }
414 411
415 412 /*
416 413 * Post as many events as the callback completed.
417 414 */
418 415 for (i = 0; i < FMEVT_FANOUT_MAX; i++) {
419 416 char uuidstr[36 + 1];
420 417 char *uuidstrp;
421 418 nvlist_t *nvl;
422 419 int err = 0;
423 420
424 421 if (class[i] == NULL)
425 422 continue;
426 423
427 424 if (!class_ok(class[i])) {
428 425 BUMPSTAT(pp_badclass);
429 426 continue;
430 427 }
431 428
432 429 if (processed++ == 0) {
433 430 uuidstrp = eap->pp_uuidstr;
434 431 } else {
435 432 uuid_generate(uu);
436 433 uuid_unparse(uu, uuidstr);
437 434 uuidstrp = uuidstr;
438 435 }
439 436
440 437 if ((nvl = fmd_nvl_alloc(fmevt_hdl, FMD_SLEEP)) == NULL) {
441 438 BUMPSTAT(pp_nvlallocfail);
442 439 continue;
443 440 }
444 441
445 442 err += nvlist_add_uint8(nvl, FM_VERSION, 0);
446 443 err += nvlist_add_string(nvl, FM_CLASS, (const char *)class[i]);
447 444 err += nvlist_add_string(nvl, FM_IREPORT_UUID, uuidstrp);
448 445 err += nvlist_add_nvlist(nvl, FM_IREPORT_DETECTOR, dtcr);
449 446 err += nvlist_add_string(nvl, FM_IREPORT_PRIORITY,
450 447 fmev_pri_string(eap->pp_pri) ?
451 448 fmev_pri_string(eap->pp_pri) : "?");
452 449
453 450 if (attr[i] != NULL)
454 451 err += nvlist_add_nvlist(nvl, FM_IREPORT_ATTRIBUTES,
455 452 attr[i]);
456 453
457 454 /*
458 455 * If we post the event into fmd_xport_post then the
459 456 * transport code is responsible for freeing the nvl we
460 457 * posted.
461 458 */
462 459 if (err == 0) {
463 460 fmd_xprt_post(fmevt_hdl, fmevt_xprt, nvl,
464 461 eap->pp_hrt);
465 462 } else {
466 463 BUMPSTAT(pp_nvlbuildfail);
467 464 nvlist_free(nvl);
468 465 }
469 466 }
470 467
471 468 if (processed != expected)
472 469 BUMPSTAT(pp_badreturn);
473 470
474 471 for (i = 0; i < FMEVT_FANOUT_MAX; i++) {
475 472 /*
476 473 * We provided storage for class[0] but any
477 474 * additional events have allocated a string.
478 475 */
479 476 if (i > 0 && class[i] != NULL)
480 477 fmd_hdl_strfree(fmevt_hdl, class[i]);
481 478
482 479 /*
483 480 * Free all attribute lists passed in if they are not
484 481 * just a pointer to the raw attributes
485 482 */
486 483 if (attr[i] != NULL && attr[i] != rawattr)
487 484 nvlist_free(attr[i]);
488 485 }
489 486 }
490 487
491 488 static int
492 489 fmevt_cb(sysevent_t *sep, void *arg)
493 490 {
494 491 char *ruleset = NULL, *rawclass, *rawsubclass;
495 492 uint32_t cbarg = (uint32_t)arg;
496 493 nvlist_t *rawattr = NULL;
497 494 struct fmevt_ppargs ea;
498 495 nvlist_t *dtcr;
499 496 int user, priv;
500 497 fmev_pri_t pri;
501 498
502 499 BUMPSTAT(raw_callbacks);
503 500
504 501 if (cbarg & ~CBF_ALL)
505 502 fmd_hdl_abort(fmevt_hdl, "event receipt callback with "
506 503 "invalid flags\n");
507 504
508 505 user = (cbarg & CBF_USER) != 0;
509 506 priv = (cbarg & CBF_PRIV) != 0;
510 507 pri = (cbarg & CBF_HV ? FMEV_HIPRI : FMEV_LOPRI);
511 508
512 509 (void) pthread_mutex_lock(&fmevt_lock);
513 510
514 511 if (fmevt_exiting) {
515 512 while (fmevt_xprt_refcnt > 0)
516 513 (void) pthread_cond_wait(&fmevt_cv, &fmevt_lock);
517 514 (void) pthread_mutex_unlock(&fmevt_lock);
518 515 return (0); /* discard event */
519 516 }
520 517
521 518 fmevt_xprt_refcnt++;
522 519 (void) pthread_mutex_unlock(&fmevt_lock);
523 520
524 521 ruleset = sysevent_get_vendor_name(sep); /* must free */
525 522 rawclass = sysevent_get_class_name(sep); /* valid with sep */
526 523 rawsubclass = sysevent_get_subclass_name(sep); /* valid with sep */
527 524
528 525 if (sysevent_get_attr_list(sep, &rawattr) != 0) {
529 526 BUMPSTAT(raw_noattrlist);
530 527 goto done;
531 528 }
532 529
533 530 if ((dtcr = fmevt_detector(rawattr, ruleset, user, priv,
534 531 pri)) == NULL) {
535 532 BUMPSTAT(raw_nodetector);
536 533 goto done;
537 534 }
538 535
539 536 ea.pp_rawclass = rawclass;
540 537 ea.pp_rawsubclass = rawsubclass;
541 538 sysevent_get_time(sep, &ea.pp_hrt);
542 539 ea.pp_user = user;
543 540 ea.pp_priv = priv;
544 541 ea.pp_pri = pri;
545 542
546 543 fmevt_postprocess(ruleset, dtcr, rawattr, &ea);
547 544 nvlist_free(dtcr);
548 545 done:
↓ open down ↓ |
243 lines elided |
↑ open up ↑ |
549 546 (void) pthread_mutex_lock(&fmevt_lock);
550 547
551 548 if (--fmevt_xprt_refcnt == 0 && fmevt_exiting)
552 549 (void) pthread_cond_broadcast(&fmevt_cv);
553 550
554 551 (void) pthread_mutex_unlock(&fmevt_lock);
555 552
556 553 if (ruleset)
557 554 free(ruleset);
558 555
559 - if (rawattr)
560 - nvlist_free(rawattr);
556 + nvlist_free(rawattr);
561 557
562 558 return (0); /* in all cases consider the event delivered */
563 559 }
564 560
565 561 void
566 562 fmevt_init_inbound(fmd_hdl_t *hdl)
567 563 {
568 564 char *sidpfx;
569 565 zoneid_t zoneid;
570 566 int i;
571 567
572 568 if (!fmevt_rs_init(hdl))
573 569 fmd_hdl_abort(hdl, "error in fmevt_rs_init\n");
574 570
575 571 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (inbound_stats) /
576 572 sizeof (fmd_stat_t), (fmd_stat_t *)&inbound_stats);
577 573
578 574 zoneid = getzoneid();
579 575 isglobalzone = (zoneid == GLOBAL_ZONEID);
580 576 if (getzonenamebyid(zoneid, zonename, sizeof (zonename)) == -1)
581 577 fmd_hdl_abort(hdl, "getzonenamebyid failed");
582 578
583 579 if ((subattr = sysevent_subattr_alloc()) == NULL)
584 580 fmd_hdl_abort(hdl, "failed to allocate subscription "
585 581 "attributes: %s");
586 582
587 583 sysevent_subattr_thrcreate(subattr, fmd_doorthr_create, NULL);
588 584 sysevent_subattr_thrsetup(subattr, fmd_doorthr_setup, NULL);
589 585
590 586 sidpfx = fmd_prop_get_string(hdl, "sidprefix");
591 587 fmevt_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL);
592 588
593 589 for (i = 0; i < sizeof (chaninfo) / sizeof (chaninfo[0]); i++) {
594 590 struct fmevt_chaninfo *cip = &chaninfo[i];
595 591 char *channel = fmd_prop_get_string(hdl, cip->ci_propname);
596 592 int err;
597 593
598 594 if (sysevent_evc_bind(channel, &cip->ci_binding,
599 595 EVCH_CREAT | EVCH_HOLD_PEND_INDEF) != 0)
600 596 fmd_hdl_abort(hdl, "failed to bind GPEC channel for "
601 597 "channel %s", channel);
602 598
603 599 (void) snprintf(cip->ci_sid, sizeof (cip->ci_sid),
604 600 "%s_%c%c%c", sidpfx,
605 601 cip->ci_cbarg & CBF_USER ? 'u' : 'k',
606 602 cip->ci_cbarg & CBF_PRIV ? 'p' : 'n',
607 603 cip->ci_cbarg & CBF_HV ? 'h' : 'l');
608 604
609 605 err = sysevent_evc_xsubscribe(cip->ci_binding, cip->ci_sid,
610 606 EC_ALL, fmevt_cb, (void *)cip->ci_cbarg,
611 607 cip->ci_sflags, subattr);
612 608
613 609 if (err == EEXIST)
614 610 fmd_hdl_abort(hdl, "another fmd is active on "
615 611 "channel %s\n", channel);
616 612 else if (err != 0)
617 613 fmd_hdl_abort(hdl, "failed to subscribe to channel %s",
618 614 channel);
619 615
620 616 fmd_prop_free_string(hdl, channel);
621 617 }
622 618
623 619 fmd_prop_free_string(hdl, sidpfx);
624 620 }
625 621
626 622 void
627 623 fmevt_fini_inbound(fmd_hdl_t *hdl)
628 624 {
629 625 int i;
630 626
631 627 for (i = 0; i < sizeof (chaninfo) / sizeof (chaninfo[0]); i++) {
632 628 struct fmevt_chaninfo *cip = &chaninfo[i];
633 629
634 630 if (cip->ci_binding) {
635 631 (void) sysevent_evc_unsubscribe(cip->ci_binding,
636 632 cip->ci_sid);
637 633 (void) sysevent_evc_unbind(cip->ci_binding);
638 634 cip->ci_binding = NULL;
639 635 }
640 636 }
641 637
642 638 if (subattr) {
643 639 sysevent_subattr_free(subattr);
644 640 subattr = NULL;
645 641 }
646 642
647 643 if (fmevt_xprt) {
648 644 /* drain before destruction */
649 645 (void) pthread_mutex_lock(&fmevt_lock);
650 646 fmevt_exiting = 1;
651 647 while (fmevt_xprt_refcnt > 0)
652 648 (void) pthread_cond_wait(&fmevt_cv, &fmevt_lock);
653 649 (void) pthread_mutex_unlock(&fmevt_lock);
654 650
655 651 fmd_xprt_close(hdl, fmevt_xprt);
656 652 }
657 653
658 654 }
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX