1*49b225e1SGavin Maltby /* 2*49b225e1SGavin Maltby * CDDL HEADER START 3*49b225e1SGavin Maltby * 4*49b225e1SGavin Maltby * The contents of this file are subject to the terms of the 5*49b225e1SGavin Maltby * Common Development and Distribution License (the "License"). 6*49b225e1SGavin Maltby * You may not use this file except in compliance with the License. 7*49b225e1SGavin Maltby * 8*49b225e1SGavin Maltby * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*49b225e1SGavin Maltby * or http://www.opensolaris.org/os/licensing. 10*49b225e1SGavin Maltby * See the License for the specific language governing permissions 11*49b225e1SGavin Maltby * and limitations under the License. 12*49b225e1SGavin Maltby * 13*49b225e1SGavin Maltby * When distributing Covered Code, include this CDDL HEADER in each 14*49b225e1SGavin Maltby * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*49b225e1SGavin Maltby * If applicable, add the following below this CDDL HEADER, with the 16*49b225e1SGavin Maltby * fields enclosed by brackets "[]" replaced with your own identifying 17*49b225e1SGavin Maltby * information: Portions Copyright [yyyy] [name of copyright owner] 18*49b225e1SGavin Maltby * 19*49b225e1SGavin Maltby * CDDL HEADER END 20*49b225e1SGavin Maltby */ 21*49b225e1SGavin Maltby 22*49b225e1SGavin Maltby /* 23*49b225e1SGavin Maltby * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*49b225e1SGavin Maltby * Use is subject to license terms. 25*49b225e1SGavin Maltby */ 26*49b225e1SGavin Maltby 27*49b225e1SGavin Maltby /* 28*49b225e1SGavin Maltby * Subscription event access interfaces. 29*49b225e1SGavin Maltby */ 30*49b225e1SGavin Maltby 31*49b225e1SGavin Maltby #include <sys/types.h> 32*49b225e1SGavin Maltby #include <limits.h> 33*49b225e1SGavin Maltby #include <atomic.h> 34*49b225e1SGavin Maltby #include <libsysevent.h> 35*49b225e1SGavin Maltby #include <umem.h> 36*49b225e1SGavin Maltby #include <fm/libfmevent.h> 37*49b225e1SGavin Maltby #include <sys/fm/protocol.h> 38*49b225e1SGavin Maltby 39*49b225e1SGavin Maltby #include "fmev_impl.h" 40*49b225e1SGavin Maltby 41*49b225e1SGavin Maltby #define API_ENTERV1(iep) \ 42*49b225e1SGavin Maltby ((void) fmev_api_enter(fmev_shdl_cmn(((iep)->ei_hdl)), \ 43*49b225e1SGavin Maltby LIBFMEVENT_VERSION_1)) 44*49b225e1SGavin Maltby 45*49b225e1SGavin Maltby typedef struct { 46*49b225e1SGavin Maltby uint32_t ei_magic; /* _FMEVMAGIC */ 47*49b225e1SGavin Maltby volatile uint32_t ei_refcnt; /* reference count */ 48*49b225e1SGavin Maltby fmev_shdl_t ei_hdl; /* handle received on */ 49*49b225e1SGavin Maltby nvlist_t *ei_nvl; /* (duped) sysevent attribute list */ 50*49b225e1SGavin Maltby uint64_t ei_fmtime[2]; /* embedded protocol event time */ 51*49b225e1SGavin Maltby } fmev_impl_t; 52*49b225e1SGavin Maltby 53*49b225e1SGavin Maltby #define FMEV2IMPL(ev) ((fmev_impl_t *)(ev)) 54*49b225e1SGavin Maltby #define IMPL2FMEV(iep) ((fmev_t)(iep)) 55*49b225e1SGavin Maltby 56*49b225e1SGavin Maltby #define _FMEVMAGIC 0x466d4576 /* "FmEv" */ 57*49b225e1SGavin Maltby 58*49b225e1SGavin Maltby #define EVENT_VALID(iep) ((iep)->ei_magic == _FMEVMAGIC && \ 59*49b225e1SGavin Maltby (iep)->ei_refcnt > 0 && fmev_shdl_valid((iep)->ei_hdl)) 60*49b225e1SGavin Maltby 61*49b225e1SGavin Maltby #define FM_TIME_SEC 0 62*49b225e1SGavin Maltby #define FM_TIME_NSEC 1 63*49b225e1SGavin Maltby 64*49b225e1SGavin Maltby /* 65*49b225e1SGavin Maltby * Transform a received sysevent_t into an fmev_t. 66*49b225e1SGavin Maltby */ 67*49b225e1SGavin Maltby 68*49b225e1SGavin Maltby uint64_t fmev_bad_attr, fmev_bad_tod, fmev_bad_class; 69*49b225e1SGavin Maltby 70*49b225e1SGavin Maltby fmev_t 71*49b225e1SGavin Maltby fmev_sysev2fmev(fmev_shdl_t hdl, sysevent_t *sep, char **clsp, nvlist_t **nvlp) 72*49b225e1SGavin Maltby { 73*49b225e1SGavin Maltby fmev_impl_t *iep; 74*49b225e1SGavin Maltby uint64_t *tod; 75*49b225e1SGavin Maltby uint_t nelem; 76*49b225e1SGavin Maltby 77*49b225e1SGavin Maltby if ((iep = fmev_shdl_alloc(hdl, sizeof (*iep))) == NULL) 78*49b225e1SGavin Maltby return (NULL); 79*49b225e1SGavin Maltby 80*49b225e1SGavin Maltby /* 81*49b225e1SGavin Maltby * sysevent_get_attr_list duplicates the nvlist - we free it 82*49b225e1SGavin Maltby * in fmev_free when the reference count hits zero. 83*49b225e1SGavin Maltby */ 84*49b225e1SGavin Maltby if (sysevent_get_attr_list(sep, &iep->ei_nvl) != 0) { 85*49b225e1SGavin Maltby fmev_shdl_free(hdl, iep, sizeof (*iep)); 86*49b225e1SGavin Maltby fmev_bad_attr++; 87*49b225e1SGavin Maltby return (NULL); 88*49b225e1SGavin Maltby } 89*49b225e1SGavin Maltby 90*49b225e1SGavin Maltby *nvlp = iep->ei_nvl; 91*49b225e1SGavin Maltby 92*49b225e1SGavin Maltby if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, clsp) != 0) { 93*49b225e1SGavin Maltby nvlist_free(iep->ei_nvl); 94*49b225e1SGavin Maltby fmev_shdl_free(hdl, iep, sizeof (*iep)); 95*49b225e1SGavin Maltby fmev_bad_class++; 96*49b225e1SGavin Maltby return (NULL); 97*49b225e1SGavin Maltby } 98*49b225e1SGavin Maltby 99*49b225e1SGavin Maltby if (nvlist_lookup_uint64_array(iep->ei_nvl, "__tod", &tod, 100*49b225e1SGavin Maltby &nelem) != 0 || nelem != 2) { 101*49b225e1SGavin Maltby nvlist_free(iep->ei_nvl); 102*49b225e1SGavin Maltby fmev_shdl_free(hdl, iep, sizeof (*iep)); 103*49b225e1SGavin Maltby fmev_bad_tod++; 104*49b225e1SGavin Maltby return (NULL); 105*49b225e1SGavin Maltby } 106*49b225e1SGavin Maltby 107*49b225e1SGavin Maltby iep->ei_fmtime[FM_TIME_SEC] = tod[0]; 108*49b225e1SGavin Maltby iep->ei_fmtime[FM_TIME_NSEC] = tod[1]; 109*49b225e1SGavin Maltby 110*49b225e1SGavin Maltby /* 111*49b225e1SGavin Maltby * Now remove the fmd-private __tod and __ttl members. 112*49b225e1SGavin Maltby */ 113*49b225e1SGavin Maltby (void) nvlist_remove_all(iep->ei_nvl, "__tod"); 114*49b225e1SGavin Maltby (void) nvlist_remove_all(iep->ei_nvl, "__ttl"); 115*49b225e1SGavin Maltby 116*49b225e1SGavin Maltby iep->ei_magic = _FMEVMAGIC; 117*49b225e1SGavin Maltby iep->ei_hdl = hdl; 118*49b225e1SGavin Maltby iep->ei_refcnt = 1; 119*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 120*49b225e1SGavin Maltby 121*49b225e1SGavin Maltby return (IMPL2FMEV(iep)); 122*49b225e1SGavin Maltby } 123*49b225e1SGavin Maltby 124*49b225e1SGavin Maltby static void 125*49b225e1SGavin Maltby fmev_free(fmev_impl_t *iep) 126*49b225e1SGavin Maltby { 127*49b225e1SGavin Maltby ASSERT(iep->ei_refcnt == 0); 128*49b225e1SGavin Maltby 129*49b225e1SGavin Maltby nvlist_free(iep->ei_nvl); 130*49b225e1SGavin Maltby fmev_shdl_free(iep->ei_hdl, iep, sizeof (*iep)); 131*49b225e1SGavin Maltby } 132*49b225e1SGavin Maltby 133*49b225e1SGavin Maltby void 134*49b225e1SGavin Maltby fmev_hold(fmev_t ev) 135*49b225e1SGavin Maltby { 136*49b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 137*49b225e1SGavin Maltby 138*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 139*49b225e1SGavin Maltby 140*49b225e1SGavin Maltby API_ENTERV1(iep); 141*49b225e1SGavin Maltby 142*49b225e1SGavin Maltby atomic_inc_32(&iep->ei_refcnt); 143*49b225e1SGavin Maltby } 144*49b225e1SGavin Maltby 145*49b225e1SGavin Maltby void 146*49b225e1SGavin Maltby fmev_rele(fmev_t ev) 147*49b225e1SGavin Maltby { 148*49b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 149*49b225e1SGavin Maltby 150*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 151*49b225e1SGavin Maltby 152*49b225e1SGavin Maltby API_ENTERV1(iep); 153*49b225e1SGavin Maltby 154*49b225e1SGavin Maltby if (atomic_dec_32_nv(&iep->ei_refcnt) == 0) 155*49b225e1SGavin Maltby fmev_free(iep); 156*49b225e1SGavin Maltby } 157*49b225e1SGavin Maltby 158*49b225e1SGavin Maltby fmev_t 159*49b225e1SGavin Maltby fmev_dup(fmev_t ev) 160*49b225e1SGavin Maltby { 161*49b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 162*49b225e1SGavin Maltby fmev_impl_t *cp; 163*49b225e1SGavin Maltby 164*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 165*49b225e1SGavin Maltby 166*49b225e1SGavin Maltby API_ENTERV1(iep); 167*49b225e1SGavin Maltby 168*49b225e1SGavin Maltby if (ev == NULL) { 169*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_API); 170*49b225e1SGavin Maltby return (NULL); 171*49b225e1SGavin Maltby } 172*49b225e1SGavin Maltby 173*49b225e1SGavin Maltby if ((cp = fmev_shdl_alloc(iep->ei_hdl, sizeof (*iep))) == NULL) { 174*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_ALLOC); 175*49b225e1SGavin Maltby return (NULL); 176*49b225e1SGavin Maltby } 177*49b225e1SGavin Maltby 178*49b225e1SGavin Maltby if (nvlist_dup(iep->ei_nvl, &cp->ei_nvl, 0) != 0) { 179*49b225e1SGavin Maltby fmev_shdl_free(iep->ei_hdl, cp, sizeof (*cp)); 180*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_ALLOC); 181*49b225e1SGavin Maltby return (NULL); 182*49b225e1SGavin Maltby } 183*49b225e1SGavin Maltby 184*49b225e1SGavin Maltby cp->ei_magic = _FMEVMAGIC; 185*49b225e1SGavin Maltby cp->ei_hdl = iep->ei_hdl; 186*49b225e1SGavin Maltby cp->ei_refcnt = 1; 187*49b225e1SGavin Maltby return (IMPL2FMEV(cp)); 188*49b225e1SGavin Maltby } 189*49b225e1SGavin Maltby 190*49b225e1SGavin Maltby nvlist_t * 191*49b225e1SGavin Maltby fmev_attr_list(fmev_t ev) 192*49b225e1SGavin Maltby { 193*49b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 194*49b225e1SGavin Maltby 195*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 196*49b225e1SGavin Maltby 197*49b225e1SGavin Maltby API_ENTERV1(iep); 198*49b225e1SGavin Maltby 199*49b225e1SGavin Maltby if (ev == NULL) { 200*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_API); 201*49b225e1SGavin Maltby return (NULL); 202*49b225e1SGavin Maltby } else if (iep->ei_nvl == NULL) { 203*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_MALFORMED_EVENT); 204*49b225e1SGavin Maltby return (NULL); 205*49b225e1SGavin Maltby } 206*49b225e1SGavin Maltby 207*49b225e1SGavin Maltby return (iep->ei_nvl); 208*49b225e1SGavin Maltby } 209*49b225e1SGavin Maltby 210*49b225e1SGavin Maltby const char * 211*49b225e1SGavin Maltby fmev_class(fmev_t ev) 212*49b225e1SGavin Maltby { 213*49b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 214*49b225e1SGavin Maltby const char *class; 215*49b225e1SGavin Maltby 216*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 217*49b225e1SGavin Maltby 218*49b225e1SGavin Maltby API_ENTERV1(iep); 219*49b225e1SGavin Maltby 220*49b225e1SGavin Maltby if (ev == NULL) { 221*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_API); 222*49b225e1SGavin Maltby return (""); 223*49b225e1SGavin Maltby } 224*49b225e1SGavin Maltby 225*49b225e1SGavin Maltby if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, (char **)&class) != 0 || 226*49b225e1SGavin Maltby *class == '\0') { 227*49b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_MALFORMED_EVENT); 228*49b225e1SGavin Maltby return (""); 229*49b225e1SGavin Maltby } 230*49b225e1SGavin Maltby 231*49b225e1SGavin Maltby return (class); 232*49b225e1SGavin Maltby } 233*49b225e1SGavin Maltby 234*49b225e1SGavin Maltby fmev_err_t 235*49b225e1SGavin Maltby fmev_timespec(fmev_t ev, struct timespec *tp) 236*49b225e1SGavin Maltby { 237*49b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 238*49b225e1SGavin Maltby uint64_t timetlimit; 239*49b225e1SGavin Maltby 240*49b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 241*49b225e1SGavin Maltby API_ENTERV1(iep); 242*49b225e1SGavin Maltby 243*49b225e1SGavin Maltby #ifdef _LP64 244*49b225e1SGavin Maltby timetlimit = INT64_MAX; 245*49b225e1SGavin Maltby #else 246*49b225e1SGavin Maltby timetlimit = INT32_MAX; 247*49b225e1SGavin Maltby #endif 248*49b225e1SGavin Maltby 249*49b225e1SGavin Maltby if (iep->ei_fmtime[FM_TIME_SEC] > timetlimit) 250*49b225e1SGavin Maltby return (FMEVERR_OVERFLOW); 251*49b225e1SGavin Maltby 252*49b225e1SGavin Maltby tp->tv_sec = (time_t)iep->ei_fmtime[FM_TIME_SEC]; 253*49b225e1SGavin Maltby tp->tv_nsec = (long)iep->ei_fmtime[FM_TIME_NSEC]; 254*49b225e1SGavin Maltby 255*49b225e1SGavin Maltby return (FMEV_SUCCESS); 256*49b225e1SGavin Maltby } 257*49b225e1SGavin Maltby 258*49b225e1SGavin Maltby uint64_t 259*49b225e1SGavin Maltby fmev_time_sec(fmev_t ev) 260*49b225e1SGavin Maltby { 261*49b225e1SGavin Maltby return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_SEC]); 262*49b225e1SGavin Maltby } 263*49b225e1SGavin Maltby 264*49b225e1SGavin Maltby uint64_t 265*49b225e1SGavin Maltby fmev_time_nsec(fmev_t ev) 266*49b225e1SGavin Maltby { 267*49b225e1SGavin Maltby return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_NSEC]); 268*49b225e1SGavin Maltby } 269*49b225e1SGavin Maltby 270*49b225e1SGavin Maltby struct tm * 271*49b225e1SGavin Maltby fmev_localtime(fmev_t ev, struct tm *tm) 272*49b225e1SGavin Maltby { 273*49b225e1SGavin Maltby time_t seconds; 274*49b225e1SGavin Maltby 275*49b225e1SGavin Maltby seconds = (time_t)fmev_time_sec(ev); 276*49b225e1SGavin Maltby return (localtime_r(&seconds, tm)); 277*49b225e1SGavin Maltby } 278