149b225e1SGavin Maltby /* 249b225e1SGavin Maltby * CDDL HEADER START 349b225e1SGavin Maltby * 449b225e1SGavin Maltby * The contents of this file are subject to the terms of the 549b225e1SGavin Maltby * Common Development and Distribution License (the "License"). 649b225e1SGavin Maltby * You may not use this file except in compliance with the License. 749b225e1SGavin Maltby * 849b225e1SGavin Maltby * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 949b225e1SGavin Maltby * or http://www.opensolaris.org/os/licensing. 1049b225e1SGavin Maltby * See the License for the specific language governing permissions 1149b225e1SGavin Maltby * and limitations under the License. 1249b225e1SGavin Maltby * 1349b225e1SGavin Maltby * When distributing Covered Code, include this CDDL HEADER in each 1449b225e1SGavin Maltby * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1549b225e1SGavin Maltby * If applicable, add the following below this CDDL HEADER, with the 1649b225e1SGavin Maltby * fields enclosed by brackets "[]" replaced with your own identifying 1749b225e1SGavin Maltby * information: Portions Copyright [yyyy] [name of copyright owner] 1849b225e1SGavin Maltby * 1949b225e1SGavin Maltby * CDDL HEADER END 2049b225e1SGavin Maltby */ 2149b225e1SGavin Maltby 2249b225e1SGavin Maltby /* 23*f6e214c7SGavin Maltby * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2449b225e1SGavin Maltby */ 2549b225e1SGavin Maltby 2649b225e1SGavin Maltby /* 2749b225e1SGavin Maltby * Subscription event access interfaces. 2849b225e1SGavin Maltby */ 2949b225e1SGavin Maltby 3049b225e1SGavin Maltby #include <sys/types.h> 3149b225e1SGavin Maltby #include <limits.h> 3249b225e1SGavin Maltby #include <atomic.h> 3349b225e1SGavin Maltby #include <libsysevent.h> 3449b225e1SGavin Maltby #include <umem.h> 3549b225e1SGavin Maltby #include <fm/libfmevent.h> 3649b225e1SGavin Maltby #include <sys/fm/protocol.h> 3749b225e1SGavin Maltby 3849b225e1SGavin Maltby #include "fmev_impl.h" 3949b225e1SGavin Maltby 40*f6e214c7SGavin Maltby #define FMEV_API_ENTER(iep, v) \ 41*f6e214c7SGavin Maltby fmev_api_enter(fmev_shdl_cmn(((iep)->ei_hdl)), LIBFMEVENT_VERSION_##v) 4249b225e1SGavin Maltby 4349b225e1SGavin Maltby typedef struct { 4449b225e1SGavin Maltby uint32_t ei_magic; /* _FMEVMAGIC */ 4549b225e1SGavin Maltby volatile uint32_t ei_refcnt; /* reference count */ 4649b225e1SGavin Maltby fmev_shdl_t ei_hdl; /* handle received on */ 4749b225e1SGavin Maltby nvlist_t *ei_nvl; /* (duped) sysevent attribute list */ 4849b225e1SGavin Maltby uint64_t ei_fmtime[2]; /* embedded protocol event time */ 4949b225e1SGavin Maltby } fmev_impl_t; 5049b225e1SGavin Maltby 5149b225e1SGavin Maltby #define FMEV2IMPL(ev) ((fmev_impl_t *)(ev)) 5249b225e1SGavin Maltby #define IMPL2FMEV(iep) ((fmev_t)(iep)) 5349b225e1SGavin Maltby 5449b225e1SGavin Maltby #define _FMEVMAGIC 0x466d4576 /* "FmEv" */ 5549b225e1SGavin Maltby 5649b225e1SGavin Maltby #define EVENT_VALID(iep) ((iep)->ei_magic == _FMEVMAGIC && \ 5749b225e1SGavin Maltby (iep)->ei_refcnt > 0 && fmev_shdl_valid((iep)->ei_hdl)) 5849b225e1SGavin Maltby 5949b225e1SGavin Maltby #define FM_TIME_SEC 0 6049b225e1SGavin Maltby #define FM_TIME_NSEC 1 6149b225e1SGavin Maltby 6249b225e1SGavin Maltby /* 6349b225e1SGavin Maltby * Transform a received sysevent_t into an fmev_t. 6449b225e1SGavin Maltby */ 6549b225e1SGavin Maltby 6649b225e1SGavin Maltby uint64_t fmev_bad_attr, fmev_bad_tod, fmev_bad_class; 6749b225e1SGavin Maltby 6849b225e1SGavin Maltby fmev_t 6949b225e1SGavin Maltby fmev_sysev2fmev(fmev_shdl_t hdl, sysevent_t *sep, char **clsp, nvlist_t **nvlp) 7049b225e1SGavin Maltby { 7149b225e1SGavin Maltby fmev_impl_t *iep; 7249b225e1SGavin Maltby uint64_t *tod; 7349b225e1SGavin Maltby uint_t nelem; 7449b225e1SGavin Maltby 7549b225e1SGavin Maltby if ((iep = fmev_shdl_alloc(hdl, sizeof (*iep))) == NULL) 7649b225e1SGavin Maltby return (NULL); 7749b225e1SGavin Maltby 7849b225e1SGavin Maltby /* 7949b225e1SGavin Maltby * sysevent_get_attr_list duplicates the nvlist - we free it 8049b225e1SGavin Maltby * in fmev_free when the reference count hits zero. 8149b225e1SGavin Maltby */ 8249b225e1SGavin Maltby if (sysevent_get_attr_list(sep, &iep->ei_nvl) != 0) { 8349b225e1SGavin Maltby fmev_shdl_free(hdl, iep, sizeof (*iep)); 8449b225e1SGavin Maltby fmev_bad_attr++; 8549b225e1SGavin Maltby return (NULL); 8649b225e1SGavin Maltby } 8749b225e1SGavin Maltby 8849b225e1SGavin Maltby *nvlp = iep->ei_nvl; 8949b225e1SGavin Maltby 9049b225e1SGavin Maltby if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, clsp) != 0) { 9149b225e1SGavin Maltby nvlist_free(iep->ei_nvl); 9249b225e1SGavin Maltby fmev_shdl_free(hdl, iep, sizeof (*iep)); 9349b225e1SGavin Maltby fmev_bad_class++; 9449b225e1SGavin Maltby return (NULL); 9549b225e1SGavin Maltby } 9649b225e1SGavin Maltby 9749b225e1SGavin Maltby if (nvlist_lookup_uint64_array(iep->ei_nvl, "__tod", &tod, 9849b225e1SGavin Maltby &nelem) != 0 || nelem != 2) { 9949b225e1SGavin Maltby nvlist_free(iep->ei_nvl); 10049b225e1SGavin Maltby fmev_shdl_free(hdl, iep, sizeof (*iep)); 10149b225e1SGavin Maltby fmev_bad_tod++; 10249b225e1SGavin Maltby return (NULL); 10349b225e1SGavin Maltby } 10449b225e1SGavin Maltby 10549b225e1SGavin Maltby iep->ei_fmtime[FM_TIME_SEC] = tod[0]; 10649b225e1SGavin Maltby iep->ei_fmtime[FM_TIME_NSEC] = tod[1]; 10749b225e1SGavin Maltby 10849b225e1SGavin Maltby /* 10949b225e1SGavin Maltby * Now remove the fmd-private __tod and __ttl members. 11049b225e1SGavin Maltby */ 11149b225e1SGavin Maltby (void) nvlist_remove_all(iep->ei_nvl, "__tod"); 11249b225e1SGavin Maltby (void) nvlist_remove_all(iep->ei_nvl, "__ttl"); 11349b225e1SGavin Maltby 11449b225e1SGavin Maltby iep->ei_magic = _FMEVMAGIC; 11549b225e1SGavin Maltby iep->ei_hdl = hdl; 11649b225e1SGavin Maltby iep->ei_refcnt = 1; 11749b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 11849b225e1SGavin Maltby 11949b225e1SGavin Maltby return (IMPL2FMEV(iep)); 12049b225e1SGavin Maltby } 12149b225e1SGavin Maltby 12249b225e1SGavin Maltby static void 12349b225e1SGavin Maltby fmev_free(fmev_impl_t *iep) 12449b225e1SGavin Maltby { 12549b225e1SGavin Maltby ASSERT(iep->ei_refcnt == 0); 12649b225e1SGavin Maltby 12749b225e1SGavin Maltby nvlist_free(iep->ei_nvl); 12849b225e1SGavin Maltby fmev_shdl_free(iep->ei_hdl, iep, sizeof (*iep)); 12949b225e1SGavin Maltby } 13049b225e1SGavin Maltby 13149b225e1SGavin Maltby void 13249b225e1SGavin Maltby fmev_hold(fmev_t ev) 13349b225e1SGavin Maltby { 13449b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 13549b225e1SGavin Maltby 13649b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 13749b225e1SGavin Maltby 138*f6e214c7SGavin Maltby (void) FMEV_API_ENTER(iep, 1); 13949b225e1SGavin Maltby 14049b225e1SGavin Maltby atomic_inc_32(&iep->ei_refcnt); 14149b225e1SGavin Maltby } 14249b225e1SGavin Maltby 14349b225e1SGavin Maltby void 14449b225e1SGavin Maltby fmev_rele(fmev_t ev) 14549b225e1SGavin Maltby { 14649b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 14749b225e1SGavin Maltby 14849b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 14949b225e1SGavin Maltby 150*f6e214c7SGavin Maltby (void) FMEV_API_ENTER(iep, 1); 15149b225e1SGavin Maltby 15249b225e1SGavin Maltby if (atomic_dec_32_nv(&iep->ei_refcnt) == 0) 15349b225e1SGavin Maltby fmev_free(iep); 15449b225e1SGavin Maltby } 15549b225e1SGavin Maltby 15649b225e1SGavin Maltby fmev_t 15749b225e1SGavin Maltby fmev_dup(fmev_t ev) 15849b225e1SGavin Maltby { 15949b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 16049b225e1SGavin Maltby fmev_impl_t *cp; 16149b225e1SGavin Maltby 16249b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 16349b225e1SGavin Maltby 164*f6e214c7SGavin Maltby if (!FMEV_API_ENTER(iep, 1)) 165*f6e214c7SGavin Maltby return (NULL); /* fmev_errno set */ 16649b225e1SGavin Maltby 16749b225e1SGavin Maltby if (ev == NULL) { 16849b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_API); 16949b225e1SGavin Maltby return (NULL); 17049b225e1SGavin Maltby } 17149b225e1SGavin Maltby 17249b225e1SGavin Maltby if ((cp = fmev_shdl_alloc(iep->ei_hdl, sizeof (*iep))) == NULL) { 17349b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_ALLOC); 17449b225e1SGavin Maltby return (NULL); 17549b225e1SGavin Maltby } 17649b225e1SGavin Maltby 17749b225e1SGavin Maltby if (nvlist_dup(iep->ei_nvl, &cp->ei_nvl, 0) != 0) { 17849b225e1SGavin Maltby fmev_shdl_free(iep->ei_hdl, cp, sizeof (*cp)); 17949b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_ALLOC); 18049b225e1SGavin Maltby return (NULL); 18149b225e1SGavin Maltby } 18249b225e1SGavin Maltby 18349b225e1SGavin Maltby cp->ei_magic = _FMEVMAGIC; 18449b225e1SGavin Maltby cp->ei_hdl = iep->ei_hdl; 18549b225e1SGavin Maltby cp->ei_refcnt = 1; 18649b225e1SGavin Maltby return (IMPL2FMEV(cp)); 18749b225e1SGavin Maltby } 18849b225e1SGavin Maltby 18949b225e1SGavin Maltby nvlist_t * 19049b225e1SGavin Maltby fmev_attr_list(fmev_t ev) 19149b225e1SGavin Maltby { 19249b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 19349b225e1SGavin Maltby 19449b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 19549b225e1SGavin Maltby 196*f6e214c7SGavin Maltby if (!FMEV_API_ENTER(iep, 1)) 197*f6e214c7SGavin Maltby return (NULL); /* fmev_errno set */ 19849b225e1SGavin Maltby 19949b225e1SGavin Maltby if (ev == NULL) { 20049b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_API); 20149b225e1SGavin Maltby return (NULL); 20249b225e1SGavin Maltby } else if (iep->ei_nvl == NULL) { 20349b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_MALFORMED_EVENT); 20449b225e1SGavin Maltby return (NULL); 20549b225e1SGavin Maltby } 20649b225e1SGavin Maltby 20749b225e1SGavin Maltby return (iep->ei_nvl); 20849b225e1SGavin Maltby } 20949b225e1SGavin Maltby 21049b225e1SGavin Maltby const char * 21149b225e1SGavin Maltby fmev_class(fmev_t ev) 21249b225e1SGavin Maltby { 21349b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 21449b225e1SGavin Maltby const char *class; 21549b225e1SGavin Maltby 21649b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 21749b225e1SGavin Maltby 218*f6e214c7SGavin Maltby if (!FMEV_API_ENTER(iep, 1)) 219*f6e214c7SGavin Maltby return (NULL); /* fmev_errno set */ 22049b225e1SGavin Maltby 22149b225e1SGavin Maltby if (ev == NULL) { 22249b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_API); 22349b225e1SGavin Maltby return (""); 22449b225e1SGavin Maltby } 22549b225e1SGavin Maltby 22649b225e1SGavin Maltby if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, (char **)&class) != 0 || 22749b225e1SGavin Maltby *class == '\0') { 22849b225e1SGavin Maltby (void) fmev_seterr(FMEVERR_MALFORMED_EVENT); 22949b225e1SGavin Maltby return (""); 23049b225e1SGavin Maltby } 23149b225e1SGavin Maltby 23249b225e1SGavin Maltby return (class); 23349b225e1SGavin Maltby } 23449b225e1SGavin Maltby 23549b225e1SGavin Maltby fmev_err_t 23649b225e1SGavin Maltby fmev_timespec(fmev_t ev, struct timespec *tp) 23749b225e1SGavin Maltby { 23849b225e1SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 23949b225e1SGavin Maltby uint64_t timetlimit; 24049b225e1SGavin Maltby 24149b225e1SGavin Maltby ASSERT(EVENT_VALID(iep)); 242*f6e214c7SGavin Maltby if (!FMEV_API_ENTER(iep, 1)) 243*f6e214c7SGavin Maltby return (fmev_errno); 24449b225e1SGavin Maltby 24549b225e1SGavin Maltby #ifdef _LP64 24649b225e1SGavin Maltby timetlimit = INT64_MAX; 24749b225e1SGavin Maltby #else 24849b225e1SGavin Maltby timetlimit = INT32_MAX; 24949b225e1SGavin Maltby #endif 25049b225e1SGavin Maltby 25149b225e1SGavin Maltby if (iep->ei_fmtime[FM_TIME_SEC] > timetlimit) 25249b225e1SGavin Maltby return (FMEVERR_OVERFLOW); 25349b225e1SGavin Maltby 25449b225e1SGavin Maltby tp->tv_sec = (time_t)iep->ei_fmtime[FM_TIME_SEC]; 25549b225e1SGavin Maltby tp->tv_nsec = (long)iep->ei_fmtime[FM_TIME_NSEC]; 25649b225e1SGavin Maltby 25749b225e1SGavin Maltby return (FMEV_SUCCESS); 25849b225e1SGavin Maltby } 25949b225e1SGavin Maltby 26049b225e1SGavin Maltby uint64_t 26149b225e1SGavin Maltby fmev_time_sec(fmev_t ev) 26249b225e1SGavin Maltby { 26349b225e1SGavin Maltby return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_SEC]); 26449b225e1SGavin Maltby } 26549b225e1SGavin Maltby 26649b225e1SGavin Maltby uint64_t 26749b225e1SGavin Maltby fmev_time_nsec(fmev_t ev) 26849b225e1SGavin Maltby { 26949b225e1SGavin Maltby return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_NSEC]); 27049b225e1SGavin Maltby } 27149b225e1SGavin Maltby 27249b225e1SGavin Maltby struct tm * 27349b225e1SGavin Maltby fmev_localtime(fmev_t ev, struct tm *tm) 27449b225e1SGavin Maltby { 27549b225e1SGavin Maltby time_t seconds; 27649b225e1SGavin Maltby 27749b225e1SGavin Maltby seconds = (time_t)fmev_time_sec(ev); 27849b225e1SGavin Maltby return (localtime_r(&seconds, tm)); 27949b225e1SGavin Maltby } 280*f6e214c7SGavin Maltby 281*f6e214c7SGavin Maltby fmev_shdl_t 282*f6e214c7SGavin Maltby fmev_ev2shdl(fmev_t ev) 283*f6e214c7SGavin Maltby { 284*f6e214c7SGavin Maltby fmev_impl_t *iep = FMEV2IMPL(ev); 285*f6e214c7SGavin Maltby 286*f6e214c7SGavin Maltby if (!FMEV_API_ENTER(iep, 2)) 287*f6e214c7SGavin Maltby return (NULL); 288*f6e214c7SGavin Maltby 289*f6e214c7SGavin Maltby return (iep->ei_hdl); 290*f6e214c7SGavin Maltby } 291