1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26#include <stdlib.h> 27#include <unistd.h> 28#include <stdio.h> 29#include <sys/types.h> 30#include <fm/fmd_api.h> 31#include <fmd_module.h> 32#include <fmd_scheme.h> 33#include <fmd.h> 34#include <libnvpair.h> 35#include <libsysevent.h> 36#include <errno.h> 37#include <string.h> 38#include <fpst-defines.h> 39 40static evchan_t *h_event; /* handle for event channel */ 41static fmd_xprt_t *h_xprt; /* transport handle */ 42static fmd_hdl_t *h_fmd; /* fmd handle */ 43 44static const fmd_hdl_ops_t fps_ops = { 45 NULL, /* receive */ 46 NULL, /* timeout */ 47 NULL, /* close */ 48 NULL, /* stats */ 49 NULL /* gc */ 50}; 51 52static const fmd_hdl_info_t fmd_info = { 53 FPS_MOD_DESC, 54 FPS_MOD_VER, 55 &fps_ops, 56 NULL 57}; 58 59static struct sysev_stats { 60 fmd_stat_t bad_class; 61 fmd_stat_t bad_attr; 62 fmd_stat_t eagain; 63} sysev_stats = { 64 { "bad_class", FMD_TYPE_UINT64, 65 "events dropped due to invalid class" }, 66 { "bad_attr", FMD_TYPE_UINT64, 67 "events dropped due to invalid nvlist" }, 68 { "eagain", FMD_TYPE_UINT64, "events retried due to low memory" }, 69}; 70 71static sysevent_subattr_t *subattr; 72 73/* 74 * event_transfer(sysevent_t *ev, void *arg) 75 * takes a sysevent ev, extracts the nvlist of 76 * data for an ereport, and posts it to the fmd. 77 */ 78/* ARGSUSED */ 79static int 80event_transfer(sysevent_t *ev, void *arg) 81{ 82 hrtime_t hrt; 83 nvlist_t *retrieved_list; 84 uint64_t seq = sysevent_get_seq(ev); 85 86 if (strcasecmp(sysevent_get_class_name(ev), CLASS) != 0) { 87 fmd_hdl_error(h_fmd, "Discarding event 0x%llx: unexpected" 88 " transport class %s\n", seq, 89 sysevent_get_class_name(ev)); 90 sysev_stats.bad_class.fmds_value.ui64++; 91 92 return (0); 93 } 94 95 if (sysevent_get_attr_list(ev, &retrieved_list) == 0) { 96 sysevent_get_time(ev, &hrt); 97 fmd_xprt_post(h_fmd, h_xprt, retrieved_list, hrt); 98 } else { 99 if (errno == EAGAIN || errno == ENOMEM) { 100 sysev_stats.eagain.fmds_value.ui64++; 101 return (EAGAIN); 102 } 103 104 fmd_hdl_error(h_fmd, "Event: 0x%llx is missing or" 105 " has an invalid payload.", seq); 106 sysev_stats.bad_attr.fmds_value.ui64++; 107 108 } 109 110 return (0); 111} 112 113/* 114 * _fmd_fini(fmd_hdl_t *handle) is the 115 * module exit point. It unsubscribes 116 * and unbinds to FPS channel as well 117 * as closes fmd transport handle 118 */ 119/* ARGSUSED */ 120void 121_fmd_fini(fmd_hdl_t *handle) 122{ 123 if (h_event != NULL) { 124 (void) sysevent_evc_unsubscribe(h_event, SUBSCRIBE_ID); 125 (void) sysevent_evc_unbind(h_event); 126 if (subattr != NULL) 127 sysevent_subattr_free(subattr); 128 } 129 130 if (h_fmd != NULL && h_xprt != NULL) 131 fmd_xprt_close(h_fmd, h_xprt); 132} 133 134/* 135 * _fmd_init(fmd_hdl_t *hdl) is the 136 * entry point into the module. It 137 * registers the handle hdl and 138 * subscribes to the fps sysevent channel. 139 */ 140void 141_fmd_init(fmd_hdl_t *hdl) 142{ 143 int ret = 0; 144 145 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) { 146 return; 147 } 148 149 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (sysev_stats) / 150 sizeof (fmd_stat_t), (fmd_stat_t *)&sysev_stats); 151 152 h_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 153 h_fmd = hdl; 154 155 if (sysevent_evc_bind(CHANNEL, &h_event, BIND_FLAGS) != 0) { 156 fmd_hdl_error(hdl, "Failed to bind to channel %s", CHANNEL); 157 fmd_hdl_unregister(hdl); 158 } 159 160 if ((subattr = sysevent_subattr_alloc()) == NULL) 161 fmd_hdl_abort(hdl, "failed to allocate subscription " 162 "attributes: %s"); 163 164 sysevent_subattr_thrcreate(subattr, fmd_doorthr_create, NULL); 165 sysevent_subattr_thrsetup(subattr, fmd_doorthr_setup, NULL); 166 167 ret = sysevent_evc_xsubscribe(h_event, SUBSCRIBE_ID, 168 SUBSCRIBE_FLAGS, event_transfer, NULL, 0, subattr); 169 if (ret != 0) { 170 if (ret == EEXIST) { 171 fmd_hdl_unregister(hdl); 172 } else { 173 fmd_hdl_error(hdl, 174 "Failed to subsrcibe to channel %s", CHANNEL); 175 fmd_hdl_unregister(hdl); 176 } 177 } 178} 179