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) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <strings.h>
  28 #include <fm/fmd_api.h>
  29 #include <sys/fm/protocol.h>
  30 #include <sys/fm/util.h>
  31 #include <sys/sysevent.h>
  32 
  33 #include "fmevt.h"
  34 
  35 static evchan_t *fmevt_outbound_chan;
  36 
  37 static struct fmevt_outbound_stats {
  38         fmd_stat_t recv_calls;
  39         fmd_stat_t recv_list;
  40         fmd_stat_t recv_ireport;
  41         fmd_stat_t recv_other;
  42         fmd_stat_t fwd_success;
  43         fmd_stat_t fwd_failure;
  44 } outbound_stats = {
  45         { "outbound_recv_calls", FMD_TYPE_UINT64,
  46             "total events received for forwarding" },
  47         { "outbound_cat1class_list", FMD_TYPE_UINT64,
  48             "events received matching list.*" },
  49         { "outbound_cat1class_ireport", FMD_TYPE_UINT64,
  50             "events received matching ireport.*" },
  51         { "outbound_cat1class_other", FMD_TYPE_UINT64,
  52             "events of other classes" },
  53         { "outbound_fwd_success", FMD_TYPE_UINT64,
  54             "events forwarded successfully" },
  55         { "outbound_fwd_failure", FMD_TYPE_UINT64,
  56             "events we failed to forward" }
  57 };
  58 
  59 #define BUMPSTAT(stat)  outbound_stats.stat.fmds_value.ui64++
  60 
  61 /*
  62  * In the .conf file we subscribe to list.* and ireport.* event classes.
  63  * Any additions to that set could cause some unexpected behaviour.
  64  * For example adding fault.foo won't work (since we don't publish
  65  * faults directly but only within a list.suspect) but we will get
  66  * any list.* including fault.foo as a suspect.
  67  */
  68 /*ARGSUSED*/
  69 void
  70 fmevt_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
  71 {
  72         BUMPSTAT(recv_calls);
  73 
  74         if (strncmp(class, "list.", 5) == 0)
  75                 BUMPSTAT(recv_list);
  76         else if (strncmp(class, "ireport.", 8) == 0)
  77                 BUMPSTAT(recv_ireport);
  78         else
  79                 BUMPSTAT(recv_other);
  80 
  81         if (sysevent_evc_publish(fmevt_outbound_chan, class, "",
  82             SUNW_VENDOR, FM_PUB, nvl, EVCH_SLEEP) == 0) {
  83                 BUMPSTAT(fwd_success);
  84         } else {
  85                 BUMPSTAT(fwd_failure);
  86                 fmd_hdl_debug(hdl, "sysevent_evc_publish failed:");
  87         }
  88 }
  89 
  90 void
  91 fmevt_init_outbound(fmd_hdl_t *hdl)
  92 {
  93         int32_t channel_depth;
  94         char *channel_name;
  95         nvlist_t *nvl;
  96 
  97         if (fmd_prop_get_int32(hdl, "protocol_forward_disable") == B_TRUE) {
  98                 fmd_hdl_debug(hdl, "protocol forwarding disabled "
  99                     "through .conf file setting\n");
 100                 return;
 101         }
 102 
 103         (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (outbound_stats) /
 104             sizeof (fmd_stat_t), (fmd_stat_t *)&outbound_stats);
 105 
 106         /*
 107          * Allow simulation environment to change outbound channel name.
 108          */
 109         channel_name = fmd_prop_get_string(hdl, "outbound_channel");
 110 
 111         if (sysevent_evc_bind(channel_name, &fmevt_outbound_chan,
 112             EVCH_CREAT | EVCH_HOLD_PEND_INDEF) != 0) {
 113                 fmd_hdl_abort(hdl, "Unable to bind channel %s",
 114                     channel_name);
 115                 return;
 116         }
 117 
 118         channel_depth = fmd_prop_get_int32(hdl, "outbound_channel_depth");
 119 
 120         if (sysevent_evc_control(fmevt_outbound_chan, EVCH_SET_CHAN_LEN,
 121             (uint32_t)channel_depth) != 0) {
 122                 fmd_hdl_abort(hdl, "Unable to set depth of channel %s to %d",
 123                     channel_name, channel_depth);
 124         }
 125         fmd_prop_free_string(hdl, channel_name);
 126 
 127         nvl = fmd_nvl_alloc(hdl, FMD_SLEEP);
 128         (void) nvlist_add_nvlist(nvl, "fmdauth",
 129             (nvlist_t *)fmd_hdl_fmauth(hdl));
 130         (void) sysevent_evc_setpropnvl(fmevt_outbound_chan, nvl);
 131         nvlist_free(nvl);
 132 
 133 }
 134 
 135 /*ARGSUSED*/
 136 void
 137 fmevt_fini_outbound(fmd_hdl_t *hdl)
 138 {
 139         if (fmevt_outbound_chan != NULL) {
 140                 (void) sysevent_evc_unbind(fmevt_outbound_chan);
 141                 fmevt_outbound_chan = NULL;
 142         }
 143 }